Life Counter Keeps Resetting - python

I have recently gotten into pygame and I am having trouble. My life counter is not working in my program.
import pygame, time, random
pygame.init() # Initializes Pygame
display_width = 1280
display_height = 720
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Cube Game')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
def life(lives):
font = pygame.font.SysFont(None, 25);
text = font.render("Lives: " + str(lives), True, white)
gameDisplay.blit(text,(1200,5))
def score(count):
font = pygame.font.SysFont(None, 25);
text = font.render("Score: " + str(count), True, white)
gameDisplay.blit(text,(5,5))
def enemyBall(ballx, bally, ballr, color):
pygame.draw.circle(gameDisplay, color, [ballx, bally], ballr)
# Creates Location for the Cube
def cube(x,y,side):
pygame.draw.rect(gameDisplay, white, [x, y, side, side])
def text_objects(text, font):
textSurface = font.render(text, True, white)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf', 50)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
__init__()
def dead():
gameDisplay.fill(black)
message_display('You have fallen out of the castle and died!')
# Game Loop
def __init__():
x = ((display_width/2) - 30)
y = (display_height - 70)
side = 60
x_change = 0
ballx_change = 25
bally_change = 25
ball_radius = 50
ball_startx = random.randrange(26, (display_width-ball_radius-1))
ball_starty = random.randrange((ball_radius+1), 100)
death = False
goodbye = False
myLives = 3
myScore = 0
# If Player has not Died
while not death:
for event in pygame.event.get():
if event.type == pygame.QUIT:
death = True
pygame.display.quit()
pygame.quit()
quit()
# Key is still Pressed
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -10
if event.key == pygame.K_RIGHT:
x_change = 10
# Key is no longer Pressed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(black)
# Defines the enemy ball
enemyBall(ball_startx, ball_starty, ball_radius, white)
ball_startx += ballx_change
ball_starty += bally_change
# Wall Collision
if ball_startx - ball_radius <= 0 or ball_startx + ball_radius >= display_width:
ballx_change = -ballx_change
myScore += 1
if ball_starty - ball_radius <= 0 or ball_starty + ball_radius >= display_height:
bally_change = -bally_change
myScore += 1
# Determines Player Position
cube(x,y,side)
# Score and Life Counter
score(myScore)
life(myLives)
# Death by Abyss
if x > display_width or x < -50:
myLives -= 1
dead()
# Death by Ball
if ball_startx + ball_radius >= x and ball_startx - ball_radius <= x + side:
if ball_starty + ball_radius >= y and ball_starty - ball_radius <= y + side:
myLives -= 1
dead()
pygame.display.update()
clock.tick(60)
time.sleep(2)
__init__()
pygame.display.quit()
pygame.quit()
quit()
I have a statement that decreases the life counter by one when the player dies. However, the life counter seems to reset to 3 (the original amount). What do I have to change to fix the life counter? Thanks!

dead() calls message_display() which calls your init() again. On every init() call, you set myLives = 3 again.

When the player dies, you call dead().
dead() calls message_display().
message_display() calls __init__() again (even though it was already running).
The beginning of __init__() says myLives = 3.
If you don't want the variable reset to 3 when the player dies, don't keep calling __init__ again, because the start of that function always resets myLives to 3.

Related

How do I update the text in python pygame when a certain command is true?

