How do I restart my game without closing the program - python

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()

Related

Problems making pygame target image (scope) move with arrow keys

When we run our pygame's code, our target scope image will NOT move, but our do robots generate. We are trying to use our arrow keys to move them and I included all of our code.
Commented out under our newest trial code for moving are two other things we tried.
import pygame, sys
from graphics import *
import time
import random
pygame.init()
level=1
bg = pygame.image.load('bg.png')
bg_width = 800
pygame.display.set_caption('Robot Apocalypse')
surfacew = 1054
surfacel = 562
surface = pygame.display.set_mode((surfacew,surfacel))
black = (0, 0, 0)
score = 0
#player_health = 99
alive=True
targetImg = pygame.image.load('target.png')
targetImg = pygame.transform.scale(targetImg, (40, 40))
targetxy = targetImg.get_rect()
targetx = targetxy[0]
targety = targetxy[1]
def move_target(targetImg):
pygame.event.clear()
while alive == True:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
targetx -= 5
if keys_pressed[pygame.K_RIGHT]:
targetx += 5
if keys_pressed[pygame.K_UP]:
targety -= 5
if keys_pressed[pygame.K_DOWN]:
targety += 5
pygame.display.update()
# pygame.event.clear()
# for event in pygame.event.get():
# if event.type ==KEYDOWN:
# if event.key == K_LEFT:
# direction = MOVE_LEFT
# elif event.key == K_RIGHT:
# direction = MOVE_RIGHT
# elif event.type == KEYUP:
# if event.key == K_LEFT:
# direction = 0
# elif event.key == K_RIGHT:
# direction = 0
# if(direction == MOVE_LEFT):
# targetx-=10
# elif(direction == MOVE_RIGHT):
# targetx+=10
# for event in pygame.event.get():
# print(event)
# if event.type==QUIT:
# pygame.quit()
# sys.exit()
# if event.type == KEYDOWN:
# if event.key == K_LEFT:
# targetx-=5
# elif event.key == K_RIGHT:
# targetx+=5
# elif event.key == K_UP:
# targety-=5
# elif event.key == K_DOWN:
# targety+=5
# pygame.display.update()
def shoot():
#while True:
shot = False
pos = (targetx, targety)
t = screen.blit(robot, (64,64))
if t.collidepoint(pos):
shot = True
return shot
def generate_robot(x,y):
#while displayrobot == True
robot=pygame.draw.rect(surface, (255,0,0), (x,y,64,64), 0)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
shoot()
if shot == True:
displayrobot = False
cover = surface.blit(bg, (x,y))
pygame.display.update()
return x, y
#if shot == True:
def die():
message("YOU DIED")
pygame.display.update()
def win(level):
level+=1
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message(text):
largeText = pygame.font.Font('freesansbold.ttf',60)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((surfacew/6),(surfacel/2))
surface.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
def main(alive):
#displayrobot = True:
robot=0
score=0
surface.fill(black)
surface.blit(bg, (0,0))
message("Level "+ str(level))
mouse = pygame.mouse.get_pos()
target = surface.blit(targetImg, (mouse))
while alive==True:
# robot = enemy(64, 64)
x=random.randint(40,760)
y=random.randint(40,560)
generate_robot(x,y)
pygame.display.update()
robot+=1
time.sleep(8/level)
if robot>50 and robot>score:
alive=False
# if pygame.mouse.get_pressed()==True:
# shoot() #maybe??
if shot==True:
score+=1
robot-=1
if robot==10/(level/2): #if 10- robots on screen then...
die()
if score>25*(level/2):
win()
move_target(targetImg)
main(alive)
pygame.quit()
quit()
.
There are no error messages, but it won't move. We've tried a ton of different things (that aren't included) and looked up a lot of websites so please help us. Thanks
To move object you have to not only change x,y and update screen (send buffer to video card which will display it) but also clean buffer, draw image in new place in buffer (blit()).
This code shows only working move_target. I skiped rest of code.
I keep position in target_rect which is pygame.Rect. You can use it to blit(img,rect) but later you can also use to check collision rect.colliderect(other_rect)
import pygame
# --- constants --- (UPPER_CASE_NAMES)
BLACK = (0, 0, 0)
SURFACE_WIDTH = 1054
SURFACE_HEIGHT = 562
# --- functions --- (lower_case_names)
def move_target(target_img, target_rect):
alive = True
clock = pygame.time.Clock()
while alive:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
alive = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
alive = False
# --- updates/changes ---
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
target_rect.x -= 5
if keys_pressed[pygame.K_RIGHT]:
target_rect.x += 5
if keys_pressed[pygame.K_UP]:
target_rect.y -= 5
if keys_pressed[pygame.K_DOWN]:
target_rect.y += 5
# --- draws ---
surface.fill(BLACK)
surface.blit(target_img, target_rect)
pygame.display.update()
# the same game's speed on all computers = 60 FPS
clock.tick(60)
# --- main --- (lower_case_names)
pygame.init()
pygame.display.set_caption('Robot Apocalypse')
surface = pygame.display.set_mode((SURFACE_WIDTH, SURFACE_HEIGHT))
target_img = pygame.image.load('target.png')
target_img = pygame.transform.scale(target_img, (40, 40))
target_rect = target_img.get_rect()
move_target(target_img, target_rect)
pygame.quit()
It looks like my original functional comment is still "in force": your code doesn't move any game object.
targetxy = targetImg.get_rect()
targetx = targetxy[0]
targety = targetxy[1]
At this point, targetxy is a reference to the bounding rectangle for your game object.
targetx and targety are copies of the values of the rect position.
def move_target(targetImg):
pygame.event.clear()
while alive == True:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
targetx -= 5
...
You've change the local copy of the x-coordinate. This does not affect the position of targetImg. You need to change the object's attributes, such as
targetxy.x -= 5
After this, you need to update the game screen.

How to make a wall tilemap?

i'm making a game but i want to make the game harder by adding walls. I found out it's called a tilemap. But it's for multiple colours, i just want one color, grey. I want it to be something like 1,1,1,1,
1,0,0,1,
1,0,0,1,
1,1,1,1
0 = nothing. 1 = grey rectangle. I also need it to be like WIDTH = 16
HEIGHT = 9
TILESIZE = dw/WIDTH
but i can't find a way to implement it.
i tried using a def code but it lagged out my game. And i tried using this site: http://usingpython.com/pygame-tilemaps/
import pygame
import os
import sys
pygame.mixer.pre_init()
pygame.mixer.init(44100, 16, 2, 262144)
pygame.init()
from pygame.locals import*
import cv2
import time
import random
import pickle
import shutil
grey = (128,128,128)
def pause():
paused = True
while paused:
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_ESCAPE:
paused = False
elif event.key == pygame.K_SPACE:
menu(1)
screen.fill(white)
mts("Paused", black, -100, 100)
mts("Press esc to go back to the game or press space to go back to the menu", black, 25, 45)
pygame.display.update()
clock.tick(60)
def score(score):
text = pygame.font.Font('Fonts/Kuiper_Belt.otf', 25).render("Score: "+str(score), True, black)
screen.blit(text, [0,0])
def highscore(highscore):
text = pygame.font.Font('Fonts/Kuiper_Belt.otf', 25).render("Highscore: "+str(highscore), True, black)
screen.blit(text, [1100,0])
#define the apple to spawn in a random place
def randAppleGen():
randAppleX = random.randrange(0, dw-at, bs)
randAppleY = random.randrange(0, dh-at, bs)
return randAppleX,randAppleY
def snake(bs, sl):
for XnY in sl:
pygame.draw.rect(screen, Dgreen, [XnY[0],XnY[1],bs,bs])
def text_objects(text,color,fontS):
font = pygame.font.Font('Fonts/Kuiper_Belt.otf', fontS)
textSurface = font.render(text, True, color)
return textSurface, textSurface.get_rect()
def mts(msg,color, y_displace=0, fs=35):
textSurf, textRect = text_objects(msg,color,fs)
textRect.center = (dw / 2), (dh / 2)+y_displace
screen.blit(textSurf, textRect)
def gameLoop():
global at
global bs
hs = pickle.load( open( os.getenv('APPDATA')+str('/Snake Universe/h.SNUN'), "rb" ) )
gameExit = False
gameOver = False
gameHack = False
tilemap = [
[1,1,1,1],
[1,0,0,1],
[1,0,0,1],
[1,1,1,1]
]
WIDTH = 4
HEIGHT = 4
TILESIZE = dw/WIDTH
Speed = 20
lead_x = dw/2
lead_y = dh/2
lead_x_change = 0
lead_y_change = 0
pygame.mixer.music.load(os.path.join(os.getcwd(), 'Sounds', 'music1.ogg'))
pygame.mixer.music.play(-1)
slist = []
sl = 0
if sl > 2304:
gameHack = True
randAppleX,randAppleY = randAppleGen()
while not gameExit:
for row in range(HEIGHT):
for column in range(WIDTH):
if tilemap[row][column] == 1:
pygame.draw.rect(screen, grey, (column*TILESIZE, row*TILESIZE, TILESIZE, TILESIZE))
while gameOver == True:
screen.fill(white)
mts("Game over", red, -50,100)
mts("Press enter to play again or press space to go back to the menu", black, 50,50)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameOver = False
gameExit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key==pygame.K_RETURN:
gameLoop()
if event.key == pygame.K_SPACE:
gameExit = False
gameOver = False
menu(1)
while gameHack == True:
pygame.mixer.music.stop()
screen.fill(white)
mts("Hacked", red, -50,100)
mts("You hacked or exploit the game, press enter to quit the game", black, 50,50)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameOver = False
gameExit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key==pygame.K_RETURN:
pygame.quit()
sys.exit()
lead_x += lead_x_change
lead_y += lead_y_change
prev_x, prev_y = lead_x_change, lead_y_change
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and prev_x != bs:
lead_x_change, lead_y_change = -bs, 0
elif event.key == pygame.K_RIGHT and prev_x != -bs:
lead_x_change, lead_y_change = bs, 0
elif event.key == pygame.K_UP and prev_y != bs:
lead_x_change, lead_y_change = 0, -bs
elif event.key == pygame.K_DOWN and prev_y != -bs:
lead_x_change, lead_y_change = 0, bs
elif event.key == pygame.K_ESCAPE:
pause()
elif event.key == pygame.K_s and Speed >= 10 and Speed < 60:
Speed += 10
clock.tick(Speed)
elif event.key == pygame.K_d and Speed <= 60 and Speed > 10:
Speed -= 10
clock.tick(Speed)
elif event.key == pygame.K_a:
sl += 1
if not pygame.Rect(0, 0, dw, dh).contains(lead_x, lead_y, bs, bs):
gameOver = True
screen.fill(white)
#draw the apple
apple = pygame.draw.rect(screen, red, [randAppleX,randAppleY,at,at])
sh = []
sh.append(lead_x)
sh.append(lead_y)
slist.append(sh)
snake(bs, slist)
if len(slist) > sl:
del slist[0]
for eachSegment in slist[:-1]:
if eachSegment == sh:
gameOver = True
score(sl)
highscore(hs)
if sl > hs:
hs += 1
os.remove( os.getenv('APPDATA')+str('/Snake Universe/h.SNUN') )
pickle.dump( sl, open( os.getenv('APPDATA')+str('/Snake Universe/h.SNUN'), "wb" ) )
hs = pickle.load( open( os.getenv('APPDATA')+str('/Snake Universe/h.SNUN'), "rb" ) )
pygame.display.update()
#make the apple spawn
appleRect = pygame.Rect(randAppleX, randAppleY, at, at)
if appleRect.collidepoint(lead_x, lead_y):
while True:
randAppleX, randAppleY = randAppleGen()
appleRect = pygame.Rect(randAppleX, randAppleY, at, at)
if not appleRect.collidepoint(lead_x, lead_y) and \
not any(appleRect.collidepoint(*p) for p in slist):
break
sl += 1
clock.tick(Speed)
pygame.quit()
sys.quit()
I expect it to display a single color tile map, but i keep on getting crashes.
I don't understand why you have problem if you already have it in code and you have example in your link.
tilemap = [
[1,1,1,1],
[1,0,0,1],
[1,0,0,1],
[1,1,1,1]
]
MAPHEIGHT = 4
MAPWIDTH = 4
TILESIZE = dw/MAPWIDTH
GREY = (128,128,128)
for row in range(MAPHEIGHT):
for column in range(MAPWIDTH):
if tilemap[row][column] == 1:
pygame.draw.rect(screen, GREY, column*TILESIZE, row*TILESIZE, TILESIZE, TILESIZE))
EDIT:
You have problem because you use it in wrong place. You have to draw between screen.fill (which clears buffer) and pygame.update (which sends buffer to video card and it displays it on screen)
screen.fill(white)
for row in range(HEIGHT):
for column in range(WIDTH):
if tilemap[row][column] == 1:
pygame.draw.rect(screen, grey, (column*TILESIZE, row*TILESIZE, TILESIZE, TILESIZE))
# ... draw other things ...
pygame.display.update()
You have mess in code. You should have
place where you update values, move object, crate/respaw object, load/save pickle, etc. but don't draw there.
place where you use screen.fill, draw all elements, use pygame.display.update but don't update object and don't load/save pickle
EDIT:
My version (with better names of variables and functions)
import pygame
import os
import sys
import random
import pickle
# --- constants --- (UPPERCASE names)
WHITE = ( 0, 0, 0)
RED = (255, 0, 0)
BLACK = (255, 255, 255)
GREEN = (255, 0, 0)
GREY = (128, 128, 128)
DISPLAY_WIDTH = 1200
DISPLAY_HEIGHT = 800
APPDATA = os.getenv('APPDATA', '')
PICKLE_PATH = os.path.join(APPDATA, 'Snake Universe', 'h.SNUN')
WIDTH = 4
HEIGHT = 4
TILE_SIZE = DISPLAY_WIDTH/WIDTH
BLOCK_SIZE = 20
# --- functions ---
def pause():
paused = True
while paused:
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_ESCAPE:
paused = False
elif event.key == pygame.K_SPACE:
menu(1)
screen.fill(WHITE)
mts("Paused", BLACK, -100, 100)
mts("Press esc to go back to the game or press space to go back to the menu", BLACK, 25, 45)
pygame.display.update()
clock.tick(60)
def text_object(text, color=BLACK, font_size=25):
font = pygame.font.SysFont(None, font_size)
surface = font.render(text, True, color)
rect = surface.get_rect()
return surface, rect
def draw_score(screen, score):
surface, rect = text_object("Score: " + str(score))
screen.blit(surface, (0, 0))
def draw_highscore(screen, highscore):
surface, rect = text_object("Highscore: " + str(highscore))
screen.blit(surface, (1100, 0))
def rand_apple_pos():
x = random.randrange(0, DISPLAY_WIDTH - BLOCK_SIZE, BLOCK_SIZE)
y = random.randrange(0, DISPLAY_HEIGHT - BLOCK_SIZE, BLOCK_SIZE)
return x, y
def draw_snake(screen, snake):
for x, y in snake:
pygame.draw.rect(screen, GREEN, (x, y, BLOCK_SIZE, BLOCK_SIZE))
def mts(msg, color, y_displace=0, fs=35):
surface, rect = text_object(msg, color, fs)
rect.center = (DISPLAY_WIDTH / 2), (DISPLAY_HEIGHT / 2) + y_displace
screen.blit(surface, rect)
def game_loop(screen):
highscore = 0
#highscore = pickle.load(open(PICKLE_PATH, "rb" ))
game_exit = False
game_over = False
game_hack = False
speed = 10
lead_x = DISPLAY_WIDTH/2
lead_y = DISPLAY_HEIGHT/2
lead_x_change = 0
lead_y_change = 0
#pygame.mixer.music.load(os.pBLOCK_SIZEh.join(os.getcwd(), 'Sounds', 'music1.ogg'))
#pygame.mixer.music.play(-1)
snake = [(100, 100)]
score = 0
apple_x, apple_y = rand_apple_pos()
apple_rect = pygame.Rect(apple_x, apple_y, BLOCK_SIZE, BLOCK_SIZE)
clock = pygame.time.Clock()
while not game_exit:
while game_over == True:
screen.fill(WHITE)
mts("Game over", RED, -50,100)
mts("Press enter to play again or press space to go back to the menu", BLACK, 50,50)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = False
game_exit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key==pygame.K_RETURN:
#gameLoop()
game_over = False
if event.key == pygame.K_SPACE:
game_exit = False
game_over = False
menu(1)
while game_hack == True:
pygame.mixer.music.stop()
screen.fill(WHITE)
mts("Hacked", RED, -50, 100)
mts("You hacked or exploit the game, press enter to quit the game", BLACK, 50,50)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = False
game_exit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_KP_ENTER or event.key==pygame.K_RETURN:
pygame.quit()
sys.exit()
lead_x += lead_x_change
lead_y += lead_y_change
prev_x, prev_y = lead_x_change, lead_y_change
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and prev_x != BLOCK_SIZE:
lead_x_change, lead_y_change = -BLOCK_SIZE, 0
elif event.key == pygame.K_RIGHT and prev_x != -BLOCK_SIZE:
lead_x_change, lead_y_change = BLOCK_SIZE, 0
elif event.key == pygame.K_UP and prev_y != BLOCK_SIZE:
lead_x_change, lead_y_change = 0, -BLOCK_SIZE
elif event.key == pygame.K_DOWN and prev_y != -BLOCK_SIZE:
lead_x_change, lead_y_change = 0, BLOCK_SIZE
elif event.key == pygame.K_ESCAPE:
pause()
elif event.key == pygame.K_s and speed >= 10 and speed < 60:
speed += 10
clock.tick(speed)
elif event.key == pygame.K_d and speed <= 60 and speed > 10:
speed -= 10
clock.tick(speed)
elif event.key == pygame.K_a:
score += 1
# --- moves ---
if not pygame.Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT).contains(lead_x, lead_y, BLOCK_SIZE, BLOCK_SIZE):
game_over = True
if apple_rect.collidepoint(lead_x, lead_y):
while True:
apple_x, apple_y = rand_apple_pos()
# update existing Rect without creating new Rect
apple_rect.x = apple_x
apple_rect.y = apple_x
if not apple_rect.collidepoint(lead_x, lead_y) and \
not any(apple_rect.collidepoint(*pos) for pos in snake):
break
score += 1
# update snake
snake.append( (lead_x, lead_y) )
if len(snake) > score:
del snake[0]
for segment in snake[:-1]:
if segment == snake[-1]:
game_over = True
if score > highscore:
#pickle.dump(score, open(PICKLE_PATH, "wb"))
highscore = score
if score > 2304:
game_hack = True
# --- draw ---
screen.fill(WHITE)
#draw_wall(screen)
for row in range(HEIGHT):
for column in range(WIDTH):
if tilemap[row][column] == 1:
pygame.draw.rect(screen, GREY, (column*TILE_SIZE, row*TILE_SIZE, TILE_SIZE, TILE_SIZE))
draw_snake(screen, snake)
#draw the apple
#draw_apple(screen, apple)
pygame.draw.rect(screen, RED, apple_rect)
draw_score(screen, score)
draw_highscore(screen, highscore)
pygame.display.update()
clock.tick(speed)
# --- end ---
pygame.quit()
sys.quit()
# --- variables ---
tilemap = [
[1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,0,0,1,1,0,0,1,1,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1],
]
HEIGHT = len(tilemap)
WIDTH = len(tilemap[0])
# --- main ---
pygame.mixer.pre_init()
pygame.mixer.init(44100, 16, 2, 262144)
pygame.init()
screen = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_WIDTH))
game_loop(screen)

