How to add an endscreen? - python

I tried different codes from here and other places but I just can't seem to get my end screen to work.
I've tried many times to transition to end screen but either the code fails completely or my sprites appear on top of the end screen. This is what I have right now because it allows my code to run.
collide = pygame.sprite.spritecollide(player, enemy_list, False)
if collide:
run = False
I want it to be game over when the enemy sprite touches the player sprite but because of the codes above which makes the enemy sprite follow the player sprite, an error always appears: "float division 0". It's probably just my fault for using the wrong code though.
I'm not sure if the other codes affect the end screen codes but just in case, this is my entire code:
Code is removed for now. Will re-upload in 1 to 2 months

Add a gameover state to the program and set the state when the player collides.
Create a separate function for the game over screen. The gameover function has its own event loop:
def gameOverScreen():
global run, gameover
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
# do event handling which continues the game
# [...]
# if [...]
# gameover = False
# draw the game over screen
# [...]
pygame.display.flip()
clock.tick(100)
Call this function dependent on the state of gameover in the main loop.
Use the continue stement to contiunue the main loop immediately.
gameover = False
run = True
while run:
# [...]
if not gameover and time_difference >= 1500:
# [...]
win.fill(white)
win.blit(background.image, background.rect)
if not pygame.mixer.music.get_busy():
pygame.mixer.music.load('bgm.mp3')
pygame.mixer.music.play()
if gameover:
gameOverScreen()
continue # continue main loop
for e in enemy_list:
e.move(player)
collide = pygame.sprite.spritecollide(player, enemy_list, False)
if collide:
gameover = True
# [...]

Related

How can I detect hitbox in my pygame game and get an output for it?

I have here my code.
#Player Spawn
player = Player() # spawn player
player.rect.y = 0 # go to y
player_list = pygame.sprite.Group()
player_list.add(player)
#Asteoriden spawn
enemy = Enemy()
enemy.rect.y = 150
enemy.rect.x = 1000
enemy_list = pygame.sprite.Group()
enemy_list.add(enemy)
running = True
while running:
pygame.display.update()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
#more code
for player in player_list:
if player.rect.colliderect(enemy):
print("hit")
win.blit(bg, (0,0))
player.update()
enemy.update()
enemy_list.draw(win)
player_list.draw(win)
pygame.display.flip()
The Player () and Enemy () are classes for my objects that should collide. But if I run the code now it will show a lot of 'hit' but I want only one 'hit' to be shown. My whole console is full of 'hit'. If I later want to replace the 'hit' with a function, it will run more often than it should.
Store the collisions in a list:
collisions = []
Whenever an enemy hits a player, save a tuple of the enemy and the player in the list. Remove the tuple when the enemy and the player no longer hit. Just print "hit" (or invoke a function) when the enemy and player collide but the tuple of the player and the enemy isn't in the list yet. This means that the enemy and player just hit but didn't hit right before:
while running:
# [...]
for enemy in enemy_list:
for player in player_list:
if player.rect.colliderect(enemy):
if not (player, enemy) in collisions:
collisions.append((player, enemy))
print("hit")
else:
if (player, enemy) in collisions:
collisions.remove((player, enemy))
# [...]

pygame - while loop makes pygame window freeze / how do I shoot the bullets out of the player?

so I was programming again this morning and I wanted to write that the player in my small game can shoot bullets. That worked fine but theres an issue: I wrote for the x and the y coordinates of the 'bullet spawner' player.x and player.y and I thought that the bullets would shoot from the player's position. but they don't. They shoot from the position, where the player was in the beginning of the game and the spawner doesn't move. So I tried to do this with a while loop and the bool isMoving, that only is True if the player moves:
...
isMoving = False
...
bullets = []
position = (player.x, player.y)
while isMoving:
position = (player.x, player.y)
...
if keys[pygame.K_d] or keys[pygame.K_a] or keys[pygame.K_w] or keys[pygame.K_s] or keys[pygame.K_UP] or keys[pygame.K_DOWN] or keys[pygame.K_LEFT] or keys[pygame.K_RIGHT]:
isMoving = True
else:
isMoving = False
But if I run pygame now, the window just freezes. If I remove the while loop again, it works but it shoots from the player's first position again.
Oh, and I get the error " while isMoving:
UnboundLocalError: local variable 'isMoving' referenced before assignment
" Any ideas how to fix that?
Pygame should run in a main while loop which has all the main actions inside it.
Try setting the position at the start, then inside the while loop check for pygame events that trigger the isMoving change. Nested while loops will cause issues with pygame. Use if functions inside the while loop instead of another while loop. For example,
position = (player.x, player.y) # initial position
while isRunning:
isMoving = False
# PyGame event interaction
for event in pygame.event.get():
# Exits loop
if event.type == pygame.QUIT:
isRunning = False
# Check if key is pressed
if event.type == pygame.KEYDOWN:
keys = [pygame.K_a, pygame.K_w, pygame.K_s, pygame.K_d, pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT]
if event.key in keys:
isMoving = True
if isMoving:
position = (player.x, player.y)
# do other stuff

How to edit a variable in a different file from where it was declared?

