Stopwatch with PyGame - python

Hi everyone! I want to create a stopwatch with pygame. I saw this code:
import pygame as pg
pg.init()
screen = pg.display.set_mode((400, 650))
clock = pg.time.Clock()
font = pg.font.Font(None, 54)
font_color = pg.Color('springgreen')
passed_time = 0
timer_started = False
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
timer_started = not timer_started
if timer_started:
start_time = pg.time.get_ticks()
if timer_started:
passed_time = pg.time.get_ticks() - start_time
screen.fill((30, 30, 30))
text = font.render(str(passed_time / 1000), True, font_color)
screen.blit(text, (50, 50))
pg.display.flip()
clock.tick(30)
pg.quit()
but when you press the spacebar, the timer restarts. how can i print it (on the screen)?

here is the updated code (since I assumed that You want to print multiple results on the screen, that is what I did):
import pygame as pg
pg.init()
screen = pg.display.set_mode((400, 650))
clock = pg.time.Clock()
font = pg.font.Font(None, 54)
font_color = pg.Color('springgreen')
passed_time = 0
start_time = None
timer_started = False
done = False
results = []
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
timer_started = not timer_started
if timer_started:
start_time = pg.time.get_ticks()
elif not timer_started:
results.append(passed_time)
if len(results) > 10:
results.pop(0)
if timer_started:
passed_time = pg.time.get_ticks() - start_time
screen.fill((30, 30, 30))
text = font.render(f'{(passed_time / 1000):.3f}', True, font_color)
screen.blit(text, (50, 50))
for index, result in enumerate(results):
text = font.render(f'{(result / 1000):.3f}', True, font_color)
screen.blit(text, (50, 50 + 54 * (len(results) - index)))
pg.display.flip()
clock.tick(30)
pg.quit()
The way this works: if the stopwatch is stopped the value it was stopped at gets appended to the list.
Then later in the code it reads each item in the list and puts it on the screen.
(50, 50 + 54 * (len(results) - index)) this makes sure that time is displayed in chronological order by when the time was recorded.
Also there is this part:
if len(results) > 10:
results.pop(0)
which makes sure that the list doesn't get overfilled.

Related

How do I fix my pause function in pygame?

