Pygame buttons not creating working buttons - python

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()

Related

Why does my program load a different screen than the one I need?

I am using PyGame, and on the press of a button "Shop" it is supposed to load shopScreen() which is just 2 white lines and 2 orange lines. the problem is, it immediately loads shopScreen() instead of introScreen() which is an image with the title and 2 buttons. When i comment out the shopScreen definition the program doesnt load, and when I make the action that the buttons do when clicked load the intro screen the program doesnt load. Here is the code:
import pygame
pygame.init()
window = pygame.display.set_mode((978, 517))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 20)
ticker = 0
intro = True
white = (255, 255, 255)
tbcolor = (255, 69, 0)
###########################MAKES BUTTONS##############################
######################################################################
######################################################################
class Button:
"""Create a button, then blit the surface in the while loop"""
def __init__(self, text, pos, font, action, bg="black", feedback=""):
self.x, self.y = pos
self.font = pygame.font.SysFont("Arial", font)
if action == None:
self.action = shopScreen()
else:
self.action = action
if feedback == "":
self.feedback = "text"
else:
self.feedback = feedback
self.change_text(text, bg)
self.do_function(action)
def do_function(self, action):
if action != None:
self.action
def change_text(self, text, bg="black"):
"""Change the text whe you click"""
self.text = self.font.render(text, 1, pygame.Color("White"))
self.size = self.text.get_size()
self.surface = pygame.Surface(self.size)
self.surface.fill(bg)
self.surface.blit(self.text, (0, 0))
self.rect = pygame.Rect(self.x, self.y, self.size[0], self.size[1])
def show(self):
window.blit(self.surface, (self.x, self.y))
def click(self, event):
x, y = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed()[0]:
if self.rect.collidepoint(x, y):
self.do_function(self.action)
self.change_text(self.feedback, bg="red")
###########################MAKES BUTTONS##############################
######################################################################
######################################################################
def introScreen():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
# Sets window size and color
white = (255, 255, 255)
tbcolor = (255, 69, 0)
#Calls to image
introWall = pygame.image.load("theOne.png").convert()
# sButton = pygame.image.load('shopButton.png')
bigger = pygame.font.SysFont('chalkduster.ttf', 150)
smaller = pygame.font.SysFont('chalkduster.ttf', 40)
side = pygame.font.SysFont('chalkduster.ttf', 90)
# click = pygame.mouse.get_pressed()
img1 = bigger.render('________', True, tbcolor)
img2 = bigger.render('________', True, white)
#buttons
# img3 = bigger.render('________', True, tbcolor)
# img4 = bigger.render('________', True, white)
sidebar = side.render('|', True, tbcolor)
title = smaller.render('Basketball Gods', True, tbcolor)
play = smaller.render('', True, white)
shop = smaller.render('', True, white)
# s the object on the screen
pygame.display.update()
window.blit(introWall, [0, 0])
#orange
window.blit(img1, (250, 50))
window.blit(img1, (250, 60))
window.blit(img1, (250, 90))
window.blit(img1, (250, 100))
#side
window.blit(sidebar, (240, 140))
window.blit(sidebar, (705, 140))
#white
window.blit(img2, (250, 55))
window.blit(img2, (250, 65))
window.blit(img2, (250, 70))
window.blit(img2, (250, 75))
window.blit(img2, (250, 80))
window.blit(img2, (250, 85))
window.blit(img2, (250, 95))
#title
window.blit(title, (385, 160))
window.blit(play, (310, 280))
window.blit(shop, (580, 280))
shopButton.click(event)
shopButton.show()
playButton.click(event)
playButton.show()
#buttons
# window.blit(button1, (0, 0))
# if sButton.get_rect().collidepoint(pygame.mouse.get_pos()) and pygame.mouse.get_pressed()[0]:
# ticker = 0
pygame.display.flip()
def shopScreen():
shop = True
intro = False
while shop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
white = (255, 255, 255)
tbcolor = (255, 69, 0)
bigger = pygame.font.SysFont('chalkduster.ttf', 150)
img3 = bigger.render('________', True, tbcolor)
img4 = bigger.render('________', True, white)
# pygame.display.update()
window.blit(img3, (250, 50))
window.blit(img3, (250, 60))
window.blit(img4, (250, 90))
window.blit(img4, (250, 100))
# window.blit()
# gameDisplay.fill(white)
pygame.display.flip()
# def mainLoop():
# """ The infinite loop where things happen """
# while True:
# for event in pygame.event.get():
# if event.type == pygame.QUIT:
# pygame.quit()
# playButton.click(event)
# playButton.show()
# if ticker == 0:
# introScreen()
# playButton.click(event)
# playButton.show()
# shopButton.click(event)
# shopButton.show()
# # elif ticker == 1:
# # shopScreen()
# clock.tick(30)
# pygame.display.update()
shopButton = Button(
"SHOP",
(600, 300),
font=50,
action = shopScreen(),
bg=(255, 69, 0),
feedback="moving")
playButton = Button(
"ahaha",
(260, 300),
font=50,
action = shopScreen(),
bg = (255, 69, 0),
feedback="haha")
introScreen()

