Broken Progress Bar in Pygame - python-3.x

So when I and my acquaintance were working in pygame, we came across a problem:Every time the progress bar reached over 100, it would crash and show us an error. The error code reads:
"Traceback (most recent call last):
File "C:/Users/Tip/Documents/loading bar/load.py", line 150, in <module>
loading(progress/2)
File "C:/Users/Tip/Documents/loading bar/load.py", line 60, in loading
screen.blit(text, (300, 100))
TypeError: argument 1 must be pygame.Surface, not str
libpng warning: iCCP: known incorrect sRGB profile".
And to help, here is the code:
import pygame
import random
pygame.init()
progress = 0
into = True
black = [0, 0, 0]
white = [255, 255, 255]
intoWhite = [249, 244, 244]
green = [0, 255, 0]
screenWidth = 600
screenHeigth = 450
size = [screenWidth, screenHeigth]
font = pygame.font.SysFont("Comic Sans MS", 25)
intoPic = pygame.image.load("images/Can You Surive Pic.png")
cory = "audio/Cory in the House - Opening Sequence.mp3"
coryPic = pygame.image.load("images/CoryBaxterFull.png")
coryMusicBool = False
coryPicBool = False
basic = "audio/basic song.mp3"
shrekPicBool = False
shrekMusicBool = False
shrek = "audio/Shrek's Fairytale Freestyle.mp3"
shrekPic = pygame.image.load("images/shrek.png")
clock = pygame.time.Clock()
clock.tick(10)
count = 0
escPressed = False
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Loading...')
escMessageText = "Press Esc to cancel"
escMessage = font.render(escMessageText, False, white)
escMessageText_2 = "You Can't Leave"
escMessage_2 = font.render(escMessageText_2, False, white)
def textobjecte(text, color, size):
if size == "small":
textsuraface = font.render(text, True, color)
return textsuraface, textsuraface.get_rect()
def loading(progress):
text = ""
if progress < 100:
text = font.render("loading: " + str(int(progress)) + "%", True, green)
screen.blit(text, (300, 100))
def message_to_screen(msg, color, y_displace, size="small"):
textsurf, textrect = textobjecte(msg, color, size)
textrect.center = (screenWidth/2), (screenHeigth/2) + y_displace
screen.blit(textsurf, textrect)
def playcory():
pygame.mixer.music.load(cory)
pygame.mixer.music.play(-1)
def playshrek():
pygame.mixer.music.load(shrek)
pygame.mixer.music.play(-1)
def basicsong():
pygame.mixer.music.load(basic)
pygame.mixer.music.play(-1)
basicsong()
while into == True:
pygame.event.pump()
screen.fill(intoWhite)
screen.blit(intoPic, (75, 0))
intoKey = pygame.key.get_pressed()
pygame.display.flip()
if intoKey[pygame.K_SPACE]:
into = False
while progress/2 < 100:
timeCount = random.randint(1, 10000)
increase = random.randint(1, 10)
progress += increase/10000
screen.fill(black)
pygame.event.pump()
pygame.draw.rect(screen, white, [300, 50, 200, 50])
pygame.draw.rect(screen, black, [301, 51, 198, 48])
if (progress/2) > 100:
pygame.draw.rect(screen, white, [302, 52, 196, 46])
else:
pygame.draw.rect(screen, white, [302, 52, progress, 46])
if coryMusicBool == True:
pygame.mixer.music.stop()
playcory()
coryMusicBool = False
if coryPicBool== True:
screen.blit(coryPic, (0, 0))
if shrekMusicBool == True:
pygame.mixer.music.stop()
playshrek()
shrekMusicBool = False
if shrekPicBool == True:
screen.blit(shrekPic, (100, 0))
if escPressed == False:
screen.blit(escMessage, (50, 50))
if escPressed == True:
screen.blit(escMessage_2, (50, 50))
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
pygame.mixer.music.stop()
progress = 0
escPressed = True
keys2 = pygame.key.get_pressed()
if keys2[pygame.K_c]:
coryMusicBool = True
coryPicBool = True
keys3 = pygame.key.get_pressed()
if keys3[pygame.K_s]:
shrekPicBool = True
shrekMusicBool = True
if progress/2 >= 100:
progress = 200
loading(progress/2)
pygame.display.flip()
Our code is supposed to be a loading bar. The text that shows the problem of the progression is in the loading x % part.
Please help, and thank you.