I'm currently working on the Alien Invasion project within the book Python Crash Course. The issue is that the picture of my ship is not moving whenever I press the right arrow key (I removed the code for the left arrow key temporarily).
I know that my function to check for key-press events works as it prints out the expected values whenever the key is pressed and when it's not.
When it's being held down, the flag movingRight is changed from its default state of false to true. What should happen then is the variable 'center' is changed by adding a predetermined movement factor to it, then using that to print the ship image in its new position.
However, when I print the state of movingRight in the ship.py file, it shows that movingRight is still False even during a KEY_DOWN event.
Here is the loop that handles the events and changing the ship state. This is within the main file called alien_invasion.py:
#Create a new Ship
ship = Ship(aiSettings, screen)
#start the main loop for the game
while True:
#Check for events that affect the ship
gf.checkEvents(ship)
#Update the status of the ship based upon checkEvents()
ship.update()
#Update the screen after pulling data from ship.update()
gf.updateScreen(aiSettings, screen, ship)
Below is the checkEvents() function in a separate file called game_functions.py:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
print("Moving Right")
ship.moveRight = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
print("Done moving right")
ship.moveRight = False
Lastly, below is the code that edits the position of the ship. This is within ship.py:
def update(self):
print("movingRight state is: " + self.movingRight) #movingRight is false during KEY_DOWN event
#Check for a right move
if self.movingRight:
#Update the ship's center to the right x amount of pixels
self.center += self.aiSettings.shipSpeedFactor
self.rect.centerx = self.center
I understand that this book is a few years old now, so could it be that the method I'm using is outdated?
From what I can see in your code, it looks like you're using different names for the moving right variables. In your second code snip, you set ship.moveRight to True, but in your third code snip, you're checking if self.movingRight is True. Try changing it so both use .movingRight or both use .moveRight

Pygame: how to display an image until a key is pressed

I'm trying to build a game in Pygame where if a player moves onto a red square, the player loses. When this happens, I want to display a picture of an explosion where the player lost until the user presses any key on the keyboard. When the user presses a key, I'll call the function new_game() to start a new game. The issue is that my code seems to skip over the line where I blit the explosion, and instead just starts a new game right away.
I've tried using something like this, but I'm not sure what to put in the while loop (I want it to wait until there is a keypress):
while event != KEYDOWN:
# Not sure what to put here
If I put time.sleep() in the while loop, the whole program seems to freeze and no image is blitted.
Here's me loading the image into Pygame:
explosionpic = pygame.image.load('C:/Users/rohan/Desktop/explosion.png')
And here's where I call it/determine if a player has lost (program seems to skip over the screen.blit line because I don't even see the image at all):
if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red: # If player lands on a red box
screen.blit(explosionpic, (p1.x, p1.y))
# Bunch of other code goes here, like changing the score, etc.
new_game()
It's supposed to display the image, then when the user presses a key, call the new_game() function.
I'd appreciate any help.
The simplest solution which comes to my mind is to write a small independent function which delay the execution of the code. Something like:
def wait_for_key_press():
wait = True
while wait:
for event in pygame.event.get():
if event.type == KEYDOWN:
wait = False
break
This function will halt the execution until a KEYDOWN signal is catch by the event system.
So your code would be:
if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red: # If player lands on a red box
screen.blit(explosionpic, (p1.x, p1.y))
pygame.display.update() #needed to show the effect of the blit
# Bunch of other code goes here, like changing the score, etc.
wait_for_key_press()
new_game()
Add a state to the game, which indicates if the game is running, the explsoion happens or a ne game has to be started. Define the states RUN, EXPLODE and NEWGAME. Initialize the state game_state:
RUN = 1
EXPLODE = 2
NEWGAME = 3
game_state = RUN
If the explosion happens, the set the state EXPLODE
if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red: # If player lands on a red box
game_state = EXPLODE
When a key is pressed then switch to the state NEWGAME:
if game_state == EXPLODE and event.type == pygame.KEYDOWN:
game_state = NEWGAME
When newgame() was executed, then set game_state = RUN:
newgame()
game_state = RUN
Implement a separated case in the main loop for each state of the game. With this solution not any "sleep" is needed:
e.g.
ENDGAME = 0
RUN = 1
EXPLODE = 2
NEWGAME = 3
game_state = RUN
while game_state != ENDGAME:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_state = ENDGAME
if game_state == EXPLODE and event.type == pygame.KEYDOWN:
game_state = NEWGAME
if game_state == RUN:
# [...]
if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red: # If player lands on a red box
game_state = EXPLODE
# [...]
elif game_state == EXPLODE:
screen.blit(explosionpic, (p1.x, p1.y))
elif game_state == NEWGAME:
newgame()
game_state = RUN
pygame.display.flip()

Pygame pong game

I am trying to get the ball object to bounce around inside the screen, I have been testing different things for hours, looking at other pong game source code and other questions on here but I just can't seem to figure it out. Could someone give some pointers on where to start? Should I make separate functions for the different movements?
# ----- Game Loop ----- #
# Setting the loop breakers
game_exit = False
# ball positon/velocity
ball_x = DISP_W/2
ball_y = DISP_H/2
velocity = 5
# Game loop
while not game_exit:
# Gets all events
for event in pygame.event.get():
# Close event
if event.type == pygame.QUIT:
# Closes game loop
game_exit = True
# Background fill
GAME_DISP.fill(black)
# Setting positions
ball.set_pos(ball_x, ball_y)
# ceil.set_pos(0, 0)
# floor.set_pos(0, DISP_H - boundary_thickness)
ball_y += velocity
# Drawing sprites
ball_group.draw(GAME_DISP)
# collision_group.draw(GAME_DISP)
pygame.display.update()
# Setting FPS
clock.tick(FPS)
# ----- Game exit ----- #
pygame.quit()
quit()
FULL CODE: http://pastebin.com/4XxJaCvf
I would have a look at the pygame sprite class. It has a lot of handy methods to help with collisions and other stuff: https://www.pygame.org/docs/ref/sprite.html

Categories