# DONT CHANGE THIS
import pygame, os
pygame.init()
pygame.font.init()
WIDTH, HEIGHT = 450, 250
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Spar")
# VARIABLES
HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
WINNER_FONT = pygame.font.SysFont('comicsans', 50)
WINCOUNT_FONT = pygame.font.SysFont('comicsans', 20)
SPACE = pygame.transform.scale(pygame.image.load(os.path.join("Assets", "space.png")), (WIDTH, HEIGHT))
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BORDER = pygame.Rect(WIDTH//2 - 5, 0, 5, HEIGHT)
FPS = 60
VEL = 3.5
SHIP_WIDTH, SHIP_HEIGHT, = 25, 20
BULLETS_VEL = 10
MAX_BULLETS = 1
YELLOW_HIT = pygame.USEREVENT + 1
RED_HIT = pygame.USEREVENT + 2
YELLOW_SPACESHIP_IMAGE = pygame.image.load(os.path.join('Assets', "spaceship_yellow.png"))
YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(YELLOW_SPACESHIP_IMAGE, (SHIP_HEIGHT, SHIP_WIDTH)), 90)
RED_SPACESHIP_IMAGE = pygame.image.load(os.path.join('Assets', "spaceship_red.png"))
RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(RED_SPACESHIP_IMAGE, (SHIP_WIDTH, SHIP_HEIGHT)), 270)
# PLACE ANYTHING ON THE WINDOW HERE
# +y = down from top left
# +x = right from top left
def draw_window(red, yellow, red_bullets, yellow_bullets, red_health, yellow_health, red_win_count, yellow_win_count):
WIN.blit(SPACE, (0, 0))
pygame.draw.rect(WIN, BLACK, BORDER)
red_health_text = HEALTH_FONT.render("Health: " + str(red_health), 1, WHITE)
yellow_health_text = HEALTH_FONT.render("Health: " + str(yellow_health), 1, WHITE)
WIN.blit(red_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
WIN.blit(yellow_health_text, (10, 10))
yellow_win_text = WINCOUNT_FONT.render('Wins: ' + str(yellow_win_count), 1, WHITE)
red_win_text = WINCOUNT_FONT.render('Wins: ' + str(red_win_count), 1, WHITE)
WIN.blit(red_win_text, (WIDTH - red_health_text.get_width() - 70, 10))
pygame.display.update()
WIN.blit(yellow_win_text, (70, 10))
pygame.display.update()
WIN.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
WIN.blit(RED_SPACESHIP, (red.x, red.y))
for bullet in red_bullets:
pygame.draw.rect(WIN, RED, bullet)
for bullet in yellow_bullets:
pygame.draw.rect(WIN, RED, bullet)
pygame.display.update()
# MOVEMENT
def yellow_movement(keys_pressed, yellow):
if keys_pressed[pygame.K_a] and yellow.x - VEL > 0: #left
yellow.x -= VEL
if keys_pressed[pygame.K_d] and yellow.x + VEL + yellow.width < BORDER.x: #right
yellow.x += VEL
if keys_pressed[pygame.K_w] and yellow.y - VEL > 0: #up
yellow.y -= VEL
if keys_pressed[pygame.K_s] and yellow.y + VEL + yellow.height < HEIGHT: #dowm
yellow.y += VEL
def red_movement(keys_pressed, red):
if keys_pressed[pygame.K_LEFT] and red.x - VEL > BORDER.x + BORDER.width: #left
red.x -= VEL
if keys_pressed[pygame.K_RIGHT] and red.x + VEL + red.width < WIDTH: #right
red.x += VEL
if keys_pressed[pygame.K_UP] and red.y - VEL > 0: #up
red.y -= VEL
if keys_pressed[pygame.K_DOWN] and red.y + VEL + red.height < HEIGHT: #dowm
red.y += VEL
def handle_bullets(yellow_bullets, red_bullets, yellow, red):
for bullet in yellow_bullets:
bullet.x += BULLETS_VEL
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(RED_HIT))
yellow_bullets.remove(bullet)
elif bullet.x > WIDTH:
yellow_bullets.remove(bullet)
for bullet in red_bullets:
bullet.x -= BULLETS_VEL
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(YELLOW_HIT))
red_bullets.remove(bullet)
elif bullet.x < 0:
red_bullets.remove(bullet)
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WIN.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT/2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(1000)
# MAIN LOOP
def main():
red = pygame.Rect(350, 150,SHIP_WIDTH, SHIP_HEIGHT)
yellow = pygame.Rect(50, 150, SHIP_WIDTH, SHIP_HEIGHT)
red_bullets = []
yellow_bullets = []
red_health = 1
yellow_health = 1
red_win_count = 0
yellow_win_count = 0
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and len(yellow_bullets) < MAX_BULLETS:
bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height//2 - 1, 15, 4)
yellow_bullets.append(bullet)
if event.key == pygame.K_LCTRL and len(red_bullets) < MAX_BULLETS:
bullet = pygame.Rect(red.x, red.y + red.height//2 - 1, 15, 4)
red_bullets.append(bullet)
if event.type == RED_HIT:
red_health -= 1
if event.type == YELLOW_HIT:
yellow_health -= 1
winner_text = ""
if red_health <= 0:
yellow_win_count += 1
pygame.display.update()
winner_text = "Yellow is cooler"
if yellow_health <= 0:
winner_text = "Red is cooler"
red_win_count += 1
pygame.display.update()
if winner_text != "":
draw_winner(winner_text)
main()
keys_pressed = pygame.key.get_pressed()
yellow_movement(keys_pressed, yellow)
red_movement(keys_pressed, red)
handle_bullets(yellow_bullets, red_bullets, yellow, red)
draw_window(red, yellow, red_bullets, yellow_bullets, red_health, yellow_health, red_win_count, yellow_win_count)
pygame.quit()
# this is to make sure its opening the right thing blah blaho
if __name__ == "__main__":
main()
I'm trying to display a win count through a variable but the variable isn't updating on the screen, why?
I took a look at the Github version of this game and determined that what you are wanting to do is add an enhancement that shows wins on the screen. The issue at the moment is that once a spaceship wins and the program again starts "main()", the win variables get reset to "0" before the screen is redisplayed.
red_health = 1
yellow_health = 1
red_win_count = 0
yellow_win_count = 0
As a quick tweak, instead of constantly restarting the game by calling "main" at the end of the "while" block, I revised the last "if" block to just do the resetting of the player health and then continue on with the while loop function.
if winner_text != "":
draw_winner(winner_text)
red_health = 4
yellow_health = 4
continue
#main()
That then allowed for viewing the win count on the screen.
You might want to check to see if any other variables need to be reset, but you can give that a try.
Related
I coded a Pong game but the ball goes out of the window.
import pygame
pygame.init()
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
#Colors
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
#Game Variables
VEL = 5
FPS = 60
CENTER = (WIDTH/2, HEIGHT/2)
DOTRAD = 10
DOT_speed_x = 2
DOT_speed_y = 0
DOT = pygame.Rect(CENTER[0], CENTER[1], DOTRAD, DOTRAD)
#Player
PLAYER1 = pygame.Rect(50, HEIGHT/2-75, 10, 150)
PLAYER2 = pygame.Rect(850, HEIGHT/2-75, 10, 150)
def draw_window():
WIN.fill(WHITE)
pygame.draw.rect(WIN, BLACK, PLAYER1)
pygame.draw.rect(WIN, BLACK, PLAYER2)
pygame.draw.circle(WIN, BLACK, DOT[0:2], DOTRAD)
pygame.display.update()
def player1_handle_movement(keys_pressed):
if keys_pressed[pygame.K_w] and PLAYER1.y > 0: #Up
PLAYER1.y -= VEL
if keys_pressed[pygame.K_s] and PLAYER1.y + PLAYER1.height < HEIGHT: #Down
PLAYER1.y += VEL
def player2_handle_movement(keys_pressed):
if keys_pressed[pygame.K_UP] and PLAYER2.y > 0: #Up
PLAYER2.y -= VEL
if keys_pressed[pygame.K_DOWN] and PLAYER2.y + PLAYER2.height < HEIGHT: #Down
PLAYER2.y += VEL
def DOT_handle_movement (DOT_speed_x, DOT_speed_y):
DOT.x += DOT_speed_x
DOT.y += DOT_speed_y
if DOT.top <= 0 or DOT.bottom >= HEIGHT:
DOT_speed_y *= -1
if DOT.left <= 0 or DOT.right >= WIDTH:
DOT_speed_x *= -1
print(DOT_speed_x, DOT_speed_y)
def main():
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys_pressed = pygame.key.get_pressed()
player1_handle_movement(keys_pressed)
player2_handle_movement(keys_pressed)
DOT_handle_movement(DOT_speed_x, DOT_speed_y)
draw_window()
pygame.quit()
if __name__ == "__main__":
main()
I print the DOT_speed_x and DOT_speed_y to see if it works that the ball detects that its out of the window.
Yes it does.
But its not changing the direction.
I saw so many tutorials that say that this method should work fine but for me it doesn't.
In Python, there is no concept of in-out parameters. If you change DOT_speed_x or DOT_speed_y, only the parameter variable that is local to the function changes, but not the arguments that are passed to the function. You have to return the new values of DOT_speed_x and DOT_speed_y from the function.
def DOT_handle_movement(DOT_speed_x, DOT_speed_y):
DOT.x += DOT_speed_x
DOT.y += DOT_speed_y
if DOT.top <= 0 or DOT.bottom >= HEIGHT:
DOT_speed_y *= -1
if DOT.left <= 0 or DOT.right >= WIDTH:
DOT_speed_x *= -1
return DOT_speed_x, DOT_speed_y
def main():
DOT_speed_x = 2
DOT_speed_y = 0
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys_pressed = pygame.key.get_pressed()
player1_handle_movement(keys_pressed)
player2_handle_movement(keys_pressed)
DOT_speed_x, DOT_speed_y = DOT_handle_movement(DOT_speed_x, DOT_speed_y)
draw_window()
pygame.quit()
Note that it is absolutely not necessary that the function arguments and the functions parameter variables have the same name.
I'm fairly new to python and I'm trying to build a game with Pygame. I kept having issues with collisions not being recognized. Here's the code I tried
import pygame
pygame.init()
WIDTH, HEIGHT = (900, 500)
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Bong Pong')
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BORDER = pygame.Rect(WIDTH// 2 -5, 0, 10, HEIGHT)
VEL = 3
PLAYER_HEIGHT = 50
PLAYER_WIDTH = 15
BALL_HEIGHT = 15
BALL_WIDTH = 15
def draw_window(player_1, player_2, game_ball):
WIN.fill(WHITE)
pygame.draw.rect(WIN, BLACK, BORDER)
pygame.draw.rect(WIN, BLACK, player_1)
pygame.draw.rect(WIN, BLACK, player_2)
pygame.draw.rect(WIN, RED, game_ball)
pygame.display.update()
def player_1_movement(keys_pressed, player_1):
if keys_pressed[pygame.K_w] and player_1.y - VEL > 0:
player_1.y -= VEL
if keys_pressed [pygame.K_s] and player_1.y + PLAYER_HEIGHT + VEL < 500:
player_1.y += VEL
def player_2_movement(keys_pressed, player_2):
if keys_pressed[pygame.K_UP] and player_2.y - VEL > 0:
player_2.y -= VEL
if keys_pressed [pygame.K_DOWN] and player_2.y + PLAYER_HEIGHT + VEL < 500:
player_2.y += VEL
def player_collision(player_1, player_2, game_ball, ball_vel_x):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
def main():
clock = pygame.time.Clock()
run = True
player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT)
ball_vel_y = 2
ball_vel_x = 2
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.QUIT()
keys_pressed = pygame.key.get_pressed()
player_1_movement(keys_pressed, player_1)
player_2_movement(keys_pressed, player_2)
draw_window(player_1, player_2, game_ball)
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel_y *= -1
game_ball.y -= ball_vel_y
player_collision(player_1, player_2, game_ball, ball_vel_x)
game_ball.x += ball_vel_x
main()
if __name__ == '__main__':
main()
I've also tried putting the
game_ball.x += ball_vel_x
in the player_collsion function but it doesn't reverse it properly.
I've already solved the issue by putting the entire player_collision function code inside the main function like so
def main():
clock = pygame.time.Clock()
run = True
player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT)
ball_vel_y = 2
ball_vel_x = 2
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.QUIT()
keys_pressed = pygame.key.get_pressed()
player_1_movement(keys_pressed, player_1)
player_2_movement(keys_pressed, player_2)
draw_window(player_1, player_2, game_ball)
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel_y *= -1
game_ball.y -= ball_vel_y
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
game_ball.x += ball_vel_x
main()
and this works exactly how I want it I just want to clear up my understanding of why this function wouldn't work properly if just called in the main function instead of putting it directly in.
Python has no concept of in-out parameters. The argument is passed by value. If you change ball_vel_x in the player_collision function, only the parameter changes, but the argument remains unchanged. You must return the new value of ball_vel_x from the function:
def player_collision(player_1, player_2, game_ball, ball_vel_x):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
return ball_vel_x
def main():
# [...]
while run:
# [...]
ball_vel_x = player_collision(player_1, player_2, game_ball, ball_vel_x)
# [...]
Another possibility is to store the velocity in an object (e.g. gyame.math.Vector2). A variable stores a reference to an object, so you can change the object's attributes in the function if the variable is an argument of the function call:
def player_collision(player_1, player_2, game_ball, ball_vel):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel.x *= -1
def main():
# [...]
ball_vel = pygame.math.Vector2(2, 2)
while run:
# [...]
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel.y *= -1
game_ball.y -= ball_vel.y
player_collision(player_1, player_2, game_ball, ball_vel)
game_ball.x += ball_vel.x
my error:
pygame 2.1.0 (SDL 2.0.16, Python 3.10.0)
Hello from the pygame community. >https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "c:\Users\Tameem\PycharmProjects\pythonProject\Games\Pygame_first_game.py", line 200, in <module>
main()
File "c:\Users\Tameem\PycharmProjects\pythonProject\Games\Pygame_first_game.py", line 194, in main
main()
File "c:\Users\Tameem\PycharmProjects\pythonProject\Games\Pygame_first_game.py", line 180, in main
draw_winner(winner_text)
File "c:\Users\Tameem\PycharmProjects\pythonProject\Games\Pygame_first_game.py", line 124, in draw_winner
WIN.blit(draw_text, (WIDTH/2 - draw_text.get_width()/2, HEIGHT/2 - draw_text.get_height()/2))
pygame.error: display Surface quit
my code:
import pygame
import os
from pygame import display
pygame.font.init()
from pygame import event #opereting system
WIDTH, HEIGHT = 900, 500 #this is to make the WINDOW
WIN = pygame.display.set_mode((WIDTH, HEIGHT)) #your telling python that you want a window with this height and width
pygame.display.set_caption("Maisa Ahmed") #it sets a name for the game
DARK_GREEN = (00, 64, 00)
BLACK = (0, 0, 0)
BLOOD_RED = (136, 8, 8)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
health_font = pygame.font.SysFont("comicsans", 40)
winner_font = pygame.font.SysFont("comicsans", 100)
boarder = pygame.Rect(WIDTH//2-5, 0, 10, HEIGHT) # so i-5 because you want to draw it from 0 , 0 (left)
FPS = 60 #to contol how many times your game refersh per second
SPACESHIP_WIDTH , SPACESHIP_HEIGHT = 55,40
velocity = 5
Bullet_velocity = 7
MAX_BULLETS = 5
YELLOW_HITS = pygame.USEREVENT + 1
RED_HITS = pygame.USEREVENT + 2
#importing images
YELLOW_SPACESHIP_IMAGE = pygame.image.load(
os.path.join('Assets', 'spaceship_yellow.png')) # assets to go in the that folder and which file
YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90) #so now the space ship is smaller and has rotated
RED_SPACESHIP_IMAGE = pygame.image.load(
os.path.join('Assets', "spaceship_red.png"))
RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)),270)
background = pygame.transform.scale(pygame.image.load(
os.path.join('Assets', 'space.png')), (WIDTH, HEIGHT)) #Mom.jpg
def draw_window(red ,yellow, red_bullets, yellow_bullets, red_health, yellow_health): #the order in which you draw matters
WIN.blit(background, (0,0))
#WIN.fill(DARK_GREEN) #to fill color to the WINDOW
pygame.draw.rect(WIN, BLACK, boarder)
red_health_text = health_font.render("health: " + str(red_health),1,WHITE )
yellow_health_text = health_font.render("health: " + str(yellow_health),1,WHITE )
WIN.blit(red_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
WIN.blit(yellow_health_text, (10, 10))
WIN.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))# you use blit when you want draw a surface on the screen (basically used to put the images/texts on the screen)
WIN.blit(RED_SPACESHIP, (red.x, red.y)) # are cordinates
for bullet in red_bullets:
pygame.draw.rect(WIN, BLOOD_RED, bullet)
for bullet in yellow_bullets:
pygame.draw.rect(WIN, YELLOW, bullet)
pygame.display.update() #you have to update the WINDOW to show anychanges
def yellow_movement(keys_pressed, yellow):
if keys_pressed[pygame.K_a] and yellow.x - velocity > 0: # left not allowing to cross the boarder
yellow.x -= velocity
if keys_pressed[pygame.K_d] and yellow.x + velocity + yellow.width < boarder.x: # right not allowing to cross the boarder
yellow.x += velocity
if keys_pressed[pygame.K_w] and yellow.y - velocity > 0: # up not allowing to cross the boarder
yellow.y -= velocity
if keys_pressed[pygame.K_s] and yellow.y + velocity + yellow.height < HEIGHT - 10: # down not allowing to cross the boarder
yellow.y += velocity
def red_movement(keys_pressed, red):
if keys_pressed[pygame.K_LEFT] and red.x - velocity > boarder.x + boarder.width: # left
red.x -= velocity
if keys_pressed[pygame.K_RIGHT] and red.x + velocity + red.width < WIDTH: # right
red.x += velocity
if keys_pressed[pygame.K_UP] and red.y - velocity > 0:# up
red.y -= velocity
if keys_pressed[pygame.K_DOWN] and red.y + velocity + red.height < HEIGHT - 10: # down
red.y += velocity
def handle_bullets(yellow_bullets, red_bullets, yellow, red):
for bullet in yellow_bullets:
bullet.x += Bullet_velocity
if red.colliderect(bullet):
pygame.event.post(event.Event(RED_HITS))
yellow_bullets.remove(bullet)
elif bullet.x > WIDTH:
yellow_bullets.remove(bullet)
for bullet in red_bullets:
bullet.x -= Bullet_velocity
if yellow.colliderect(bullet):
pygame.event.post(event.Event(YELLOW_HITS))
red_bullets.remove(bullet)
elif bullet.x < 0:
red_bullets.remove(bullet)
def draw_winner(text):
draw_text = winner_font.render(text, 1, WHITE)
WIN.blit(draw_text, (WIDTH/2 - draw_text.get_width()/2, HEIGHT/2 - draw_text.get_height()/2))
pygame,display.update
pygame.time.delay(5000)
def main():
red = pygame.Rect(700, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
yellow = pygame.Rect(100, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT) # x,y , width , height
red_bullets = []
yellow_bullets = []
red_health = 10
yellow_health = 10
clock = pygame.time.Clock() # create a clock object which can be used to keep track of time
run = True
while run: #event loop
clock.tick(FPS) #ensures that you will never go above the FPS you set the game on
for event in pygame.event.get():
if event.type == pygame.QUIT: #.QUIT to end pygame in the loop
run = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL and len(yellow_bullets) < MAX_BULLETS:
bullet = pygame.Rect(
yellow.x + yellow.width, yellow.y + yellow.height//2 - 2,10,5) # so it goes from the middle
yellow_bullets.append(bullet)
if event.key == pygame.K_RCTRL and len(red_bullets) < MAX_BULLETS:
bullet = pygame.Rect(
red.x, red.y + red.height//2 - 2,10,5) # so it goes from the middle
red_bullets.append(bullet)
if event.type == RED_HITS:
red_health -= 1
if event.type == YELLOW_HITS:
yellow_health -= 1
winner_text = ''
if red_health <= 0:
winner_text = "Yellow WINS!"
if yellow_health <= 0:
winner_text = "Red WINS!"
if winner_text == '':
draw_winner(winner_text)
break
keys_pressed = pygame.key.get_pressed() # this tells us what keys are being clicked every 1
yellow_movement(keys_pressed, yellow)
red_movement(keys_pressed, red)
handle_bullets(yellow_bullets, red_bullets, yellow, red)
draw_window(red, yellow, red_bullets, yellow_bullets, red_health, yellow_health) #you took the yellow and red to the Drawing funcations
main()
#pygame.quit .quit to end pygame in general
if __name__ == "__main__": #doesnt matter
main()
the code was working fine until i added the winning messages , if you anyone has a fix please tell me.
The problem is that you call pygame.quit() in the application loop. You have to call pygame.quit() after the application loop:
def main():
# [...]
run = True
while run: #event loop
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# pygame.quit() <--- DELETE
# [...]
pygame.quit() # <--- INSERT
Note, when pygame.quit() is executed, all PyGame modules will be uninstalled. Every further call to a PyGame function throws an exception.
I'd like to draw your attention to the block that, per comments, you just added.
winner_text = ''
if red_health <= 0:
winner_text = "Yellow WINS!"
if yellow_health <= 0:
winner_text = "Red WINS!"
if winner_text == '':
draw_winner(winner_text)
break
This will break out of the game loop the first time a non-winning condition is encountered, so probably directly at the start. You probably intended quite the opposite.
You might also want to make this compatible with the overall looping mechanism via the run variable, so either universally leave the loop via setting run=False or universally use the break keyword. This then leads to the point of the other answer, the clean-up should happen for all ways that the main loop can be exited, so best centralized after the loop.
so i'm watching Teach with Tim pygame in 90 min and i'm at 1:24:39. When i run the code the red ship health keep decrasing when i shoot it(by yellow ship and when the red ship hit the yellow ship) until i move one of the ship or press shoot when i just shoot the other ship once. what went wrong can anyone help?
i think the issue is this part but i'm not sure:
if event.type == red_hit:
red_health -= 1
if event.type == yellow_hit:
yellow_health -= 1
import pygame
import os
import time
pygame.font.init()
width , height = 900 , 500
dispay_surface = pygame.display.set_mode((width, height))
pygame.display.set_caption("first game")
teal = (153,255,255)
light_green = (102,255,102)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)
BORDER = pygame.Rect(width//2,0,10,height)
health_font = pygame.font.SysFont('comicsans', 40)
fps = 60
VEL = 5
BULLET_VEL = 7
max_bullet = 10
spaceship_width, spaceship_height = 55, 40
yellow_hit = pygame.USEREVENT +1
red_hit = pygame.USEREVENT +2
#making the space ship and rotating it correctly
yellow_spaceship_image = pygame.image.load(
os.path.join('Assets','spaceship_yellow.png'))
yellow_spaceship_nr = pygame.transform.scale(
yellow_spaceship_image, (spaceship_width, spaceship_height))
yellow_spaceship = pygame.transform.rotate(yellow_spaceship_nr, 90)
red_spaceship_image = pygame.image.load(
os.path.join('Assets','spaceship_red.png'))
red_spaceship_nr= pygame.transform.scale(
red_spaceship_image, (spaceship_width, spaceship_height))
red_spaceship = pygame.transform.rotate(red_spaceship_nr, -90)
space_background = pygame.transform.scale(pygame.image.load(os.path.join('Assets','space.png')),(width,height))
def draw_window(red,yellow,red_bullet,yellow_bullet,red_health,yellow_health):
dispay_surface.blit(space_background,(0,0))
#showing the health
red_health_text = health_font.render("health: " + str(red_health), 1 , teal)
yellow_health_text = health_font.render("health: " + str(yellow_health), 1, teal)
dispay_surface.blit(red_health_text,(width - red_health_text.get_width()- 10 , 10))
dispay_surface.blit(yellow_health_text, (10 , 10))
#use to draw the ship
dispay_surface.blit(yellow_spaceship,(yellow.x, yellow.y))
dispay_surface.blit(red_spaceship,(red.x, red.y))
#drawing a border so the 2 spaceship can't go on top of each other
pygame.draw.rect(dispay_surface,BLACK,BORDER)
for bullet in red_bullet:
pygame.draw.rect(dispay_surface,RED,bullet)
for bullet in yellow_bullet:
pygame.draw.rect(dispay_surface,YELLOW,bullet)
pygame.display.update()
#getting yellow ship to move when player input
def yellow_mov(keys_pressed,yellow):
if keys_pressed[pygame.K_d] and yellow.x + VEL + yellow.width < BORDER.x: #right
yellow.x += VEL
if keys_pressed[pygame.K_a] and yellow.x - VEL > 0: #left
yellow.x -= VEL
if keys_pressed[pygame.K_w] and yellow.y - VEL > 0: #up
yellow.y -= VEL
if keys_pressed[pygame.K_s] and yellow.y - VEL + yellow.height < height - 15 : #down
yellow.y += VEL
#getting red to move
def red_mov(keys_pressed,red):
if keys_pressed[pygame.K_RIGHT] and red.x + VEL + red.width < width: #right
red.x += VEL
if keys_pressed[pygame.K_LEFT] and red.x - VEL >BORDER.x + BORDER.width: #left
red.x -= VEL
if keys_pressed[pygame.K_UP] and red.y - VEL > 0: #up
red.y -= VEL
if keys_pressed[pygame.K_DOWN] and red.y - VEL + red.height < height - 15: #down
red.y += VEL
def handle_bullet(yellow_bullet,red_bullet,yellow,red):
for bullet in yellow_bullet:
bullet.x += BULLET_VEL
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(red_hit))
yellow_bullet.remove(bullet)
elif bullet.x > width:
yellow_bullet.remove(bullet)
for bullet in red_bullet:
bullet.x -= BULLET_VEL
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(red_hit))
red_bullet.remove(bullet)
elif bullet.x < 0 :
red_bullet.remove(bullet)
#keep window running
def main():
#determin the player position
red = pygame.Rect(700,300,spaceship_width,spaceship_height)
yellow = pygame.Rect(100,300,spaceship_width,spaceship_height)
red_bullet = []
yellow_bullet = []
red_health = 10
yellow_health = 10
clock = pygame.time.Clock()
run = True
while run:
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#Shoot the bullet
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL and len(yellow_bullet) < max_bullet:
bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height//2 , 10 ,5)
yellow_bullet.append(bullet)
if event.key == pygame.K_RCTRL and len(red_bullet) < max_bullet:
bullet = pygame.Rect(red.x , red.y + red.height//2 , 10 ,5)
red_bullet.append(bullet)
if event.type == red_hit:
red_health -= 1
if event.type == yellow_hit:
yellow_health -= 1
if red_health <=0:
winner_text = "yellow wins"
if yellow_health <=0:
winner_text = "red wins"
keys_pressed = pygame.key.get_pressed()
yellow_mov(keys_pressed,yellow)
red_mov(keys_pressed,red)
handle_bullet(yellow_bullet,red_bullet,yellow,red)
draw_window(red,yellow,red_bullet,yellow_bullet,red_health,yellow_health)
pygame.quit()
if __name__ == '__main__':
main()
I went over your code, and I believe the issue is that this snippet of code:
if event.type == red_hit:
red_health -= 1
if event.type == yellow_hit:
yellow_health -= 1
is in your main loop instead of your
for event in pygame.event.get():
loop.
Try changing the format to this:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#Shoot the bullet
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL and len(yellow_bullet) < max_bullet:
bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height // 2, 10, 5)
yellow_bullet.append(bullet)
if event.key == pygame.K_RCTRL and len(red_bullet) < max_bullet:
bullet = pygame.Rect(red.x, red.y + red.height // 2, 10 ,5)
red_bullet.append(bullet)
if event.type == red_hit:
red_health -= 1
if event.type == yellow_hit:
yellow_health -= 1
There is an issue in your code here.
def handle_bullet(yellow_bullet,red_bullet,yellow,red):
for bullet in yellow_bullet:
bullet.x += BULLET_VEL
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(red_hit))
yellow_bullet.remove(bullet)
elif bullet.x > width:
yellow_bullet.remove(bullet)
for bullet in red_bullet:
bullet.x -= BULLET_VEL
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(red_hit))
red_bullet.remove(bullet)
elif bullet.x < 0 :
red_bullet.remove(bullet)
You have considered both events for red_hit. Change as follows.
def handle_bullet(yellow_bullet,red_bullet,yellow,red):
for bullet in yellow_bullet:
bullet.x += BULLET_VEL
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(red_hit))
yellow_bullet.remove(bullet)
elif bullet.x > width:
yellow_bullet.remove(bullet)
for bullet in red_bullet:
bullet.x -= BULLET_VEL
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(yellow_hit))
red_bullet.remove(bullet)
elif bullet.x < 0 :
red_bullet.remove(bullet)
There is an indentation issue as well.Change as follows.
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#Shoot the bullet
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL and len(yellow_bullet) < max_bullet:
bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height//2 , 10 ,5)
yellow_bullet.append(bullet)
if event.key == pygame.K_RCTRL and len(red_bullet) < max_bullet:
bullet = pygame.Rect(red.x , red.y + red.height//2 , 10 ,5)
red_bullet.append(bullet)
if event.type == red_hit:
red_health-= 1
if event.type == yellow_hit:
yellow_health-= 1
Found another issue with your code. The health of spaceships keep decreasing below 0. It has something to do with here.
if red_health <=0:
winner_text = "yellow wins"
You have to stop the game when health becomes less than or equal zero.Use break to stop.
Change as follows=>
if red_health <=0:
winner_text = "yellow wins"
print(winner_text)
break
if yellow_health <=0:
winner_text = "red wins"
print(winner_text)
break
import pygame
import os
pygame.font.init()
pygame.mixer.init()
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game")
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BORDER = pygame.Rect(WIDTH//2-5, 0, 10, HEIGHT)
HEALTH_FONT = pygame.font.SysFont('comicsans', 40)
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
REDhealth = 15
YELLOWhealth = 15
YELLOWbullets = []
REDbullets = []
FPS = 60
VEL = 5
BULLETspeed = 7
BULLETnum = 4
YELLOWhit = pygame.USEREVENT + 1
REDhit = pygame.USEREVENT + 2
SHIPWIDTH, SHIPHEIGHT = 55, 40
red = pygame.Rect(700, 220, SHIPWIDTH, SHIPHEIGHT)
yellow = pygame.Rect(100, 220, SHIPWIDTH, SHIPHEIGHT)
YELLOW_SPACESHIP_IMAGE = pygame.image.load(
os.path.join('Downloads', 'Heggo.png'))
YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
YELLOW_SPACESHIP_IMAGE, (SHIPWIDTH, SHIPHEIGHT)), 270)
RED_SPACESHIP_IMAGE = pygame.image.load(
os.path.join('Downloads', 'spaceship_red.png'))
RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
RED_SPACESHIP_IMAGE, (SHIPWIDTH, SHIPHEIGHT)), 270)
BACKGROUND = pygame.transform.scale(pygame.image.load(os.path.join('Downloads', 'Space.jpeg')), (WIDTH, HEIGHT))
BACKGROUND = pygame.transform.rotate(BACKGROUND, 180)
def draw_window(red, yellow, REDbullets, YELLOWbullets, REDhealth, YELLOWhealth):
WIN.blit(BACKGROUND, (0, 0))
pygame.draw.rect(WIN, BLACK, BORDER)
red_health_text = HEALTH_FONT.render(
"Health: " + str(REDhealth), 1, WHITE)
yellow_health_text = HEALTH_FONT.render(
"Health: " + str(YELLOWhealth), 1, WHITE)
WIN.blit(red_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
WIN.blit(yellow_health_text, (10, 10))
WIN.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
WIN.blit(RED_SPACESHIP, (red.x, red.y))
for bullet in REDbullets:
pygame.draw.rect(WIN, YELLOW, bullet)
for bullet in YELLOWbullets:
pygame.draw.rect(WIN, RED, bullet)
pygame.display.update()
def yellowmovement(keys_pressed, yellow):
if keys_pressed[pygame.K_a] and yellow.x - VEL > 0: #left
yellow.x -= VEL
if keys_pressed[pygame.K_d] and yellow.x + VEL + yellow.width < BORDER.x: #right
yellow.x += VEL
if keys_pressed[pygame.K_w] and yellow.y - VEL > 0: #up
yellow.y -= VEL
if keys_pressed[pygame.K_s] and yellow.y + 10 + VEL + yellow.height < HEIGHT: #down
yellow.y += VEL
def redmovement(keys_pressed, yellow):
if keys_pressed[pygame.K_LEFT] and red.x - VEL -5 > BORDER.x +BORDER.width : #left
red.x -= VEL
if keys_pressed[pygame.K_RIGHT] and red.x + VEL + red.width -15 < WIDTH: #right
red.x += VEL
if keys_pressed[pygame.K_UP] and red.y - VEL > 0: #up
red.y -= VEL
if keys_pressed[pygame.K_DOWN] and red.y + 10 + VEL + red.height < HEIGHT: #down
red.y += VEL
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WIN.blit(draw_text, (WIDTH/2 - draw_text.get_width() /
2, HEIGHT/2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(5000)
def bulletscontrol(yellow_bullets, red_bullets, yellow, red):
for bullet in YELLOWbullets:
bullet.x += BULLETspeed
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(REDhit))
YELLOWbullets.remove(bullet)
elif bullet.x > WIDTH:
YELLOWbullets.remove(bullet)
for bullet in REDbullets:
bullet.x -= BULLETspeed
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(YELLOWhit))
REDbullets.remove(bullet)
elif bullet.x < 0:
REDbullets.remove(bullet)
def main():
global REDhealth
global YELLOWhealth
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL and len(YELLOWbullets) < BULLETnum:
bullet = pygame.Rect(
yellow.x + yellow.width, yellow.y + yellow.height//2 -2, 10, 5)
YELLOWbullets.append(bullet)
if event.key == pygame.K_RCTRL and len(REDbullets) < BULLETnum:
bullet = pygame.Rect(
red.x, red.y + red.height//2 -2, 10, 5)
REDbullets.append(bullet)
if event.type == REDhit:
REDhealth -= 1
if event.type == YELLOWhit:
YELLOWhealth -= 1
winner_text = ""
if REDhealth <= 0:
winner_text = "Yellow Wins!"
if YELLOWhealth <= 0:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
keys_pressed = pygame.key.get_pressed()
redmovement(keys_pressed, red)
yellowmovement(keys_pressed, yellow)
bulletscontrol(YELLOWbullets, REDbullets, yellow, red)
draw_window(red, yellow, YELLOWbullets, REDbullets, REDhealth, YELLOWhealth)
main()
if __name__ == "__main__":
main()
This code gives a syntax error after roughly 30 seconds:
File "c:\Users\chris\OneDrive\Desktop\Helllo.py", line 161, in main
draw_window(red, yellow, YELLOWbullets, REDbullets, REDhealth, YELLOWhealth)
File "c:\Users\chris\OneDrive\Desktop\Helllo.py", line 52, in draw_window
"Health: " + str(REDhealth), 1, WHITE)
RecursionError: maximum recursion depth exceeded while getting the str of an object
PS C:\Users\chris>
Does anyone know what this error is and why it is happening? Thanks
The problem is you are calling main function inside the while loop.
So every frame, you are calling main function. Which if you call it a bunch of time, will trigger the recursion limit error.