Why are some events don't execute when called? - python

Python 3.
Hello. I made a game which starts off with a main menu and when 'd' is pressed, it will cut to the game screen.
Before I made this main menu, when I would hold space bar, the shapes would rumble. Now when I press 'd' to start the game, the objects are displayed, but holding space bar doesn't do anything, and neither does pressing escape or closing the game. It seems like the keyboard events / game events are not being called anymore once the 'd' is pressed.
Code:
import pygame
import random
import time
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
# Edit the intensity of the shake (Must be one number apart)
# Ex: a = -100, b = 101. A is negative, B is positive
a = -4
b = 5
up = 10
intensity = (a, b)
startGame = True
# Image Loading
pygame.init()
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
done = False
clock = pygame.time.Clock()
class Rectangle():
def __init__(self):
self.x = random.randrange(0, 700)
self.y = random.randrange(0, 500)
self.height = random.randrange(20, 70)
self.width = random.randrange(20, 70)
self.x_change = random.randrange(-3, 3)
self.y_change = random.randrange(-3, 3)
self.color = random.sample(range(250), 4)
def draw(self):
pygame.draw.rect(screen, self.color, [self.x, self.y, self.width, self.height])
def move(self):
self.x += self.x_change
self.y += self.y_change
class Ellipse(Rectangle):
pass
def draw(self):
pygame.draw.ellipse(screen, self.color, [self.x, self.y, self.width, self.height])
def move(self):
self.x += self.x_change
self.y += self.y_change
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
def game_intro():
global event
intro = True
keys = pygame.key.get_pressed()
while intro:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill(WHITE)
largeText = pygame.font.Font('freesansbold.ttf', 45)
smallText = pygame.font.Font('freesansbold.ttf', 30)
TextSurf, TextRect = text_objects("Welcome to Crazy Rumble.", largeText)
TextRect.center = ((700 / 2), (100 / 2))
TextSurff, TextRectt = text_objects("Press enter to start", smallText)
TextRectt.center = ((700 / 2), (900 / 2))
TextStart, TextRecttt = text_objects("Hold space to make the shapes shake!", smallText)
TextRecttt.center = ((700 / 2), (225 / 2))
screen.blit(TextSurf, TextRect)
screen.blit(TextSurff, TextRectt)
screen.blit(TextStart, TextRecttt)
pygame.display.update()
if event.type == pygame.KEYUP:
intro = False
startGame = True
global intro
my_list = []
for number in range(600):
my_object = Rectangle()
my_list.append(my_object)
for number in range(600):
my_object = Ellipse()
my_list.append(my_object)
# -------- Main Program Loop -----------
while not done:
game_intro()
game_intro = True
if event.type == pygame.KEYUP:
game_intro = False
keys = pygame.key.get_pressed()
# --- Main event loop
while game_intro == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(BLACK)
for rect in my_list:
rect.draw()
rect.move()
for rectElli in my_list:
rectElli.draw()
if keys[pygame.K_SPACE]:
rectElli.y_change = random.randrange(a, b)
rectElli.x_change = random.randrange(a, b)
rectElli.move()
if keys[pygame.K_UP]:
print(up)
print(intensity)
up += 1
if up % 10 == 0:
a -= 1
b -= -1
else:
a, b = -4, 5
pygame.display.flip()
clock.tick(60)

You're just setting keys once with
keys = pygame.key.get_pressed()
You need to put that call inside the loop, so it gets updated after every event.

Related

How do I get my game to loop when calling the function from a button?

