I have a question regarding the restart and quit option.
Whenever I press q after hitting the "wall" it quits the program as intended, however the c button doesn't seem to restart the gameloop() but I can't find the reason why.
I did try adding game_over and game_close = False in that same line, however that did not seem to fix the problem. I also tried to add Else gameloop() which did not solve it either.
import pygame
import time
pygame.init()
dis_width = 800
dis_height = 600
dis=pygame.display.set_mode((dis_width,dis_height))
pygame.display.set_caption('Snake delux')
#define colors
blue=(0,0,255)
red=(255,0,0)
white = (255, 255, 255)
black = (0, 0, 0)
#starting values
x1_change = 0
y1_change = 0
x1 = dis_width/2
y1 = dis_height/2
#game parameters
snake_speed = 144
snake_block = 10
font_style = pygame.font.SysFont(None, 30)
game_over = False
game_close = False
clock = pygame.time.Clock()
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width/3, dis_height/3])
def gameLoop():
global game_over
global game_close
global x1_change
global y1_change
global x1
global y1
while not game_over:
while game_close == True:
dis.fill(black)
message("Press Q-Quit or C-Play Again", red)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN:
y1_change = snake_block
x1_change = 0
if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
game_close = True
x1 += x1_change
y1 += y1_change
pygame.draw.rect(dis, blue, [x1, y1, snake_block, snake_block])
pygame.display.update()
clock.tick(snake_speed)
pygame.quit()
quit()
gameLoop()
If you reach the line where event.key == pygame.K_c is evaluated, then game_close must be True. You recursively call into the gameLoop function if c is being held down, but you don't change the game_over or game_close values so nothing will change.
If you imagine stepping through the code while pressing 'c':
if event.key == pygame.K_c:
This evaluates to True, so execution goes into the gameLoop function, game_close is still True, so you go right back to where you were.
I think, rather than recursively calling gameLoop() if the c key is pressed, what you need to do is change your game_close variable similar to what you do for quitting the game.
Do not call the gameLoop recursively, but run the game in a loop. Calling the main function recursively will mess up your variables and actually result in a game running within a game.
e.g.:
def gameLoop():
global game_end
# [...]
while not game_over:
while game_close == True:
[...]
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
game_end = True
if event.key == pygame.K_c:
game_over = True
game_close = False
game_end = False
# [...]
game_end False
while not game_end
x1_change = 0
y1_change = 0
x1 = dis_width/2
y1 = dis_height/2
snake_speed = 144
snake_block = 10
game_over = False
game_close = False
gameLoop()
Related
So I am currently mid way through coding snake, in an attempt at learning pygame. I am quite new to coding so apologies if I have explained this badly. I have a game loop which is active when running = True, when the snake hits a boundary, running becomes False, ending the game loop and switches to a different while loop that says game over. I will of course add more to this screen later down the line. I am just currently trying to figure out how to make it when I click r, within this second loop, running becomes true again, triggering the game loop once again to effectively restart this game. I would really appreciate any suggestions, thank you!
import pygame
pygame.init()
display_x = 400
display_y = 300
display = pygame.display.set_mode((display_x, display_y))
pygame.display.set_caption("Ned's snake game")
x1 = display_x / 2
y1 = display_y / 2
x1_change = 0
y1_change = 0
clock = pygame.time.Clock()
fps = 45
game_over_font = pygame.font.Font("freesansbold.ttf", 16)
def game_over():
over_text = game_over_font.render("GAME OVER", True, (200, 0, 0))
display.blit(over_text, ((display_x / 2) - 54, (display_y / 2) - 16))
running = True
while running is True:
print("thing")
display.fill((50, 200, 20))
pygame.draw.rect(display, (0, 0, 255), [x1, y1, 10, 10])
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x1_change = -5
y1_change = 0
elif event.key == pygame.K_RIGHT:
x1_change = 5
y1_change = 0
elif event.key == pygame.K_UP:
y1_change = -5
x1_change = 0
elif event.key == pygame.K_DOWN:
y1_change = 5
x1_change = 0
elif event.key == pygame.K_ESCAPE:
pygame.quit()
x1 += x1_change
y1 += y1_change
if x1 <= 0 or x1 >= display_x or y1 <= 0 or y1 >= display_y:
running = False
end_screen = True
clock.tick(fps)
pygame.display.update()
while end_screen is True:
display.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
elif event.key == pygame.K_r:
running = True
end_screen = False
game_over()
pygame.display.update() ```
One way to approach this would be to put your entire while running == True block into a def. Doing so will push a number of your variables out of scope. To get around that you can move most of them inside of the def and use the global keyword to access the rest, as I've shown in the code.
I've called that def playGame(), and since you've put that block inside of playGame() you'll have to execute the statement playGame() to kickstart it, as you can see in the code. When the while in playGame() goes false it then falls through to the while end_screen == True block which then checks for that r key and, if it finds it, re-runs playGame().
This is a very quick and dirty fix to get you to where you want to be quickly, and I suspect that this has probably resulted in one or two bugs being created, but it's a start. If I were to offer you a constructive criticism it would be that you do not have a proper game loop in your program. If I get time later this evening I will add more commentary on that.
import pygame
pygame.init()
display_x = 400
display_y = 300
display = pygame.display.set_mode((display_x, display_y))
pygame.display.set_caption("Ned's snake game")
clock = pygame.time.Clock()
fps = 45
game_over_font = pygame.font.Font("freesansbold.ttf", 16)
def game_over():
over_text = game_over_font.render("GAME OVER", True, (200, 0, 0))
display.blit(over_text, ((display_x / 2) - 54, (display_y / 2) - 16))
def playGame():
global display_x, display_y, end_screen #"globals" are variables defined outside of the def block
x1 = display_x / 2 #moved these inside the def block
y1 = display_y / 2
x1_change = 0
y1_change = 0
#just moved this inside of a def block
running = True
while running is True:
#print("thing")
display.fill((50, 200, 20))
pygame.draw.rect(display, (0, 0, 255), [x1, y1, 10, 10])
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x1_change = -5
y1_change = 0
elif event.key == pygame.K_RIGHT:
x1_change = 5
y1_change = 0
elif event.key == pygame.K_UP:
y1_change = -5
x1_change = 0
elif event.key == pygame.K_DOWN:
y1_change = 5
x1_change = 0
elif event.key == pygame.K_ESCAPE:
pygame.quit()
x1 += x1_change
y1 += y1_change
if x1 <= 0 or x1 >= display_x or y1 <= 0 or y1 >= display_y:
running = False
end_screen = True
clock.tick(fps)
pygame.display.update()
playGame() #kickstart the game
while end_screen is True:
display.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
elif event.key == pygame.K_r:
running = True
end_screen = False
playGame() #restart the game
game_over()
pygame.display.update()
pygame.quit()
import pygame, sys
pygame.init()
pygame.display.set_caption("test 1")
#main Variables
clock = pygame.time.Clock()
window_size = (700, 700)
screen = pygame.display.set_mode(window_size, 0, 32)
#player variables
playerx = 150
playery = -250
player_location = [playerx, playery]
player_image = pygame.image.load("player/player.png").convert_alpha()
player_rect = player_image.get_rect(center = (80,50))
#button variables
move_right = False
move_left = False
move_up = False
move_down = False
while True:
screen.fill((4, 124, 32))
screen.blit(player_image, player_location, player_rect)
if move_right == True:
playerx += 4
if move_left == True:
playerx -= 4
if move_up == True:
playery -= 4
if move_down == True:
playery += 4
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
move_right = True
if event.key == pygame.K_a:
move_left = True
if event.key == pygame.K_w:
move_up = True
if event.key == pygame.K_s:
move_down = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_d:
move_right = False
if event.key == pygame.K_a:
move_left = False
if event.key == pygame.K_w:
move_up = False
if event.key == pygame.K_s:
move_down = False
pygame.display.update()
clock.tick(120)
I cant get it to work. I pressed the button but it wont go up or down. It worked well when i used no rectangle for the player. I wanter so i can move the character up and down in the y axis also. I just started to learn how to use PyGame so please help me thanks.
As you move the player, you change the playerx and playery variables. However, the player id drawn to the position that is stored in player_location. You must update player_location before drawing the player:
while True:
screen.fill((4, 124, 32))
player_location = [playerx, playery]
screen.blit(player_image, player_location, player_rect)
# [...]
Note that you don't need player_location at all. Draw the player at [playerx, playery]:
while True:
screen.fill((4, 124, 32))
screen.blit(player_image, [playerx, playery], player_rect)
I was working on the basic game "Snake" in Python using "pygame". When I move around at the start and I am alive, my arrow keys are working fine. When I die, then I can't use any key and I can't close the window by pressing the X button on the top right of the window. The only way to terminate it is by pressing Ctrl-x in the console, and that way it doesn't close.
When I debugged it, my console says that my q and c values are 59, 248 accordingly but the pygame. K_q and pygame.K_c have the values 113, 99. Does anybody knows the reason? My code when I die is the following:
while game_close == True:
self.dis.fill(colors("blue"))
self.message("You Lost! Press C-Play Again or Q-Quit", colors("red"))
self.Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
elif event.key == pygame.K_c:
game_close = False
self.gameLoop()
If anybody has any clue why this happened it will be useful.
It is my first time writing any quest so sorry for not having the best description or there is any duplicate( I have searched and found nothing that works for me)
edit: This is the whole script:
game_over = False
game_close = False
x1 = self.dis_width / 2
y1 = self.dis_height / 2
x1_change = 0
y1_change = 0
snake_List = []
Length_of_snake = 1
foodx = round(random.randrange(0, self.dis_width - self.snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, self.dis_height - self.snake_block) / 10.0) * 10.0
flagex=True
flagey=True
while not game_over:
while game_close :
self.dis.fill(colors.blue())
self.message("You Lost! Press C-Play Again or Q-Quit", colors.red())
self.Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_close = True
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
elif event.key == pygame.K_c:
game_close = False
self.gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and flagey==True:
flagey = False
flagex = True
x1_change = -self.snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT and flagey==True:
flagey = False
flagex = True
x1_change = self.snake_block
y1_change = 0
elif event.key == pygame.K_UP and flagex==True:
flagey = True
flagex = False
y1_change = -self.snake_block
x1_change = 0
elif event.key == pygame.K_DOWN and flagex==True:
flagey = True
flagex = False
y1_change = self.snake_block
x1_change = 0
if x1 >= self.dis_width or x1 < 0 or y1 >= self.dis_height or y1 < 0:
game_close = True
x1 += x1_change
y1 += y1_change
self.dis.fill(colors.blue())
pygame.draw.rect(self.dis, colors.green(), [foodx, foody, self.snake_block, self.snake_block])
snake_Head = []
snake_Head.append(x1)
snake_Head.append(y1)
snake_List.append(snake_Head)
if len(snake_List) > Length_of_snake:
del snake_List[0]
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
self.our_snake(self.snake_block, snake_List)
self.Your_score(Length_of_snake - 1,)
pygame.display.update()
if x1 == foodx and y1 == foody:
foodx = round(random.randrange(0, self.dis_width - self.snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, self.dis_height - self.snake_block) / 10.0) * 10.0
Length_of_snake += 1
self.clock.tick(self.snake_speed)
pygame.quit()
quit()
I won't be able to answer your question completely because it would be nice to see the whole code but I would definietly change it to this:
while game_close:
self.dis.fill(colors("blue"))
self.message("You Lost! Press C-Play Again or Q-Quit", colors("red"))
self.Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_close = True
game_over = True
# exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_q]:
game_over = True
game_close = False
if keys[pygame.K_c]:
game_close = False
self.gameLoop()
Try changing it to this
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key == pygame.K_q:
game_over = True
game_close = False
elif event.key == pygame.K_c:
game_close = False
self.gameLoop()
The whole code is not included, a class is missing and some methods are not defined. But first I would suggest changing all the key presses to this:
keys = pygame.key.get_pressed()
if keys[pygame.K_yourkey]:
# do something
if keys[pygame.K_yourotherkey]:
# do something
# and so on
and dont put it in event for loop
Basically I am trying to add some boundaries to a small game I am making, I have a sprite which can only move left to right and I am trying to prevent it from it from moving off the game window, if the sprite reaches the edge they can go no further and can then go in the opposite direction.
My current code:
tankSprite = pygame.image.load('Sprites/Tank.png') #fixed apostrophe
tankSprite_width = 28
def tank(x,y):
gameWindow.blit(tankSprite, (x,y))
def game_loop():
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
gameExit = False
gameMove = True
while not gameExit and gameMove == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFTor event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameWindow.fill(white)
tank(x,y)
if x > display_width - tankSprite_width or x < 0:
gameMove = False
elif x < display_width - tankSprite_width or x > 0:
gameMove = True
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
My current code partially works, when the sprite reaches the edge the solution closes itself rather than letting me go back. If I remove:
pygame.quit()
quit()
Then the sprite just stops and I can't move it back. In a project I did a while back I used something like:
if event.key == pygame.K_LEFT and sprite.x < 590:
sprite.x += 5
The above code worked well from what I can remember but I can't seem to figure it out for my project now, can anyone help me out please?
I wish to make it so that the sprite can't go past the screen border, when the player reaches the border they either stay or go back in the opposite direction. Thanks
p.s. Sorry about the dodgy formatting
Just split your if-statement and check the condition for each direction separately:
tankSprite = pygame.image.load('Sprites/Tank.png')
tankSprite_width = 28
def tank(x,y):
gameWindow.blit(tankSprite, (x,y))
def game_loop():
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
gameExit = False
gameMove = True
while not gameExit and gameMove == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFTor event.key == pygame.K_RIGHT:
x_change = 0
#valid move, add x_change
if((x+x_change)> 0 and (x+x_change)<(display_width - tankSprite_width):
x += x_change
gameWindow.fill(white)
tank(x,y)
#deleted stuff here
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
With this method, you don't need to even use the gameMove variable anymore.
You could also get rid of the x_change variable entirely by simply applying the changes directly to x instead.
Also, I think you may have meant gameExit = True under the if statement if event.type == pygame.QUIT:, as it makes sense to exit when event pygame.QUIT is triggered.
Im working on a simple game( a semi copy of the 'Dodger' game), and the game runs, yet displays nothing. I have a while loop running, so why is nothing showing up? Is it a problem with spacing, the images themselves, or am i just overlooking something?
import pygame,sys,random, os
from pygame.locals import *
pygame.init()
#This One Works!!!!!!!
WINDOWHEIGHT = 1136
WINDOWWIDTH = 640
FPS = 40
TEXTCOLOR = (255,255,255)
BACKGROUNDCOLOR = (0,0,0)
PLAYERMOVEMENT = 6
HARVEYMOVEMENT = 5
TJMOVEMENT = 7
LASERMOVEMENT = 10
ADDNEWBADDIERATE = 8
COLOR = 0
TJSIZE = 65
HARVEYSIZE = 65
#Check the sizes for these
def terminate():
if pygame.event() == QUIT:
pygame.quit()
def startGame():
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
terminate()
return
def playerHasHitBaddies(playerRect,TjVirus,HarVirus):
for b in TjVirus and HarVirus:
if playerRect.colliderect(b['rect']):
return True
return False
def drawText(text,font,surface, x, y):
textobj = font.render(text, 1, TEXTCOLOR)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
mainClock = pygame.time.Clock()
WindowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.mouse.set_visible(False)
pygame.display.set_caption('Virus')
#Player Images
# Check the name of the .png file
TjImage = pygame.image.load('Virus_TJ_edited-1.png')
TjRect = TjImage.get_rect()
#chanhe this part from the baddies variable in the 'baddies' area
playerImage = pygame.image.load('Tank_RED.png')
playerRect = playerImage.get_rect()
LaserImage = pygame.image.load('laser.png')
LaserRect = LaserImage.get_rect()
pygame.display.update()
startGame()
while True:
TjVirus = []#the red one / make a new one for the blue one
HarVirus = []#The BLue one / Need to create a new dictionary for this one
playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
moveLeft = moveRight = moveUp = moveDown = laser = False
baddieAddCounter = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == ord('a'):
moveRight = False
moveLeft = True
if event.key == ord('d'):
moveLeft = False
moveRight = True
if event.key == ord('w'):
moveDown = False
moveUp = True
if event.key == ord('s'):
moveUp = False
moveDown = True
if event.key == K_SPACE:
lasers = True
if event.type == KEYUP:
if evnet.type == K_ESCAPE:
terminate()
if event.key == K_LEFT or event.key == ord('a'):
moveLeft = False
if event.key == K_RIGHT or event.key == ord('d'):
moveRight = False
if event.key == K_UP or event.key == ord('w'):
moveUp = False
if event.key == K_DOWN or event.key == ord('s'):
moveDown = False
if event.key == K_SPACE:
LaserImage.add(LaserRect)
if event.key == ord('j'):
COLOR = 2
if event.key == ord('k'):
if COLOR == 2:
COLOR = 1
playerImage = pygame.image.load('Tank_RED.png')
if COLOR == 1:
COLOR = 2
playerImage = pygame.image.load('Tank_BLUE.png')
if event.type == MOUSEMOTION:
playerRect.move_ip(event.pos[0] - playerRect.centerx, event.pos[1] - playerRect.centery)
if baddieAddCounter == ADDNEWBADDIERATE:
baddieAddCounter = 0
#Dict for TJ(RED) VIRUS
baddieSize = (TJSIZE)
NewTjVirus = {'rect':pygame.Rect(random.rantint(0,WINDOWWIDTH - TJSIZE),0 - TJSIZE,TJSIZE,TJSIZE),
'speed':(TJMOVEMENT),
'surface':pygame.transform.scale(TJImage,(TJSIZE,TJSIZE)),
}
TjVirus.append(NewTjVirus)
#Dict for Harvey(BLUE) virus
baddieSize = (HARVEYSIZE)
NewHarveyVirus = {'rect':pygame.Rect(random.randint(0,WINDOWWIDTH - HARVEYSIZE),0 - HARVEYSIZE,HARVEYSIZE,HARVEYSIZE),
'speed':(HARVEYMOVEMENT),
'surface':pygame.transform.scale(HARVEYSIZE,(HARVEYSIZE,HARVEYSIZE))
}
HarVirus.append(NewHarveyVirus)
#Player Movement
if moveLeft and playerRect.left >0:
playerRect.move_ip(-1*PLAYERMOVEMENT,0)
if moveRight and playerRect.right < WINDOWWIDTH:
playerRect.move_ip(PLAYERMOVEMENT,0)
if moveUp and playerRect.top >0:
playerRect.move_ip(0,-1*PLAYERMOVEMENT)
if moveDown and playerRect.bottom < WINDOWHEIGHT:
playerRect.move_ip(0,PLAYERMOVEMENT)
pygame,mouse.set_pos(playerRect.centerx,playerRect.centery)
#Need to change for each individual virus
for b in HarVirus and TjVirus:
b['rect'].move_ip(0,b['speed'])
for b in HarVirus and TjVirus:
if b['rect'].top > WINDOWHEIGHT:
baddies.remove(b)
windowSurface.fill(pygame.image.load('Background_Proto copy.png'))
for b in HarVirus and TjVirus:
windowSurface.blit(b['surface'],b['rect'])
pygame.display.update()
if playerHasHitBaddies(playerRect,HarVirus,TjVirus):
break
for b in TjVirus and HarVirus[:]:
if b['rect'].top < WINDOWHEIGHT:
HarVirus.remove(b)
TjVirus.remove(b)
mainClock.tick(FPS)
Usally I use pygame.display.flip() not pygame.display.update()
You call your startGame() in your script, which looks like this:
def startGame():
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
terminate()
return
The game is stuck in that while loop until you press a key.
That's your current problem, but there are other errors as well, like
def terminate():
if pygame.event() == QUIT:
pygame.quit()
pygame.event() is not callable. Maybe you wanted to pass an event as argument here?
And also
pygame,mouse.set_pos(playerRect.centerx,playerRect.centery)
, instead of .