Try This
import pygame
import random
pygame.init()
progress = 0
into = True
black = [0, 0, 0]
white = [255, 255, 255]
intoWhite = [249, 244, 244]
green = [0, 255, 0]
screenWidth = 600
screenHeigth = 450
size = [screenWidth, screenHeigth]
font = pygame.font.SysFont("Comic Sans MS", 25)
intoPic = pygame.image.load("images/Can You Surive Pic.png")
cory = "audio/Cory in the House - Opening Sequence.mp3"
coryPic = pygame.image.load("images/CoryBaxterFull.png")
coryMusicBool = False
coryPicBool = False
basic = "audio/basic song.mp3"
shrekPicBool = False
shrekMusicBool = False
shrek = "audio/Shrek's Fairytale Freestyle.mp3"
shrekPic = pygame.image.load("images/shrek.png")
clock = pygame.time.Clock()
clock.tick(10)
count = 0
escPressed = False
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Loading...')
escMessageText = "Press Esc to cancel"
escMessage = font.render(escMessageText, False, white)
escMessageText_2 = "You Can't Leave"
escMessage_2 = font.render(escMessageText_2, False, white)
def textobjecte(text, color, size):
if size == "small":
textsuraface = font.render(text, True, color)
return textsuraface, textsuraface.get_rect()
def loading(progress):
text = ""
if progress < 101:
text = font.render("loading: " + str(int(progress)) + "%", True, green)
screen.blit(text, (300, 100))
def message_to_screen(msg, color, y_displace, size="small"):
textsurf, textrect = textobjecte(msg, color, size)
textrect.center = (screenWidth/2), (screenHeigth/2) + y_displace
screen.blit(textsurf, textrect)
def playcory():
pygame.mixer.music.load(cory)
pygame.mixer.music.play(-1)
def playshrek():
pygame.mixer.music.load(shrek)
pygame.mixer.music.play(-1)
def basicsong():
pygame.mixer.music.load(basic)
pygame.mixer.music.play(-1)
basicsong()
while into == True:
pygame.event.pump()
screen.fill(intoWhite)
screen.blit(intoPic, (75, 0))
intoKey = pygame.key.get_pressed()
pygame.display.flip()
if intoKey[pygame.K_SPACE]:
into = False
while progress/2 < 100:
timeCount = random.randint(1, 10000)
increase = random.randint(1, 10)
progress += increase/10000
screen.fill(black)
pygame.event.pump()
pygame.draw.rect(screen, white, [300, 50, 200, 50])
pygame.draw.rect(screen, black, [301, 51, 198, 48])
if (progress/2) > 100:
pygame.draw.rect(screen, white, [302, 52, 196, 46])
else:
pygame.draw.rect(screen, white, [302, 52, progress, 46])
if coryMusicBool == True:
pygame.mixer.music.stop()
playcory()
coryMusicBool = False
if coryPicBool== True:
screen.blit(coryPic, (0, 0))
if shrekMusicBool == True:
pygame.mixer.music.stop()
playshrek()
shrekMusicBool = False
if shrekPicBool == True:
screen.blit(shrekPic, (100, 0))
if escPressed == False:
screen.blit(escMessage, (50, 50))
if escPressed == True:
screen.blit(escMessage_2, (50, 50))
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
pygame.mixer.music.stop()
progress = 0
escPressed = True
keys2 = pygame.key.get_pressed()
if keys2[pygame.K_c]:
coryMusicBool = True
coryPicBool = True
keys3 = pygame.key.get_pressed()
if keys3[pygame.K_s]:
shrekPicBool = True
shrekMusicBool = True
if progress/2 >= 100:
progress = 200
loading(progress/2)
pygame.display.flip()
For the SRGb error add this to your code pngcrush -ow -rem allb -reduce file.png. its from this link. libpng warning: iCCP: known incorrect sRGB profile
For your game quitting at 100% its because your while loop ends when you reach 100% so you should make it so the draw screen statement is in a separate loop from the draw the loading bar one