How to make entities take damage with color collision in pygame?

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()

Using a variable instead of the actual value causes a bug

I was messing around trying to figure out how to centre text in a button. This is the code.
import pygame
pygame.init()
win = pygame.display
d = win.set_mode((500, 500))
text = "A Button"
size = 50
size = [3*size, 1*size]
rectx = size[0]
recty = size[1]+ 5
textsizey = recty
t = len(text) * 5
textsize = int(textsizey/ t)
if textsize >= recty:
textsize = recty
testrect = pygame.Surface((rectx, recty))
testrect.fill((255, 255, 255))
def write(screen, text, color, position, size):
font = pygame.font.Font(pygame.font.get_default_font(), size)# Defining a font with font and size
text_surface = font.render(text, True, color)# Defining the text color which will be rendered
screen.blit(text_surface, (position[0], position[1])) # Rendering the font
while True:
pygame.event.get()
d.fill((0, 0, 0))
d.blit(testrect, (10, 10))
write(d, text, (0, 255, 0), [10, 10+(0.5*recty)-(0.5*textsize)], textsize)
win.flip()
On line 11, the variable t = len(text) * 5 is used in the next line textsize = int(textsizey/ t). When i do this the text size diminishes, which is not supposed to happen. But, if i use the value of t and replace the line with textsize = int(textsizey/ len(text) * 5), it works just fine. Printing the value of the variable and the actual value just before using it gives the same result. I am not using the variable t elsewhere in the program either. Why could this be happening?
To center text on button you need pygame.Rect() and its .center
button_rect = testrect.get_rect()
and then
text_rect = text_surface.get_rect()
text_rect.center = button_rect.center
or in one line
text_rect = text_surface.get_rect(center = button_rect.center)
and then you draw
text_rect.x = position[0]
text_rect.y = position[1]
blit(text_surface, text_rect)
BTW: If you don't change text then you could define Font, text_surface and text_rect only once. And later only change .x .y or .center
BTW: pygame.Rect() has other useful values - .centerx, .centery, .widht, .height, .x, .y, .left (the same as .x), .right (x + width), .top(the same as.y), .bottom (y+height), .size`,
Minimal working code with other changes.
It moves button randomly and it uses .center to center text on button.
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
size = 50
# --- button's rectange ---
button_image = pygame.Surface((3*size, 1*size))
button_rect = button_image.get_rect(x=10, y=10)
button_image.fill((255, 255, 255))
# --- button's text ---
text = "A Button"
font = pygame.font.Font(pygame.font.get_default_font(), size//2)
text_image = font.render(text, True, (255, 0, 0))
text_rect = text_image.get_rect(center=button_rect.center)
# --- main loop ---
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
# clear buffer
win.fill((0, 0, 0))
# draw button in buffer
win.blit(button_image, button_rect)
win.blit(text_image, text_rect)
# send buffer on screen
pygame.display.flip()
# slow down to 2 FPS (2 frames per second)
clock.tick(2)
# move button to new place
button_rect.x = random.randint(0, 500-button_rect.width)
button_rect.y = random.randint(0, 500-button_rect.height)
# center text on button
text_rect.center = button_rect.center
BTW: I use smaller text - size//2 but if you want to fit button to text size then you can do
button_rect.width = text_rect.width + margins
button_rect.height = text_rect.height + margins
and recreate image/surface
button_image = pygame.Surface(button_rect.size)
button_image.fill((255, 255, 255))
text_rect.center = button_rect.center
Minimal working code
import pygame
import random
pygame.init()
win = pygame.display.set_mode((500, 500))
size = 50
margins = 10
# --- button's rectange ---
button_image = pygame.Surface((3*size, 1*size))
#button_rect = pygame.Rect((10, 10, 3*size, 1*size))
button_rect = button_image.get_rect(x=100, y=100)
button_image.fill((255, 255, 255))
# --- button's text ---
text = "A Button"
font = pygame.font.Font(pygame.font.get_default_font(), size)
text_image = font.render(text, True, (255, 0, 0))
text_rect = text_image.get_rect(center=button_rect.center)
# --- resize button to text ---
button_rect.width = text_rect.width + margins
button_rect.height = text_rect.height + margins
button_image = pygame.Surface(button_rect.size)
button_image.fill((255, 255, 255))
text_rect.center = button_rect.center
# --- main loop ---
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
# clear buffer
win.fill((0, 0, 0))
# draw button in buffer
win.blit(button_image, button_rect)
win.blit(text_image, text_rect)
# send buffer on screen
pygame.display.flip()
# slow down to 2 FPS (2 frames per second)
clock.tick(2)
# move button to new place
button_rect.x = random.randint(0, 500-button_rect.width)
button_rect.y = random.randint(0, 500-button_rect.height)
# center text on button
text_rect.center = button_rect.center

Why doesn't pygame continue through the loop?

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()

How to Move a Pygame Surface?

import pygame, sys, os.path
pygame.init()
# set up the colours
# R G B
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 50, 130, 255)
screen_surf = pygame.display.set_mode((500,500), 0, 24)
pygame.display.set_caption("Lewis' Menu")
screen_surf.fill((100,0,0))
class Button():
def create(self,w,h,colour):
self.button_surf = pygame.Surface((w,h), 0, 24)
self.button = pygame.draw.rect(self.button_surf, colour, (0, 0, w, h))
def view(self,text,x,y):
width = self.button_surf.get_width()
height = self.button_surf.get_height()
sys_font = pygame.font.SysFont(("None"), 25)
rendered = sys_font.render(text,0,(255,255,255))
self.button_surf.blit(rendered, ((width - 140),((height / 2) - 10)))
screen_surf.blit(self.button_surf, (x,y))
start_button = Button()
start_button.create(300,100,BLUE), start_button.view("Clicky Button!",10,10)
exit_button = Button()
exit_button.create(300,50,GREEN), exit_button.view("Exit!",10,200)
while True:
pos = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
if start_button.button.collidepoint(pos):
print("You opened a chest!")
if exit_button.button.collidepoint(pos):
pygame.quit()
sys.exit()
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
The 'button click' functionality works by checking to see if the mouse position overlaps the button rect. I can reposition the blitted view of the rectangle in the Button.view() method, but the actual rectangle doesn't move with it, which makes the clicking functionality trigger in the wrong location in the window. Is there any way to move the actual button rectangle collision along with the blitted view of it?
Thanks in advance.
I'd replace the create method with an __init__ method in which the background surface, the text surface and their corresponding rects are created. That allows you to pass all the needed parameters during the instantiation:
start_button = Button(10, 10, 300, 100, "Clicky Button!", BLUE)
Use the parameters to place the self.button rect at the desired coordinates:
self.button = pygame.Rect(x, y, w, h)
You can also use the get_rect method of the button surface to create the rect (see the text_rect creation).
The only purpose of the view method is to blit the surfaces at their rects.
import sys
import pygame
pygame.init()
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 50, 130, 255)
screen_surf = pygame.display.set_mode((500,500), 0, 24)
screen_surf.fill((100,0,0))
clock = pygame.time.Clock()
# No need to recreate the font object all the time.
SYS_FONT = pygame.font.SysFont(None, 25)
class Button():
def __init__(self, x, y, w, h, text, colour):
self.button_surf = pygame.Surface((w,h), 0, 24)
self.button_surf.fill(colour)
self.button = pygame.Rect(x, y, w, h)
self.text_surf = SYS_FONT.render(text, False, (255,255,255))
# Pass the center coords of the button rect to the newly
# created text_rect for the purpose of centering the text.
self.text_rect = self.text_surf.get_rect(center=self.button.center)
def view(self, screen_surf):
screen_surf.blit(self.button_surf, self.button)
screen_surf.blit(self.text_surf, self.text_rect)
# Button() calls the __init__ method.
start_button = Button(10, 10, 300, 100, "Clicky Button!", BLUE)
start_button.view(screen_surf) # Call `view` in a separate line.
exit_button = Button(10, 200, 300, 50, "Exit!", GREEN)
exit_button.view(screen_surf)
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
if start_button.button.collidepoint(event.pos):
print("You opened a chest!")
elif exit_button.button.collidepoint(event.pos):
pygame.quit()
sys.exit()
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
clock.tick(60) # Limit the frame rate to 60 FPS.

Categories

Resources