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
Related
I am new at coding and on stack exchange. I have been trying to get this code to run a game based off a tutorial and it keeps appearing as a black screen. I think it probably has something to do with spacing? Can anyone help me? I am sure this code can also be simplified, so any advice on that would be appreciated as well.
import pygame
import random
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.fill((255, 255, 255))
surf = pygame.Surface((50, 50))
surf.fill((0, 0, 0))
rect = surf.get_rect()
screen.blit(surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
pygame.display.flip()
surf_center = (
(SCREEN_WIDTH-surf.get_width())/2,
(SCREEN_HEIGHT-surf.get_height())/2
)
screen.blit(surf, surf_center)
pygame.display.flip()
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.image.load("Jake.anime.png").convert()
self.surf.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.surf.get_rect()
player = Player()
screen.fill((0, 0, 0))
screen.blit(player.surf, player.rect)
pygame.display.flip()
pressed_keys = pygame.key.get_pressed()
def update(self, pressed_keys):
if presed_keys[K_UP]:
self.rect.move_ip(0, -5)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0, 5)
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5,0)
if self.rect.left < 0:
self.rect.left = 0
if self.rect.right > SCREEN_WIDTH:
self.rect.right = SCREEN_WIDTH
if self.rect.top <= 0:
self.rect.top = 0
if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
running = False
elif event.type == QUIT:
running = False
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
screen.fill((0,0,0))
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super(Enemy, self).__init__()
self.surf = pygame.image.load("graham.enemy.png").convert()
self.surf.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
self.speed = random.randint(5, 20)
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
self.kill()
class Cloud(pygame.sprite.Sprite):
def __init__(self):
super(Cloud, self).__init__()
self.surf = pygame.image.load("cloud for game.png").convert()
self.surf.set_colorkey((0, 0, 0), RLEACCEL)
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
def update(self):
self.rect.move_ip(-5, 0)
if self.rect.right < 0:
self.kill()
player = Player()
enemies = pygame.sprite.Group()
clouds = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
running = True
screen.fill((0, 0, 0))
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
pygame.display.flip()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, 250)
ADDCLOUD = pygame.USEREVENT +2
pygame.time.set_timer(ADDCLOUD, 1000)
player = Player()
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
elif event.type == ADDENEMY:
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy)
elif event.type ==ADDCLOUD:
new_cloud = Cloud()
clouds.add(new_cloud)
all_sprites.add(new_cloud)
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
enemies.update()
clouds.update()
screen.fill((135, 206, 250))
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
running = False
You have multiple while running loops and are not calling pygame.display.update at the end to draw everything. You should have one loop which checks for events, updates everything, and draws everything.
while running:
get_events()
update()
draw()
move all the code for each thing inside its own function. Collision checking would be at the end of update(). Also I am not sure why you have indented the from pygame.locals import, that should be left aligned, as should the class definitions.
You need to restructure your program. Write 1 application loop only. The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage
See also Python Pygame Introduction and see the following example for a minimal application loop:
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
# main application loop
run = True
while run:
# limit frames per second
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# clear the display
window.fill(0)
# draw the scene
pygame.draw.circle(window, (255, 0, 0), (250, 250), 100)
# update the display
pygame.display.flip()
pygame.quit()
exit()
repl.it/#Rabbid76/PyGame-MinimalApplicationLoop
See also Event and application loop
Complete applicaition:
import pygame
import random
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.image.load("Jake.anime.png").convert()
self.surf.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.surf.get_rect()
def update(self, pressed_keys):
if pressed_keys[K_UP]:
self.rect.move_ip(0, -5)
if pressed_keys[K_DOWN]:
self.rect.move_ip(0, 5)
if pressed_keys[K_LEFT]:
self.rect.move_ip(-5, 0)
if pressed_keys[K_RIGHT]:
self.rect.move_ip(5,0)
if self.rect.left < 0:
self.rect.left = 0
if self.rect.right > SCREEN_WIDTH:
self.rect.right = SCREEN_WIDTH
if self.rect.top <= 0:
self.rect.top = 0
if self.rect.bottom >= SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super(Enemy, self).__init__()
self.surf = pygame.image.load("graham.enemy.png").convert()
self.surf.set_colorkey((255, 255, 255), RLEACCEL)
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
self.speed = random.randint(5, 20)
def update(self):
self.rect.move_ip(-self.speed, 0)
if self.rect.right < 0:
self.kill()
class Cloud(pygame.sprite.Sprite):
def __init__(self):
super(Cloud, self).__init__()
self.surf = pygame.image.load("cloud for game.png").convert()
self.surf.set_colorkey((0, 0, 0), RLEACCEL)
self.rect = self.surf.get_rect(
center=(
random.randint(SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
random.randint(0, SCREEN_HEIGHT),
)
)
def update(self):
self.rect.move_ip(-5, 0)
if self.rect.right < 0:
self.kill()
player = Player()
enemies = pygame.sprite.Group()
clouds = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
ADDENEMY = pygame.USEREVENT + 1
pygame.time.set_timer(ADDENEMY, 250)
ADDCLOUD = pygame.USEREVENT +2
pygame.time.set_timer(ADDCLOUD, 1000)
clock = pygame.time.Clock()
running = True
while running:
# limit frames per second
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
if event.type == ADDENEMY:
new_enemy = Enemy()
enemies.add(new_enemy)
all_sprites.add(new_enemy)
elif event.type ==ADDCLOUD:
new_cloud = Cloud()
clouds.add(new_cloud)
all_sprites.add(new_cloud)
# update objects
pressed_keys = pygame.key.get_pressed()
player.update(pressed_keys)
enemies.update()
clouds.update()
# clear the display
screen.fill((135, 206, 250))
# draw the scene
for entity in all_sprites:
screen.blit(entity.surf, entity.rect)
if pygame.sprite.spritecollideany(player, enemies):
player.kill()
running = False
screen.blit(player.surf, player.rect)
# update the display
pygame.display.flip()
pygame.quit()
exit()
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
I am trying to resolve the cause of my triggered bullet disappearing if in a short period of seconds I fire a second bullet. I imagine that screen.fill(GRAY) might be a cause and it should be inside the Class Bullet() or maybe I need to use all_sprites_list.update() elsewhere.
Here is my MWE code:
import pygame
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
GRAY = (128,128,128)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Cowboy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([14,20])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
class Bullet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("bullet.png").convert()
self.rect = self.image.get_rect()
def update(self):
self.rect.y += -3
def main():
pygame.init()
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
all_sprites_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
enemies_list = pygame.sprite.Group()
bullet = Bullet()
enemy = Cowboy()
enemies_list.add(enemy)
all_sprites_list.add(enemy)
enemy.rect.y = 50
enemy.rect.x = 50
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet_list.add(bullet)
all_sprites_list.add(bullet)
bullet.rect.x = 340
bullet.rect.y = 200
screen.fill(GRAY)
all_sprites_list.draw(screen)
clock.tick(60)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
You have to create a new instance of Bullet, when the mouse button is pressed and you have to invoke the update method of the bullets calling update on the bullet_list:
def main():
# [...]
# bullet = Bullet() <--- DELETE
# [...]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
# create new bullet and add it to the groups
bullet = Bullet()
bullet.rect.center = enemy.rect.center
bullet_list.add(bullet)
all_sprites_list.add(bullet)
# update the bullets
bullet_list.update()
# [...]
import pygame
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
GRAY = (128,128,128)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Cowboy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([14,20])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("bullet.png").convert()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
self.rect.y += -3
def main():
pygame.init()
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size, pygame.RESIZABLE)
all_sprites_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
enemies_list = pygame.sprite.Group()
bullet = Bullet(340, 240)
enemy = Cowboy()
enemies_list.add(enemy)
all_sprites_list.add(enemy)
enemy.rect.y = 50
enemy.rect.x = 50
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet(340, 200)
bullet_list.add(bullet)
all_sprites_list.add(bullet)
bullet.rect.x = 340
bullet.rect.y = 200
screen.fill(GRAY)
all_sprites_list.update()
all_sprites_list.draw(screen)
clock.tick(60)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
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.
I'm still working on a game in Pygame. I've got the gameplay to work, I just want to make a main menu function so when a button is pressed, the game starts.
When I added in the main menu, and edited the game loop, I was unable to move the player sprite, and the game wouldn't close when I press the "X out" button (it goes irresponsive(this didn't happen before)).
This didn't happen originally.
And there's no traceback.
Here's my code:
import pygame
import time
import itertools
import os
pygame.init()
SCREENWIDTH = 1000
SCREENHEIGHT = 650
screen = pygame.display.set_mode([SCREENWIDTH, SCREENHEIGHT])
screen.fill((255, 123, 67))
screen.blit(pygame.image.load("Backgrounds/mainmenu.png"), (0, 0))
background = screen.copy()
clock = pygame.time.Clock()
mi_level = False
class Player(pygame.sprite.Sprite):
sprite = pygame.image.load("Sprites/lee.png")
def __init__(self, *groups):
super().__init__(*groups)
self.image = Player.sprite
self.rect = self.image.get_rect(topleft=(445, 550))
self.pos = pygame.Vector2(self.rect.center)
self.lives = 50
self.score = 0
self.hitbox = self.rect.inflate(-20, -30)
def update(self):
self.pos = self.rect.center
key = pygame.key.get_pressed()
dist = 3
if key[pygame.K_DOWN]:
self.rect.y += dist
self.hitbox.y += dist
elif key[pygame.K_UP]:
self.rect.y -= dist
self.hitbox.y -= dist
if key[pygame.K_RIGHT]:
self.rect.x += dist
self.hitbox.x += dist
elif key[pygame.K_LEFT]:
self.rect.x -= dist
self.hitbox.x -= dist
if self.rect.right > SCREENWIDTH:
self.rect.right = SCREENWIDTH
if self.rect.left < 0:
self.rect.left = 0
if self.rect.bottom > SCREENHEIGHT:
self.rect.bottom = SCREENHEIGHT
if self.rect.top < 50:
self.rect.top = 50
self.hitbox.center = self.pos
if self.lives <= 0:
screen.blit(pygame.image.load("gameover.png"), (0,0))
pygame.display.flip()
time.sleep(5)
os._exit(0)
pygame.quit()
stageon = False
sprites = pygame.sprite.Group()
player = Player(sprites)
def main():
running = True
mi_level = False
screen.blit(pygame.image.load("Backgrounds/mainmenu.png"), (0, 0))
pygame.display.update()
while True:
for events in pygame.event.get():
if events.type == pygame.QUIT or running == False:
time.sleep(1)
running = False
pygame.quit()
return
pygame.draw.rect(screen, (255, 204, 204), (690, 110, 700, 135), 0)
if pygame.mouse.get_pressed()[0] and pygame.Rect(690, 110, 880, 165).collidepoint(pygame.mouse.get_pos()):
screen.fill((255, 123, 67))
screen.blit(pygame.image.load("Backgrounds/mi_level.png"), (0, 50))
pygame.display.flip
background = screen.copy()
mi_level = True
pygame.display.update()
while mi_level:
sprites.update()
screen.blit(background, (0, 0))
sprites.draw(screen)
pygame.display.update()
clock.tick(100)
if mi_level == False:
return
if events.type == pygame.QUIT or running == False:
time.sleep(1)
running = False
pygame.quit()
return
if __name__ == '__main__':
main()
I wonder what amateur mistake I've made this time...
Any help would be appreciated. Thanks :)
There is already a game loop. There is not any need of "nested" game loops:
while mi_level:
A simple if statement, which evaluates if the game is started is sufficient:
if mi_level:
# []...]
Note, in your code in the inner loops, the events haven't been evaluated, because pygame.event.get() is missing. This causes that the pygame.QUIT event wasn't handled any more and the window didn't close and react as intended.
See the changes to the main loop:
def main():
running = True
mi_level = False
screen.blit(pygame.image.load("Backgrounds/mainmenu.png"), (0, 0))
pygame.display.update()
while True:
for events in pygame.event.get():
if events.type == pygame.QUIT or running == False:
time.sleep(1)
running = False
pygame.quit()
return
pygame.draw.rect(screen, (255, 204, 204), (690, 110, 700, 135), 0)
if pygame.mouse.get_pressed()[0] and pygame.Rect(690, 110, 880, 165).collidepoint(pygame.mouse.get_pos()):
screen.fill((255, 123, 67))
screen.blit(pygame.image.load("Backgrounds/mi_level.png"), (0, 50))
pygame.display.flip()
background = screen.copy()
mi_level = True
if mi_level:
sprites.update()
screen.blit(background, (0, 0))
sprites.draw(screen)
pygame.display.update()
clock.tick(100)
pygame.display.update()