In the loading function, text is either a string if the progress is >= 100 or a pygame.Surface if the progress is < 100.
Since the pygame.Surface.blit method only takes a pygame.Surface as the first argument, a TypeError will be raised when you pass a string.
A simple fix would be to blit the text surface in the if clause:
def loading(progress):
if progress < 100:
text = font.render("loading: " + str(int(progress)) + "%", True, green)
screen.blit(text, (300, 100))
You could also blit a transparent surface or do text = font.render("", True, green), but that would be pointless. Just don't blit anything when the progress is >= 100.

Related

when adding new text it appears on bottom and rest of text goes up

I want to display text on the text box that says if I hit and how much damage I do and vice versa for the enemy, but I just can't figure out how to make the text to display in this manner.
Here is the code I'm working on:
def textBox(textv):
lText = []
text = font.render(str(textv),True,(1,1,1))
lText.append(text)
if len(lText) >= 10:
lText.pop(9)
screen.blit(lText[0],(20,400))
screen.blit(lText[1],(20,380))
while True:
battle_screen()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(enemy_background,(20,20))
player.drawPlayer()
enemy.newEnemy()
textBox("Daniel")
textBox("Jenny")
pygame.display.update()
Rendere the text an add the rendered text into a list:
text_surf_list = []
text_surf = font.render("Daniel", True, (255, 255, 0))
text_surf_list.append(text_surf)
text_surf = font.render("Jenny", True, (255, 255, 0))
text_surf_list.append(text_surf)
Define a rectangular area for the text box:
text_box_rect = pygame.Rect(20, 20, 250, 360)
Iterate through list in reversed order. Draw the text from the bottom up. Remove the text from the list if it is not in the box (see How to remove items from a list while iterating?):
text_y = box_rect.bottom - font.get_height()
for text_surf in reversed(text_surf_list[:]):
if text_y <= box_rect.top:
text_surf_list.remove(text_surf)
else:
surf.blit(text_surf, (box_rect.left + 10, text_y))
text_y -= font.get_height()
Set a temporary clipping area while drawing the text box withpygame.Surface.set_clip:
# set clipping
surf.set_clip(box_rect)
# draw text box
# [...]
# disable clipping
surf.set_clip(None)
Minimal example:
import pygame, random
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
def draw_scroll_text_box(surf, font, box_rect, text_surf_list):
surf.set_clip(box_rect)
text_y = box_rect.bottom - font.get_height() - 10
for text_surf in reversed(text_surf_list[:]):
if text_y <= box_rect.top:
text_surf_list.remove(text_surf)
else:
surf.blit(text_surf, (box_rect.left + 10, text_y))
text_y -= font.get_height()
pygame.draw.rect(surf, (164, 164, 164), box_rect, 5)
surf.set_clip(None)
font = pygame.font.SysFont(None, 50)
text_box_rect = pygame.Rect(20, 20, 250, 360)
text_surf_list = []
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 200)
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *background.get_size(), (32, 32, 32), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == timer_event:
names = ["Daniel", "Jenny", "Patrick", "Sandy", "Bob"]
text_surf = font.render(random.choice(names), True, (255, 255, 0))
text_surf_list.append(text_surf)
window.blit(background, (0, 0))
draw_scroll_text_box(window, font, text_box_rect, text_surf_list)
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()

Pygame code very slow despite all troubleshooting