I'm just recently finished watching a tutorial / introduction to pygame and I'm trying to add some changes to it, one of them being a pause function which I've gotten to work apart from some problems e.g when I jump it sets the score to zero and while I'm in the pause screen it still increases the score, I've tried fixing the two problems and looking other things similar but can't seem to fix it.
here's the code:
import pygame
from sys import exit
from random import randint, choice
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
player_walk_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/player_walk_2.png').convert_alpha()
self.player_walk = [player_walk_1, player_walk_2]
self.player_index = 0
self.player_jump = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Player/jump.png').convert_alpha()
self.image = self.player_walk[self.player_index]
self.rect = self.image.get_rect(midbottom=(80, 300))
self.gravity = 0
self.jump_sound = pygame.mixer.Sound('C:/Users/user/Documents/Dragon_Runner/audio/jump.mp3')
self.jump_sound.set_volume(0.5)
def player_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
self.gravity = -22
self.jump_sound.play()
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
def animation(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.060
if self.player_index >= len(self.player_walk): self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
def update(self):
self.player_input()
self.apply_gravity()
self.animation()
class Obstacle(pygame.sprite.Sprite):
def __init__(self, type):
super().__init__()
if type == 'snail':
snail_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1, snail_2]
y_pos = 300
else:
dragon_1 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon1.png').convert_alpha()
dragon_2 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon2.png').convert_alpha()
dragon_3 = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/Green Dragon3.png').convert_alpha()
self.frames = [dragon_1, dragon_2, dragon_3]
y_pos = 190
self.animation_index = 0
self.image = self.frames[self.animation_index]
self.rect = self.image.get_rect(midbottom=(randint(900, 1100), y_pos))
def animation(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames):
self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
def update(self):
self.animation()
self.rect.x -= 7
self.destroy()
def destroy(self):
if self.rect.x <= -100:
self.kill()
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surf = font1.render(f'Score: {current_time}', False, 'black')
score_rect = score_surf.get_rect(center=(400, 50))
screen.blit(score_surf, score_rect)
return current_time
def collision_sprite():
if pygame.sprite.spritecollide(player.sprite, obstacle_group, False):
obstacle_group.empty()
return False
else:
return True
pygame.init()
screen = pygame.display.set_mode((800, 400))
pygame.display.set_caption('Dragon Runner')
clock = pygame.time.Clock()
font1 = pygame.font.Font('C:/Users/user/Documents/Dragon_Runner/font/Pixeltype.ttf', 50)
game_active = False
paused = False
start_time = 0
score = 0
bg_music = pygame.mixer.Sound('C:/Users/user/Documents/Dragon_Runner/audio/music.wav')
bg_music.set_volume(0.2)
bg_music.play(loops=-1)
player = pygame.sprite.GroupSingle()
player.add(Player())
obstacle_group = pygame.sprite.Group()
sky_surface = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/Sky.png').convert()
ground_surface = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/ground.png').convert()
player_stand = pygame.image.load('C:/Users/user/Documents/Dragon_Runner/graphics/player/player_stand.png').convert_alpha()
player_stand = pygame.transform.rotozoom(player_stand, 0, 2)
player_stand_rect = player_stand.get_rect(center=(400, 200))
game_name = font1.render('Dragon Runner', False, (11, 196, 169))
game_name_rect = game_name.get_rect(center=(400, 80))
game_message = font1.render('Press space to run', False, (11, 196, 169))
game_message_rect = game_message.get_rect(center=(400, 330))
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, 1500)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
else:
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
start_time = int(pygame.time.get_ticks() / 1000)
if game_active and not paused:
if event.type == obstacle_timer:
obstacle_group.add(Obstacle(choice(['fly', 'snail', 'snail', 'snail'])))
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
paused = True
if paused:
if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
paused = False
if game_active and not paused:
screen.blit(sky_surface, (0, 0))
screen.blit(ground_surface, (0, 300))
score = display_score()
player.draw(screen)
player.update()
obstacle_group.draw(screen)
obstacle_group.update()
game_active = collision_sprite()
if not game_active:
screen.fill((94, 129, 162))
screen.blit(player_stand, player_stand_rect)
score_message = font1.render(f'Your score: {score}', False, (11, 196, 169))
score_message_rect = score_message.get_rect(center = (400, 330))
screen.blit(game_name, game_name_rect)
if score == 0:
screen.blit(game_message, game_message_rect)
else:
screen.blit(score_message, score_message_rect)
if paused:
screen.fill((94, 129, 162))
screen.blit(player_stand, player_stand_rect)
pause_message = font1.render('GAME PAUSED', False, (11, 196, 169))
pause_message_rect = pause_message.get_rect(center = (400, 80))
unpause_message = font1.render("Press 'c' to continue", False, (11, 196, 169))
unpause_message_rect = unpause_message.get_rect(center = (400, 330))
screen.blit(pause_message, pause_message_rect)
screen.blit(unpause_message, unpause_message_rect)
pygame.display.update()
clock.tick(60)
You need to minus paused time from the score, which
you can create a variable to store the accumulated paused time, as follows:
Define a new variable paused_total_time:
start_time = 0
paused_total_time = 0
score = 0
When game paused, you start the pause timer:
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
paused = True
pause_start_time = int(pygame.time.get_ticks() / 1000)
When game continue, you add paused time to paused_total_time:
if paused:
if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
paused = False
paused_total_time = paused_total_time + (int(pygame.time.get_ticks() / 1000) - pause_start_time)
Finally in display_score(), you can minus current_time by paused time.
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time - paused_total_time
score_surf = font1.render(f'Score: {current_time}', False, 'black')
score_rect = score_surf.get_rect(center=(400, 50))
screen.blit(score_surf, score_rect)
return current_time
Edit: There is a bug that the score reduces when character jumps, it is because start_time is reset when jump is triggered, you can add a statement to check if the game is started before resetting start_time and other variables for game start
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# check whether game is active before start game
if game_active == False:
game_active = True
start_time = int(pygame.time.get_ticks() / 1000)
paused_total_time = 0
score = 0

