I made a game on python pygame similar to space invaders but instead the aliens shoot at you. So if I manage to get hit by an alien. The game is over, I have two options, Menu, and quit. If I quit and try to play again it says game over AGAIN right after I click play. Any help would be appreciated.
I know its because when the game is over, and I restart my game again, the spaceship spawns again back where it was when it died. And I don't know how to fix that.
import sys
from pygame import *
from math import *
from random import *
import random
import math
init()
display_width = 1000
display_height = 700
shipx = 350
shipy = 550
asteroids=[]
astroidX=randint(0,800)
astroidY=randint(50,500)
astroidY_change=0
alien=[]
aliencounter=0
enemy_y =0
enemy_x=0
alienbullets=[]
w=[0,5]
gameDisplay = display.set_mode((display_width,display_height))
screen=display.set_mode((1000,700))
white = (255,255,255)
black = (0,0,0)
red = (200,0,0)
light_red = (255,0,0)
yellow = (200,200,0)
light_yellow = (255,255,0)
green = (34,177,76)
light_green = (0,255,0)
blue = (0,0,255)
clock = time.Clock()
explosion_sound = mixer.Sound('./sounds/boom.wav')
bullet_sound = mixer.Sound('./sounds/shot1.wav')
bg_sound = mixer.Sound('./sounds/bgmusic1.ogg')
smallfont = font.SysFont("comicsansms", 25)
medfont = font.SysFont("comicsansms", 50)
largefont = font.SysFont("comicsansms", 85)
xlargefont = font.SysFont("Girassol", 100)
textx = 10
texty = 10
bg_imgs = ['./image/bg_big.png',
'./image/seamless_space.png',
'./image/space3.jpg']
bg_move_dis = 0
bg_1 = image.load(bg_imgs[0]).convert()
bg_2 = image.load(bg_imgs[1]).convert()
bg_3 = image.load(bg_imgs[2]).convert()
Score_1 = 200
Score_2 = 200
if (Score_1 + Score_2) < 500:
background = bg_1
elif (Score_1 + Score_2) < 1500:
background = bg_2
else:
background = bg_3
v=[0,-5]#horiz and vertical speed of the bullet
#print(ets)
bullets=[]#empty list for bullets
astroid=image.load("image/meteorBrown_med1.png").convert_alpha()
alienspaceship=image.load("image/ufo.png").convert_alpha()
def show_score(x,y):
score = smallfont.render("Score : " + str(score_value), True, light_yellow)
screen.blit(score,(x,y))
def show_lives(x,y):
lives = smallfont.render("Lives : " + str(livesr), True, light_yellow)
screen.blit(lives,(x,y))
def text_objects(text, color,size = "small"):
if size == "small":
textSurface = smallfont.render(text, True, color)
if size == "medium":
textSurface = medfont.render(text, True, color)
if size == "large":
textSurface = largefont.render(text, True, color)
if size == "xlarge":
textSurface = xlargefont.render(text, True, color)
return textSurface, textSurface.get_rect()
def text_to_button(msg, color, buttonx, buttony, buttonwidth, buttonheight, size = "small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = ((buttonx+(buttonwidth/2)), buttony+(buttonheight/2))
gameDisplay.blit(textSurf, textRect)
def message_to_screen(msg,color, y_displace = 0, size = "small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = (int(display_width / 2), int(display_height / 2)+y_displace)
gameDisplay.blit(textSurf, textRect)
def button(text, x, y, width, height, inactive_color, active_color, action = None):
cur = mouse.get_pos()
click = mouse.get_pressed()
#print(click)
if x + width > cur[0] > x and y + height > cur[1] > y:
draw.rect(gameDisplay, active_color, (x,y,width,height))
if click[0] == 1 and action != None:
if action == "Quit":
quit()
if action == "Play":
play()
if action == "Controls":
control_menu()
if action == "Back":
game_intro()
else:
draw.rect(gameDisplay, inactive_color, (x,y,width,height))
text_to_button(text,black,x,y,width,height)
def game_intro():
menu_1 = image.load('./image/menubackground.jpg')
gameDisplay.blit(menu_1,(0,0))
intro = True
while intro:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
if evt.type == KEYDOWN:
if evt.key == K_c:
intro = False
elif evt.key == K_q:
quit()
message_to_screen("Space Heroes!",green,-210,size="xlarge")
message_to_screen("The objective is to shoot and destroy",white,-30)
message_to_screen("the enemy ships before they destroy you.",white,10)
message_to_screen("Defeat all of them to advance to next level!.",white,50)
message_to_screen("By Wafi Hassan",blue, 110)
button("Play", 230,500,100,50, green, light_green, action="Play")
button("Controls", 430,500,100,50, yellow, light_yellow, action="Controls")
button("Quit", 630,500,100,50, red, light_red, action ="Quit")
display.update()
clock.tick(15)
def control_menu():
menu_1 = image.load('./image/menubackground.jpg')
gameDisplay.blit(menu_1,(0,0))
intro = True
while intro:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
if evt.type == KEYDOWN:
if evt.key == K_c:
intro = False
elif evt.key == K_q:
quit()
message_to_screen("Controls",blue,-210,size="large")
message_to_screen("SPACE - SHOOT",white,-30)
message_to_screen("W-A-S-D - up, down, left, right movement",white,10)
button("Back", 550,500,100,50, red, light_red, action ="Back")
display.update()
clock.tick(15)
def game_over():
bg_sound.stop()
menu_1 = image.load('./image/gameover.jpg').convert()
gameDisplay.blit(menu_1,(0,0))
gameover = True
while gameover:
for evt in event.get():
if evt.type == QUIT:
quit()
button("QUIT", 550,500,100,50, red, light_red, action ="Quit")
button("MENU", 310,500,100,50, red, light_red, action ="Back")
display.update()
clock.tick(15)
def play():
display_width = 1000
display_height = 700
screen=display.set_mode((display_width,display_height))
running=True
y=0
while running:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
exit()
if evt.type == KEYDOWN:
if evt.key == K_e:
gameLoop()
rel_y = y % bg_3.get_rect().width
screen.blit(bg_3,(0,rel_y - bg_3.get_rect().width))
if rel_y < 600:
screen.blit(bg_3,(0,rel_y))
y +=1
message_to_screen("Attention, Fighter! ",blue,-300,size="medium")
message_to_screen("You have been summoned by our government to protect our planet Kiblar.",white,-210)
message_to_screen("We are being attacked by incoming enemies from the planet Noxus.",white,-170)
message_to_screen("You are our only defender left, protect us at all costs!",white,-130)
message_to_screen("Intelligence reports that there are 2 waves of enemies.",white,-90)
message_to_screen("After you eliminate them all, they will send their mothership Dengrau.",white,-50)
message_to_screen("Killing Dengrau will save our existence on galaxy 1029 from the rival planet Noxus.",white,-10)
message_to_screen("ARE YOU READY TO TAKE THIS CHALLENGE?!",white,130)
message_to_screen("CLICK [E] TO START!",red,190)
display.update()
myclock.tick(120)
quit()
##def enemy_generate():
##
## for i in range(5):
## asteroids.append((randint(50 ,800),randint(0,100)))
##
def drawScene(screen,sx,sy,bull,alienbull,alien,asteroids):
lee=image.load("image/laserRed16.png").convert_alpha()
bt=image.load("image/missile.png").convert_alpha()
spaceship=image.load("image/ship.png").convert_alpha()
screen.blit(spaceship,[sx,sy])
for b in bull:
screen.blit(bt,(b[0],b[1]))#drawing the bullets
for en in alien:
screen.blit(alienspaceship,(en[0],en[1]))
for a in asteroids:
screen.blit(astroid,(a[0] ,(a[1] + astroidY_change)))
for eb in alienbull:
screen.blit(lee,(eb[0],eb[1]))#drawing the bullets
display.update()
score_value=0
lives=3
def checkHits(bull,targ):
global score_value
for b in bull:# go through each bullet
## for a in astero:
## aliendistance = math.sqrt((math.pow(b[0]-a[0],2)) + (math.pow(b[1]-a[1],2)))
## if aliendistance < 50:
## asteroids.remove(a)
## bull.remove(b)
## explosion_sound.play()
## score_value+=1
## break
for t in targ: #go through each target
distance = math.sqrt((math.pow(b[0]-t[0],2)) + (math.pow(b[1]-t[1],2)))
if distance < 30:
targ.remove(t)#removes the target
bull.remove(b)#removes the bullet
explosion_sound.play()
score_value += 1
if score_value==10:
next_level()
break
livesr=3
def checkalienbullets(alienbull):
global livesr
global score_value
for a in alienbull:
alienbdistance=math.sqrt((math.pow(a[0]-shipx,2)) + (math.pow(a[1]-shipy,2)))
if alienbdistance<40:
livesr-=3
print(livesr)
if livesr<=0:
game_over()
def moveBullets(bull):
for b in bull:
b[0]+=b[2]
b[1]+=b[3]
if b[1]>700:#off-screen
bull.remove(b)
def move_alien_bull(ebull):
for e in ebull:
e[0]+=e[2]
e[1]+=e[3]
if e[1]>700:#off-screen
ebull.remove(e)
def next_level():
if random.randrange(0,6*40) == 1:
aliencounter+=1
x= randint(50,700)
y= randint(0,100)
alien.append([x,y])
alienbullets.append([x,y,w[0],w[1]])
myclock=time.Clock()
##y=0
##enemy_generate()
def gameLoop():
livesr=3
bg_sound.play(-1)
rapidbullet=20
y=0
score=0
ship_x =0
ship_y=0
global shipx
global shipy
global aliencounter
global astroidY
global astroidY_change
global enemy_y
global alien
## global livesr
direction= None
running=True
function=True
while running:
astroidY_change += .5
#enemy_y += 0
#global alienbullets
for evt in event.get():
if evt.type==QUIT:
running=False
quit()
if evt.type==KEYDOWN:
if evt.key == K_LEFT:
ship_x = -2.5
if evt.key == K_RIGHT:
ship_x = 2.5
## if evt.key == K_UP:
## ship_y = -2
## if evt.key == K_DOWN:
## ship_y = 2
if evt.type==KEYUP:
if evt.key == K_LEFT or evt.key == K_RIGHT:
ship_x = 0
## ship_y = 0
shipx += ship_x
## shipy += ship_y
if shipx <= 0:
shipx = 0
elif shipx >= 900:
shipx = 900
## if shipy <= 0:
## shipy = 0
## elif shipy >= 650:
## shipy = 650
# astroid Movement
astroidY += astroidY_change
if astroidY_change >=650:
astroidY_change =0
if rapidbullet<20:
rapidbullet+=1
keys=key.get_pressed()
if keys[32] and rapidbullet==20:#32 is the space key
bullet_sound.play()
bullets.append([shipx,shipy,v[0],v[1]])
rapidbullet=0
while function:
if random.randrange(0,6*40) == 1:
aliencounter+=1
x= randint(50,700)
y= randint(0,100)
alien.append([x,y])
alienbullets.append([x,y,w[0],w[1]])
if aliencounter==10:
function=False
rel_y = y % bg_3.get_rect().width
screen.blit(bg_3,(0,rel_y - bg_3.get_rect().width))
if rel_y < 700:
screen.blit(bg_3,(0,rel_y))
y +=1
if enemy_y >= 600:
enemy_y = 0
show_score(textx,texty)
show_lives(10,40)
moveBullets(bullets)
move_alien_bull(alienbullets)
checkHits(bullets,alien)
checkalienbullets(alienbullets)
drawScene(screen,shipx,shipy,bullets,alienbullets,alien,asteroids)
display.update()
myclock.tick(120)
quit()
game_intro()
You can call your introductory position setup for the spaceship when you start the game, like this:
import sys
from pygame import *
from math import *
from random import *
import random
import math
init()
display_width = 1000
display_height = 700
shipx = 350
shipy = 550
asteroids=[]
astroidX=randint(0,800)
astroidY=randint(50,500)
astroidY_change=0
alien=[]
aliencounter=0
enemy_y =0
enemy_x=0
alienbullets=[]
w=[0,5]
gameDisplay = display.set_mode((display_width,display_height))
screen=display.set_mode((1000,700))
white = (255,255,255)
black = (0,0,0)
red = (200,0,0)
light_red = (255,0,0)
yellow = (200,200,0)
light_yellow = (255,255,0)
green = (34,177,76)
light_green = (0,255,0)
blue = (0,0,255)
clock = time.Clock()
explosion_sound = mixer.Sound('./sounds/boom.wav')
bullet_sound = mixer.Sound('./sounds/shot1.wav')
bg_sound = mixer.Sound('./sounds/bgmusic1.ogg')
smallfont = font.SysFont("comicsansms", 25)
medfont = font.SysFont("comicsansms", 50)
largefont = font.SysFont("comicsansms", 85)
xlargefont = font.SysFont("Girassol", 100)
textx = 10
texty = 10
bg_imgs = ['./image/bg_big.png',
'./image/seamless_space.png',
'./image/space3.jpg']
bg_move_dis = 0
bg_1 = image.load(bg_imgs[0]).convert()
bg_2 = image.load(bg_imgs[1]).convert()
bg_3 = image.load(bg_imgs[2]).convert()
Score_1 = 200
Score_2 = 200
if (Score_1 + Score_2) < 500:
background = bg_1
elif (Score_1 + Score_2) < 1500:
background = bg_2
else:
background = bg_3
v=[0,-5]#horiz and vertical speed of the bullet
#print(ets)
bullets=[]#empty list for bullets
astroid=image.load("image/meteorBrown_med1.png").convert_alpha()
alienspaceship=image.load("image/ufo.png").convert_alpha()
def show_score(x,y):
score = smallfont.render("Score : " + str(score_value), True, light_yellow)
screen.blit(score,(x,y))
def show_lives(x,y):
lives = smallfont.render("Lives : " + str(livesr), True, light_yellow)
screen.blit(lives,(x,y))
def text_objects(text, color,size = "small"):
if size == "small":
textSurface = smallfont.render(text, True, color)
if size == "medium":
textSurface = medfont.render(text, True, color)
if size == "large":
textSurface = largefont.render(text, True, color)
if size == "xlarge":
textSurface = xlargefont.render(text, True, color)
return textSurface, textSurface.get_rect()
def text_to_button(msg, color, buttonx, buttony, buttonwidth, buttonheight, size = "small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = ((buttonx+(buttonwidth/2)), buttony+(buttonheight/2))
gameDisplay.blit(textSurf, textRect)
def message_to_screen(msg,color, y_displace = 0, size = "small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = (int(display_width / 2), int(display_height / 2)+y_displace)
gameDisplay.blit(textSurf, textRect)
def button(text, x, y, width, height, inactive_color, active_color, action = None):
cur = mouse.get_pos()
click = mouse.get_pressed()
#print(click)
if x + width > cur[0] > x and y + height > cur[1] > y:
draw.rect(gameDisplay, active_color, (x,y,width,height))
if click[0] == 1 and action != None:
if action == "Quit":
quit()
if action == "Play":
play()
if action == "Controls":
control_menu()
if action == "Back":
game_intro()
else:
draw.rect(gameDisplay, inactive_color, (x,y,width,height))
text_to_button(text,black,x,y,width,height)
def game_intro():
shipx = 350
shipy = 550
menu_1 = image.load('./image/menubackground.jpg')
gameDisplay.blit(menu_1,(0,0))
intro = True
while intro:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
if evt.type == KEYDOWN:
if evt.key == K_c:
intro = False
elif evt.key == K_q:
quit()
message_to_screen("Space Heroes!",green,-210,size="xlarge")
message_to_screen("The objective is to shoot and destroy",white,-30)
message_to_screen("the enemy ships before they destroy you.",white,10)
message_to_screen("Defeat all of them to advance to next level!.",white,50)
message_to_screen("By Wafi Hassan",blue, 110)
button("Play", 230,500,100,50, green, light_green, action="Play")
button("Controls", 430,500,100,50, yellow, light_yellow, action="Controls")
button("Quit", 630,500,100,50, red, light_red, action ="Quit")
display.update()
clock.tick(15)
def control_menu():
menu_1 = image.load('./image/menubackground.jpg')
gameDisplay.blit(menu_1,(0,0))
intro = True
while intro:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
if evt.type == KEYDOWN:
if evt.key == K_c:
intro = False
elif evt.key == K_q:
quit()
message_to_screen("Controls",blue,-210,size="large")
message_to_screen("SPACE - SHOOT",white,-30)
message_to_screen("W-A-S-D - up, down, left, right movement",white,10)
button("Back", 550,500,100,50, red, light_red, action ="Back")
display.update()
clock.tick(15)
def game_over():
bg_sound.stop()
menu_1 = image.load('./image/gameover.jpg').convert()
gameDisplay.blit(menu_1,(0,0))
gameover = True
while gameover:
for evt in event.get():
if evt.type == QUIT:
quit()
button("QUIT", 550,500,100,50, red, light_red, action ="Quit")
button("MENU", 310,500,100,50, red, light_red, action ="Back")
display.update()
clock.tick(15)
def play():
display_width = 1000
display_height = 700
screen=display.set_mode((display_width,display_height))
running=True
y=0
while running:
for evt in event.get():
#print(event)
if evt.type == QUIT:
quit()
exit()
if evt.type == KEYDOWN:
if evt.key == K_e:
gameLoop()
rel_y = y % bg_3.get_rect().width
screen.blit(bg_3,(0,rel_y - bg_3.get_rect().width))
if rel_y < 600:
screen.blit(bg_3,(0,rel_y))
y +=1
message_to_screen("Attention, Fighter! ",blue,-300,size="medium")
message_to_screen("You have been summoned by our government to protect our planet Kiblar.",white,-210)
message_to_screen("We are being attacked by incoming enemies from the planet Noxus.",white,-170)
message_to_screen("You are our only defender left, protect us at all costs!",white,-130)
message_to_screen("Intelligence reports that there are 2 waves of enemies.",white,-90)
message_to_screen("After you eliminate them all, they will send their mothership Dengrau.",white,-50)
message_to_screen("Killing Dengrau will save our existence on galaxy 1029 from the rival planet Noxus.",white,-10)
message_to_screen("ARE YOU READY TO TAKE THIS CHALLENGE?!",white,130)
message_to_screen("CLICK [E] TO START!",red,190)
display.update()
myclock.tick(120)
quit()
##def enemy_generate():
##
## for i in range(5):
## asteroids.append((randint(50 ,800),randint(0,100)))
##
def drawScene(screen,sx,sy,bull,alienbull,alien,asteroids):
lee=image.load("image/laserRed16.png").convert_alpha()
bt=image.load("image/missile.png").convert_alpha()
spaceship=image.load("image/ship.png").convert_alpha()
screen.blit(spaceship,[sx,sy])
for b in bull:
screen.blit(bt,(b[0],b[1]))#drawing the bullets
for en in alien:
screen.blit(alienspaceship,(en[0],en[1]))
for a in asteroids:
screen.blit(astroid,(a[0] ,(a[1] + astroidY_change)))
for eb in alienbull:
screen.blit(lee,(eb[0],eb[1]))#drawing the bullets
display.update()
score_value=0
lives=3
def checkHits(bull,targ):
global score_value
for b in bull:# go through each bullet
## for a in astero:
## aliendistance = math.sqrt((math.pow(b[0]-a[0],2)) + (math.pow(b[1]-a[1],2)))
## if aliendistance < 50:
## asteroids.remove(a)
## bull.remove(b)
## explosion_sound.play()
## score_value+=1
## break
for t in targ: #go through each target
distance = math.sqrt((math.pow(b[0]-t[0],2)) + (math.pow(b[1]-t[1],2)))
if distance < 30:
targ.remove(t)#removes the target
bull.remove(b)#removes the bullet
explosion_sound.play()
score_value += 1
if score_value==10:
next_level()
break
livesr=3
def checkalienbullets(alienbull):
global livesr
global score_value
for a in alienbull:
alienbdistance=math.sqrt((math.pow(a[0]-shipx,2)) + (math.pow(a[1]-shipy,2)))
if alienbdistance<40:
livesr-=3
print(livesr)
if livesr<=0:
game_over()
def moveBullets(bull):
for b in bull:
b[0]+=b[2]
b[1]+=b[3]
if b[1]>700:#off-screen
bull.remove(b)
def move_alien_bull(ebull):
for e in ebull:
e[0]+=e[2]
e[1]+=e[3]
if e[1]>700:#off-screen
ebull.remove(e)
def next_level():
if random.randrange(0,6*40) == 1:
aliencounter+=1
x= randint(50,700)
y= randint(0,100)
alien.append([x,y])
alienbullets.append([x,y,w[0],w[1]])
myclock=time.Clock()
##y=0
##enemy_generate()
def gameLoop():
livesr=3
bg_sound.play(-1)
rapidbullet=20
y=0
score=0
ship_x =0
ship_y=0
global shipx
global shipy
global aliencounter
global astroidY
global astroidY_change
global enemy_y
global alien
## global livesr
direction= None
running=True
function=True
while running:
astroidY_change += .5
#enemy_y += 0
#global alienbullets
for evt in event.get():
if evt.type==QUIT:
running=False
quit()
if evt.type==KEYDOWN:
if evt.key == K_LEFT:
ship_x = -2.5
if evt.key == K_RIGHT:
ship_x = 2.5
## if evt.key == K_UP:
## ship_y = -2
## if evt.key == K_DOWN:
## ship_y = 2
if evt.type==KEYUP:
if evt.key == K_LEFT or evt.key == K_RIGHT:
ship_x = 0
## ship_y = 0
shipx += ship_x
## shipy += ship_y
if shipx <= 0:
shipx = 0
elif shipx >= 900:
shipx = 900
## if shipy <= 0:
## shipy = 0
## elif shipy >= 650:
## shipy = 650
# astroid Movement
astroidY += astroidY_change
if astroidY_change >=650:
astroidY_change =0
if rapidbullet<20:
rapidbullet+=1
keys=key.get_pressed()
if keys[32] and rapidbullet==20:#32 is the space key
bullet_sound.play()
bullets.append([shipx,shipy,v[0],v[1]])
rapidbullet=0
while function:
if random.randrange(0,6*40) == 1:
aliencounter+=1
x= randint(50,700)
y= randint(0,100)
alien.append([x,y])
alienbullets.append([x,y,w[0],w[1]])
if aliencounter==10:
function=False
rel_y = y % bg_3.get_rect().width
screen.blit(bg_3,(0,rel_y - bg_3.get_rect().width))
if rel_y < 700:
screen.blit(bg_3,(0,rel_y))
y +=1
if enemy_y >= 600:
enemy_y = 0
show_score(textx,texty)
show_lives(10,40)
moveBullets(bullets)
move_alien_bull(alienbullets)
checkHits(bullets,alien)
checkalienbullets(alienbullets)
drawScene(screen,shipx,shipy,bullets,alienbullets,alien,asteroids)
display.update()
myclock.tick(120)
quit()
game_intro()
I just copied shipx = 350 and shipy = 550 from the start to game_intro(). Hope this helps!
Found where the problem lies.
livesr=3
def checkalienbullets(alienbull):
global livesr
global score_value
for a in alienbull:
alienbdistance=math.sqrt((math.pow(a[0]-shipx,2)) + (math.pow(a[1]-shipy,2)))
if alienbdistance<40:
livesr-=3
print(livesr)
if livesr<=0:
game_over()
The problem is in the alienbdistance value. I printed out these values while the program ran and got this:
alienbdistance 281.1440911703463
alienbdistance 81.04936767180853
alienbdistance 170.03823099526764
alienbdistance 205.36065835500236
alienbdistance 162.5207679036744
alienbdistance 46.17358552246078
alienbdistance 134.1044369139217
alienbdistance 272.7673000929547
alienbdistance 128.37834708392222
alienbdistance 39.96248240537617
0 <--this is livesr value
alienbdistance 35.805027579936315 <--first alienbdistance value after restarting the game
-3 <--this is livesr value
If the alienbdistance value is below 40, you execute these lines of code:
if alienbdistance<40:
livesr-=3
print(livesr)
if livesr<=0:
game_over()
So now that livesr=0 after the first game over, livesr will immediately be set to -3 since the first or one of the initial values for alienbdistance is below 40. After that statement, you execute the livesr<=0 statement, which will be executed since livesr = -3 at this point, initiating the gameover.
I would recommend fine tuning your alienbdistance value. Somehow between the first run and second run, alienbdistance is being calculated differently. I tried resetting
shipx = 350
shipy = 550
alienbullets=[]
after each game over, but that did not help.
I am building a mole shooter game. I want to be able to restart the game when you press the space bar. I have currently set it to 'a' for testing purposes but that also doesn't seem to be working. I need help to restart my game without exiting the program.
I have added /// to the area where I seem to be facing a problem. I also need a way to reset my score and counter.
import pygame
import random
import time
from threading import Timer
pygame.font.init()
win_width = 1000
win_height = 710
FPS = 90
screen = pygame.display.set_mode((win_width, win_height))
pygame.display.set_caption("Mole Shooter")
white = (255, 255, 255)
red = (255, 0, 0)
counter, text = 30, 'Time Left: 30'.rjust(3)
font = pygame.font.Font('freesansbold.ttf', 32)
score = pygame.font.Font('freesansbold.ttf', 32)
score_text = 'Score: 0'.rjust(3)
run = True
clock = pygame.time.Clock()
background = pygame.transform.scale(pygame.image.load('back_land.png'), (win_width, win_height))
aim = pygame.image.load("aim.png")
mole = pygame.image.load("mole.png")
moles = []
score_check = 0
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
moles.append((molex, moley))
pygame.time.set_timer(pygame.USEREVENT, 1000)
# pygame.time.set_timer(pygame.USEREVENT, 1000)
# mask = pygame.mask.from_surface(mole.png)
def paused():
largeText = pygame.font.Font("freesansbold.ttf", 115)
# TextSurf, TextRect = text_objects("Your Score: " + score_check, largeText)
# TextRect.center = ((display_width/2),(display_height/2))
# screen.blit(TextSurf, TextRect)
final_score = ('Your Score: ' + str(score_check)).rjust(3)
screen.blit(score.render(final_score, True, (0, 0, 0)), (((win_width / 2) - 100), (win_height / 2)))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
# gameDisplay.fill(white)
# button("Continue",150,450,100,50,green,bright_green,unpause)
# button("Quit",550,450,100,50,red,bright_red,quitgame)
pygame.display.update()
clock.tick(15)
def main():
global FPS
global screen
global counter
global text
global font
global score
global score_text
global run
global background
global aim
global mole
global moles
global score_check
global clock
while run:
ax, ay = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
# print("game over")
paused()
///if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
main()
counter = 30///
if event.type == pygame.MOUSEBUTTONDOWN:
mx = mole.get_width()
my = mole.get_height()
for i in moles:
if ax in range(i[0], i[0] + int(mx)) and ay in range(i[1], i[1] + int(my)):
# print("hit")
score_check += 1
score_text = ("Score: " + str(score_check)).rjust(3)
screen.blit(background, [0, 0])
for pos in moles:
screen.blit(mole, pos)
# print(pos)
if len(moles) >= 2:
del (moles[0])
screen.blit(aim, ((ax - 32), (ay - 32)))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
screen.blit(score.render(score_text, True, (0, 0, 0)), (800, 48))
clock.tick(FPS)
pygame.display.flip()
main()
Your indenting is incorrect in this section:
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
# print("game over")
paused()
///if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
main()
counter = 30///
You have the if testing for the event.KEYDOWN inside the if that tested if the event was a USEREVENT, so it will never match. It needs to be like this:
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
# print("game over")
paused()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
main()
counter = 30
However, I should point out a different issue I see with your code structure. To restart the game you are calling main(), but you are doing that from inside main(), causing it to be recursive. You would be better off to do this in a non recursive way. perhaps move the run loop to a new method that main calls and then have the above exit from that and then main can recall it or something.
Just break the run loop whenever you want, set the default values of your variables after that loop, and call to main again.
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
# print("game over")
paused()
if event.type == pygame.KEYDOWN:
break
After run loop:
# Prev code ....
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
screen.blit(score.render(score_text, True, (0, 0, 0)), (800, 48))
clock.tick(FPS)
pygame.display.flip()
reset_vars() // You have to implement this method or reset your variables here
main()
Im creating a snake Pygame with a menu and am fine tuning the bugs and such when I come across the error
IndexError: list index out of range
the error actually appears after I open the tab itself and move the cursor over it
I have a faint idea of what it actually means but I am quite new to python and coding in general so I would appreciate it if someone could explain and show a solution,
thank you very much and here is the code
import pygame
import sys
import random
import time
pygame.init()
WHITE = (255, 255, 255)
YELLOW = (255, 255, 102)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
DARKRED = (125, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
screenWidth = 800
screenHeight = 800
screen = pygame.display.set_mode((screenWidth, screenHeight))
pygame.display.set_caption('Snake Game')
clock = pygame.time.Clock()
snakeBlock = 10
snakeSpeed = 15
fontTitle = pygame.font.SysFont("arial",100)
fontStyle = pygame.font.SysFont("ariel", 50)
scoreFont = pygame.font.SysFont("ariel", 35)
def score(score):
value = scoreFont.render(" Score: " + str(score), True, BLACK)
screen.blit(value, [50, 50])
def snake(snakeBlock, snake_list):
for x in snake_list:
pygame.draw.rect(screen, GREEN, [x[0], x[1], snakeBlock, snakeBlock])
def message(msg, colour):
msg = fontStyle.render(msg, True, BLACK)
screen.blit(msg, [screenWidth / 20, screenHeight / 2])
def gameLoop():
gameOver = False
gameEnd = False
instructions = False
game = True
intro = True
main = True
x1 = screenWidth / 2
y1 = screenHeight / 2
dx = 0
dy = 0
snakeList = []
snakeLength = 2
foodx = round(random.randrange(0, screenWidth - snakeBlock) / 10.0) * 10.0
foody = round(random.randrange(0, screenHeight - snakeBlock) / 10.0) * 10.0
def menu(titles):
buttonTitleFont = pygame.font.SysFont("arial", 52)
selection = []
rectWidth = 400
rectHeight = 60
x = int(screen.get_width()/2 - rectWidth/2)
y = 450
length = len(titles)
num = 0
hover = False
# creates the Rects (containers) for the buttons
for i in range (0,length,1):
choiceRect = pygame.Rect(x,y,rectWidth,rectHeight)
selection.append(choiceRect)
y += 100
#main loop in menu
menu = True
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
menu = False
pygame.quit()
sys.exit()
if event.type ==pygame.MOUSEMOTION: # if mouse moved
hover = False
mx, my = pygame.mouse.get_pos() # get the mouse position
for i in range (length):
if selection[i].collidepoint((mx,my)): # check if x,y of mouse is in a button
num = i
hover = True
if event.type == pygame.MOUSEBUTTONDOWN and hover == True: #if mouse is in button
menu = False # and has been clicked
# draw all buttons
for choice in selection:
pygame.draw.rect(screen,WHITE,choice,0)
# redraw selected button in another colour
pygame.draw.rect(screen,GREEN,selection[num],0)
# draw all the titles on the buttons
x = int(screen.get_width()/2 - 150)
y = 450
for i in range(0,length,1):
buttonTitle = buttonTitleFont.render(titles[i],True,BLACK)
screen.blit(buttonTitle,(x,y))
y += 100
pygame.display.update()
return num
while main:
for event in pygame.event.get(): # check for any events (i.e key press, mouse click etc.)
if event.type ==pygame.QUIT: # check to see if it was "x" at top right of screen
main = False # set the "main" variable to False to exit while loop
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
main = False
intro = False
screen.fill(BLACK)
menuMain = ["Launch", "Instructions","QUIT"]
mainMenu = True
mainInt = True
while mainInt:
for event in pygame.event.get():
if event.type == pygame.QUIT:
main = False
intro = False
mainInt = False
screen.fill(BLACK)
#Centers the rendered tiles
textTitle = fontTitle.render("Snake", True, GREEN )
textW = textTitle.get_width()
textH = textTitle.get_height()
xTitle = int(screenWidth/2 - textW/2)
yTitle = int(screenHeight/4 - textH/2)
screen.blit(textTitle, (xTitle,yTitle))
pygame.display.update()
# in the intro, this asks the user where they would like to go
if mainMenu ==True:
choose = menu(menuMain)
if choose == 0:
menu = False
intro = False
mainInt = False
mainMenu = False
game = True
screen.fill(BLACK)
elif choose ==1:
menu = False
instructions = True
mainMenu = False
screen.fill(BLACK)
pygame.display.update()
else:
menu = False
main = False
intro = False
mainInt = False
mainMenu = False
while game:
if gameOver == True:
game = False
while gameEnd == True:
screen.fill(DARKRED)
message("You Lost! Press C to Play Again or Q to Quit", RED)
score(snakeLength - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = True
gameEnd = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameOver = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
dx = -snakeBlock
dy = 0
elif event.key == pygame.K_RIGHT:
dx = snakeBlock
dy = 0
elif event.key == pygame.K_UP:
dx = 0
dy = -snakeBlock
elif event.key == pygame.K_DOWN:
dx = 0
dy = snakeBlock
if x1 >= screenWidth or x1 < 0 or y1 >= screenHeight or y1 < 0:
gameEnd = True
x1 += dx
y1 += dy
screen.fill(WHITE)
pygame.draw.rect(screen, RED, [foodx, foody, snakeBlock, snakeBlock])
snakeHead = []
snakeHead.append(x1)
snakeHead.append(y1)
snakeList.append(snakeHead)
if len(snakeList) > snakeLength:
del snakeList[0]
for x in snakeList[:-1]:
if x == snakeHead:
gameEnd = True
snake(snakeBlock, snakeList)
score(snakeLength - 1)
pygame.display.update()
if x1 == foodx and y1 == foody:
foodx = round(random.randrange(0, screenWidth - snakeBlock) / 10.0) * 10.0
foody = round(random.randrange(0, screenHeight - snakeBlock) / 10.0) * 10.0
snakeLength += 1
clock.tick(snakeSpeed)
pygame.quit()
quit()
gameLoop()
These lines:
mainMenu = True
if mainMenu ==True:
choose = menu(mainMenu)
mean that you are passing a bool (True is a type of bool) to your menu() function.
This is how the first argument of menu() is being used:
def menu(titles):
...
length = len(titles)
So like the error message says, you're trying to take the length of a boolean (e.g. len(True) does not make sense, so you get an error). You'll have to reconcile this on your own, I'm guessing you meant for main() to accept a list of menu titles rather than True or False
I am creating a basic game. I have mainly two codes for :(i) Menu (ii) Basic Game. I want to run 'while game_over' loop after clicking 'start' button. But the code does not respond after I click 'start' button.
import pygame
import random
import sys
pygame.init()
w=800
h=600
yellow=(255,255,0)
player_size=25
player_pos=[w/2,h-(2*player_size)]
enemy_size=25
enemy_pos=[random.randint(0,w-enemy_size),0]
enemy_list=[ ]
Menu_bg_color=(34,139,34)
red=(255,0,0)
blue=(0,0,125)
bright_blue=(0,0,255)
font_size=35
b1_pos=[w/2-50,h/2]
b1_size=[105,50]
bg_color=(0,0,0)
screen=pygame.display.set_mode((w,h))
speed=10
score=0
clock=pygame.time.Clock()
myFont=pygame.font.SysFont("monospace",font_size)
Menu_myFont=pygame.font.SysFont("freesansbold.tff",font_size)
running=True
Menu_running=True
#GAME CODE
def GameCode():
global game_over
global score
global speed
global player_pos
def set_level(score,speed):
if score<10:
speed=5
elif score<20:
speed=6
elif score<30:
speed=8
elif score<40:
speed=10
elif score<50:
speed=13
elif score<200:
speed=15
else:
speed=20
return speed
def drop_enemies(enemy_list):
delay=random.random()
if len(enemy_list)<6 and delay<0.1:
x_pos=random.randint(0,w-enemy_size)
y_pos=0
enemy_list.append([x_pos,y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,blue, (enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))
def update_enemy_pos(enemy_list,score):
for idx,enemy_pos in enumerate(enemy_list):
if enemy_pos[1]>=0 and enemy_pos[1]<h:
enemy_pos[1]+=speed
else:
enemy_list.pop(idx)
score+=1
return score
def detect_collision(player_pos,enemy_pos):
p_x=player_pos[0]
p_y=player_pos[1]
e_x=enemy_pos[0]
e_y=enemy_pos[1]
if (e_x>=p_x and e_x<(p_x+player_size)) or (p_x>=e_x and p_x<(e_x+enemy_size)):
if (e_y>=p_y and e_y<(p_y+player_size)) or (p_y>=e_y and p_y<(e_y+enemy_size)):
return True
return False
def collision_check(enemy_list,player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos,player_pos):
return True
return False
while game_over==False:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if event.type==pygame.KEYDOWN:
x=player_pos[0]
y=player_pos[1]
if event.key==pygame.K_LEFT:
x-=player_size
elif event.key==pygame.K_UP:
y-=player_size
elif event.key==pygame.K_RIGHT:
x+=player_size
elif event.key==pygame.K_DOWN:
y+=player_size
player_pos=[x,y]
screen.fill(bg_color)
#screen.blit(road,(0,0))
drop_enemies(enemy_list)
score=update_enemy_pos(enemy_list,score)
speed=set_level(score,speed)
text='Your Score is:' + str(score)
label=myFont.render(text,1,yellow)
screen.blit(label,(w/2,h-40))
if collision_check(enemy_list,player_pos):
game_over=True
break
draw_enemies(enemy_list)
pygame.draw.rect(screen,red,(player_pos[0],player_pos[1],player_size,player_size))
clock.tick(30)
pygame.display.update()
pygame.display.flip()
#MENU CODE
def MenuCode():
global game_over
def button(b1_pos,b1_size):
mouse_pos=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if (b1_pos[0]<mouse_pos[0]<(b1_pos[0]+b1_size[0])) and (b1_pos[1]<mouse_pos[1]<(b1_pos[1]+b1_size[1])):
pygame.draw.rect(screen,bright_blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
if click[0]==1:
game_over=False
else:
pygame.draw.rect(screen,blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
text='START'
label=Menu_myFont.render(text,1,red)
screen.blit(label,(w/2-38,h/2+5))
Menu_running=True
while Menu_running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(Menu_bg_color)
button(b1_pos,b1_size)
#button(b1_pos,b1_size,'quit')
pygame.display.update()
clock.tick(30)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break;
screen.fill(bg_color)
if MenuCode():
if game_over==False:
GameCode()
clock.tick(30)
pygame.display.update()
Here's a substantially revised version of your code that doesn't have the problem. I have revised the code so it closely adheres to the PEP 8 - Style Guide for Python Code guidelines and also eliminated many of the global variables you had by making them local to the function that uses them.
One of the primary cosmetic things I did was determine which of the globals were unchanging constants and which were variables whose values actually changed. After doing that, I changed the names of the constant ones to all UPPERCASE (as per PEP 8) and moved those with varying values to inside whichever function was actually using them.
The most extensive changes were made to the menu handling function — now named menu_code() — which was probably the main source of your problems. To help facilitate the rewrite, I've added a MenuButton class to encapsulate their behavior to a large degree and reduce repetitious code.
Note that there may be problems with the game_code() function because because I didn't attempted to optimize, test, or debug it.
Hopefully this will provide you with a good base upon which to further develop the game. I strongly suggest you read and start following PEP 8.
import random
import pygame as pyg
W, H = 800, 600
RED = (255, 0, 0)
BLUE = (0, 0, 125)
BRIGHT_BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PLAYER_SIZE = 25
ENEMY_SIZE = 25
FONT_SIZE = 35
BG_COLOR = BLACK
FPS = 30
START, QUIT = 0, 1 # Button selection codes returned by menu_code()
pyg.init()
screen = pyg.display.set_mode((W, H))
pyg.display.set_caption('Basic Game')
clock = pyg.time.Clock()
game_font = pyg.font.SysFont("monospace", FONT_SIZE)
menu_font = pyg.font.SysFont("freesansbold.ttf", FONT_SIZE)
def game_code():
enemy_pos = [random.randint(0, W-ENEMY_SIZE), 0]
enemy_list = []
game_over = False
player_pos = [W/2, H - 2*PLAYER_SIZE]
score = 0
speed = 10
def get_speed(score):
if score < 10:
speed = 5
elif score < 20:
speed = 6
elif score < 30:
speed = 8
elif score < 40:
speed = 10
elif score < 50:
speed = 13
elif score < 200:
speed = 15
else:
speed = 20
return speed
def drop_enemies(enemy_list):
delay = random.random()
if len(enemy_list) < 6 and delay < 0.1:
x_pos = random.randint(0, W-ENEMY_SIZE)
y_pos = 0
enemy_list.append([x_pos, y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pyg.draw.rect(screen, BLUE,
(enemy_pos[0], enemy_pos[1], ENEMY_SIZE, ENEMY_SIZE))
def update_enemy_pos(enemy_list, score):
for idx, enemy_pos in enumerate(enemy_list):
if enemy_pos[1] >= 0 and enemy_pos[1] < H:
enemy_pos[1] += speed
else:
enemy_list.pop(idx)
score += 1
return score
def detect_collision(player_pos, enemy_pos):
p_x, p_y = player_pos
e_x, e_y = enemy_pos
if ((e_x >= p_x and e_x < (p_x + PLAYER_SIZE))
or (p_x >= e_x and p_x < (e_x + ENEMY_SIZE))):
if ((e_y >= p_y and e_y < (p_y+PLAYER_SIZE))
or (p_y >= e_y and p_y < (e_y + ENEMY_SIZE))):
return True
return False
def collision_check(enemy_list, player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos, player_pos):
return True
return False
while not game_over:
for event in pyg.event.get():
if event.type == pyg.QUIT:
game_over = True
break
if event.type == pyg.KEYDOWN:
x = player_pos[0]
y = player_pos[1]
if event.key == pyg.K_LEFT:
x -= PLAYER_SIZE
elif event.key == pyg.K_UP:
y -= PLAYER_SIZE
elif event.key == pyg.K_RIGHT:
x += PLAYER_SIZE
elif event.key == pyg.K_DOWN:
y += PLAYER_SIZE
player_pos = [x, y]
screen.fill(BG_COLOR)
drop_enemies(enemy_list)
score = update_enemy_pos(enemy_list, score)
speed = get_speed(score)
text = 'Your Score is:' + str(score)
label = game_font.render(text, 1, YELLOW)
screen.blit(label, (W/2, H-40))
if collision_check(enemy_list, player_pos):
game_over = True
break
draw_enemies(enemy_list)
pyg.draw.rect(screen, RED,
(player_pos[0], player_pos[1], PLAYER_SIZE, PLAYER_SIZE))
clock.tick(FPS)
pyg.display.update()
# pyg.display.flip() # Don't do both update() and flip().
class MenuButton:
def __init__(self, text, value, rect):
self.text = text
self.value = value
self.rect = rect
def draw(self):
# Background color determined by whether mouse is positioned over label.
mouse_pos = pyg.mouse.get_pos()
fg_color = RED
bg_color = BRIGHT_BLUE if self.rect.collidepoint(mouse_pos) else BLUE
pyg.draw.rect(screen, bg_color, self.rect)
pyg.draw.rect(screen, YELLOW, self.rect, 1) # Draw a border.
label = menu_font.render(self.text, 1, fg_color)
# Center lable text inside its rectangle.
txw, txh = menu_font.size(self.text)
screen.blit(label, (self.rect.left + txw/2, self.rect.top + txh/2))
def menu_code():
MENU_BG_COLOR = (34, 139, 34)
LABEL_SIZE = LABEL_WIDTH, LABEL_HEIGHT = (105, 50)
B1_RECT = pyg.Rect((W/2 - LABEL_WIDTH/2, H/2 - LABEL_HEIGHT/2), LABEL_SIZE)
B2_RECT = pyg.Rect((W/2 - LABEL_WIDTH/2, H/2 + LABEL_HEIGHT/2), LABEL_SIZE)
MENU_BUTTONS = [MenuButton('Start', START, B1_RECT),
MenuButton('Quit', QUIT, B2_RECT)]
choice = None
while choice is None:
screen.fill(MENU_BG_COLOR)
for button in MENU_BUTTONS:
button.draw()
for event in pyg.event.get():
if event.type == pyg.QUIT:
choice = QUIT
# Handle left mouse button clicks.
if event.type == pyg.MOUSEBUTTONDOWN and event.button == 1:
for button in MENU_BUTTONS:
if button.rect.collidepoint(event.pos):
choice = button.value
break
pyg.display.update()
clock.tick(FPS)
return choice
# Main loop.
running = True
while running:
for event in pyg.event.get():
if event.type == pyg.QUIT:
running = False
break;
screen.fill(BG_COLOR)
choice = menu_code()
if choice == START:
game_code()
if choice == QUIT:
running = False
pyg.display.update()
clock.tick(FPS)