so i wrote this game from a pygame intro tutorial, added menus and all to modify it. whenever i run the game on my MBP 17, it runs extremely slow. i googled it, and tried all solutions, to no avail. also, typing in my event.unicode works extremely horribly, i have to press the same key more than once for it to register. any help is appreciated.
import sys
import pygame
import random
import math
import mysql.connector as mysql
import pygame_textinput
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Die Alien Die')
#database requirements
msql = mysql.connect(user='root', password='7014403396', database='gamer')
cursor = msql.cursor()
#background
background = pygame.image.load('back.png').convert()
pygame.mixer.music.load('y2mate.com - Star Wars_ Sith Battle Theme Music_XS4_5xlA3Ls_320kbps.mp3')
pygame.mixer.music.play(-1)
clock = pygame.time.Clock()
#millenium falcom
playerimg = pygame.image.load('mfc.png')
playerX = 350
playerY = 480
dx = 0
dy = 0
#alien die
alienimg = []
alienX =[]
alienY =[]
adx = []
ady = []
no_of_aliens = 8
for i in range(no_of_aliens):
alienimg.append(pygame.image.load('spaceship.png'))
alienX.append(random.randint(0,735))
alienY.append(random.randint(50,250))
adx.append(0.3)
ady.append(random.randint(20,43))
#bullets
bulletimg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bdx = 0
bdy = 1
visibility = False
score = 0
font=pygame.font.Font('freesansbold.ttf',32)
font2 = pygame.font.Font('freesansbold.ttf',25)
font3 = pygame.font.Font('freesansbold.ttf',22)
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
click = False
def EnterUser():
texty = ''
global click
while True:
screen.fill((255, 255, 255))
textinput = pygame_textinput.TextInput()
events = pygame.event.get()
textinput.update(events)
screen.blit(textinput.get_surface(), (50, 150))
buttong = pygame.Rect(50, 330, 200, 50)
mx, my = pygame.mouse.get_pos()
pygame.draw.rect(screen, (255, 0, 0), buttong)
draw_text('enter username', font, (0, 0, 0), screen, 20, 20)
draw_text("Press Enter", font2, (0, 0, 0), screen, 50, 200)
draw_text("If you leave username blank", font2, (0, 0, 0), screen, 50, 250)
draw_text("your score wont register", font2, (0, 0, 0), screen, 50, 280)
text_surface = font.render(texty, True, (0,0,0))
screen.blit(text_surface, (50, 150))
draw_text('Lets Go', font2, (0, 0, 0), screen, 52, 340)
if buttong.collidepoint((mx, my)):
if click:
main_menu()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
texty += event.unicode
if event.key == pygame.K_BACKSPACE:
texty = texty[:-1]
if event.key == pygame.K_ESCAPE:
pygame.quit()
if event.type == pygame.K_RETURN:
main_menu()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
def draw_text(text, font, color, surface, x, y):
textobj = font.render(text, 1, color)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
def player(x, y):
screen.blit(playerimg, (x, y))
def alien(x,y,i):
screen.blit(alienimg[i],(x,y))
def shoot(x,y):
global visibility
visibility = True
screen.blit(bulletimg,(x+25,y+10))
def collide(bulletX,bulletY,alienX,alienY):
distance = math.sqrt(math.pow(alienX-bulletX,2)+math.pow(alienY-bulletY,2))
if distance < 27:
return True
else:
return False
def showscore(x,y):
sscore=font.render('Score: '+str(score),True,(141,27,31))
screen.blit(sscore,(x,y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
fscore = score
save_score()
def save_score():
t = "INSERT INTO alien VALUES('{}', '{}')".format(texty, str(score))
#val = (texty, str(score))
cursor.execute(t)
msql.commit()
#def show_high():
def main_menu():
while True:
screen.fill((0, 0, 0))
draw_text('Main Menu', font, (255, 255, 255), screen, 20, 20)
mx, my = pygame.mouse.get_pos()
button_1 = pygame.Rect(50, 100, 200, 50)
button_2 = pygame.Rect(50, 200, 200, 50)
if button_1.collidepoint((mx, my)):
if click:
game()
if button_2.collidepoint((mx, my)):
if click:
options()
pygame.draw.rect(screen, (255, 0, 0), button_1)
pygame.draw.rect(screen, (255, 0, 0), button_2)
draw_text('Alien Destroyer', font2, (0,0,0), screen, 52, 110)
draw_text('Show high scores', font3, (0,0,0), screen, 52, 206)
draw_text('for Alien Destroyer', font3, (0,0,0), screen, 52, 230)
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
click = True
pygame.display.update()
# game loop
def game():
global dx
global dy
global adx
global ady
global bdx
global bdy
global playerY
global playerX
global alienX
global alienY
global bulletY
global bulletX
global visibility
global score
running = True
while running:
clock.tick(60)
screen.fill((0, 0, 0))
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
dx = -1
if event.key == pygame.K_RIGHT:
dx = 1
if event.key == pygame.K_SPACE:
pygame.mixer.music.load('laser.wav')
pygame.mixer.music.play()
bulletX = playerX
shoot(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dx = 0
playerX += dx
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
for i in range(no_of_aliens):
if alienY[i] > 440:
for j in range(no_of_aliens):
alienY[j] = 2000
game_over_text()
break
alienX[i] += adx[i]
if alienX[i] <= 0:
adx[i] = 0.3
alienY[i] += ady[i]
elif alienX[i] >= 736:
adx[i] = -0.3
alienY[i] += ady[i]
death = collide(bulletX, bulletY, alienX[i], alienY[i])
if death:
pygame.mixer.music.load('explosion.wav')
pygame.mixer.music.play()
bulletY = 480
visibility = False
score += 1
alienX[i] = random.randint(0, 735)
alienY[i] = random.randint(30, 130)
alien(alienX[i], alienY[i], i)
if bulletY <= 0:
bulletY = 480
visibility = False
if visibility is True:
shoot(bulletX, bulletY)
bulletY -= bdy
showscore(10, 10)
player(playerX, playerY)
pygame.display.update()
EnterUser()
The problem is that you are calling pygame.event.get() multiple times (Lines: 89, 174, 208). This causes different events queues to disagree and causes problems. There is an easy fix.
In you main application loop, call pygame.event.get() once.
def game:
while running:
#omitted code
events = pygame.event.get()
for event in events:
#...
Then, you can pass events variable to other functions as an argument.

TypeError getting too many positional arguments when there are only supposed to be 4

Recently tried to complete a pygame assignment, but am receiving a TypeError for having too many positional arguments (5) when I have clearly only entered 4.
Below is my code:
import pygame
import random
import math
import os
import time
import sys
from os import path
from newsettings import *
from spritesdata import *
class Game:
def __init__(self):
pygame.init()
self.clock = pygame.time.Clock()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
self.time = pygame.time.get_ticks()
pygame.key.set_repeat(500, 100)
self.all_sprites = pygame.sprite.Group()
self.console = Console(self, 0)
self.player = Player(self, 390, 595)
self.work = Work(self, 450, 250)
self.food_station = Food_Station(self, 750, 200)
self.food = Food(self, 0, 10)
self.education = Education(self, 300, 10)
self.school = School(self, 100, 200)
self.family = Family(self, 600, 10)
self.money = Money(self, 850, 15)
self.food_bar = 100
def run(self):
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000
self.hunger()
self.events()
self.update()
self.draw()
def hunger(self):
HUNGEREVENT = pygame.USEREVENT + 1
pygame.time.set_timer(HUNGEREVENT, 10000)
def food_food(self, x, y, cool):
if cool < 0:
cool = 0
BAR_LENGTH = 100
BAR_HEIGHT = 10
fill = (cool / 100) * BAR_LENGTH
outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT)
pygame.draw.rect(self, GREEN, fill_rect)
pygame.draw.rect(self, WHITE, outline_rect, 2)
def quit(self):
pygame.quit()
sys.exit()
def update(self):
self.all_sprites.update()
def draw(self):
self.screen.fill(BGCOLOR)
self.all_sprites.draw(self.screen)
font = pygame.font.SysFont('Arial', 15, True, False)
self.food_food(screen, 5, 5, self.food_bar)
text = font.render("Number of days:" , True, BLACK)
screen.blit(text, [0, 110])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("=" , True, BLACK)
screen.blit(text, [120, 40])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("=" , True, BLACK)
screen.blit(text, [400, 40])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("=" , True, BLACK)
screen.blit(text, [700, 40])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("=" , True, BLACK)
screen.blit(text, [950, 40])
self.all_sprites.update()
pygame.display.flip()
def events(self):
# catch all events here
HUNGEREVENT = pygame.USEREVENT + 1
pygame.time.set_timer(HUNGEREVENT, 10000)
if pygame.event.get(HUNGEREVENT):
self.food_bar = self.food_bar - 10
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.key == pygame.K_ESCAPE:
self.quit()
def end_screen(self):
screen.fill(BLUE)
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("Life Simulator V2" , True, WHITE)
screen.blit(text, [400, 100])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("Controls: F for food, E for education, W for work", True, WHITE)
screen.blit(text, [175, 250])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("Hard mode: h Easy mode: e Normal mode: m", True, WHITE)
screen.blit(text, [175, 400])
font = pygame.font.SysFont('Arial', 30, True, False)
text = font.render("Start by pressing a key corresponding to that mode", True, WHITE)
screen.blit(text, [150, 600])
pygame.display.flip()
waiting = True
while waiting:
pygame.init()
clock = pygame.time.Clock()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_h:
waiting = False
initial_money = 50
self.food_bar = 100
if event.key == pygame.K_m:
waiting = False
initial_money = 100
self.food_bar = 100
if event.key == pygame.K_e:
waiting = False
initial_money = 200
self.food_bar = 100
g = Game()
g.end_screen()
g.run()
And here is the TypeError:
Traceback (most recent call last):
File "final_project.py", line 135, in <module>
g.run()
File "final_project.py", line 37, in run
self.draw()
File "final_project.py", line 65, in draw
self.food_food(screen, 5, 5, self.food_bar)
TypeError: food_food() takes 4 positional arguments but 5 were given
Although in the application of self.food_food() I have given 4 arguments, it prompts me that it received 5 positional arguments which causes me to be extremely confused. Any help would be appreciated. Thanks!
In python, methods recieves your arguments and self. You are sending 4 arguments and self. It is like: so you areself.food_food(self, screen, 5, 5, self.food_bar) and your function recives only 4 arguments. (If def is: def food_food(self, x, y, cool) you may call it self.food_food(x, y, cool)) You might want to use food_food(self, screen, x, y, cool):.

Progress bar inside a button in Pygame

The desired behavior is:
When user hold the mouse on the button, the dark gray progress bar appears and starts to get incremented at a constant pace. I want to be able to determine how long it will take for it to completely fill (like 2 seconds).
If the mouse move out the button BEFORE the progress bar has reached 100%, the progress bar should go straight to 0%.
If the bar reaches 100%, the program should print something in the terminal.
Here is the code:
import sys
import pygame
import time
from pygame.locals import *
from os import path
pygame.init()
screen = pygame.display.set_mode((900, int(900 * (16 / 9))))
clock = pygame.time.Clock()
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
WHITE = (255, 255, 255)
BACKGROUND_COLOR = (237, 225, 192)
LIGHT_GRAY = (60, 60, 60)
GRAY = (30, 30, 30)
class Button:
def __init__(self, screen, x, y, w, h, button_color_active, button_color_inactive, text, font, size = 50, text_color = BLACK):
self.screen = screen
self.game_folder = path.dirname(__file__)
self.font = path.join(self.game_folder, font + '.ttf')
self.x, self.y, self.w, self.h = x, y, w, h
self.button_color_active = button_color_active
self.button_color_inactive = button_color_inactive
self.text, self.size = text, size
self.text_color = text_color
self.button_rect = pygame.Rect(self.x, self.y, self.w, self.h)
self.button_font = pygame.font.Font(self.font, self.size)
self.label = self.button_font.render(self.text, 1, self.text_color)
def draw(self):
if self.button_rect.collidepoint(pygame.mouse.get_pos()):
#pygame.draw.rect(self.screen, self.button_color_inactive, self.button_rect)
for progress in range(42):
pygame.draw.rect(screen, LIGHT_GRAY, pygame.Rect(50,600,10*progress,80))
pygame.display.update()
else:
pygame.draw.rect(self.screen, self.button_color_active, self.button_rect)
self.screen.blit(self.label, (self.x + 20, self.y + 5))
def is_clicked(self, mouse_pos):
return bool(self.button_rect.collidepoint(mouse_pos))
def set_new_color(self, active_color, inactive_color):
self.button_color_active = active_color
self.button_color_inactive = inactive_color
button_start = Button(screen, 50, 600, 400, 80, GRAY, LIGHT_GRAY, 'START', 'roboto-black', 50, WHITE)
while True:
screen.fill(BACKGROUND_COLOR)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
#pygame.draw.rect(screen, GRAY, pygame.Rect(50,600,400,80))
#pygame.draw.rect(screen, LIGHT_GRAY, pygame.Rect(50,600,10*progress,80))
button_start.draw()
pygame.display.flip()
clock.tick(60)
a = str(input('shomething: '))
First you need a timer. You can use the dt (delta time) that pygame.clock.tick(fps) returns to increase a time variable. Do this only if the mouse is hovering over the button, otherwise reset the timer.
To calculate the width of the rect you can do this (proportionality):
width = time * coefficient
Here's a minimal example:
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
FONT = pg.font.Font(None, 36)
BACKGROUND_COLOR = (237, 225, 192)
LIGHT_GRAY = (120, 120, 120)
GRAY = (30, 30, 30)
# Button variables.
button_rect = pg.Rect(50, 100, 200, 80)
max_width = 200 # Maximum width of the rect.
max_time = 4 # Time after which the button should be filled.
# Coefficient to calculate the width of the rect for a given time.
coefficient = max_width / max_time
time = 0
dt = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
mouse_pos = pg.mouse.get_pos()
if button_rect.collidepoint(mouse_pos):
# If mouse is over the button, increase the timer.
if time < max_time: # Stop increasing if max_time is reached.
time += dt
if time >= max_time:
time = max_time
else: # If not colliding, reset the time.
time = 0
width = time * coefficient
screen.fill(BACKGROUND_COLOR)
pg.draw.rect(screen, LIGHT_GRAY, (51, 100, width, 80))
pg.draw.rect(screen, GRAY, button_rect, 2)
txt = FONT.render(str(round(time, 2)), True, GRAY)
screen.blit(txt, (20, 20))
pg.display.flip()
dt = clock.tick(60) / 1000
pg.quit()

Piano tiles: background image

I'm trying to make piano tiles in python using pygame. So, I've started with making an intro window but I'm unable to upload a background image1 in my into window. I actually want to display the name 'Piano tiles' and the background image whenever the player starts the game. Here's my code:
import pygame,os,random,time
from pygame.locals import *
wix=800
wiy=800
pygame.init()
white=(255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,155,0)
clock = pygame.time.Clock()
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 100)
gameDisplay=pygame.display.set_mode((wix,wiy))
bg = pygame.image.load("background.jpg")
pygame.display.set_caption("Piano Tiles")
def game_intro():
screen=pygame.display.set_mode((wix,wiy))
intro =True
while intro:
bg = pygame.image.load("background.jpg")
screen.blit(bg,(0,0))
gameDisplay.fill(white)
message_to_screen("PIANO TILES",black,-100,"large")
pygame.display.update()
clock.tick(8)
def text_objects(text,color,size):
if size == "small":
textSurface = smallfont.render(text, True, color)
elif size == "medium":
textSurface = medfont.render(text, True, color)
elif size == "large":
textSurface = largefont.render(text, True, color)
return textSurface, textSurface.get_rect()
def message_to_screen(msg,color, y_displace=0, size = "small"):
textSurf, textRect = text_objects(msg,color, size)
textRect.center = (wix/ 2), (wiy / 2)+y_displace
gameDisplay.blit(textSurf, textRect)
game_intro()
pygame.time.wait(4000)
pygame.quit()
quit()
You have to use fill(white) before you blit anything because it clear screen.
It could look like this
import pygame
# --- constants --- (UPPER_CASE names)
WIX = 800
WIY = 800
WHITE = (255,255,255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0,155, 0)
FPS = 8
# --- functions --- (lower_case names)
def text_objects(text, color, size):
if size == "small":
text_font = small_font
elif size == "medium":
font = med_font
elif size == "large":
font = large_font
#fonts = {"small": small_font, "medium": med_font, "large": large_font}
#font = fonts[size]
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
return text_surface, text_rect
def message_to_screen(screen, msg, color, y_displace=0, size="small"):
text_surface, text_rect = text_objects(msg, color, size)
text_rect.center = screen.get_rect().center
text_rect.y += y_displace
screen.blit(text_surface, text_rect)
def game_intro(screen, text):
#bg = pygame.image.load("background.jpg")
screen.fill(WHITE) # use if background is smaller then screen
screen.blit(bg, (0,0))
message_to_screen(screen, text, BLACK, -100, "large")
message_to_screen(screen, text, BLACK, 0, "large")
message_to_screen(screen, text, BLACK, 100, "large")
pygame.display.update()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False # exit program
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
return True # go to next stage
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
return True # go to next stage
clock.tick(FPS)
# --- main --- (lower_case names)
# - init -
pygame.init()
screen = pygame.display.set_mode((WIX, WIY))
#screen_rect = screen.get_rect()
pygame.display.set_caption("Piano Tiles")
# - resources -
bg = pygame.image.load("Obrazy/test.png")#"background.jpg")
small_font = pygame.font.SysFont("comicsansms", 25)
med_font = pygame.font.SysFont("comicsansms", 50)
large_font = pygame.font.SysFont("comicsansms", 100)
#fonts = {"small": small_font, "medium": med_font, "large": large_font}
# - stages -
go_next = game_intro(screen, "HELLO WORLD")
if go_next:
go_next = game_intro(screen, "PIANO TILES")
if go_next:
go_next = game_intro(screen, "BYE, BYE")
# - exit -
pygame.quit()

Resources