CREATING A REACTION TIME TEST GAME IN PYGAME

I am trying to create a reaction time test game in python using pygame for gui. Since, I am fairly new to the technology, I am stuck at a portion of the code as how to register further keypresses and then record time accordingly.
This is my code till now:
import pygame
from datetime import datetime
import time
import random
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Reaction Time Test")
font = pygame.font.SysFont(None, 30)
text = font.render("PRESS ANY KEY TO START TEST", 0, (255,255,255))
w = font.render("PRESS ANY KEY",0,(0,255,0))
count = 0
screen.blit(text, (150,240))
running = True
while running:
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if count <= 5 and event.type == pygame.KEYDOWN:
screen.fill(pygame.Color("black"))
pygame.display.flip()
wait_time = random.randint(1,4)
time.sleep(wait_time)
reaction_start = datetime.now()
print(reaction_start)
screen.blit(w,(225,200))
count = count + 1
if event.type == pygame.KEYDOWN:
reaction_end = datetime.now()
print(reaction_end)
t = reaction_end - reaction_start
print(t)
f = font.render("REACTION TIME: "+ str(t),0,(255,255,255))
screen.blit(f,(225,300))
if count > 5:
screen.fill(pygame.Color("black"))
pygame.display.flip()
s = font.render("AVERAGE REACTION TIME IS: ",0,(255,255,255))
screen.blit(s,(150,200))
pygame.display.flip()
The part where I am stuck at it is this code snippet
if count <= 5 and event.type == pygame.KEYDOWN:
screen.fill(pygame.Color("black"))
pygame.display.flip()
wait_time = random.randint(1,4)
time.sleep(wait_time)
reaction_start = datetime.now()
print(reaction_start)
screen.blit(w,(225,200))
count = count + 1
if event.type == pygame.KEYDOWN:
reaction_end = datetime.now()
print(reaction_end)
t = reaction_end - reaction_start
print(t)
f = font.render("REACTION TIME: "+ str(t),0,(255,255,255))
screen.blit(f,(225,300))
It would register the reaction_start and reaction_end almost simulataneously and would not wait for the key press.
This currently prints both the statements "PRESS ANY KEY" and "REACTION TIME:" together, but when I had put the statements of screen.fill(pygame.Color("black") and pygame.display.flip() before the screen.blit(f), it would only show REACTION TIME: and not "PRESS ANY KEY"
In pygame the system time can be obtained by calling pygame.time.get_ticks(), which returns the number of milliseconds since pygame.init() was called.
Do not try to delay or to wait in the application loop. Add a game_state variabel, that which can have the states "start", "wait" and "wait_for_reaction".
Get the current time at the begin of the application loop:
while running:
current_time = pygame.time.get_ticks()
Set the start time when a key is pressed:
if event.type == pygame.KEYDOWN:
if game_state == "start":
game_state = "wait"
start_time = current_time + random.randint(1000, 4000)
Chang the game_state form "wait" to "wait_for_reaction" when the current time is greater or equal the start time:
if game_state == "wait":
if current_time >= start_time:
game_state = "wait_for_reaction"
Compute the reaction time and restart the process, when a key is hit again:
if event.type == pygame.KEYDOWN:
# [...]
if game_state == "wait_for_reaction":
game_state = "wait"
reaction_time = (current_time - start_time) / 1000
start_time = current_time + random.randint(1000, 4000)
count += 1
average_time = (average_time * (count-1) + reaction_time) / count
r_surf = font.render(f"REACTION TIME: {reaction_time:.03f}",0,(255,255,255))
ar_surf = font.render(f"AVERAGE REACTION TIME IS: {average_time:.03f}",0,(255,255,255))
Redraw the scene in every frame, dependent on the state of the game:
while running:
# [...]
screen.fill(pygame.Color("black"))
center = screen.get_rect().center
if game_state == "start":
screen.blit(text, text.get_rect(center = center))
if game_state == "wait_for_reaction":
screen.blit(w, w.get_rect(center = center))
if r_surf:
screen.blit(r_surf, r_surf.get_rect(center = (center[0], 350)))
if ar_surf:
screen.blit(ar_surf, ar_surf.get_rect(center = (center[0], 400)))
pygame.display.flip()
Complete example:
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Reaction Time Test")
font = pygame.font.SysFont(None, 30)
text = font.render("PRESS ANY KEY TO START TEST", 0, (255,255,255))
w = font.render("PRESS ANY KEY",0,(0,255,0))
r_surf = None
ar_surf = None
game_state = "start"
start_time = 0
average_time = 0
count = 0
running = True
while running:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if game_state == "start":
game_state = "wait"
start_time = current_time + random.randint(1000, 4000)
if game_state == "wait_for_reaction":
game_state = "wait"
reaction_time = (current_time - start_time) / 1000
start_time = current_time + random.randint(1000, 4000)
count += 1
average_time = (average_time * (count-1) + reaction_time) / count
r_surf = font.render(f"REACTION TIME: {reaction_time:.03f}",0,(255,255,255))
ar_surf = font.render(f"AVERAGE REACTION TIME IS: {average_time:.03f}",0,(255,255,255))
if game_state == "wait":
if current_time >= start_time:
game_state = "wait_for_reaction"
screen.fill(pygame.Color("black"))
center = screen.get_rect().center
if game_state == "start":
screen.blit(text, text.get_rect(center = center))
if game_state == "wait_for_reaction":
screen.blit(w, w.get_rect(center = center))
if r_surf:
screen.blit(r_surf, r_surf.get_rect(center = (center[0], 350)))
if ar_surf:
screen.blit(ar_surf, ar_surf.get_rect(center = (center[0], 400)))
pygame.display.flip()

How do I restart my game without closing the program

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

Pointer not moving up or down despite using earlier and already working code

been trying for a while to find the problem with the following code. I'm trying to have the pointer move up and down like the title of the question states but it just won't move. Any and all help is welcome.
Code for Pause Screen event processing:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP or event.key == pygame.K_w:
self.pointer.moveUp()
print("Up we go")
if event.key == pygame.K_DOWN or event.key == pygame.K_s:
self.pointer.moveDown()
print("Down we go")
if event.key == pygame.K_RETURN:
self.selection = int(pointer.Pointer.getPosition(self.pointer))
print(str(pointer.Pointer.getPosition(self.pointer)))
return True
return False
Code for displaying which shows the pointer in the same place.
self.active_sprite_list.draw(screen)
font = pygame.font.SysFont("serif", 25)
text = []
center_x = []
center_y = []
for counter in range(1,5):
text.append(font.render(self.options[counter-1], True, constants.WHITE))
center_x.append(150)
center_y.append((counter * 120) - (text[counter-1].get_height() // 2) + (self.pointer.image.get_height() // 2))
screen.blit(text[counter-1], [center_x[counter-1],center_y[counter-1]])
pygame.display.flip()
And for reference the same code in the Menu which has the pointer moving up and down:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP or event.key == pygame.K_w:
self.pointer.moveUp()
if event.key == pygame.K_DOWN or event.key == pygame.K_s:
self.pointer.moveDown()
if event.key == pygame.K_RETURN:
self.selection = int(pointer.Pointer.getPosition(self.pointer))
#print(str(self.selection))
return True
###Some code later###
screen.fill(constants.BLACK)
font = pygame.font.SysFont("serif", 25)
for counter in range(1,5):
text = font.render(self.options[counter-1], True, constants.WHITE)
center_x = 150
center_y = (counter * 120) - (text.get_height() // 2) + (self.pointer.image.get_height() // 2)
screen.blit(text, [center_x, center_y])
self.active_sprite_list.draw(screen)
pygame.display.flip()
And before you suggest, the screen for the pause has been declared before here:
while notPaused == False:
#print("Received")
notPaused = pause.processEvents()
print(str(notPaused))
if firstTime == True:
self.pauseScreen.fill(constants.ABLACK)
pause.displayFrame(self.pauseScreen)
self.pauseScreen.set_alpha(128)
screen.blit(self.pauseScreen, [0,0])
firstTime = False
pause.displayFrame(self.pauseScreen)
clock.tick(60)
As per requested, here is the MoveUp and MoveDown functions in the Pointer Class:
def moveUp(self):
if self.rect.y <= 120:
self.rect.y = 480
else:
self.rect.y -= 120
def moveDown(self):
if self.rect.y >= 480:
self.rect.y = 120
else:
self.rect.y += 120
And as suggested, the modular/self-contained code that can be run on its own as long as you have some kind of image in a Resources Folder next to the saved code file.
import pygame, sys
"""
Global constants
"""
# Colors
ABLACK = ( 0, 0, 0, 125)
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
BLUE = ( 0, 0, 255)
YELLOW = ( 255, 255, 0)
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Pointer(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Resources/Pointer.png")
self.rect = self.image.get_rect()
self.rect.x = 100
self.rect.y = 120
def moveUp(self):
if self.rect.y <= 120:
self.rect.y = 480
else:
self.rect.y -= 120
print("Within pointer object moving up from ",self.rect.x,self.rect.y)
def moveDown(self):
if self.rect.y >= 480:
self.rect.y = 120
else:
self.rect.y += 120
print("Within pointer object moving up from ",self.rect.x,self.rect.y)
def getPosition(self):
self.position = self.rect.y / 120
return self.position
class Pause(object):
def __init__(self,screen):
self.selection = 4
self.options = ["Resume Game","Review Controls","Back to Menu","Quit"]
self.active_sprite_list = pygame.sprite.Group()
self.pointer = Pointer()
self.active_sprite_list.add(self.pointer)
def processEvents(self):
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP or event.key == pygame.K_w:
self.pointer.moveUp()
print("Up we go")
if event.key == pygame.K_DOWN or event.key == pygame.K_s:
self.pointer.moveDown()
print("Down we go")
if event.key == pygame.K_RETURN:
self.selection = int(Pointer.getPosition(self.pointer))
print(str(Pointer.getPosition(self.pointer)))
return False
return True
def displayFrame(self,screen):
self.active_sprite_list.draw(screen)
for pointer in self.active_sprite_list:
print("The y value of this pointer is:" + str(pointer.rect.y))
font = pygame.font.SysFont("serif", 25)
text = []
center_x = []
center_y = []
for counter in range(1,5):
text.append(font.render(self.options[counter-1], True, WHITE))
center_x.append(150)
center_y.append((counter * 120) - (text[counter-1].get_height() // 2) + (self.pointer.image.get_height() // 2))
for pointer in self.active_sprite_list:
print("The y value of this pointer is:" + str(pointer.rect.y))
screen.blit(text[counter-1], [center_x[counter-1],center_y[counter-1]])
for pointer in self.active_sprite_list:
print("The y value of this pointer is:" + str(pointer.rect.y))
pygame.display.flip()
pygame.init()
pygame.display.set_caption("Pause Error Finder")
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
Paused = True
clock = pygame.time.Clock()
pauseScreen = pygame.Surface(size,pygame.SRCALPHA,32)
pauseScreen.fill(ABLACK)
pause = Pause(screen)
pauseScreen.set_alpha(128)
Paused = pause.processEvents()
print(str(notPaused))
pause.displayFrame(pauseScreen)
screen.blit(pauseScreen, [0,0])
while Paused:
notPaused = pause.processEvents()
print(str(Paused))
pause.displayFrame(pauseScreen)
#screen.blit(pauseScreen, [0,0])
clock.tick(60)
Your issue is in the main game loop, first off, you had the blitting of Pause Screen to Screen commented out. readding that in gave the pointer seeming to multiply and go all over the place (getting closer!).
The reason it does that is you did not update your pauseScreen in each pass of the loop. Your displayFrame will add your pointer to the proper location, but the one from last frame, and 2 frames ago, and... are still there. by moving the lines
pauseScreen.fill(ABLACK)
pauseScreen.set_alpha(128)
And placing them within your game loop, the pause screen is reset ever frame and only the latest pointer is displayed. Here is the updated game loop:
pygame.init()
pygame.display.set_caption("Pause Error Finder")
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
notPaused = False
clock = pygame.time.Clock()
pauseScreen = pygame.Surface(size,pygame.SRCALPHA,32)
pause = Pause(screen)
notPaused = pause.processEvents()
print(str(notPaused))
pause.displayFrame(pauseScreen)
screen.blit(pauseScreen, [0,0])
while not notPaused:
notPaused = pause.processEvents()
print(str(notPaused))
pauseScreen.fill(ABLACK)
pauseScreen.set_alpha(128)
pause.displayFrame(pauseScreen)
screen.blit(pauseScreen, [0,0])
clock.tick(60)

How can you add movement to shapes in pygame?

I am using python 2.7 an tried to make a simple game using the pygame module. In the program it makes a rectangle, and what I am having trouble doing is getting it to move upon keys being pressed. I believe the problem is with the 'player.move' part in my code, but the documentation was poor for it on pygames website. Any help is appreciated.
import pygame
import random
import time
pygame.init()
white = (255,255,255)
black = (0,0,0)
displayWidth = 800
displayHeight = 800
FPS = 30
clock = pygame.time.Clock()
blockWidth = 50
blockHeight = 50
pygame.display.set_caption('Test Game')
screen = pygame.display.set_mode([displayWidth, displayHeight])
background = pygame.Surface(screen.get_size())
background.fill((white))
background = background.convert()
screen.blit(background, (0,0))
global xStart, yStart
xStart = 400
yStart = 400
global player
player = pygame.draw.rect(screen, black, ([xStart,yStart,blockWidth,blockHeight]))
pygame.display.update()
def mainloop():
global x, y
x = xStart
y = yStart
mainloop = True
pygame.display.update()
while mainloop == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False
if event.key == pygame.K_UP:
player.move(x, y + 10)
pygame.display.update()
if event.key == pygame.K_DOWN:
player.move(x, y - 10)
pygame.display.update()
if event.key == pygame.K_LEFT:
player.move(x - 10, y)
pygame.display.update()
if event.key == pygame.K_RIGHT:
player.move(x + 10, y)
pygame.display.update()
clock.tick(FPS)
pygame.display.flip()
mainloop()
pygame.quit()
Find tutorial (ie, Program Arcade Games With Python And Pygame) because you have many things to change.
PyGame is low-level library and you have to do everything on your own. In while loop you have to clear screen or draw background and draw player - again and again.
Here your code after modifications.
You have to learn pygame.Rect, pygame.Surface, (pygame.Sprite), events, etc.
import pygame
import random
import time
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255)
BLACK = (0 , 0, 0)
DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 800
FPS = 30
BLOCK_WIDTH = 50
BLOCK_HEIGHT = 50
# --- functions --- (lower_case names)
def run():
mainloop = True
speed_x = 0
speed_y = 0
while mainloop:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False
# - start moving -
elif event.key == pygame.K_UP:
speed_y = -10
elif event.key == pygame.K_DOWN:
speed_y = 10
elif event.key == pygame.K_LEFT:
speed_x = -10
elif event.key == pygame.K_RIGHT:
speed_x = 10
#elif event.type == pygame.KEYUP:
# # - stop moving -
# if event.key == pygame.K_UP:
# speed_y = 0
# elif event.key == pygame.K_DOWN:
# speed_y = 0
# elif event.key == pygame.K_LEFT:
# speed_x = 0
# elif event.key == pygame.K_RIGHT:
# speed_x = 0
# --- updates ---
player_rect.move_ip(speed_x, speed_y)
# --- draws ---
screen.blit(background, background_rect)
screen.blit(player, player_rect)
pygame.display.flip()
clock.tick(FPS)
# --- main ---
pygame.init()
pygame.display.set_caption('Test Game')
screen = pygame.display.set_mode( (DISPLAY_WIDTH, DISPLAY_HEIGHT) )
screen_rect = screen.get_rect()
background_rect = screen_rect
background = pygame.Surface(background_rect.size)
background.fill(WHITE)
background = background.convert()
player_rect = pygame.Rect(400, 400, BLOCK_WIDTH, BLOCK_HEIGHT)
player = pygame.Surface(player_rect.size)
player.fill(BLACK)
clock = pygame.time.Clock()
run()
pygame.quit()

Categories