Slowly decrement variable with timer?

I've got a variable that increases when the user presses a button.
When the user presses another button, I'd like to set that variable to 0,
but not instantly-- I'd like it to tick down over the course of a few seconds.
During this time I'd like the user to be able to perform other actions-- hence why I'm not using sleep.
I've looked at using pygame's events, time.clock, etc., but I can't seem to get this to work. Here is what I've tried so far:
import pygame, sys, math
from pygame.locals import *
pygame.init()
pygame.font.init()
scrw = 640
scrh = 480
screen = pygame.display.set_mode((scrw, scrh))
ttwist = 0
recentering = False
fps = 15
clock = pygame.time.Clock()
my_font = pygame.font.SysFont("arial", 12)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pressed = pygame.key.get_pressed()
if not recentering:
if pressed[pygame.K_d]:
ttwist +=1
if pressed[pygame.K_a]:
ttwist -=1
RECENTERTORSOEVENT = USEREVENT
if event.type == pygame.KEYDOWN and event.key == pygame.K_BACKSLASH:
recentering = True
pygame.time.set_timer(RECENTERTORSOEVENT, 1000*abs(ttwist))
if ttwist == 0:
recentering = False
if event.type == USEREVENT:
if ttwist < 0:
ttwist += 1
elif ttwist > 0:
ttwist -= 1
drawtext = my_font.render("TTWIST:"+str(ttwist), True, (255,255,255),(0,0,0))
screen.blit(drawtext,(10,130))
pygame.display.update()
clock.tick(fps)
What am i doing wrong?
You are on the right track, but some parts of the code need to be changed:
All the if event.type == ... blocks should be inside of the event loop.
RECENTERTORSOEVENT = USEREVENT should be defined above the while loop (but that doesn't cause problems).
You're setting the time interval for the RECENTERTORSOEVENT way too high: 1000*abs(ttwist). That means, if the ttwist is 10, you're setting it to 10.000 ms (10 seconds). Just set it to a constant value like 100 ms.
When the ttwist is recentered, call pygame.time.set_timer(RECENTERTORSOEVENT, 0) to stop the timer.
Fill the screen each frame screen.fill((30, 30, 30)), otherwise you see artifacts because the font surface keeps changing its size.
import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
my_font = pygame.font.SysFont('arial', 22)
clock = pygame.time.Clock()
ttwist = 0
RECENTERTORSOEVENT = pygame.USEREVENT
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
print('recentering')
# Start to add the USEREVENT every 100 ms.
pygame.time.set_timer(RECENTERTORSOEVENT, 100)
elif event.type == RECENTERTORSOEVENT:
ttwist += 1 if ttwist < 0 else -1
if ttwist == 0:
print('done')
# Stop to add the USEREVENT to the queue.
pygame.time.set_timer(RECENTERTORSOEVENT, 0)
pressed = pygame.key.get_pressed()
if pressed[pygame.K_d]:
ttwist += 1
if pressed[pygame.K_a]:
ttwist -= 1
screen.fill((30, 30, 30))
drawtext = my_font.render(
'TTWIST: {}'.format(ttwist), True, (255, 255, 255))
screen.blit(drawtext, (10, 130))
pygame.display.update()
clock.tick(30)
ttwist += 1 if ttwist < 0 else -1 is a conditional expression and does basically the same as:
if ttwist < 0:
ttwist += 1
elif ttwist > 0:
ttwist -= 1

A variable in my code won't define properly

This is my code for a maths program I am making for high school. I am struggling at the moment because I can't figure out what I've done wrong, it says that sum1 isn't defined. If someone could please take their time to go through my code and sort it out I would be very grateful.
my error is on this line: (line 130)
message_to_screen("What is: " + str(sum1) + " + " + str(sum2),
black,
-100,
"medium")
Do let me know if I need to clarify anything.
Thanks!
# Below I am importing the modules that I will need
import pygame
import random
import time
from pygame.locals import *
# This initiates pygame
pygame.init()
# These are my defined colours
white = (255,255,255)
lightGrey = (200,200,200)
black = (0,0,0)
grey = (100,100,100)
red = (255,0,0)
yellow = (200,200,0)
green = (34,177,76)
# This sets the display width and height
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Major League Mathematics')
clock = pygame.time.Clock()
FPS = 30
easyvalues = list(range(10, 100 + 1))
mediumvalues = list(range(100, 1000 + 1))
hardvalues = list(range(1000, 10000 + 1))
# These are my set sizes for my message_to_screen definition
smallfont = pygame.font.SysFont("Arial", 30)
medfont = pygame.font.SysFont("Arial", 50)
largefont = pygame.font.SysFont("Arial", 100)
menufont = pygame.font.SysFont("Arial", 80)
# The next 3 definitions define how text is displayed
def text_objects(text,color,size):
# This is an 'if' statement
if size == "small":
textSurface = smallfont.render(text, True, color)
elif size == "medium":
textSurface = medfont.render(text, True, color)
elif size == "large":
textSurface = largefont.render(text, True, color)
elif size == "menu":
textSurface = menufont.render(text, True, color)
return textSurface, textSurface.get_rect()
def text_to_button(msg, color, buttonx, buttony, buttonwidth, buttonheight, size = "medium"):
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 = (display_width / 2), (display_height / 2) + y_displace
gameDisplay.blit(textSurf, textRect)
def button(text, color, x, y, width, height, inactive_color, active_color, value = None):
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + width > cur[0] > x and y + height > cur[1] > y:
pygame.draw.rect(gameDisplay, active_color, (x, y, width, height))
if click[0] == 1 and value != None:
if value == "easy":
easyvalues = list(range(10, 100 + 1))
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
gameLoop()
if value == "medium":
mediumvalues = list(range(100, 1000 + 1))
sum1 = random.choice(mediumvalues)
sum2 = random.choice(mediumvalues)
gameLoop()
if value == "hard":
hardvalues = list(range(1000, 10000 + 1))
sum1 = random.choice(hardvalues)
sum2 = random.choice(hardvalues)
gameLoop()
else:
easyvalues = list(range(10, 100 + 1))
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
gameLoop()
else:
pygame.draw.rect(gameDisplay, inactive_color, (x, y, width, height))
text_to_button(text, black, x, y, width, height)
def question():
if value == "easy":
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
if value == "medium":
sum1 = random.choice(mediumvalues)
sum2 = random.choice(mediumvalues)
if value == "hard":
sum1 = random.choice(hardvalues)
sum2 = random.choice(hardvalues)
else:
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
print sum1
print sum2
print sum1 + sum2
print value
#Here I am trying to enable raw input from the user
def answer():
answer = ""
font = pygame.font.SysFont("Arial", 50)
pygame.draw.rect(gameDisplay, white, [200,250,400,100])
message_to_screen("What is: " + str(sum1) + " + " + str(sum2),
black,
-100,
"medium")
input = True
while input:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.unicode.isdigit():
answer += event.unicode
if event.key == K_BACKSPACE:
answer = answer[:-1]
# This is temporary, while I program the rest
elif event.key == K_RETURN:
if answer == sum1 + sum2:
message_to_screen("Correct!", green, 0, "large")
else:
message_to_screen("Wrong!", red, 0, "large")
elif event.key == pygame.K_KP_ENTER:
if answer == sum1 + sum2:
message_to_screen("Correct!", green, 0, "large")
else:
message_to_screen("Wrong!", red, 0, "large")
elif event.key == K_ESCAPE:
pygame.quit()
quit()
elif event.type == pygame.QUIT:
pygame.quit()
quit()
block = font.render("Answer: " + answer, True, black)
rect = 210,280
gameDisplay.blit(block, rect)
pygame.display.flip()
## This is a reference so that I can get my code working
##def name():
## pygame.init()
## screen = pygame.display.set_mode((480, 360))
## name = ""
## font = pygame.font.Font(None, 50)
## while True:
## for evt in pygame.event.get():
## if evt.type == KEYDOWN:
## if evt.unicode.isalpha():
## name += evt.unicode
## elif evt.key == K_BACKSPACE:
## name = name[:-1]
## elif evt.key == K_RETURN:
## name = ""
## elif evt.type == QUIT:
## return
## screen.fill((0, 0, 0))
## block = font.render(name, True, (255, 255, 255))
## rect = block.get_rect()
## rect.center = screen.get_rect().center
## screen.blit(block, rect)
## pygame.display.flip()
##def input_box():
##
## pygame.draw.rect(gameDisplay, grey, [(display_width / 2) - 150,(display_height / 2) + 160,300,80])
##
##
## for event in pygame.get():
## if event.type == pygame.KEYDOWN:
# This definition defines a start screen so that my game doesnt play straight away
def startScreen():
menu = True
while menu:
# This allows me to quit the game without any problems
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
quit()
# This takes away the menu screen and starts the game once you've pressed 'Enter'
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
menu = False
gameDisplay.fill(grey)
message_to_screen("Major League Mathematics", black, -200, "menu")
#button building
button("Easy", black, 100, 220, 150, 100, lightGrey, white, value = "easy")
button("Medium", black, 325, 220, 150, 100, lightGrey, white, value = "medium")
button("Hard", black, 550, 220, 150, 100, lightGrey, white, value = "hard")
message_to_screen("Select a difficulty to start!", black, 250, "small")
pygame.display.update()
# This is my main loop that my game will run off
def gameLoop():
gameExit = False
gameOver = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
quit()
gameDisplay.fill(grey)
answer()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
startScreen()
Inside you question() function, if value is not equal to "easy", "medium" or "hard", it'll bump into an undefined sum1 variable. As you didn't say exactly in which line the exception is raised, that would be my best bet.
EDIT:
OK, the reason I asked if you knew about some variable scope concepts is because I see you have some functions not being called and tries to access variables outside their scope. I strongly suggest you further readings about variable scoping, but as an immediate answer, the following changes in your code should work for you (can't test it from here):
- In your button function
if x + width > cur[0] > x and y + height > cur[1] > y:
pygame.draw.rect(gameDisplay, active_color, (x, y, width, height))
if click[0] == 1 and value != None:
if value == "easy":
easyvalues = list(range(10, 100 + 1))
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
gameLoop(sum1, sum2)
if value == "medium":
mediumvalues = list(range(100, 1000 + 1))
sum1 = random.choice(mediumvalues)
sum2 = random.choice(mediumvalues)
gameLoop(sum1, sum2)
if value == "hard":
hardvalues = list(range(1000, 10000 + 1))
sum1 = random.choice(hardvalues)
sum2 = random.choice(hardvalues)
gameLoop(sum1, sum2)
else:
easyvalues = list(range(10, 100 + 1))
sum1 = random.choice(easyvalues)
sum2 = random.choice(easyvalues)
gameLoop(sum1, sum2)
- In your gameLoop function
def gameLoop(sum1, sum2):
gameExit = False
gameOver = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
quit()
gameDisplay.fill(grey)
answer(sum1, sum2)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
- In your answer function
def answer(sum1, sum2):

2 functions in pygame related code not working. (probably syntax)

I wrote a code to make a game where, a player moves upwards and downwards, and has to dodge the flames. But the waitforkey() and drawtext() functions are not working at all.
so the code gives an error as soon as the game ends.
here is the code :
#Import modules
import pygame, random, sys
from pygame.locals import *
#intialising variables for ease
window_height=600
window_width=600
blue = (0,0,255)
black = (0,0,0)
fps=30
flamesize=20
speed = 5
addnewflamerate =20
#defining the required function
def terminate(): #to end the program
pygame.quit()
sys.exit()
def waitforkey(): #to wait for user to start
for event in pygame.event.get():
if event.type == "QUIT":
terminate()
if event.type == "KEYDOWN": #to terminate if the user presses the escape key
if event.key == "K_ESCAPE":
terminate()
return
def flamehitsmario(playerrect, flames): #to check if flame has hit mario or not
for f in flames:
if playerrect.colliderect(f['rect']):
return True
return False
def drawtext(text, WindowSurface, font, x, y): #to display text on the screen
textobj = font.render(text, 1, blue)
textrect = textobj.get_rect()
textrect.topleft = (x,y)
WindowSurface.blit(textobj, textrect)
#end of functions, begin to start the main code
pygame.init()
mainClock = pygame.time.Clock()
WindowSurface = pygame.display.set_mode((window_width,window_height))
pygame.display.set_caption('MARIO')
#setting up font and sounds and images
font = pygame.font.SysFont(None, 48)
playerimage = pygame.image.load('player.png')
playerrect = playerimage.get_rect()
flameimage = pygame.image.load('flame.png')
#getting to the start screen
#waitforkey() : if i remove the '#', the game hangs.
drawtext("Mario", WindowSurface, font, (window_width/3), (window_height/3))
drawtext("Press any key to start", WindowSurface, font, (window_width/3-50), (window_height/3+50))
pygame.display.update()
#start for the main code
topscore = 0
while True:
score = 0
flames = []
playerrect.topleft = (50,window_height/2)
moveup = movedown = False
flameaddcounter = 0
while True: #the main game loop
score+=1
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_UP:
movedown = False
moveup = True
if event.key == K_DOWN:
movedown = True
moveup = False
if event.type == KEYUP:
if event.key == K_UP:
moveup = False
if event.key == K_DOWN:
movedown = False
if event.key == K_ESCAPE:
terminate()
flameaddcounter += 1
if flameaddcounter == addnewflamerate:
flameaddcounter = 0
newflame = {'rect' : pygame.Rect(window_width - flamesize,random.randint(0, window_height - flamesize), flamesize, flamesize),
'speed' : speed,
'Surface' : pygame.transform.scale(flameimage, (flamesize,flamesize))
}
flames.append(newflame)
if (moveup and (playerrect.top > 0)):
playerrect.top -= speed
if (movedown and (playerrect.bottom < window_height)):
playerrect.bottom += speed
for f in flames:
f['rect'].left -= speed
for f in flames:
if f['rect'].left <= 0:
flames.remove(f)
WindowSurface.fill(black)
WindowSurface.blit(playerimage, playerrect)
for f in flames:
WindowSurface.blit(f['Surface'], f['rect'])
pygame.display.update()
if flamehitsmario(playerrect, flames):
if score > topscore:
topscore = score
drawtext('GAME OVER', font, WindowSurface, (window_width / 3), (window_height / 3))
drawtext('Press a key to play again.', font, WindowSurface, (window_width / 3) - 80, (window_height / 3) + 50)
pygame.display.update()
waitforkey()
mainClock.tick(fps)
And the required images :
http://inventwithpython.com/player.png
http://haryanacitygas.com/wp-content/uploads/2010/12/flame.png
THANKS :D.
if event.type == "QUIT":
You are seeing if event.type is equal to the string "QUIT". It will not be. Nor will any of the other events be equal to strings.
pygame defines a number of constants (ints actually) that you should test against.
if event.type == pygame.QUIT:
#etc
And similarly for your other event.type checks.
I can see that you switch the order of the arguments you pass to the function
drawtext. In your game loop you call the function with these arguments
drawtext('GAME OVER', font, WindowSurface, (window_width / 3), (window_height / 3))
But you define the function like this:
def drawtext(text, WindowSurface, font, x, y):
As you can see the font argument is passed in the place of the WindowSurface argument, and hence you are trying to basically render from a surface instead of a font :).
Just fix the order with which you pass the arguments to the function and it should work smoothly :)

Categories