I'm trying to build a space invader-like game for fun.
It's mostly done, but when I shoot the enemy I want the text on the screen with his health to decrease.
Here is my code stripped only to the health updating part:
import pygame
from sys import exit
enemy_health = 10
pygame.init()
win = pygame.display.set_mode((1000, 1000))
pygame.display.set_caption("Fighter Pilot Go!")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 55)
enemy_health_text = font.render(f'Enemy Health: {enemy_health}', False, 'white')
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
enemy_health_text -= 1
win.blit(enemy_health_text, (350, 60)
That's not all of the game, but it's the basic idea.
The score doesn't update in the game till a laser hits the enemy.
Here is the whole game, if the code helps you understand my issue:
import pygame
from sys import exit
import random
speed = 5
laser_speed = 7
bullets = []
score = 0
max_num_of_bullet = 3
background_speed = 3
enemy_health = 10
direction = True
enemy_speed = 7
pygame.init()
win = pygame.display.set_mode((1000, 1000))
pygame.display.set_caption("Fighter Pilot Go!")
clock = pygame.time.Clock()
background1 = pygame.image.load('assets/background.gif')
background2 = pygame.image.load('assets/background.gif')
background1_rect = background1.get_rect(topleft=(0, 0))
background2_rect = background2.get_rect(topleft=(0, -1000))
player = pygame.image.load('assets/player.gif')
player_rect = player.get_rect(midtop=(500, 750))
enemy = pygame.image.load('assets/enemy.gif')
enemy_rect = enemy.get_rect(center=(500, 350))
laser = pygame.image.load('assets/laser.gif')
# laser_rect = laser.get_rect(midtop=(500, 800))
font = pygame.font.Font(None, 55)
enemy_health_text = font.render(f'Enemy Health: {enemy_health}', False, 'white')
def is_collided_with(a, b):
return abs(a[0] - b.centerx) < 51 and abs(a[1] - b.centery) < 51
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if len(bullets) <= max_num_of_bullet - 1:
bullets.append([player_rect.x + 49, player_rect.y - 60])
elif len(bullets) > max_num_of_bullet - 1:
continue
else:
print("Something Weird is Happening!")
key = pygame.key.get_pressed()
if key[pygame.K_a]:
player_rect.x -= speed
if key[pygame.K_d]:
player_rect.x += speed
win.blit(background1, background1_rect)
win.blit(background2, background2_rect)
win.blit(player, player_rect)
win.blit(enemy, enemy_rect)
background1_rect.y += background_speed
background2_rect.y += background_speed
if direction:
enemy_rect.x -= enemy_speed
elif not direction:
enemy_rect.x += enemy_speed
if enemy_rect.x <= 0:
direction = False
elif enemy_rect.x >= 900:
direction = True
if player_rect.x < -20:
player_rect.x = 1020
if player_rect.x > 1020:
player_rect.x = -20
for bullet in bullets:
win.blit(laser, bullet)
for bullet in bullets:
bullet[1] -= laser_speed
win.blit(enemy_health_text, (350, 60))
for bullet in bullets:
if is_collided_with(bullet, enemy_rect):
bullets.remove(bullet)
enemy_health -= 1
for bullet in bullets:
if bullet[1] < 0:
bullets.remove(bullet)
if background1_rect.y >= 1000:
background1_rect.topleft = (0, -1000)
if background2_rect.y >= 1000:
background2_rect.topleft = (0, -1000)
if enemy_health <= 0:
pass
pygame.display.update()
clock.tick(60)
Any help would be appreciated. :) Thanks!
The text is rendered in the enemy_health_text Surface with the value of enemy_health. You have to change enemy_health and render the text again:
font = pygame.font.Font(None, 55)
enemy_health_text = font.render(f'Enemy Health: {enemy_health}', False, 'white')
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
enemy_health -= 1
enemy_health_text = font.render(f'Enemy Health: {enemy_health}', False, 'white')
win.fill(0)
win.blit(enemy_health_text, (350, 60)
pygame.display.flip()

Python PyGame Restart

so i was learning python and i finished the game and everything is working but now i have no idea about how to restart the game i mean when it ends what is next? how to start again
i will put a link for my full code and here is what have done so far.
Thank you so much!
if Bullet_state is "fire":
fire(BulletX, BulletY)
BulletY -= Bullet_MovementY
player(playerX, playerY)
score(textX, textY)
pygame.display.update()
For the restart logic, keep the current game loop but add a flag to indicate that the game has ended. In the loop, check for this flag and display the restart prompt if the flag is set. Also encapsulate the initialization process in a function so it can be called at each restart.
Note that I tested this in Python 3.8.
Try this code. When the score reaches 3, the game ends and the restart prompt is displayed.
import pygame
import random
import math
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Space Invadors')
icon = pygame.image.load('1.png')
pygame.display.set_icon(icon)
#Background
Background = pygame.image.load('background.png')
def SetGameStart(): # initialize variables
global Player_Image,playerX,playerY,Key_Movement,Enemy_Image,EnemyX,EnemyY,Enemy_MovementX,Enemy_MovementY
global Bullet_Image,BulletX,BulletY,Bullet_MovementX,Bullet_MovementY,Bullet_state,Score
# Player
Player_Image = pygame.image.load('player.png')
playerX = 370
playerY = 480
Key_Movement = 0
# Enemy
Enemy_Image = pygame.image.load('monster2.png')
EnemyX = random.randint(0, 735)
EnemyY = random.randint(50, 150)
Enemy_MovementX = 1.5
Enemy_MovementY = 40
# Bullet
Bullet_Image = pygame.image.load('bullet.png')
BulletX = 0
BulletY = 480
Bullet_MovementX = 0
Bullet_MovementY = 10
Bullet_state = "Ready"
Score = 0
def Fire(x, y):
global Bullet_state
Bullet_state = "Fire"
screen.blit(Bullet_Image, (x + 16, y + 10))
def player(x, y):
# blit is draw! draw an image on the screen
screen.blit(Player_Image, (x, y))
def Enemy(x, y):
screen.blit(Enemy_Image, (x, y))
def is_Collided(BulletX, BulletY, EnemyX, EnemyY):
distance = math.sqrt(math.pow(BulletX - EnemyX, 2) + math.pow(BulletY - EnemyY, 2))
if distance < 27:
return True
else:
return False
SetGameStart() # initialize variables
GameDone = False
def text_objects(text, font):
textSurface = font.render(text, True, (0,200,0))
return textSurface, textSurface.get_rect()
Close = True
while Close:
screen.fill((0, 0, 0))
screen.blit(Background, (0, 0))
if GameDone: # pause game loop, show restart prompt
largeText = pygame.font.SysFont("comicsansms",20)
TextSurf, TextRect = text_objects("Game Over. Press Space to restart.", largeText)
TextRect.center = ((800/2),(600/2))
screen.blit(TextSurf, TextRect)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
Close = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q: # press Q to quit
Close = False
break
if event.key == pygame.K_SPACE: # press space to restart
GameDone = False
SetGameStart() # initialize variables
continue # skip game process
for event in pygame.event.get():
if event.type == pygame.QUIT:
Close = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
Key_Movement = -4
if event.key == pygame.K_RIGHT:
Key_Movement = 4
if event.key == pygame.K_SPACE:
# to fix the Pressing on space will reload the Bullet
if Bullet_state is "Ready":
BulletX = playerX
Fire(BulletX, playerY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
Key_Movement = 0
playerX += Key_Movement
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy movement limit
EnemyX += Enemy_MovementX
if EnemyX <= 0:
Enemy_MovementX = 1.5
EnemyY += Enemy_MovementY
elif EnemyX >= 736:
Enemy_MovementX = -1.5
EnemyY += Enemy_MovementY
if BulletY <= 0:
BulletY = 480
Bullet_state = "Ready"
if Bullet_state is "Fire":
Fire(BulletX, BulletY)
BulletY -= Bullet_MovementY
Collision = is_Collided(EnemyX, EnemyY, BulletX, BulletY)
if Collision:
BulletY = 480
Bullet_state = "Ready"
Score += 1
print(Score)
EnemyX = random.randint(0, 735)
EnemyY = random.randint(50, 150)
Enemy(EnemyX, EnemyY)
player(playerX, playerY)
pygame.display.update()
if Score == 3:
GameDone = True
Prompt

How do i add lives into this python 3.0 game

I am quite new to python just trying to learn it. I've followed a tutorial on how to make this game and added my own stuff but I cant seem to add lives. I've tried all I know (not a lot). Anyway, all the tutorials I have watched have not worked either and I have been pulling my hair out over it for like 2 days now, so if anyone can help it would be very appreciated.
import math
import random
import pygame
from pygame import mixer
# Intialize the pygame
pygame.init( )
# create the screen
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('editor.jpg')
opensound = mixer.Sound("ftw.wav")
opensound.play( )
# Sound
mixer.music.load("bg noise.wav")
mixer.music.play(-1)
# Caption and Icon
pygame.display.set_caption("Virus Invader")
icon = pygame.image.load('virus.png')
pygame.display.set_icon(icon)
# Player
playerImg = pygame.image.load('people.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('virus.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyX_change.append(1)
enemyY_change.append(40)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bulletImg = pygame.image.load('ligature.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 2
bullet_state = "ready"
# Score
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
testY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
def Game_start_text():
over_text = over_font.render("Let the games begin!", True, (64, 64, 64))
screen.blit(over_text, (200, 250))
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 16, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX - bulletX, 2) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get( ):
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check if its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
if event.key == pygame.K_RIGHT:
playerX_change = 2
if event.key == pygame.K_SPACE:
if bullet_state is "ready":
bulletSound = mixer.Sound("stab.wav")
bulletSound.play( )
# Get the current x cordinate of the charctar
bulletX = playerX
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy Movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text( )
break
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 1
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 736:
enemyX_change[i] = -1
enemyY[i] += enemyY_change[i]
# Collision
collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
explosionSound = mixer.Sound("street fighter die.wav")
explosionSound.play( )
bulletY = 480
bullet_state = "ready"
score_value += 1
enemyX[i] = random.randint(0, 736)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state is "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(textX, testY)
pygame.display.update( )
The reason adding this to your code is so difficult is because there's a whole bunch of extra code that's in the way.
When this happens, take a step back, and try to write a skeleton to do just what you need. When working on a huge system, say tracking down a complex bug, normally you would comment out sections of the code to pair the problem-space back to something manageable. Your code is pretty small, so maybe you can just ignore a lot of it.
In any event, take a backup of your code, then start adding the changes bit by bit, testing as you go.
First add a life-counter:
# Player
playerLives = 3 # <<-- HERE
playerImg = pygame.image.load('people.png')
playerX = 370
playerY = 480
playerX_change = 0
Then some way to test life-loss:
# if keystroke is pressed check if its right or left
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -2
elif event.key == pygame.K_RIGHT:
playerX_change = 2
elif event.key == pygame.K_d: # TEST CODE - Die on 'd' <<-- HERE
print( "Player Dies" )
playerLives -= 1
Now test this? Did it print "Player Dies" when you press d?
So... what should happen when the lives is zero? Maybe the player can't move any more:
# Has the player run out of lives?
if ( playerLives <= 0 ):
game_over_text()
else:
# Player still alive, allow controls, draw player
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
player(playerX, playerY)
Add these next changes in, test them. Does pressing d three times print "Player Dies" every time, and result in the game_over_text() function being called?
Then change the show_score() function to also draw the lives left:
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
# Write the Lives-left to the right of the score
lives = font.render("Lives : " + str(playerLives), True, (255, 255, 255))
screen.blit(lives, (x+200, y))
Test that. Does the on-screen score work? No? Make some small changes, test again, keep tweaking, keep fixing. If it all goes to hell-in-a-handcart you only need small changes to undo it.
Now that the losing-lives mechanism is working, find where it should actually take away lives, and add the changes in:
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
playerLives -= 1 # <<-- lose a life
#game_over_text( )
reset_enemy_positions() # <<-- move enemies back to top, TODO!
break
Of course if you leave your enemies below line 440, the lose-a-life condition is still true. Thus the player will continue to lose many lives per second, every frame update. The enemies need to move back to start-position (or some suchlike).
Anyway I hope this gives you a nudge in the right direction. Maybe it would help you to try to write something yourself from scratch. Even just opening a window. Then adding key handling. Then drawing something... Incrementally add to your knowledge, I think you'll learn much faster this way. There's a reason every programming book starts with "Hello World".

Python Snake Tutorial, Tail/Speed

I am trying to add a tail to my snake (at the very end use a triangle image rather than a square fill). While I think I got the code to work for the most part, I was seeing that if I changed directions, the last few seconds the tail would "disconnect" from the body. (tail points right and body going down leaves a gap). I tried to fix this by upping my FPS which seemed to work; however I wanted the snake speed to be the same as before and since I doubled the FPS I would have to 1/2 the speed. When I did that however, my collision detection was out of sync and if I slowed it down my body would draw over my face, and if I sped up I would have my body getting disconnected (block, space, block). I have tried it a few different ways so any help would be appreciated.
Please note that block_speed = 10, and if I manually type 10 it works, but if I change to 5 or 20, or if I change to a variable with value of 5 or 20 (say speed for example), the code does not work.
Code:
import pygame, sys
from pygame.locals import*
import time
import random
import os
pygame.init()
#GUI Settings
display_Width = 800
display_Height = 600
gameDisplay = pygame.display.set_mode((display_Width,display_Height))
pygame.display.set_caption("Gluttonous Snake")
gameicon = pygame.image.load('icon.png')
potatoimg = pygame.image.load('potato.png')
pygame.display.set_icon(gameicon)
FPS = 15
direction = "up"
#set path to where to .py/.exe is
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
print(dname)
snakeheadimg = pygame.image.load('snakehead.png')
snaketailimg = pygame.image.load('snaketail.png')
appleimg = pygame.image.load('apple.png')
#define colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
yellow = (255,255,0)
eggwhite = (255,255,204)
lightgrey = (242,242,242)
#Game Variables
block_size = 10
clock = pygame.time.Clock()
def game_intro():
intro = True
x = 500
y = 400
x_dir = "left"
while intro:
gameDisplay.fill(eggwhite)
gameDisplay.blit(potatoimg, (50, 25))
message_to_screen("Potato Productions Presents...", black, -100, size=45)
message_to_screen("Gluttonous Snake", green, -25, size=75)
message_to_screen("A game made by a potato to run on a potato", black, 50, size=25)
message_to_screen("Press C to Start!", red, 75, size=25)
gameDisplay.blit(gameicon, (x, y))
if x_dir == "left":
if x > 0:
x -= 10
else:
x_dir = "right"
else:
if x < 500:
x += 10
else:
x_dir = "left"
if x < 125 or x > 375:
y -= 9.66
else:
y += 10
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
intro = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key == pygame.K_q:
pygame.quit()
quit()
def pickFont(name,size):
font = pygame.font.SysFont(name, size, bold=False)
return font
#font size = 25
#font = pygame.font.SysFont("comicsansms",size=25)
def snake(snakelist):
# faster GPU method is
# gameDisplay.fill(red, rect=[200,200,50,50])
if direction == "left":
head = pygame.transform.rotate(snakeheadimg,90)
if direction == "right":
head = pygame.transform.rotate(snakeheadimg,270)
if direction == "down":
head = pygame.transform.rotate(snakeheadimg,180)
if direction == "up":
head = pygame.transform.rotate(snakeheadimg,0)
gameDisplay.blit(head,(snakelist[-1][0],snakelist[-1][1]))
#-1 because we are drawing that above
# for XnY in snakelist[:-1]:
# #gameDisplay.fill(green, rect=[lead_x, lead_y, block_size, block_size])
# gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])
# -1 because we are drawing that above
if len(snakelist) >= 2:
for XnY in snakelist[1:-1]:
gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])
if direction == "up":
tail = pygame.transform.rotate(snaketailimg, 180)
if snakelist[1][0] > snakelist[0][0]:
tail = pygame.transform.rotate(snaketailimg, 90)
elif snakelist[1][0] < snakelist[0][0]:
tail = pygame.transform.rotate(snaketailimg, 270)
elif snakelist[1][1] > snakelist[0][1]:
tail = pygame.transform.rotate(snaketailimg, 0)
elif snakelist[1][1] < snakelist[0][1]:
tail = pygame.transform.rotate(snaketailimg, 180)
gameDisplay.blit(tail, (snakelist[-len(snakelist)][0], snakelist[-len(snakelist)][1]))
def text_objects(text, color,size):
font = pickFont("comicsansms", size)
textSurface = font.render(text,True,color,size)
return textSurface, textSurface.get_rect()
def message_to_screen(msg,color,y_displace=0, size=25):
#True is anti-aliasing
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (display_Width/2),(display_Height/2) + y_displace
gameDisplay.blit(textSurf,textRect)
def gameLoop():
# set up variables
global direction
gameExit = False
gameOver = False
lead_x = display_Width / 2
lead_y = display_Height / 2
coinflip = random.randint(0, 1)
if coinflip == 0:
coinflip = random.randint(0, 1)
if coinflip == 0:
lead_x_change = **10**
lead_y_change = 0
direction = "right"
else:
lead_x_change = -**10**
lead_y_change = 0
direction = "left"
else:
coinflip = random.randint(0, 1)
if coinflip == 0:
lead_x_change = 0
lead_y_change = **10**
direction = "down"
else:
lead_x_change = 0
lead_y_change = -**10**
direction = "up"
#lead_x_change = 0
#lead_y_change = 0
#the 10 is round to 10
randAppleX = random.randrange(0, display_Width - block_size, 10)
randAppleY = random.randrange(0, display_Height - block_size, 10)
snakelist = []
snakelength = 1
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
#message_to_screen("Game over \n Press C to play again or Q to quit", red)
message_to_screen("Game Over", red, y_displace=-50, size=75)
message_to_screen("Press C to play again or Q to quit",black,y_displace=50,size=25)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
#gameOver = False
for event in pygame.event.get():
#shows every mouse move and key pressed
#print(event)
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
#check for single depress of keys
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
#lead_x -= 10
#this is so they can't back over themselves
if lead_x_change != **block_size**:
lead_x_change = - **block_size**
lead_y_change = 0
direction = "left"
#elif is only tested if the ifs and elifs above it are not true
elif event.key == pygame.K_RIGHT:
#lead_x += 10
if lead_x_change != -**block_size**:
lead_x_change = **block_size**
lead_y_change = 0
direction = "right"
elif event.key == pygame.K_UP:
if lead_y_change != **block_size**:
lead_x_change = 0
lead_y_change = -**block_size**
direction = "up"
elif event.key == pygame.K_DOWN:
if lead_y_change != -**block_size**:
lead_x_change = 0
lead_y_change = **block_size**
direction = "down"
# user releases key
# if event.type == pygame.KEYUP:
# if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
# lead_x_change = 0
#Ends the game once the square has left the window
if lead_x >= (display_Width - block_size) or lead_x <= 0 or lead_y >= (display_Height - block_size) or lead_y <= 0:
print("snake left at " + str(lead_x)+","+str(lead_y))
lead_x_change = 0
lead_y_change = 0
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(lightgrey)
snakehead = []
snakehead.append(lead_x)
snakehead.append(lead_y)
snakelist.append(snakehead)
if len(snakelist) > snakelength:
del snakelist[0]
#-1 because last element is the head
for eachSegement in snakelist[:-1]:
if eachSegement == snakehead:
print("snake eats itself")
gameOver = True
#draw snake first so if apple spawns on it I can still see it
snake(snakelist)
#gameDisplay.fill(red, rect=[randAppleX, randAppleY, block_size, block_size])
gameDisplay.blit(appleimg,(randAppleX, randAppleY))
pygame.display.update()
#better collison detection as part of the snake can go over part of the apple
# if lead_x >= randAppleX and lead_x + block_size < randAppleX + block_size or lead_x + block_size >= randAppleX and lead_x + block_size < randAppleX + block_size:
# if lead_y >= randAppleY and lead_y < randAppleY + block_size or lead_y + block_size >= randAppleY and lead_y + block_size < randAppleY + block_size:
if lead_x >= randAppleX:
if lead_x + block_size <= randAppleX + block_size:
if lead_y >= randAppleY:
if lead_y + block_size <= randAppleY + block_size:
print("nom nom nom")
randAppleX = random.randrange(0, display_Width - block_size, 10)
randAppleY = random.randrange(0, display_Height - block_size, 10)
snakelength += 1
#used to make FPS
clock.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
Reply to answer provided:
Great thanks I will look into this. Were you able to figure out why I can't adjust the speed though? Seems weird it would draw the body over the head if I slow down the speed, or it will leave gaps if I speed it up. The part were I was adjusting the speed was in bold
You can probably smooth things a bit (and make your code clearer) by doing the following:
1 - store the tail (head) rotated images:
tail_left = pygame.transform.rotate(snaketailimg, 180) # choose appropriate rotation
tail_right = ...
tail_up = ...
tail_down = ...
2 - determine which direction the snake goes, and look up the images from a dict (for instance)
tail_oriented_images = {'left': tail_left, 'right': tail_right, ...}
...
tail_direction = get_tail_direction() # to be extracted
3- then replace the if cascade in snake(snakelist) with:
tail = tail_oriented_images[tail_direction]
4- Do the same for the head direction

Why does my game crash in PYGAME every time I try to shoot

I am making a 2 player fighting game and whenever I try and press "v" the, the key to shoot my game seems to crash and not work. I am new to pygame and I am learning as I go. Any help is appreciated. Thanks!
import pygame
pygame.init()
#Sets up 8 bit colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
lightblue = (180,235,255)
grassgreen =(20,200,50)
#Sets up pygame window
gameDisplay = pygame.display.set_mode((1000,600))
pygame.display.set_caption('Block Fighter')
#Variables
gameExit = False
x = 0
y = 0
x_change = 0
y_change = 0
isShooting = False
clock = pygame.time.Clock()
class Player:
def __init__(self, x_change, y_change, x, y):
self.x_change = 0
self.y_change = 0
self.x= 50
self.y= 480
def Left(self, x_change):
self.x_change = -5
def Right(self, x_change):
self.x_change =5
def Jump(self, y_change):
if (self.y == 480):
self.y_change = -70
return
p1 = Player(x_change, y_change, x, y)
class Bullet:
def __init__(self, x, y, Player, x_change):
self.x = p1.x
self.y = p1.y
self.x_change = 0
def Show(self, x_change, x , y, Player ):
pygame.draw.rect(gameDisplay, black , [p1.x,p1.y,5,5])
self.x_change = 10
b1 = Bullet(x, y, Player, x_change)
#Main Game Loop
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
p1.Left(x_change)
if event.key == pygame.K_d:
p1.Right(x_change)
if event.key == pygame.K_w:
p1.Jump(y_change)
if event.key == pygame.K_v:
b1.Show(x, y, x_change, Player)
isShooting = True
while isShooting:
pygame.draw.rect(gameDisplay, black, [b1.x, b1.y , 5,5])
if b1.x > 1000:
pass
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
p1.x_change = 0
if p1.x <= 0:
p1.x = 0
if p1.x >= 500:
p1.x = 500
if p1.y > 480:
p1.y_change = 0
p1.y = 480
if p1.y < 480:
p1.y_change = 5
p1.x += p1.x_change
p1.y += p1.y_change
b1.x += b1.x_change
gameDisplay.fill(lightblue)
pygame.draw.rect(gameDisplay, grassgreen, [1000,600,-1000,-100])
pygame.draw.rect(gameDisplay, red, [p1.x,p1.y,20,20])
pygame.display.update()
clock.tick(40)
pygame.quit()
quit()
It looks like once isShooting is set to True, the program gets stuck in the while loop (while isShooting:). It seems like you need a condition in the while loop to set isShooting back to False if a certain conditions is met, for example, if the v key is released.
Just get rid of the while loop. while isShooting should be removed. The player should shoot at most one time per game loop - any more than that and they won't be able to see the effects of them firing. Plus, you create an infinite loop.
On another note, welcome to Stack Overflow! If you haven't yet, check out the tour here.

Categories