I'm trying to fix my game. When the game is over, it calls a crash() function. It gives the user the option to play again or quit. When calling my game_loop function in the "Play Again" button inside the crash() function, the game will not restart. Any suggestions? Thanks in advance.......................
import math
import random
import time
import pygame
from pygame import mixer
# Intialize the pygame
pygame.init()
# next setup the display
display_width = 800
display_height = 600
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('waterbackground.jpg')
# game clock to time frames per second
clock = pygame.time.Clock()
# Sound
mixer.music.load("ocean.wav")
mixer.music.play(-1)
# setup colors needed in the game
black = (0,0,0)
white = (255, 255, 255)
red = (200, 0, 0)
bright_red = (255,0,0)
block_color = (53,115,255)
green = (0,200,0)
bright_green = (0,255,0)
# Caption and Icon
pygame.display.set_caption("Pirate War")
icon = pygame.image.load('pirateship.png')
pygame.display.set_icon(icon)
# cannon
cannonImg = pygame.image.load('cannonball.png')
cannonX = 0
cannonY = 480
cannonX_change = 0
cannonY_change = 10
cannon_state = "ready"
# Player
playerImg = pygame.image.load('cannon.png')
playerX = 370
playerY = 480
playerX_change = 0
# Score
score_value = 0
# add explosion sound
crash_sound = pygame.mixer.Sound("explosion.wav")
# ship
shipImg = []
shipX = []
shipY = []
shipX_change = []
shipY_change = []
num_of_ships = 6
for i in range(num_of_ships):
shipImg.append(pygame.image.load('pirateship.png'))
shipX.append(random.randint(0, 736))
shipY.append(random.randint(50, 150))
shipX_change.append(4)
shipY_change.append(40)
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
testY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
credits_font = pygame.font.Font('freesansbold.ttf', 24)
# text object function called by message display function
def text_objects(text, font):
textSurface = font.render(text, True, white)
return textSurface, textSurface.get_rect()
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER!", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
crash()
def game_credits_text(text):
over_text = over_font.render(text, True, (255, 255, 255))
screen.blit(over_text, (200, 150))
def game_credits_text_small(text):
credits_text = credits_font.render(text, True, (255, 255, 255))
screen.blit(credits_text, (20, 350))
def game_intro_text_small(text):
credits_text = credits_font.render(text, True, (255, 255, 255))
screen.blit(credits_text, (125, 375))
def player(x, y):
screen.blit(playerImg, (x, y))
def ship(x, y, i):
screen.blit(shipImg[i], (x, y))
def fire_cannon(x, y):
global cannon_state
cannon_state = "fire"
screen.blit(cannonImg, (x + 16, y + 10))
def isCollision(shipX, shipY, cannonX, cannonY):
distance = math.sqrt(math.pow(shipX - cannonX, 2) + (math.pow(shipY - cannonY, 2)))
if distance < 27:
return True
else:
return False
# function to setup message display
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf', 70)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2), (display_height/2))
screen.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
def crash():
#add crash sound
pygame.mixer.music.stop()
pygame.mixer.Sound.play(crash_sound)
game_credits_text("Game Over!")
game_credits_text_small("Created by: Dominique Kellam, Hayley Cull and Dewayne Bowen")
while True:
# check for quit
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((0, 0, 0))
#add buttons to start screen
button("Play Again",150, 450, 100, 50, green, bright_green, game_loop)
button("Quit",550, 450, 100, 50, red, bright_red, quitgame)
pygame.display.update()
clock.tick(15)
def button(msg, x, y, w, h, ic, ac, action=None):
mouse = pygame.mouse.get_pos() # returns a list of [x,y]
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y: #check is mouse over button
# redraw the rectange with active color when mouseover
pygame.draw.rect(screen, ac, (x, y, w, h))
#check for a click
if click[0] == 1 and action!=None:
action()
else:
pygame.draw.rect(screen, ic, (x, y, w, h))
# now display text on top of button that was just redrawn
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)
def quitgame():
pygame.quit()
quit()
# start screen code
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects("Pirate War", largeText)
game_intro_text_small("[space bar] - fire cannon, [<] [>] arrows to move")
TextRect.center = ((display_width/2), (display_height/2))
screen.blit(TextSurf, TextRect)
#add buttons to start screen
button("Go!",150, 450, 100, 50, green, bright_green, game_loop)
button("Quit",550, 450, 100, 50, red, bright_red, quitgame)
pygame.display.update()
clock.tick(15)
def game_loop():
global playerX
global playerX_change
global cannonX
global cannonY
global cannon_state
global score_value
# Game Loop
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if cannon_state == "ready":
cannonSound = mixer.Sound("cannon_x.wav")
cannonSound.play()
# Get the current x cordinate of the spaceship
cannonX = playerX
fire_cannon(cannonX, cannonY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# ship Movement
for i in range(num_of_ships):
# Game Over
if shipY[i] > 440:
for j in range(num_of_ships):
shipY[j] = 2000
game_over_text()
break
shipX[i] += shipX_change[i]
if shipX[i] <= 0:
shipX_change[i] = 1 #######SHIP MOVEMENT
shipY[i] += shipY_change[i]
elif shipX[i] >= 736:
shipX_change[i] = -1 ######SHIP MOVEMENT
shipY[i] += shipY_change[i]
# Collision
collision = isCollision(shipX[i], shipY[i], cannonX, cannonY)
if collision:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
cannonY = 480
cannon_state = "ready"
score_value += 1
shipX[i] = random.randint(0, 736)
shipY[i] = random.randint(50, 150)
ship(shipX[i], shipY[i], i)
# cannon Movement
if cannonY <= 0:
cannonY = 480
cannon_state = "ready"
if cannon_state == "fire":
fire_cannon(cannonX, cannonY)
cannonY -= cannonY_change
player(playerX, playerY)
show_score(textX, testY)
pygame.display.update()
game_intro()
You are setting the ship y to 2000 which is > 400 so it just goes back to crash. Change this to zero and it will work.

One click activates multiple buttons if overlapping

Alright, so yes, I get that it is a lot of code I am about to display.
My problem: I am making a zombie shooter game where you are the main character on top of a building and you have to click on zombies as they come in waves. My current problem is whenever multiple zombies overlap on top of each other, I can kill both of them (or as many are overlapping) in one click because technically, all of their hitboxes are colliding.
If this is a bigger problem than sought out to be, I would like someone to just say that.
import pygame
import random
import time
pygame.init()
#Setting Variables
screenW = 1020
screenH = 630
x = 125
y = 164
width = 50
height = 50
velocity = 5
wave = 2
GOLD = (255, 215, 0)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 128, 0)
wallHealth = 0
zombieKilled = 0
class ZombieChars():
def __init__(self):
self.damage = 0
self.vel = 5
self.x_change = random.randrange(2,5)
self.y_change = 1
self.height = 120
self.width = 149
self.color = random.sample(range(250), 4)
self.image = pygame.Surface([self.width, self.height], pygame.HWSURFACE, 32)
self.rect = self.image.get_rect(topleft = (random.randrange(900, 1150), 330))
#pygame.draw.rect(self.image, (self.color), (self.x, self.y, self.width, self.height))
def draw(self):
window.blit(ZombieWalking, self.rect.topleft)
def update(self):
if self.rect.x >= 364:
self.rect.x -= self.x_change
else:
self.rect.x -= 0
def wallHP(self):
global wallHealth
if self.rect.x < 365:
self.damage += 1
if self.damage == 30:
self.damage = 0
wallHealth += 1
def death(self):
global zombieKilled
if event.type == pygame.MOUSEBUTTONDOWN:
gunShot.play()
mouse_pos = event.pos
if self.rect.collidepoint(mouse_pos):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
def waveCounter(self):
global wave
print(wave)
if wave == zombieKilled / 2:
wave = 2
#FPS
clock = pygame.time.Clock()
clock.tick(60)
#Screen
window = pygame.display.set_mode((screenW,screenH))
pygame.display.set_caption(("Zombie Shooter"))
#Image Loading
bg = pygame.image.load("bg.jpg")
mainmenu = pygame.image.load("mainmenu.jpg")
ZombieWalking = pygame.image.load("Sprites/AAIdle.png")
#Sound Loading
gunShot = pygame.mixer.Sound('sounds/gunShot.wav')
zombieHit = pygame.mixer.Sound('sounds/zombieHit.wav')
gameMusic = pygame.mixer.music.load('sounds/gameMusic.mp3')
menuMusic = pygame.mixer.music.load('sounds/menuMusic.mp3')
zombies = ZombieChars()
my_list = []
for zombs in range(wave):
my_object = ZombieChars()
my_list.append(my_object)
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
smallText = pygame.font.Font('freesansbold.ttf', 30)
tinyText = pygame.font.Font('freesansbold.ttf', 20)
TextSurf3, TextRect3 = text_objects("Wave: " + str(wave), smallText)
TextRect3.center = ((1020 / 2), (50))
#Main Loop
run = True
mainMenu = True
pygame.mixer.music.play()
global event
while mainMenu == True:
window.blit(mainmenu, (0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False #if x is pressed dont run game
mainMenu = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
mainMenu = False #if a is pressed run game
def wallHPBar():
pygame.draw.rect(window, GREEN, (20, 20, 100, 10))
if wallHealth == 0:
pass
if wallHealth == 1:
pygame.draw.rect(window, RED, (20, 20, 25, 10))
if wallHealth == 2:
pygame.draw.rect(window, RED, (20, 20, 50, 10))
if wallHealth == 3:
pygame.draw.rect(window, RED, (20, 20, 75, 10))
if wallHealth >= 4:
pygame.draw.rect(window, RED, (20, 20, 100, 10))
def overlapKill():
if zombieKilled == 1:
print("oh my goodness we going")
if zombieKilled == 2:
print("we 2 ")
while run:
pygame.mixer.music.stop()
window.blit(bg, (0, 0))
window.blit(TextSurf3, TextRect3)
wallHPBar()
pygame.time.delay(25)
for zombie in my_list:
zombie.draw()
zombie.update()
zombie.death()
zombie.wallHP()
zombie.waveCounter()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Thank you.
Remove the event handling from the method death and return a boolean value, that indicates if a zombie was killed:
class ZombieChars():
# [...]
def death(self):
global zombieKilled
mouse_pos = pygame.mouse.get_pos()
if self.rect.collidepoint(mouse_pos):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
return True
return False
Do the pygame.MOUSEBUTTONDOWN event handling in the event loop and evaluate if a zombie was killed in a loop. break the loop when a zombie is killed. Thus only one zombie can be get killed on one klick:
while run:
# [...]
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
gunShot.play()
for zombie in (reversed):
if zombie.death():
break
for zombie in my_list:
zombie.draw()
zombie.update()
# zombie.death() <--- DELETE
zombie.wallHP()
zombie.waveCounter()
A Zombie object should not be dealing with user-input. Handle the click outside of the zombie, then the outside code gets to decide if the click is "used up".
class ZombieChars():
[ ... ]
def death( self, mouse_position ):
killed = False
global zombieKilled
if self.rect.collidepoint( mouse_position ):
self.rect.x = 5000
self.rect.x -= self.x_change
zombieHit.play()
zombieKilled += 1
print(zombieKilled)
killed = True
return killed
Then in your main loop, stop processing hits once the first is found:
### Main Loop
while not exiting:
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
exiting = True
elif ( event.type == pygame.MOUSEBUTTONDOWN ):
gunShot.play()
mouse_pos = event.pos
for zombie in my_list:
if ( zombie.death( mouse_pos ) ):
break # stop on first hit

Python - Game is not responding?

Trying to create a new game instance so that I can create a main menu that shows up before the actual game occurs.
I am attempting to make it so that when you press a on the keyboard, the game will start and the main menu will disappear, but the game loops some kind of code and makes it crash; not responding.
import pygame
import random
import time
pygame.init()
#Setting Variables
screenW = 1020
screenH = 630
x = 125
y = 164
width = 50
height = 50
velocity = 5
wave = 3
GOLD = (255,215,0)
BLACK = (0, 0, 0)
class ZombieChars():
def __init__(self):
self.y = 164
self.vel = 5
self.x_change = random.randrange(1,3)
self.y_change = 1
self.height = random.randrange(35, 60)
self.width = random.randrange(60, 70)
self.color = random.sample(range(250), 4)
self.image = pygame.Surface([self.width, self.height], pygame.HWSURFACE, 32)
self.rect = self.image.get_rect(topleft = (random.randrange(700, 1200), 550))
self.image.fill(self.color)
#pygame.draw.rect(self.image, (self.color), (self.x, self.y, self.width, self.height))
def draw(self):
#print(self.rect.x)
window.blit(self.image, self.rect.topleft)
def update(self):
if self.rect.x >= 220:
self.rect.x -= self.x_change
else:
self.rect.x -= 0
def death(self):
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos
if self.rect.collidepoint(mouse_pos):
self.rect.x = -500
print ("Square Clicked")
print(self.rect.x)
#FPS
clock = pygame.time.Clock()
clock.tick(60)
#Screen
window = pygame.display.set_mode((screenW,screenH))
pygame.display.set_caption(("Zombie Shooter"))
bg = pygame.image.load("bg.jpg")
mainmenu = pygame.image.load("mainmenu.jpg")
zombies = ZombieChars()
my_list = []
for sanjh in range(wave):
my_object = ZombieChars()
my_list.append(my_object)
def text_objects(text, font):
textSurface = font.render(text, True, BLACK)
return textSurface, textSurface.get_rect()
smallText = pygame.font.Font('freesansbold.ttf', 30)
TextSurf, TextRect = text_objects("Welcome to Zombie Shooter Alpha", smallText)
TextRect.center = ((1020 / 2), (50))
TextSurf2, TextRect2 = text_objects("Shoot the zombies before they arrive at your fortress!", smallText)
TextRect2.center = ((1020 / 2 - 80), (100))
TextSurf3, TextRect3 = text_objects("Wave: " + str(wave), smallText)
TextRect3.center = ((1020 / 2), (50))
#Main Loop
run = True
mainMenu = True
keys = pygame.key.get_pressed()
global event
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
mainMenu = False
while mainMenu == True:
window.blit(mainmenu, (0,0))
pygame.display.flip()
if keys[pygame.K_a]:
mainMenu = False
print ("yeah i clicked")
while mainMenu == False:
window.blit(bg, (0,0))
window.blit(TextSurf, TextRect)
window.blit(TextSurf2, TextRect2)
pygame.time.delay(25)
for zombie in my_list:
zombie.draw()
zombie.update()
zombie.death()
pygame.display.flip()
#Drawing
If anyone could identify what is breaking my game that would be amazing.
You have a game loop inside a game loop inside a game loop. no no no. you have while mainMenu == True then inside that loop you have a while mainMenu == False so when it is mainmenu it is looping through big loop, then when its false, it loops through small one and never goes out.
you can have multiple game loops but not in each other
while mainMenu == True:
window.blit(mainmenu, (0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False #if x is pressed dont run game
mainMenu = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
mainMenu = False #if a is pressed run game
print ("yeah i clicked")
while run:
window.blit(bg, (0,0))
window.blit(TextSurf, TextRect)
window.blit(TextSurf2, TextRect2)
pygame.time.delay(25)
for zombie in my_list:
zombie.draw()
zombie.update()
zombie.death()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False

how do i connect a page to a button - pygame?

I have a menu with 3 buttons. I want one of the buttons to connect to my game page which I have but am not sure how to make this happen. So I want the "game" button to lead to the screen which has the actual game (like the screen where you play the game). i am trying to figure out how to connect a page to a button in this pygame. Thanks
# import images
background = pygame.image.load('background.png')
backgroundX = 0
backgroundX2 = background.get_width()
homeScreen = pygame.image.load('home_screen.png')
obstacle = pygame.image.load('obstacle.png')
obstacleX = 0
obstacleX2 = obstacle.get_width()
instructions = pygame.image.load('instructions.png')
# frame rate
clock = pygame.time.Clock()
# use procedure for game window rather than using it within loop
def redrawGameWindow():
# background images for right to left moving screen
screen.blit(background, (backgroundX, 0))
screen.blit(background, (backgroundX2, 0))
man.draw(screen)
screen.blit(obstacle, (obstacleX, 400))
screen.blit(obstacle, (obstacleX2, 400))
pygame.display.update()
# create class for character (object)
class player(object):
def __init__(self, x, y, width, height): # initialize attributes
self.x = x
self.y = y
self.width = width
self.height = height
self.left = True
self.right = True
self.isJump = False
self.stepCount = 0
self.jumpCount = 10
self.standing = True
def draw(self, screen):
if self.stepCount + 1 >= 27: # 9 sprites, with 3 frames - above 27 goes out of range
self.stepCount = 0
if not self.standing:
if self.left:
screen.blit(leftDirection[self.stepCount // 5], (self.x, self.y), )
self.stepCount += 1
elif self.right:
screen.blit(rightDirection[self.stepCount // 5], (self.x, self.y), )
self.stepCount += 1
else:
if self.right:
screen.blit(rightDirection[0], (self.x, self.y)) # using index, include right faced photo
else:
screen.blit(leftDirection[0], (self.x, self.y))
class enlargement(object):
def __init__(self, x, y, radius, color, facing):
self.x = x
self.y = y
self.radius = radius
self.color = color
self.facing = facing
def draw(self, screen):
pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius, 1)
man = player(200, 313, 64, 64)
font = pygame.font.Font(None, 75) # font for home screen
instructionsFont = pygame.font.Font(None, 30) # font for instructions page
# HOME SCREEN
WHITE = (255,255,255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0,255, 0)
BLUE = ( 0, 0,255)
YELLOW = (255,255, 0)
def button_create(text, rect, inactive_color, active_color, action):
font = pygame.font.Font(None, 40)
button_rect = pygame.Rect(rect)
text = font.render(text, True, BLACK)
text_rect = text.get_rect(center=button_rect.center)
return [text, text_rect, button_rect, inactive_color, active_color, action, False]
def button_check(info, event):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if event.type == pygame.MOUSEMOTION:
# hover = True/False
info[-1] = rect.collidepoint(event.pos)
elif event.type == pygame.MOUSEBUTTONDOWN:
if hover and action:
action()
def button_draw(screen, info):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if hover:
color = active_color
else:
color = inactive_color
pygame.draw.rect(screen, color, rect)
screen.blit(text, text_rect)
# ---
def on_click_button_1():
global stage
stage = 'game'
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# --- classes --- (CamelCaseNanes)
# empty
# --- functions --- (lower_case_names_
def button_create(text, rect, inactive_color, active_color, action):
font = pygame.font.Font(None, 40)
button_rect = pygame.Rect(rect)
text = font.render(text, True, BLACK)
text_rect = text.get_rect(center=button_rect.center)
return [text, text_rect, button_rect, inactive_color, active_color, action, False]
def button_check(info, event):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if event.type == pygame.MOUSEMOTION:
# hover = True/False
info[-1] = rect.collidepoint(event.pos)
elif event.type == pygame.MOUSEBUTTONDOWN:
if hover and action:
action()
def button_draw(screen, info):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if hover:
color = active_color
else:
color = inactive_color
pygame.draw.rect(screen, color, rect)
screen.blit(text, text_rect)
# ---
def on_click_button_1():
global stage
stage = 'game'
print('You clicked Button 1')
def on_click_button_2():
global stage
stage = 'options'
print('You clicked Button 2')
def on_click_button_3():
global stage
global running
stage = 'exit'
running = False
print('You clicked Button 3')
def on_click_button_return():
global stage
stage = 'menu'
print('You clicked Button Return')
# --- main --- (lower_case_names)
# - init -
pygame.init()
screen = pygame.display.set_mode((800, 600))
screen_rect = screen.get_rect()
# - objects -
stage = 'menu'
button_1 = button_create("GAME", (300, 100, 200, 75), RED, GREEN, on_click_button_1)
button_2 = button_create("OPTIONS", (300, 200, 200, 75), RED, GREEN, on_click_button_2)
button_3 = button_create("EXIT", (300, 300, 200, 75), RED, GREEN, on_click_button_3)
button_return = button_create("RETURN", (300, 400, 200, 75), RED, GREEN, on_click_button_return)
# - mainloop -
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if stage == 'menu':
button_check(button_1, event)
button_check(button_2, event)
button_check(button_3, event)
elif stage == 'game':
button_check(button_return, event)
elif stage == 'options':
button_check(button_return, event)
# elif stage == 'exit':
# pass
# - draws -
screen.fill(BLACK)
if stage == 'menu':
button_draw(screen, button_1)
button_draw(screen, button_2)
button_draw(screen, button_3)
elif stage == 'game':
button_draw(screen, button_return)
elif stage == 'options':
button_draw(screen, button_return)
# elif stage == 'exit':
# pass
pygame.display.update()
print('You clicked Button 1')
def on_click_button_2():
global stage
stage = 'options'
print('You clicked Button 2')
def on_click_button_3():
global stage
global running
stage = 'exit'
running = False
print('You clicked Button 3')
def on_click_button_return():
global stage
stage = 'menu'
print('You clicked Button Return')
# --- main --- (lower_case_names)
# - init -
pygame.init()
screen = pygame.display.set_mode((800,600))
screen_rect = screen.get_rect()
# - objects -
stage = 'menu'
button_1 = button_create("GAME", (300, 100, 200, 75), RED, GREEN, on_click_button_1)
button_2 = button_create("OPTIONS", (300, 200, 200, 75), RED, GREEN, on_click_button_2)
button_3 = button_create("EXIT", (300, 300, 200, 75), RED, GREEN, on_click_button_3)
button_return = button_create("RETURN", (300, 400, 200, 75), RED, GREEN, on_click_button_return)
# - mainloop -
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if stage == 'menu':
button_check(button_1, event)
button_check(button_2, event)
button_check(button_3, event)
elif stage == 'game':
button_check(button_return, event)
elif stage == 'options':
button_check(button_return, event)
#elif stage == 'exit':
# pass
# - draws -
screen.fill(BLACK)
if stage == 'menu':
button_draw(screen, button_1)
button_draw(screen, button_2)
button_draw(screen, button_3)
elif stage == 'game':
button_draw(screen, button_return)
elif stage == 'options':
button_draw(screen, button_return)
#elif stage == 'exit':
# pass
pygame.display.update()
# - end -
pygame.quit()
run = True
while run:
clock.tick(30)
pygame.display.update()
redrawGameWindow() # call procedure
backgroundX -= 1.4 # Move both background images back
backgroundX2 -= 1.4
obstacleX -= 1.4
obstacleX2 -= 1.4
if backgroundX < background.get_width() * -1: # If our background is at the -width then reset its position
backgroundX = background.get_width()
if backgroundX2 < background.get_width() * -1:
backgroundX2 = background.get_width()
if obstacleX < obstacle.get_width() * -10:
obstacleX = obstacle.get_width
if obstacleX2 < obstacle.get_width() * -10:
obstacleX2 = obstacle.get_width()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
man.left = True
man.right = False
man.standing = False # false, because man is walking
# verify that character is within window parameters
elif keys[pygame.K_RIGHT]:
man.right = True
man.left = False
man.standing = False # false, because man is walking
else:
man.standing = True
man.stepCount = 0
if not man.isJump:
if keys[pygame.K_SPACE]:
man.isJump = True # when jumping, man shouldn't move directly left or right
man.right = False
man.left = False
man.stepCount = 0
else:
if man.jumpCount >= -10:
neg = 1
if man.jumpCount < 0:
neg = -1
man.y -= (man.jumpCount ** 2) * .5 * neg # to jump use parabola
man.jumpCount -= 1
else:
man.isJump = False
man.jumpCount = 10
pygame.quit()
Every page or stage has similar elements - create items, draw, update, handle events, mainloop - which you can put in class to separate one stage from another.
At start create MenuStage and run its mainloop(). When you press button in MenuStage then create GameStage and runs its mainloop(). To go back from GameStage to MenuStage use button (or other event) to set self.running = False to stop GameStage.mainloop and go back to MenuStage.mainloop
This example doesn't use your code but it shows how Stages would work.
import pygame
# === CONSTANTS === (UPPER_CASE_NAMES)
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# === CLASSES === (CamelCaseNames)
class Player():
def __init__(self, screen, config):
self.screen = screen
self.screen_rect = screen.get_rect()
self.config = config
self.direction = 'right'
self.rect = pygame.Rect(100, 100, 20, 20)
self.speed = 10
def draw(self, surface):
pygame.draw.rect(surface, RED, self.rect)
def update(self):
self.rect.x += self.speed
if self.direction == 'right':
if self.rect.right > self.screen_rect.right:
self.rect.right = self.screen_rect.right
self.speed = -self.speed
self.direction = 'left'
elif self.direction == 'left':
if self.rect.left < self.screen_rect.left:
self.rect.left = self.screen_rect.left
self.speed = -self.speed
self.direction = 'right'
class Stage():
# --- (global) variables ---
# empty
# --- init ---
def __init__(self, screen, config):
self.screen = screen
self.config = config
self.screen_rect = screen.get_rect()
self.clock = pygame.time.Clock()
self.is_running = False
self.widgets = []
self.create_objects()
def quit(self):
pass
# --- objects ---
def create_objects(self):
'''
self.player = Player()
'''
'''
btn = Button(...)
self.widgets.append(btn)
'''
# --- functions ---
def handle_event(self, event):
'''
self.player.handle_event(event)
'''
'''
for widget in self.widgets:
widget.handle_event(event)
'''
def update(self, ):
'''
self.player.update()
'''
'''
for widget in self.widgets:
widget.update()
'''
def draw(self, surface):
#surface.fill(BLACK)
'''
self.player.draw(surface)
'''
'''
for widget in self.widgets:
widget.draw(surface)
'''
#pygame.display.update()
def exit(self):
self.is_running = False
# --- mainloop --- (don't change it)
def mainloop(self):
self.is_running = True
while self.is_running:
# --- events ---
for event in pygame.event.get():
# --- global events ---
if event.type == pygame.QUIT:
self.is_running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.is_running = False
# --- objects events ---
self.handle_event(event)
# --- updates ---
self.update()
# --- draws ---
self.screen.fill(BLACK)
self.draw(self.screen)
pygame.display.update()
# --- FPS ---
self.clock.tick(25)
# --- the end ---
self.quit()
class IntroStage(Stage):
def create_objects(self):
self.font = pygame.font.Font(None, 40)
self.text = self.font.render("INTRO STAGE (Press ESC or Click Mouse)", True, BLACK)
self.text_rect = self.text.get_rect(center=self.screen_rect.center)
def draw(self, surface):
surface.fill(GREEN)
surface.blit(self.text, self.text_rect)
def handle_event(self, event):
# close on mouse click
if event.type == pygame.MOUSEBUTTONDOWN:
#self.is_running = False
self.exit()
class MenuStage(Stage):
def create_objects(self):
self.font = pygame.font.Font(None, 40)
self.text = self.font.render("MENU STAGE (Press ESC)", True, BLACK)
self.text_rect = self.text.get_rect(center=self.screen_rect.center)
self.text_rect.top = 10
self.stage_game = GameStage(self.screen, self.config)
self.stage_options = OptionsStage(self.screen, self.config)
self.button1 = button_create("GAME", (300, 200, 200, 50), GREEN, BLUE, self.stage_game.mainloop)
self.button2 = button_create("OPTIONS", (300, 300, 200, 50), GREEN, BLUE, self.stage_options.mainloop)
self.button3 = button_create("EXIT", (300, 400, 200, 50), GREEN, BLUE, self.exit)
def draw(self, surface):
surface.fill(RED)
surface.blit(self.text, self.text_rect)
button_draw(surface, self.button1)
button_draw(surface, self.button2)
button_draw(surface, self.button3)
def handle_event(self, event):
button_check(self.button1, event)
button_check(self.button2, event)
button_check(self.button3, event)
class OptionsStage(Stage):
def create_objects(self):
self.font = pygame.font.Font(None, 40)
self.text = self.font.render("OPTIONS STAGE (Press ESC)", True, BLACK)
self.text_rect = self.text.get_rect(center=self.screen_rect.center)
def draw(self, surface):
surface.fill(RED)
surface.blit(self.text, self.text_rect)
class ExitStage(Stage):
def create_objects(self):
self.font = pygame.font.Font(None, 40)
self.text = self.font.render("EXIT STAGE (Press ESC or Click Mouse)", True, BLACK)
self.text_rect = self.text.get_rect(center=self.screen_rect.center)
def draw(self, surface):
surface.fill(GREEN)
surface.blit(self.text, self.text_rect)
def handle_event(self, event):
# close on mouse click
if event.type == pygame.MOUSEBUTTONDOWN:
#self.is_running = False
self.exit()
class GameStage(Stage):
def create_objects(self):
self.font = pygame.font.Font(None, 40)
self.text = self.font.render("GAME STAGE (Press ESC)", True, BLACK)
self.text_rect = self.text.get_rect(center=self.screen_rect.center)
self.player = Player(self.screen, self.config)
def draw(self, surface):
surface.fill(BLUE)
surface.blit(self.text, self.text_rect)
self.player.draw(surface)
def update(self):
self.player.update()
# === FUNCTIONS === (lower_case_names)
# TODO: create class Button()
def button_create(text, rect, inactive_color, active_color, action):
font = pygame.font.Font(None, 40)
button_rect = pygame.Rect(rect)
text = font.render(text, True, BLACK)
text_rect = text.get_rect(center=button_rect.center)
return [text, text_rect, button_rect, inactive_color, active_color, action, False]
def button_check(info, event):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if event.type == pygame.MOUSEMOTION:
# hover = True/False
info[-1] = rect.collidepoint(event.pos)
elif event.type == pygame.MOUSEBUTTONDOWN:
if hover and action:
action()
def button_draw(screen, info):
text, text_rect, rect, inactive_color, active_color, action, hover = info
if hover:
color = active_color
else:
color = inactive_color
pygame.draw.rect(screen, color, rect)
screen.blit(text, text_rect)
# === MAIN === (lower_case_names)
class App():
# --- init ---
def __init__(self):
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
config = {}
stage = IntroStage(screen, config)
stage.mainloop()
stage = MenuStage(screen, config)
stage.mainloop()
stage = ExitStage(screen, config)
stage.mainloop()
pygame.quit()
#def run(self):
#----------------------------------------------------------------------
if __name__ == '__main__':
App() #.run()
EDIT: Image which I made long time ago:

Python Snake Game Finalization Issues

I am coding a game of snake using the pygame module in python and am very near the end yet running into some unforeseen issues. My code runs yet my snake won't turn left and when I collide with an apple I do not grow in size and the apple does not disappear. Additionally, when my character hits the wall the end screen also does not come up. I am positive this is due to some small issue in my code and would appreciate for anyone to take a look and see if they can root it out since I have been unable to do so. Also, any tips for improving the code would be greatly appreciated.
import sys, time, random, pygame
from random import randrange
pygame.init()
fps_controller = pygame.time.Clock()
#Screen Dimensions
screen_width = 800
screen_height = 800
#Screen Set Up
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Snake by Bela Zumbansen")
pygame.mouse.set_visible(0)
#Colours
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
GREY = (200, 200, 200)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
LIGHTBLUE = (0, 155, 155)
#Directions
RIGHT = 1
LEFT = 2
UP = 3
DOWN = 4
#Game Set Up
snake_pos = [100, 100]
snake_body = [[100, 100], [190, 100], [180, 400]]
snake_speed = 10
apple_pos = [random.randrange(1,80)*10, random.randrange(1,80)*10]
apple_spawn = True
direction = RIGHT
update = direction
score = 0
def over():
run = False
return run
def game_over():
screen.fill(LIGHTBLUE)
draw_text("GAME OVER", 48, WHITE, screen_width/2, screen_height/4)
draw_text("Score: " + str(score), 22, WHITE, screen_width / 2, screen_height / 3)
draw_text("Press SPACE to play again or ESC to exit", 22, WHITE, screen_width/2, screen_height / 4)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
run = True
if event.key == pygame.K_ESCAPE:
pygame.quit()
return run
def draw_text(text, size, color, x, y):
font = pygame.font.Font('freesansbold.ttf', size)
TextSurf, TextRect = text_objects(text, font, color)
TextRect.center = (x, y)
screen.blit(TextSurf, TextRect)
def text_objects(text, font, color):
textSurface = font.render(text, True, color)
return textSurface, textSurface.get_rect()
def eating_apple():
global score, apple_spawn
score += 1
apple_spawn = False
def spawnApple():
global apple_pos
apple_pos = [random.randrange(1,80)*10, random.randrange(1,80)*10]
def score(score):
font = pygame.font.SysFont(None, 25)
text = font.render("Score: "+str(score), True, WHITE)
screen.blit(text,(10,10))
def main():
global update, direction, run, snake_pos, snake_speed, apple_spawn, apple_pos
pygame.time.delay(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
update = 'LEFT'
elif keys[pygame.K_RIGHT]:
update = RIGHT
elif keys[pygame.K_UP]:
update = UP
elif keys[pygame.K_DOWN]:
update = DOWN
if update == RIGHT and direction != LEFT:
direction = RIGHT
if update == LEFT and direction != RIGHT:
direction = LEFT
if update == UP and direction != DOWN:
direction = UP
if update == DOWN and direction != UP:
direction = DOWN
if direction == RIGHT:
snake_pos[0] += snake_speed
if direction == LEFT:
snake_pos[0] -= snake_speed
if direction == UP:
snake_pos[1] -= snake_speed
if direction == DOWN:
snake_pos[1] += snake_speed
snake_body.insert(0, list(snake_pos))
if snake_pos[0] == apple_pos[0] and snake_pos[1] == apple_pos[1]:
eating_apple()
else:
snake_body.pop()
if not apple_spawn:
spawnApple()
screen.fill(BLACK)
for pos in snake_body:
# Snake body
# .draw.rect(play_surface, color, xy-coordinate)
# xy-coordinate -> .Rect(x, y, size_x, size_y)
pygame.draw.rect(screen, GREEN, pygame.Rect(pos[0], pos[1], 20, 20))
pygame.draw.rect(screen, RED, pygame.Rect(apple_pos[0], apple_pos[1], 20, 20))
if snake_pos[0] < 0 or snake_pos[0] > screen_width-20:
over()
if snake_pos[1] < 0 or snake_pos[1] > screen_height-20:
over()
for block in snake_body[1:]:
if snake_pos[0] == block[0] and snake_pos[1] == block[1]:
over()
# score(score)
pygame.display.update()
fps_controller.tick(25)
#main loop
run = True
while run:
main()
while not run:
game_over()
[...] my snake won't turn left [...]
It has to be update = LEFT rather than update = 'LEFT'
[...] when I collide with an apple I do not grow in size and the apple does not disappear
There is a variable and a function with the name score. Rename the variable e.g. scoreval. See also [Python: function and variable with same name](Python: function and variable with same name):
scoreval = 0
def eating_apple():
global scoreval, apple_spawn
scoreval += 1
apple_spawn = False
Use pygame.Rect.colliderect(), to check if the head of the snake eats the apple:
if pygame.Rect(*snake_pos, 20, 20).colliderect(*apple_pos, 20, 20):
eating_apple()
else:
snake_body.pop()
When the apple has been spawned, the the state apple_spawn has to be reset:
def spawnApple():
global apple_pos, apple_spawn
apple_pos = [random.randrange(1,80)*10, random.randrange(1,80)*10]
apple_spawn = True
Referring to the comment:
[...] I'm still running into are that the game doesn't end if the snake collides with itself or runs into the wall. I have if statements for those so I'm a little lost as to why nothing is happening [...]
You've to use the global statement to change the value of the variable run in global scope in the function over:
def over():
global run
run = False

Categories