I am making a game, and when I want to go through the loop normally, it doesn't work.
it goes through the loop, but for some reason, it backtracks, rather than starting over. When I add a continue statement, the button just disappears.
Why isn't the continue statement working properly?
Here is my code:
import pygame
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((400, 300))
pygame.font.init()
done = False
bro = True
x = 100
y = 100
#button1 = pygame.draw.rect(screen, (0, 0, 255), (200, 200, 30, 30))
#if check <= pos - (w/2) and check >=
pygame.display.set_caption("Auto Maze!")
donk = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = event.pos
try:
assert button1.collidepoint(mouse)
except AssertionError:
pass
except NameError:
pass
else:
donk = True
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
y -= 5
elif pressed[pygame.K_s]:
y += 5
elif pressed[pygame.K_a]:
x -= 5
elif pressed[pygame.K_d]:
x += 5
screen.fill((0, 0, 0))
"""try:
assert player.colliderect(wall1)
except AssertionError:
pass
except NameError:
pass
else:
death_screen = pygame.display.set_mode((400, 300))
button1 = pygame.draw.rect(death_screen, (0, 0, 255), (200, 200, 30, 30))
if donk:
break"""
player = pygame.draw.rect(screen, (0, 255, 0), (x, y, 60, 60))
wall1 = pygame.draw.rect(screen, (255, 0, 0), (300, 0, 100, 300))
if player.colliderect(wall1):
death_screen = pygame.display.set_mode((400, 300))
myfont = pygame.font.SysFont("Comic Sans MS", 10)
button1 = pygame.draw.rect(death_screen, (0, 0, 255), (175, 100, 60, 30))
text = myfont.render("Try Again", False, (255, 0, 0))
screen.blit(text, (175, 100))
if donk:
screen = pygame.display.set_mode((400, 300))
clock.tick(60)
pygame.display.flip()
quit()
Add a gameover to your application:
gameover = False:
Do different things in the application loop, dependent on the state of gameover:
while not done:
# [...]
if not gameover:
# draw game scene
# [...]
else:
# draw gamover scene (button)
# [...]
Set the gameover state if the player collides:
gameover = player.colliderect(wall1)
Reset the position of the player if the continue button is pressed:
if event.type == pygame.MOUSEBUTTONDOWN:
if gameover:
if button1.collidepoint(event.pos):
gameover = False
x, y = 100, 100
See the example:
import pygame
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("Auto Maze!")
pygame.font.init()
myfont = pygame.font.SysFont("Comic Sans MS", 10)
x, y = 100, 100
gameover = False
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
if gameover:
if button1.collidepoint(event.pos):
gameover = False
x, y = 100, 100
screen.fill((0, 0, 0))
if not gameover:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
y -= 5
elif pressed[pygame.K_s]:
y += 5
elif pressed[pygame.K_a]:
x -= 5
elif pressed[pygame.K_d]:
x += 5
player = pygame.draw.rect(screen, (0, 255, 0), (x, y, 60, 60))
wall1 = pygame.draw.rect(screen, (255, 0, 0), (300, 0, 100, 300))
gameover = player.colliderect(wall1)
else:
button1 = pygame.draw.rect(screen, (0, 0, 255), (175, 100, 60, 30))
text = myfont.render("Try Again", False, (255, 0, 0))
screen.blit(text, (175, 100))
pygame.display.flip()
clock.tick(60)
quit()
This does the same as your code, but just cleaned up. Hopefully it solves your problem
import pygame
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((400, 300))
pygame.font.init()
done = False
mouse = None
click = False
state = "main"
myfont = pygame.font.SysFont("Comic Sans MS", 10)
player = pygame.Rect(100,100,60,60)
wall1 = pygame.Rect(300, 0, 100, 300)
button1 = pygame.Rect(175, 100, 60, 30)
pygame.display.set_caption("Auto Maze!")
while not done:
click = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
mouse = event.pos
click = True
screen.fill((0, 0, 0))
if state == "main":
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
player.y -= 5
elif pressed[pygame.K_s]:
player.y += 5
elif pressed[pygame.K_a]:
player.x -= 5
elif pressed[pygame.K_d]:
player.x += 5
#draw player and wall
pygame.draw.rect(screen, (0, 255, 0), player)
pygame.draw.rect(screen, (255, 0, 0), wall1)
if player.colliderect(wall1):
state = "death"
else:
pygame.draw.rect(screen, (0, 0, 255), button1)
text = myfont.render("Try Again", False, (255, 0, 0))
screen.blit(text, (175, 100))
if click:
if button1.collidepoint(mouse):
state = "main"
player.x = 100
player.y = 100
clock.tick(60)
pygame.display.flip()
quit()
Related
I am making simple game about clicking circles to learn pygame. I initialize pygame and pygame.font but it gives me an error randomly when I play the game. When I close the game before I get that error it gives me a diffrent error (pygame.error: video system not initialized)
import pygame
import random
import time
#I init here
pygame.init()
pygame.font.init()
class Target():
def __init__(self, p, color):
self.visible = True
self.pos = p
self.color = color
self.startT = time.time()
def isAlive(self):
if time.time()-self.startT >= aliveTime:
global gameOver
gameOver = True
return 0
else:
if self.visible:
return 1
return 0
def colisionCheck(self, color):
if color == pygame.Color(self.color):
self.visible = False
global alive
global score
alive -= 1
score += 1
def update(self):
if self.isAlive():
global targetSize
pygame.draw.circle(screen, self.color, self.pos, targetSize)
class Circle(pygame.sprite.Sprite):
def __init__(self, pos, color, *grps):
super().__init__(*grps)
self.image = pygame.Surface((32, 32))
self.image.set_colorkey((1, 2, 3))
self.image.fill((1, 2, 3))
pygame.draw.circle(self.image, pygame.Color(color), (15, 15), 15)
self.rect = self.image.get_rect(center=pos)
running = True
gameOver = False
score = 0
frames = 0
targetSize = 20
aliveTime = 10
startAliveNum = 5
screenX = 1000
screenY = screenX*0.6
alive = startAliveNum
targets = []
screen = pygame.display.set_mode((screenX, screenY))
font = pygame.font.Font('freesansbold.ttf', 12)
player = Circle(pygame.mouse.get_pos(), 'dodgerblue', targets)
pygame.display.set_caption('My Pygame game')
pygame.display.flip()
def newTargets(ammount):
for i in range(ammount):
pos = random.randint(50, screenX-50), random.randint(50, screenY-50)
targets.append(Target(pos, (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))))
newTargets(5)
startT = time.time() + 0.000001
targetStartT = startT
while running:
if gameOver:
running = False
pygame.quit()
frames += 1
text = font.render("{:.2f}fps".format(frames/(time.time()-startT)), True, (0, 0, 0), (255, 255, 255))
##############error here (pygame.error Library not initialized)##############
text2 = font.render("{:.2f} seconds left".format(targetStartT+10-time.time()), True, (0, 0, 0), (255, 255, 255))
text3 = font.render("score: " + str(score), True, (0, 0, 0), (255, 255, 255))
rect = text.get_rect()
rect2 = text2.get_rect()
rect2.center = (rect2.width/2, rect.height*1.5)
rect3 = text3.get_rect()
rect3.center = (rect3.width/2, rect.height*1.5*1.5)
screen.fill((30, 30, 30))
screen.blit(text, rect)
screen.blit(text2, rect2)
screen.blit(text3, rect3)
player.rect.center = pygame.mouse.get_pos()
player.update()
if alive == 0:
startAliveNum += 1
newTargets(startAliveNum)
alive += startAliveNum
aliveTime += 0.5
targetStartT = time.time() + 0.000001
for i in range(len(targets)):
targets[i].update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
color = screen.get_at(pygame.mouse.get_pos())
for i in range(len(targets)):
targets[i].colisionCheck(color)
pygame.display.flip()
########error here when I close the game before It gives me the first error (pygame.error: video system not initialized)########
Could someone please help me fix the errors.
(Sory if I spelled someting incorectly)
The problem is calling pygame.quit() at the beginning of the application loop. When pygame.quit() is called, all pygame modules will not be initialized and all subsequent calls to pygame functions will fail. Because the application loop executes the statement once to the end of the loop, you get an error. Call pygame.quit() after the application loop:
while running:
if gameOver:
running = False
#pygame.quit() <--- DELETE
# your code
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
# pygame.quit() <--- DELETE
running = False # <--- INSERT
# your code
# [...]
pygame.quit() # <--- INSERT
How can i make this kind of countdown in Pygame? (i'm looking for how could i make the circle's perimeter decrease, that's the issue, because displaying the time isn't hard )
Keep in mind that how long the perimeter of the circle is and the displayed time should be in proportion with each other.
Just use pygame.draw.arc and specify the stop_angle argument depending on the counter:
percentage = counter/100
end_angle = 2 * math.pi * percentage
pygame.draw.arc(window, (255, 0, 0), arc_rect, 0, end_angle, 10)
Minimal example:
import pygame
import math
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 100
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
def drawArc(surf, color, center, radius, width, end_angle):
arc_rect = pygame.Rect(0, 0, radius*2, radius*2)
arc_rect.center = center
pygame.draw.arc(surf, color, arc_rect, 0, end_angle, width)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
drawArc(window, (255, 0, 0), (100, 100), 90, 10, 2*math.pi*counter/100)
pygame.display.flip()
pygame.quit()
exit()
Sadly the quality of pygame.draw.arc with a width > 1 is poor. However this can be improved, using cv2 and cv2.ellipse:
import pygame
import cv2
import numpy
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 100
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
def drawArcCv2(surf, color, center, radius, width, end_angle):
circle_image = numpy.zeros((radius*2+4, radius*2+4, 4), dtype = numpy.uint8)
circle_image = cv2.ellipse(circle_image, (radius+2, radius+2),
(radius-width//2, radius-width//2), 0, 0, end_angle, (*color, 255), width, lineType=cv2.LINE_AA)
circle_surface = pygame.image.frombuffer(circle_image.flatten(), (radius*2+4, radius*2+4), 'RGBA')
surf.blit(circle_surface, circle_surface.get_rect(center = center))
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
drawArcCv2(window, (255, 0, 0), (100, 100), 90, 10, 360*counter/100)
pygame.display.flip()
pygame.quit()
exit()
How do I make entities take damage with colors? I made a game with enemies shooting blue lasers and I want the player to take damage. And the player shoots a red laser. Upon detecting colors, I want a certain statement to be true. That would lower an entity's health by one. If color collision is a thing, it can be very useful for making many different games. Here is my code:
# importing packages
import pygame
import random
import time
import sys
# Initializing Pygame
pygame.init()
# Setting a display caption
pygame.display.set_caption("Space Invaders")
spaceship = pygame.image.load("spaceship2.png")
blue_enemy = pygame.image.load("blue_enemy.png")
green_enemy = pygame.image.load("green_enemy.png")
orange_enemy = pygame.image.load("orange_enemy.png")
pink_enemy = pygame.image.load("pink_enemy.png")
yellow_enemy = pygame.image.load("yellow_enemy.png")
# Creating a font
pygame.font.init()
font = pygame.font.SysFont("consolas", 30)
large_font = pygame.font.SysFont("consolas", 60)
small_font = pygame.font.SysFont("consolas", 20)
# Setting a display width and height and then creating it
display_width = 700
display_height = 500
display_size = [display_width, display_height]
game_display = pygame.display.set_mode(display_size)
intro_display = pygame.display.set_mode(display_size)
# Creating a way to add text to the screen
def message(sentence, color, x, y, font_type, display):
sentence = font_type.render(str.encode(sentence), True, color)
display.blit(sentence, [x, y])
def main():
global white
global black
global clock
# Spaceship coordinates
spaceship_x = 300
spaceship_y = 375
spaceship_x_change = 0
blue_enemy_health = 5
green_enemy_health = 5
orange_enemy_health = 5
pink_enemy_health = 5
yellow_enemy_health = 5
# Clock making
# Initializing pygame
pygame.init()
# Creating colors
red = (0, 0, 0)
blue = (0, 0, 255)
# clock stuff
clock = pygame.time.Clock()
time_elapsed_since_last_action = 0
time_elapsed_since_last_action2 = 0
time_elapsed_since_last_action3 = 0
# Creating a loop to keep program running
while True:
laser_rect = pygame.Rect(spaceship_x + 69, 70, 4, 310)
# --- Event Processing and controls
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
spaceship_x_change = 10
elif event.key == pygame.K_LEFT:
spaceship_x_change = -10
elif event.key == pygame.K_r:
red = (255, 0, 0)
elif time_elapsed_since_last_action2 > 250:
pygame.draw.rect(game_display, red, laser_rect)
time_elapsed_since_last_action2 = 0
elif event.type == pygame.KEYUP:
spaceship_x_change = 0
red = (0, 0, 0)
spaceship_x += spaceship_x_change
# Preventing the ship from going off the screen
if spaceship_x > display_width - 140:
spaceship_x -= 10
if spaceship_x < 1:
spaceship_x += 10
# Setting Display color
game_display.fill(black)
laser_coords = [70, 209, 348, 505, 630]
random_x_coord = random.choice(laser_coords)
dt = clock.tick()
time_elapsed_since_last_action += dt
if time_elapsed_since_last_action > 500:
pygame.draw.rect(game_display, blue, [random_x_coord, 85, 6, 305])
time_elapsed_since_last_action = 0
time_elapsed_since_last_action2 += dt
# Creating a spaceship, lasers, and enemies
game_display.blit(spaceship, (spaceship_x, spaceship_y))
message(str(blue_enemy_health), white, 65, 10, font, game_display)
game_display.blit(blue_enemy, (20, 25))
message(str(green_enemy_health), white, 203, 10, font, game_display)
game_display.blit(green_enemy, (160, 25))
message(str(orange_enemy_health), white, 341, 10, font, game_display)
game_display.blit(orange_enemy, (300, 25))
message(str(pink_enemy_health), white, 496, 10, font, game_display)
game_display.blit(pink_enemy, (440, 25))
message(str(yellow_enemy_health), white, 623, 10, font, game_display)
game_display.blit(yellow_enemy, (580, 25))
health = 10
message("Spaceship durability: " + str(health), white, 20, 480, small_font, game_display)
# Updating Screen so changes take places
pygame.display.update()
# Setting FPS
FPS = pygame.time.Clock()
FPS.tick(60)
black = (0, 0, 0)
white = (255, 255, 255)
gray = (100, 100, 100)
while True:
intro_display.fill(black)
pygame.event.poll()
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
message("Space Bugs", white, 180, 150, large_font, intro_display)
if 150 + 100 > mouse[0] > 150 and 350 + 50 > mouse[1] > 350:
pygame.draw.rect(game_display, gray, [150, 350, 100, 50])
if click[0] == 1:
break
else:
pygame.draw.rect(game_display, white, [150, 350, 100, 50])
if 450 + 100 > mouse[0] > 450 and 350 + 50 > mouse[1] > 350:
pygame.draw.rect(game_display, gray, [450, 350, 100, 50])
if click[0] == 1:
pygame.quit()
quit()
else:
pygame.draw.rect(game_display, white, [450, 350, 100, 50])
message("Start", black, 155, 360, font, intro_display)
message("Quit", black, 465, 360, font, intro_display)
# Go ahead and update the screen with what we've drawn.
pygame.display.update()
# Wrap-up
# Limit to 60 frames per second
clock = pygame.time.Clock()
clock.tick(60)
# Executing the function
if __name__ == "__main__":
main()
No, there is no such a "thing" as a "color collision". What color have the images? Are they uniformly colored? Most likely the pictures are only different in some details. A collision which checks for a uniform color is completely useless. A collision that also looks for a uniform color is almost useless.
If you detect a collision, you know the laser and the enemy. Hence, you know the color with which you represent them. All you have to do is do an additional check after the collision is detected.
Use pygame.sprite.Sprite to implement the objects. Add an attribute that indicates the color of the object:
class ColoredSprite(pygame.sprite.Sprite):
def __init__(self, x, y, image, color):
super().__init__()
self.image = image
self.rect = self.image.get_rect(center = (x, y)
slef.color = color
Manage the spites in pygame.sprite.Groups and use spritecollide to detect the collisions. Check the color attributes when a collision is detected
collide_list = sprite.spritecollide(sprite_group, False):
for other_sprite in collide_list:
if sprite.color == 'red' and other_sprite.color == 'blue':
# [...]
elif sprite.color == 'blue' and other_sprite.color == 'red':
# [...]
It is even possible to implement your own collision detection method and use it in combination with spritecollide by setting the optional collided argument:
def color_collision(sprite1, sprite2):
if sprite1.rect.colliderect(sprite2.rect):
return ((sprite1.color == 'red' and sprite2.color == 'blue') or
(sprite1.color == 'blue' and sprite2.color == 'red'))
return false
collide_list = sprite.spritecollide(sprite_group, False, color_collision):
for other_sprite in collide_list:
# [...]
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
sprite1 = pygame.sprite.Sprite()
sprite1.image = pygame.Surface((75, 75))
sprite1.image.fill('red')
sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
sprite1.color = 'red'
sprite2 = pygame.sprite.Sprite()
sprite2.image = pygame.Surface((75, 75))
sprite2.image.fill('blue')
sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)
sprite2.color = 'blue'
all_group = pygame.sprite.Group([sprite2, sprite1])
def color_collision(sprite1, sprite2):
if sprite1.rect.colliderect(sprite2.rect):
return ((sprite1.color == 'red' and sprite2.color == 'blue') or
(sprite1.color == 'blue' and sprite2.color == 'red'))
return False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
sprite1.rect.center = pygame.mouse.get_pos()
collide = pygame.sprite.spritecollide(sprite1, all_group, False, color_collision)
window.fill(0)
all_group.draw(window)
for s in collide:
pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1)
pygame.display.flip()
pygame.quit()
exit()
This question already has answers here:
Why is my pygame application loop not working properly?
(1 answer)
Pygame window freezes when it opens
(1 answer)
Closed 2 years ago.
I asked you how to make a main menu window and a game window, buttons, and more. Okay, done. This is the code so far:
import pygame
from pygame.locals import *
pygame.init()
win = pygame.display.set_mode((800, 600))
win.fill((0, 180, 210))
pygame.display.set_caption("Baloon War!")
icon = pygame.image.load("Baloon war icon.png")
pygame.display.set_icon(icon)
class button():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self, win, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 60)
text = font.render(self.text, 1, (0, 0, 0))
win.blit(text, (self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))
def isOver(self, pos):
# Pos is the mouse position or a tuple of (x,y) coordinates
if pos[0] > self.x and pos[0] < self.x + self.width:
if pos[1] > self.y and pos[1] < self.y + self.height:
return True
return False
def redrawMenuWindow():
win.fill((0, 255, 110))
greenButton.draw(win, (0, 0, 0))
redButton.draw(win, (0, 0, 0))
def redrawGameWindow():
win.fill((0, 180, 210))
greenButton = button((0, 255, 0), 280, 255, 250, 100, "Start")
redButton = button ((255, 0, 0), 280, 380, 250, 100, "Quit")
game_state = "menu"
run = True
while run:
if game_state == "menu":
redrawMenuWindow()
elif game_state == "game":
redrawGameWindow()
pygame.display.update()
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if greenButton.isOver(pos):
print("clicked the button")
game_state = "game"
if redButton.isOver(pos):
print("clicked the 2button")
run = False
pygame.quit()
quit()
if event.type == pygame.MOUSEMOTION:
if greenButton.isOver(pos):
greenButton.color = (105, 105, 105)
else:
greenButton.color = (0, 255, 0)
if redButton.isOver(pos):
redButton.color = (105, 105, 105)
else:
redButton.color = (255, 0, 0)
So then I wanted to make my main game part. After pressing the Start/greenButton the game_state is "game". But how do I write what the game should be like, where???? I didn't know how so I wrote this:
game_state = "game"
while game_state is "game":
redrawGameWindow():
But this just doesn't work. Anyone here that can explain me how to do it?
You have to put the game implementation in redrawGameWindow. You don't need any extra loop.
You have to draw the scene dependent on the state of the game redrawMenuWindowin redrawGameWindow. Note you can have more than 2 game states, then you'll need more functions, which draw the scene dependent on the state.
def redrawMenuWindow():
win.fill((0, 255, 110))
# draw menu
# [...]
def redrawGameWindow():
win.fill((0, 180, 210))
# draw main game part
# [...]
game_state = "menu"
run = True
while run:
if game_state == "menu":
redrawMenuWindow()
elif game_state == "game":
redrawGameWindow()
# elif game_state == "gameover":
# redrawGameoverWindow()
pygame.display.update()
# [...]
And you have to handle the event dependent on the state of the game:
while run:
# [...]
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
if game_state == "menu":
if event.type == pygame.MOUSEBUTTONDOWN:
if greenButton.isOver(pos):
print("clicked the button")
game_state = "game"
if redButton.isOver(pos):
print("clicked the 2button")
run = False
# [...]
elif game_state == "game":
# handel main game events
# [...]
I am trying to make a hangman game in pygame, but I cannot get buttons to work after they have been created from an event (in my case after pressing enter), they appear on screen but do not work ( rollover or activate events), please help!
from pygame.locals import *
import pygame, sys, eztext
import time
pygame.init()
Black = ( 0, 0, 0)
Grey = (100, 100, 100)
DarkGrey = (70, 70, 70)
White = (255, 255, 255)
Blue = ( 0, 0, 255)
NavyBlue = ( 60, 60, 100)
Cyan = ( 0, 255, 255)
Purple = (255, 0, 255)
Red = (255, 0, 0)
DarkRed = (180, 0, 0)
Orange = (255, 128, 0)
Yellow = (255, 255, 0)
Green = ( 0, 255, 0)
DarkGreen = ( 0, 180, 0)
LightBlue = ( 90, 164, 213)
Magenta = (153, 0, 76)
screen = pygame.display.set_mode((1000,600),0,32)
screen.fill(Orange)
txtbx = eztext.Input(maxlength=45, color=(0,0,0), prompt='Enter username: ')
def text_objects(text, font):
textSurface = font.render(text, True, Black)
return textSurface, textSurface.get_rect()
smallText = pygame.font.Font("freesansbold.ttf",20)
def button(msg,x,y,w,h,ic,ac,action=None):
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(screen, ac,(x, y, w, h))
if click [0] == 1 and action!= None:
if action == "Quit":
pygame.quit()
if action == "Single player":
pygame.draw.rect(screen, Green,(10, 10, 500, 500))
else:
pygame.draw.rect(screen, ic,(x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x+(w/2)), (y + (h/2)))
screen.blit(textSurf, textRect)
while True:
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
string1 = txtbx.value
pygame.display.update()
time.sleep(0.02)
pygame.draw.rect(screen, Green,(10, 100, 500, 50))
clock = pygame.time.Clock()
clock.tick(30)
events = pygame.event.get()
txtbx.set_pos(10,110)
label = smallText.render("Enter you user name and then press enter!", 1, (0,0,0))
screen.blit(label, (10, 10))
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key == pygame.K_RETURN:
button("Single player",10, 400, 150, 50, Green, DarkGreen,"Single player")
if string1 in open('Users.txt').read():
username = string1
Welcomeold1 = smallText.render('Welcome back', 1, (0,0,0))
screen.blit(Welcomeold1, (10, 200))
Welcomeold2 = smallText.render(username, 1, (0,0,0))
screen.blit(Welcomeold2, (160, 200))
else:
username = string1
f = open('Users.txt','a')
string1 = txtbx.value
f.write(string1)
f.write('\n')
f.close()
Welcomenew1 = smallText.render('Welcome to my game', 1, (0,0,0))
screen.blit(Welcomenew1, (10, 200))
Welcomenew2 = smallText.render(username, 1, (0,0,0))
screen.blit(Welcomenew2, (230, 200))
if event.key == pygame.K_BACKSPACE:
screen.fill(Orange)
txtbx.update(events)
txtbx.draw(screen)
pygame.display.flip()
if __name__ == '__main__': main()
button function is inside event.key so it will work only when RETURN is pressed, released, and pressed again, and released again, etc.
You should create class with method draw and handle_event to use this method in mainloop in different places. You can create button in event.key but you have to check button pressed in different place.
-
Simple button. Full working example.
When you press button function do_it is called and background changed color.
#
# pygame (simple) template - by furas
#
# ---------------------------------------------------------------------
import pygame
import pygame.gfxdraw
import random
# === CONSTANS === (UPPER_CASE names)
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
CYAN = ( 0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# === CLASSES === (CamelCase names)
class Button():
def __init__(self, text, x, y, width, height, on_click=None, fg_color=RED, bg_color=WHITE, font_size=35):
self.text = text
font = pygame.font.SysFont(None, font_size)
# rectangle - without position, to put text in correct place
self.rect = pygame.Rect(0, 0, width, height)
# normal button - fill background
self.normal_image = pygame.surface.Surface( self.rect.size )
self.normal_image.fill(bg_color)
# normal button - add text
text_image = font.render(text, True, fg_color)
text_rect = text_image.get_rect(center=self.rect.center)
self.normal_image.blit(text_image, text_rect)
# hover button - fill background
self.hover_image = pygame.surface.Surface( self.rect.size )
self.hover_image.fill(fg_color)
# hover button - add text
text_image = font.render(text, True, bg_color)
text_rect = text_image.get_rect(center=self.rect.center)
self.hover_image.blit(text_image, text_rect)
# set position
self.rect.x = x
self.rect.y = y
# other
self.on_click = on_click
self.hover = False
def draw(self, surface):
# draw normal or hover image
if self.hover:
surface.blit(self.hover_image, self.rect)
else:
surface.blit(self.normal_image, self.rect)
def event_handler(self, event):
# is mouse over button ?
if event.type == pygame.MOUSEMOTION:
self.hover = self.rect.collidepoint(event.pos)
# is mouse clicked ? run function.
if event.type == pygame.MOUSEBUTTONDOWN:
if self.hover and self.on_click:
self.on_click()
# === FUNCTIONS === (lower_case names)
def do_it():
global background_color
if background_color == BLACK:
background_color = RED
elif background_color == RED:
background_color = GREEN
else:
background_color = BLACK
print("Button pressed")
# === MAIN ===
# --- init ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()
# --- objects ---
# create button
button = Button('CHANGE COLOR', 0, 0, 300, 50, on_click=do_it)
# add function later
#button_quit.on_click = do_it
# center button
button.rect.center = screen_rect.center
# default bacground color - changed in do_it()
background_color = BLACK
# --- mainloop ---
clock = pygame.time.Clock()
is_running = True
while is_running:
# --- events ---
for event in pygame.event.get():
# --- global events ---
if event.type == pygame.QUIT:
is_running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
is_running = False
# --- objects events ---
button.event_handler(event)
# --- updates ---
# empty
# --- draws ---
# clear buffer
screen.fill(background_color)
# draw all objects - widgets (buttons, labels)
button.draw(screen)
clock.tick(25)
# send buffer to video card
pygame.display.update()
# --- the end ---
pygame.quit()