How to make Pacman's ghost randomly move around in Python? - python

How do I make a ghost in Pacman move around randomly? I figured out how to move your own player. I tried using the random.randiant command but instead it kept coming up with a blank screen. I tried bliting all the images but it still keeps coming up with a blank screen. I just want to experiment with the ghost first before I program it to kill the player. I'm running Window 7, Python 3.1 and Pygame 3.1.
import pygame, sys
from pygame.locals import *
pygame.init()
windowSurface = pygame.display.set_mode((640,480), 0, 32)
pygame.display.set_caption('Pacman')
background = pygame.image.load('back.jpg').convert()
pacman = pygame.image.load('aimball.png').convert_alpha()
ghost = pygame.image.load('ghosts.png').convert_alpha()
food = pygame.image.load('food.png').convert_alpha()
windowSurface.blit(background, (0,0))
windowSurface.blit(pacman, (0,0))
windowSurface.blit(pacman,(x,y))
windowSurface.blit(ghost, (100,100))
windowSurface.blit(ghost, (x,y ))
windowSurface.blit(food, (0,0))
def pacman():
x, y = 0,0
movex, movey = 0,0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_q:
pygame.quit()
sys.exit()
elif event.key == K_LEFT:
movex = -1
elif event.key == K_RIGHT:
movex = +1
elif event.key == K_UP:
movey = -1
elif event.key == K_DOWN:
movey = +1
elif event.type == KEYUP:
if event.key == K_LEFT:
movex = 0
elif event.key == K_RIGHT:
movex = 0
elif event.key == K_UP:
movey = 0
elif event.key == K_DOWN:
movey = 0
x+=movex
y+=movey
def ghosts():
x, y = 0,0
movex, movey = 0,0
while True:
random.randiant = move(1,2,3,4)
if random.randiant == 1:
movex=-1
elif random.randiant == 2:
movex=+1
elif random.randiant == 3:
movey=-1
elif random.randiant == 4:
movey=+1
x+=movex
y+=movey
windowSurface.blit(background,(0,0))
windowSurface.blit(pacman,(x,y))
windowSurface.blit(pacman, (0,0))
windowSurface.blit(ghost, (x,y ))
windowSurface.blit(ghost, (100,100))
windowSurface.blit(food, (0,0))
pygame.display.update()
pygame.display.flip()
NOTE: I will not be making boundaries for my Pacman game. The ghost can move freely around the Pygame screen display.

so here is my pacman game, i hope it helps
import pygame
from pygame.locals import *
from sys import exit
import random as r
import time
# SET CHARECTERS POSITIONS START
player_x = 400
player_y = 200
ghost_1_x = -50
ghost_1_y = r.randint(1, 400)
ghost_2_x = r.randint(1, 800)
ghost_2_y = -50
ghost_3_x = 850
ghost_3_y = r.randint(1, 400)
ghost_4_x = r.randint(1, 800)
ghost_4_y = 450
point_x = r.randint(50, 750)
point_y = r.randint(10, 390)
# SET CHARECTERS POSITIONS END
# EXTRA VARIABLES START
points = .2
speed = points
running = True
size = 20
# EXTRA VARIABLES END
# START THE BEGINING OF THE MAIN PYTHON CODE START
pygame.init()
# START THE BEGINING OF THE MAIN PYTHON CODE END
# SET SCREEN SIZE START
screen = pygame.display.set_mode((800, 400))
# SET SCREEN SIZE END
# SET TITLE START
pygame.display.set_caption('my pac_man')
# SET TITLE END
# LOADING THE IMAGES OF THE CHARACTARS START
player = pygame.image.load ('pacman.png').convert()
ghost_1 = pygame.image.load('ghost1.png').convert()
ghost_2 = pygame.image.load('ghost2.png').convert()
ghost_3 = pygame.image.load('ghost1.png').convert()
ghost_4 = pygame.image.load('ghost2.png').convert()
point = pygame.image.load('Star.png').convert()
# LOADING THE IMAGES OF THE CHARECTERS END
# DEFINING DIRECTIONS START
up = 1
down = 2
left = 3
right = 4
# DEFINING DIRECTIONS END
# DEFINING STARTING DIRECTION VARIABLE START
direction = up
# DEFINING STARTING DIRECTION VARIABLE END
# MAIN GAME LOOP START
while running:
# TRANSFORMING THE IMAGES SO THAT THEY FIT ON THE SCREEN START
player = pygame.transform.scale(player, (size, size))
ghost_1 = pygame.transform.scale(ghost_1, (size, size))
ghost_2 = pygame.transform.scale(ghost_2, (size, size))
ghost_3 = pygame.transform.scale(ghost_1, (size, size))
ghost_4 = pygame.transform.scale(ghost_2, (size, size))
point = pygame.transform.scale(point, (size, size))
# TRANSFORMING THE IMAGES SO THAT THEY FIT ON THE SCREEN END
# EXTRA VARIABLES NEEDED IN GAME LOOP START
speed = points
# EXTRA VARIABLES NEEDED IN GAME LOOP END
# LOOK FOR EVENTS IN PYGAME START
for event in pygame.event.get():
# CHECK IF THE MOUSE HITS THE X START
if event.type == pygame.QUIT:
# IF THE MOUSE HITS THE X THEN EXIT START
pygame.quit()
exit()
# IF THE MOUSE HITS THE X THEN EXIT END
#CHECK IF THE MOUSE HITS THE X END
# SENCE A KEY IS PRESSED START
if event.type == pygame.KEYDOWN:
# SENCE IF AN ARROW KEY IS PRESSED
if event.key == pygame.K_LEFT:
direction = left
if event.key == pygame.K_RIGHT:
direction = right
if event.key == pygame.K_UP:
direction = up
if event.key == pygame.K_DOWN:
direction = down
# SENCE IF AN ARROW KEY IS PRESSED END
# SENCE IF A KEY IS PERSSED END
# LOOK FOR EVENTS IN PYGAME END
# PLAYER MOVEMENT START
if direction == up:
player_y -= speed
if direction == down:
player_y += speed
if direction == left:
player_x -= speed
if direction == right:
player_x += speed
# PLAYER MOVEMENT END
# PLAYER EDGE SENCING START
if player_x >= 800:
running = False
if player_x <= 0:
running = False
if player_y >= 400:
running = False
if player_y <= 0:
running = False
# PLAYER EDGE SENCING END
# GHOST 1 MOVEMENT START
if ghost_1_x <= player_x:
ghost_1_x += speed / 2
if ghost_1_x >= player_x:
ghost_1_x -= speed / 2
if ghost_1_y <= player_y:
ghost_1_y += speed / 2
if ghost_1_y >= player_y:
ghost_1_y -= speed / 2
# GHOST 1 MOVEMSNT END
# GHOST 2 MOVEMENT START
if ghost_2_x <= player_x:
ghost_2_x += speed / 2
if ghost_2_x >= player_x:
ghost_2_x -= speed / 2
if ghost_2_y <= player_y:
ghost_2_y += speed / 2
if ghost_2_y >= player_y:
ghost_2_y -= speed / 2
# GHOST 2 MOVEMSNT END
# GHOST 3 MOVEMENT START
if ghost_3_x <= player_x:
ghost_3_x += speed / 2
if ghost_3_x >= player_x:
ghost_3_x -= speed / 2
if ghost_3_y <= player_y:
ghost_3_y += speed / 2
if ghost_3_y >= player_y:
ghost_3_y -= speed / 2
# GHOST 3 MOVEMSNT END
# GHOST 4 MOVEMENT START
if ghost_4_x <= player_x:
ghost_4_x += speed / 2
if ghost_4_x >= player_x:
ghost_4_x -= speed / 2
if ghost_4_y <= player_y:
ghost_4_y += speed / 2
if ghost_4_y >= player_y:
ghost_4_y -= speed / 2
# GHOST 4 MOVEMSNT END
# BACKGROUND COLOR START
screen.fill((0, 0, 0))
# BACKGROUND COLOR END
# collision sencing format
# if rect_1 x < rect_2 x + rect_1 width and rect_1 x + rect_2 width > rect_2 x and rect_1 y < rect_2 y + rect_1 height and rect_1 height + rect_1 y > rect_2 y
# CHECKING FOR COLLISION START
if player_x < ghost_1_x + size and player_x + size > ghost_1_x and player_y < ghost_1_y + size and size + player_y > ghost_1_y:
running = False
if player_x < ghost_2_x + size and player_x + size > ghost_2_x and player_y < ghost_2_y + size and size + player_y > ghost_2_y:
running = False
if player_x < ghost_3_x + size and player_x + size > ghost_3_x and player_y < ghost_3_y + size and size + player_y > ghost_3_y:
running = False
if player_x < ghost_4_x + size and player_x + size > ghost_4_x and player_y < ghost_4_y + size and size + player_y > ghost_4_y:
running = False
if player_x < point_x + size and player_x + size > point_x and player_y < point_y + size and size + player_y > point_y:
points += 0.1
size += 5
point_x = r.randint(50, 750)
point_y = r.randint(10, 390)
# CHECKING FOR COLLISION END
# PLACE CHARACTERS START
screen.blit(player, (player_x, player_y))
screen.blit(ghost_1, (ghost_1_x, ghost_1_y))
screen.blit(ghost_2, (ghost_2_x, ghost_2_y))
screen.blit(ghost_3, (ghost_3_x, ghost_3_y))
screen.blit(ghost_4, (ghost_4_x, ghost_4_y))
screen.blit(point, (point_x, point_y))
# PLACE CHARECTERS END
# SHOW SCORE START
font = pygame.font.Font(None, size)
if size == 20:
text = font.render(('20'), 1, (255, 0, 0))
if size == 25:
text = font.render(('25'), 1, (255, 0, 255))
if size == 30:
text = font.render(('30'), 1, (255, 255, 0))
if size == 35:
text = font.render(('35'), 1, (0, 255, 0))
if size == 40:
text = font.render(('40'), 1, (0, 0, 255))
if size == 45:
text = font.render(('45'), 1, (255, 0, 255))
if size == 50:
text = font.render(('50'), 1, (255, 255, 255))
if size == 55:
text = font.render(('55'), 1, (255, 255, 255))
if size == 60:
text = font.render(('YOU WIN'), 1, (255, 255, 255))
screen.blit(text, (200,200))
# SHOW SCORE END
# UPDATE CHANGES IN CODE, VARIABLES, PICTURES, ECT... IN PYGAME START
pygame.display.update()
# UPDATE CHANGES IN CODE, VARIABLES, PICTURES, ECT... IN PYGAME END
# MAIN GAME LOOP END

I think what you're asking for is
class Ghost():
def __init__(self):
self.x, self.y = 0, 0
self.movex, self.movey = 0, 0
def move(self):
# move in random directions.
self.movex = random.randint(-1,1)
self.movey = random.randint(-1,1)
self.x += movex
self.y += movey

Related

Is there a way to make the box like go towards the x which the player is going and also being able to change direction if the player jumps over it

import pygame
from sys import exit
import random
pygame.init()
WIDTH, HEIGHT = 800, 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My game!")
fps = pygame.time.Clock()
active = True
score = 0
startedplus = False
startedminus = False
test_font = pygame.font.Font("letters.ttf", 50)
text_surface = test_font.render((f"Score: {score}") , False, (64,64,64))
text_rect = text_surface.get_rect(center = (400,50))
#game over
game_over = pygame.image.load("game_over.png").convert()
#Heart
heart = pygame.image.load("heart.png").convert_alpha()
heart = pygame.transform.rotozoom(heart,0,0.6)
#Box
box = pygame.image.load("box.png").convert_alpha()
box = pygame.transform.rotozoom(box,0,0.3)
box_rect = box.get_rect(midbottom = (100,305))
#Background och Ground
background = pygame.image.load("sky.png").convert()
ground = pygame.image.load("ground.png").convert()
#player PNG
player = pygame.image.load("player.png").convert_alpha()
player = pygame.transform.rotozoom(player,0,2.5)
player_rect = player.get_rect(midbottom = (400,325))
#pickaxe PNG
pickaxe = pygame.image.load("pickaxe.png").convert_alpha()
pickaxe = pygame.transform.rotozoom(pickaxe,0,3.5)
pickaxe_rect = pickaxe.get_rect(center = (400,325))
#Gravity
player_gravity = 0
pickaxe_gravity = 0
adding = 0.01
hearts = 4
collided_in_the_last_frame = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if active:
if event.type == pygame.MOUSEBUTTONDOWN:
if player_rect.collidepoint(event.pos) and player_rect.bottom >= 325:
player_gravity = -20
pickaxe_gravity = -20
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
player_rect.x -= 40
pickaxe_rect.x -= 40
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
player_rect.x += 40
pickaxe_rect.x += 40
if (event.key == pygame.K_SPACE or event.key == pygame.K_w or event.key == pygame.K_UP) and player_rect.bottom >= 325:
player_gravity = -20
pickaxe_gravity = -20
else:
if event.type == pygame.KEYDOWN and event.key == pygame.K_x:
box_x = random.randint(10, 800)
box_rect = box.get_rect(midbottom = (box_x,305))
hearts = 4
active = True
if active:
collides = player_rect.colliderect(box_rect)
if collides and not collided_in_the_last_frame:
hearts -= 1
collided_in_the_last_frame = collides
screen.blit(background,(0,0))
screen.blit(ground,(0,300))
if player_rect.colliderect(box_rect):
box_x = random.randint(10, 800)
box_rect = box.get_rect(midbottom = (box_x,305))
adding = adding + 0.001
if player_rect.x <= 400:
box_rect.x += (1 + adding)
elif player_rect.x >= 400:
box_rect.x -= (1 + adding)
if hearts == 0:
active = False
elif hearts == 1:
screen.blit(heart, (35,35))
elif hearts == 2:
screen.blit(heart, (35,35))
screen.blit(heart, (65,35))
elif hearts == 3:
screen.blit(heart, (35,35))
screen.blit(heart, (65,35))
screen.blit(heart, (95,35))
else:
screen.blit(heart, (35,35))
screen.blit(heart, (65,35))
screen.blit(heart, (95,35))
screen.blit(heart, (125,35))
screen.blit(box, box_rect)
screen.blit(pickaxe, pickaxe_rect)
screen.blit(player,player_rect)
screen.blit(text_surface, text_rect)
player_gravity += 1
pickaxe_gravity += 1
player_rect.y += player_gravity
pickaxe_rect.y += pickaxe_gravity
if pickaxe_rect.bottom >= 325: pickaxe_rect.bottom = 325
if player_rect.bottom >= 325: player_rect.bottom = 325
if player_rect.x <= -10 and pickaxe_rect.x <= -10:
player_rect.x = -10
pickaxe_rect.x = player_rect.x - 70
mouse_pos = pygame.mouse.get_pos()
if player_rect.collidepoint(mouse_pos):
player_gravity = -20
pickaxe_gravity = -20
player_rect.y += player_gravity
pickaxe_rect.y += pickaxe_gravity
if pickaxe_rect.bottom >= 325: pickaxe_rect.bottom = 325
if player_rect.bottom >= 325: player_rect.bottom = 325
else:
screen.blit(game_over, (0,0))
pygame.display.update()
fps.tick(60)
How can I make the box like follow the player. I want it like when the player is "right" of the box then the box will start going right and when the player is "left" of the box the box will start going left.
I tried many ways but none worked so in the end I was left with this:
adding = adding + 0.001
if player_rect.x <= 400:
box_rect.x += (1 + adding)
elif player_rect.x >= 400:
box_rect.x -= (1 + adding)
And I thought it would work but it didnt.
You have to compare the position of the box with the position of the player. e.g.:
if box_rect.right < player_rect.left:
box_rect.x += 1
elif box_rect.left > player_rect.right:
box_rect.x -= 1
Also not, that pygame.Rect is supposed to represent an area on the screen, therfore a pygame.Rect object can only store integral data.
The coordinates for Rect objects are all integers. [...]
The fractional part of the coordinates is lost when a floating point value is added to a coordinate of a pygame.Rect object. Therefore box_rect.x += (1 + adding) always adds 1 to and box_rect.x -= (1 + adding) always subtracts 2 (as long 0 < a <= 1).
Also see Pygame doesn't let me use float for rect.move, but I need it

Trying to control the speed of my loop for Pong

I'm trying to get my pong game to run the loop at a certain fps, but I've tried a couple things and it hasn't worked and I wasn't taught how to use pygame speed/clock so I gotta figure it out on my own
I'm trying to make the loop run at a certain speed to make it look smoother, because if I edit the dx or the position it goes to when you change it, it looks chunky, so instead of a paddle 10 x down (looks chunky) i want to move it 1 x down a bunch of times so it moves down just as fast as 10 x but smoother
Full Code
import pygame #how to fix paddle widths from hitting ball
import sys
pygame.init()
screenSize = (800,600)
screen = pygame.display.set_mode((screenSize),0)
pygame.display.set_caption("HajarPongBasicCollision")
# colours
WHITE = (255,255,255)
BLACK = (0, 0, 0)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
PURPLE = (154, 136, 180)
screen.fill(BLACK)
pygame.display.update()
# retrieve screen measurements
screenw = screen.get_width()
screenh = screen.get_height()
# retrieve position of center of screen
centerx= 400 #tried not to use hard coded values but program gives me an error when i use screenw/2 ASK MR H TO HELP WITH NO HARD CODED VALUES (HCV)
centery= 300
# variables for first paddle
p1x = 10
p1y = 10
p1w = 10
p1h = 100
p1dy = 0
p1_score = 0
# variables for second paddle
p2w = 10
p2h = 100
p2x = screenw - 20
p2y = 10
p2dy = 0
p2_score = 0
# variable for ball
bx = 400 #HCV
by = 300 #HCV
br = 9
bdx = 1
bdy = 1
# speed of loop
fpsClock = pygame.time.Clock()
FPS = 60
go = True
while go:
fpsClock.tick(FPS)
for event in pygame.event.get():
if event.type ==pygame.QUIT:
go = False
elif event.type == pygame.KEYDOWN:
# control for the first paddle
if event.key == pygame.K_w:
p1dy = -1
elif event.key == pygame.K_s:
p1dy = 1
# controls for the second paddle
elif event.key == pygame.K_UP:
p2dy = -1
elif event.key == pygame.K_DOWN:
p2dy = 1
elif event.key == pygame.K_q:
go = False
# stops rectangles from going continously
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
p1dy = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
p2dy = 0
# stops paddle one from going off the screen
if (p1y < 0):
p1dy = 0
p1y = 0
if (p1y + p1h > screenh):
p1dy = 0
p1y = screenh - p1h
# stops paddle two from going off the screen
if (p2y < 0):
p2dy = 0
p2y = 0
if (p2y + p2h > screenh):
p2dy = 0
p2y = screenh - p2h
# stops ball from going off the screen
if (bx + br >= screenw):
bx = centerx
by = centery
elif (bx <= br):
bx = centerx
by = centery
if (by + br >= screenh):
bdy = -bdy
elif (by <= br):
bdy = -bdy
# detects if ball hit paddles
if bx - br <= p1x + p1w and by >= p1y and by <= p1y + p1h:
bdx = -bdx
if bx + br >= p2x and by >= p2y and by <= p2y + p2h:
bdx = -bdx
# moves the rectangles
p1y = p1y + p1dy
p2y = p2y + p2dy
# moves the ball
bx = bx + bdx
by = by + bdy
# removes screen trail
screen.fill(BLACK)
# draws the rectangles
pygame.draw.rect(screen, WHITE,(p1x, p1y, p1w, p1h))
pygame.draw.rect(screen, WHITE,(p2x, p2y, p2w, p2h))
pygame.draw.circle(screen, WHITE, (bx, by), br, 0)
pygame.display.update()
pygame.quit()
sys.exit()
Uncouple the speed of your objects from the fps.
That way you don't need to change your fps if you want objects to move faster, you just increase the speed of the object.
and if a computer has performance issues and can't keep a reliable fps. Your game still runs at the same speed, it just shows less frames.
import time
...
# speed of objects
ball_speed = 50
paddle_speed = 200
...
last_update = time.time()
while True:
...
dt = time.time() - last_update
...
# moves the ball
bx += bdx * ball_speed * dt
...
pygame.draw.circle(screen, WHITE, (int(bx), int(by)), br, 0)
...
last_update = time.time()

add a stopwatch to a game in pygame

i want to add a stopwatch in my pygame. I am planning to modify this code and add in my pygame:
Sec += 1
print(str(Min) + " Mins " + str(Sec) + " Sec ")
if Sec == 60:
Sec = 0
Min += 1
print(str(Min) + " Minute")
Should i add a timer box in my def init part and create a new def for the timer code? I want to have the timer without using the code tick since my game is running clock.tick(60) so it does not effect the tick
UPDATED
So here is my game code:
import sys, pygame, random
class Breakout():
def main(self):
xspeed_init = 6
yspeed_init = 6
max_lives = 5
bat_speed = 30
score = 0
bgcolour = 0x2F, 0x4F, 0x4F # darkslategrey
size = width, height = 640, 480
pygame.init()
screen = pygame.display.set_mode(size)
#screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
bat = pygame.image.load("bat.png").convert()
batrect = bat.get_rect()
ball = pygame.image.load("ball.png").convert()
ball.set_colorkey((255, 255, 255))
ballrect = ball.get_rect()
pong = pygame.mixer.Sound('Blip_1-Surround-147.wav')
pong.set_volume(10)
wall = Wall()
wall.build_wall(width)
# Initialise ready for game loop
batrect = batrect.move((width / 2) - (batrect.right / 2), height - 20)
ballrect = ballrect.move(width / 2, height / 2)
xspeed = xspeed_init
yspeed = yspeed_init
lives = max_lives
clock = pygame.time.Clock()
pygame.key.set_repeat(1,30)
pygame.mouse.set_visible(0) # turn off mouse pointer
while 1:
# 60 frames per second
clock.tick(60)
# process key presses
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
if event.key == pygame.K_LEFT:
batrect = batrect.move(-bat_speed, 0)
if (batrect.left < 0):
batrect.left = 0
if event.key == pygame.K_RIGHT:
batrect = batrect.move(bat_speed, 0)
if (batrect.right > width):
batrect.right = width
# check if bat has hit ball
if ballrect.bottom >= batrect.top and \
ballrect.bottom <= batrect.bottom and \
ballrect.right >= batrect.left and \
ballrect.left <= batrect.right:
yspeed = -yspeed
pong.play(0)
offset = ballrect.center[0] - batrect.center[0]
# offset > 0 means ball has hit RHS of bat
# vary angle of ball depending on where ball hits bat
if offset > 0:
if offset > 30:
xspeed = 7
elif offset > 23:
xspeed = 6
elif offset > 17:
xspeed = 5
else:
if offset < -30:
xspeed = -7
elif offset < -23:
xspeed = -6
elif xspeed < -17:
xspeed = -5
# move bat/ball
ballrect = ballrect.move(xspeed, yspeed)
if ballrect.left < 0 or ballrect.right > width:
xspeed = -xspeed
pong.play(0)
if ballrect.top < 0:
yspeed = -yspeed
pong.play(0)
# check if ball has gone past bat - lose a life
if ballrect.top > height:
lives -= 1
# start a new ball
xspeed = xspeed_init
rand = random.random()
if random.random() > 0.5:
xspeed = -xspeed
yspeed = yspeed_init
ballrect.center = width * random.random(), height / 3
if lives == 0:
msg = pygame.font.Font(None,70).render("Game Over", True, (0,255,255), bgcolour)
msgrect = msg.get_rect()
msgrect = msgrect.move(width / 2 - (msgrect.center[0]), height / 3)
screen.blit(msg, msgrect)
pygame.display.flip()
# process key presses
# - ESC to quit
# - any other key to restart game
while 1:
restart = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
if not (event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT):
restart = True
if restart:
screen.fill(bgcolour)
wall.build_wall(width)
lives = max_lives
score = 0
break
if xspeed < 0 and ballrect.left < 0:
xspeed = -xspeed
pong.play(0)
if xspeed > 0 and ballrect.right > width:
xspeed = -xspeed
pong.play(0)
# check if ball has hit wall
# if yes yhen delete brick and change ball direction
index = ballrect.collidelist(wall.brickrect)
if index != -1:
if ballrect.center[0] > wall.brickrect[index].right or \
ballrect.center[0] < wall.brickrect[index].left:
xspeed = -xspeed
else:
yspeed = -yspeed
pong.play(0)
wall.brickrect[index:index + 1] = []
score += 10
screen.fill(bgcolour)
scoretext = pygame.font.Font(None,40).render(str(score), True, (0,255,255), bgcolour)
scoretextrect = scoretext.get_rect()
scoretextrect = scoretextrect.move(width - scoretextrect.right, 0)
screen.blit(scoretext, scoretextrect)
for i in range(0, len(wall.brickrect)):
screen.blit(wall.brick, wall.brickrect[i])
# if wall completely gone then rebuild it
if wall.brickrect == []:
wall.build_wall(width)
xspeed = xspeed_init
yspeed = yspeed_init
ballrect.center = width / 2, height / 3
screen.blit(ball, ballrect)
screen.blit(bat, batrect)
pygame.display.flip()
class Wall():
def __init__(self):
self.brick = pygame.image.load("brick.png").convert()
brickrect = self.brick.get_rect()
self.bricklength = brickrect.right - brickrect.left
self.brickheight = brickrect.bottom - brickrect.top
def build_wall(self, width):
xpos = 0
ypos = 60
adj = 0
self.brickrect = []
for i in range (0, 52):
if xpos > width:
if adj == 0:
adj = self.bricklength / 2
else:
adj = 0
xpos = -adj
ypos += self.brickheight
self.brickrect.append(self.brick.get_rect())
self.brickrect[i] = self.brickrect[i].move(xpos, ypos)
xpos = xpos + self.bricklength
if __name__ == '__main__':
br = Breakout()
br.main()
You can use for example pygame.time.get_ticks() to get the number of milliseconds since pygame.init() was called, and then use simple division to get the seconds and minutes etc from that number.
Here's a simple example:
import pygame
import pygame.freetype
def main():
pygame.init()
screen=pygame.display.set_mode((400, 300))
clock=pygame.time.Clock()
font=pygame.freetype.SysFont(None, 34)
font.origin=True
while True:
for e in pygame.event.get():
if e.type == pygame.QUIT: return
screen.fill(pygame.Color('grey12'))
ticks=pygame.time.get_ticks()
millis=ticks%1000
seconds=int(ticks/1000 % 60)
minutes=int(ticks/60000 % 24)
out='{minutes:02d}:{seconds:02d}:{millis}'.format(minutes=minutes, millis=millis, seconds=seconds)
font.render_to(screen, (100, 100), out, pygame.Color('dodgerblue'))
pygame.display.flip()
clock.tick(60)
if __name__ == '__main__': main()
If you want to have your stopwatch "to start later", you could store the output of pygame.time.get_ticks() at this moment and simply substract it from the result of further calls (something like starttime=pygame.time.get_ticks() and ticks=pygame.time.get_ticks()-starttime later in the loop, you'll get the idea).
If your game is running on while loop, with fps of 60, you can get minutes and seconds by doing so:
frame_count = 0
frame_rate = 60
... while block of game running 60 fps
# Every second passes 60 frames, so you get seconds by dividing
# by 60
seconds = total_seconds // 60
# Because 1 second is 60 frames, minute is 60 seconds * 60 frames.
# So you divide by 60 * 60 = 3600
minutes = total_seconds // 3600 # Because every second is 60 fps
output_string = "Time: {0:02}:{1:02}".format(minutes, seconds)
frame_count += 1
I found this solution here

How to implement jump in Pygame without sprites?

I'm new to programming and to Python as well as Pygame. As such, I'm not yet comfortable with sprites in Pygame. I'm trying to make a game where a block jumps whenever the spacebar is pressed - similar to Mario.
My code doesn't work as desired because whenever the spacebar is pressed, the block incrementally moves up (I've added a gravity component), instead of "jumping".
import pygame
pygame.init()
game_display = pygame.display.set_mode((800, 800))
# fixed variables at the start
x_pos = 400
y_pos = 400
current_speed = 15
def jump_coords(y_position, speed):
if speed >= 0:
#to move up, reduce the y-coordinate
y_position -= speed
return y_position
game_exit = False
# main loop
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
y_pos = jump_coords(y_pos, current_speed)
# 1 represents gravity value
current_speed -= 1
rect_one = pygame.Rect(x_pos, y_pos, 10, 10)
pygame.draw.rect(game_display, (255, 0, 0), rect_one)
pygame.display.update()
I know that I have to somehow make y_pos keep updating in the while loop whilst speed >= 0 but I'm not sure how to implement it.
I made the minimal changes to your code to get the block to bounce:
import pygame
pygame.init()
game_display = pygame.display.set_mode((800, 800))
# fixed variables at the start
x_pos = 400
y_pos = 400
x_old = x_pos
y_old = y_pos
current_speed = 15
def jump_coords(y_position, speed):
# to move up, reduce the y-coordinate
y_position -= speed
if y_position > 400:
y_position = 400
global jump_flag
jump_flag = False
global current_speed
current_speed = 15
return y_position
game_exit = False
jump_flag = False
# main loop
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
jump_flag = True
elif event.key == pygame.K_ESCAPE:
exit(0)
if jump_flag:
x_old = x_pos
y_old = y_pos
y_pos = jump_coords(y_pos, current_speed)
# 1 represents gravity value
current_speed -= 1
rect_old = pygame.Rect(x_old, y_old, 10, 10)
pygame.draw.rect(game_display, (0, 0, 0), rect_old)
rect_one = pygame.Rect(x_pos, y_pos, 10, 10)
pygame.draw.rect(game_display, (255, 0, 0), rect_one)
pygame.display.update()
The most important changes was the removal of the check for speed greater than zero. The speed has to go negative if the block is going to come back down. The next change was to save the old x and y coordinates so that we can draw a black square over the old position. I also made it possible to exit the program by pressing the Escape key.
I made this from scratch, I hope it's not too daunting!
import pygame,sys
pygame.init()
screen = pygame.display.set_mode((800, 800))
tm = 20 # Terminal Velocity
gravity = 1
class Player:
def __init__(self,speed,x,y):
self.speed = speed
self.x = x; self.y = y
self.yVelocity = 0
self.xVelocity = 0
def getKeys(self):
key = pygame.key.get_pressed()
if key[pygame.K_a]: self.xVelocity -= self.speed
if key[pygame.K_d]: self.xVelocity += self.speed
if key[pygame.K_SPACE]:
if isGround(self.x,self.y):
self.yVelocity -= 20
def move(self,dt):
if self.x < 0:
self.x = 0
if self.x > 800-15:
self.x = 800-15
if self.y < 0:
self.y = 0
if self.y > 800-10:
self.y = 800-10
self.x += self.xVelocity
self.y += self.yVelocity
if self.xVelocity != 0:
self.xVelocity /= 70*dt
if self.yVelocity < tm and not isBlocking(self.x,self.y+self.yVelocity):
self.yVelocity += gravity
if isBlocking(self.x,self.y):
self.yVelocity = 0
def draw(self):
screen.fill((255,0,0),(self.x,self.y,10,10))
def isBlocking(x,y):
if x < 0 or x > 800 or y < 0 or y > 800:
return True
elif y >= 400:
return True
else:
return False
def isGround(x,y):
if y >= 400:
return True
else:
return False
player = Player(1,400,400)
clock = pygame.time.Clock()
while True:
dt = clock.tick(60)/1000 # limit to 60 FPS.
screen.fill((0,0,0))
if pygame.event.poll().type == pygame.QUIT: pygame.quit(); sys.exit()
player.getKeys()
player.move(dt)
player.draw()
pygame.display.flip()
Hope it helps!

Using scrolling camera in pygame

I have tried to implement a camera function in my 2d game made with pygame but the only I obtain is my player set in the middle of the window. I see how its x and y cordenates changes but the player does not move.I know I must use the camera's apply method to the map but I don't know how to do it since is my first approach to pygame. Here is my code:
import pygame, sys
from pygame.locals import *
import random
"""
dirt 0
grass 1
water 2
coal 3
"""
DIRT = 0
GRASS = 1
WATER = 2
COAL = 3
DIAMOND = 4
CLOUD = 5
cloudx = -200
cloudy = 0
WHITE = (255, 255, 255)
BLACK = (0, 0, 0 )
BROWN = (153, 76, 0 )
GREEN = (0, 255, 0 )
BLUE = (0, 0, 255)
TILESIZE = 40
MAPWIDTH = 140
MAPHEIGHT = 120
WIN_WIDTH = 800
WIN_HEIGHT = 600
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)
fpsClock = pygame.time.Clock()
colours = {
DIRT: BROWN,
GRASS: GREEN,
WATER: BLUE,
COAL: BLACK
}
"""tilemap = [
[GRASS, COAL, DIRT ],
[WATER, WATER, GRASS],
[COAL, WATER, GRASS],
[DIRT, WATER, COAL ],
[GRASS, WATER, DIRT]
]"""
resources = [WATER, GRASS, COAL, DIRT, DIAMOND]
tilemap = [[random.choice(resources) for w in range(MAPWIDTH)] for h in range(MAPHEIGHT)]
textures = {
DIRT: pygame.image.load("dirt.gif"),
GRASS: pygame.image.load("grass.gif"),
COAL: pygame.image.load("coal.gif"),
WATER: pygame.image.load("water.gif"),
DIAMOND: pygame.image.load("diamond.gif"),
CLOUD: pygame.image.load("nube.gif")
}
inventory = {
DIRT :0,
WATER :0,
GRASS :0,
COAL :0,
DIAMOND :0
}
playerPos = [50,50]
move = 0
vel_x = 0
vel_y = 0
speed = 1
class Camera(object):
def __init__(self, camera_func, width, height):
self.camera_func = camera_func
self.state = pygame.Rect(0, 0, width, height)
def apply(self, rect):
return rect.move(self.state.topleft)
def update(self, target_rect):
self.state = self.camera_func(self.state, target_rect)
def simple_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
return pygame.Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)
def complex_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
l, t, _, _ = -l+HALF_WIDTH, -t+HALF_HEIGHT, w, h
l = min(0, l) # stop scrolling at the left edge
l = max(-(camera.width-SCREEN_WIDTH), l) # stop scrolling at the right edge
t = max(-(camera.height-SCREEN_HEIGHT), t) # stop scrolling at the bottom
t = min(0, t) # stop scrolling at the top
return pygame.Rect(l, t, w, h)
global cameraX, cameraY
total_level_width = len(tilemap[0]) * TILESIZE
total_level_height = len(tilemap)*TILESIZE
camera = Camera(simple_camera ,total_level_width, total_level_height)
pygame.init()
DISPLAYSURF = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pygame.display.set_caption("My first game :)")
pygame.display.set_icon(pygame.image.load("player.gif"))
PLAYER = pygame.image.load("player.gif")
playerrect = PLAYER.get_rect()
for rw in range(MAPHEIGHT):
for cl in range(MAPWIDTH):
randomNumber = random.randint(0,50)
if randomNumber <= 10:
tile = COAL
elif randomNumber > 11 and randomNumber <= 20:
tile = WATER
elif randomNumber > 21 and randomNumber <= 45:
tile = GRASS
elif randomNumber > 46 and randomNumber <= 49:
tile = DIRT
else:
tile = DIAMOND
tilemap[rw][cl] = tile
INVFONT = pygame.font.Font("freeSansBold.ttf", 18)
while True:
for event in pygame.event.get():
if event.type == QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
#movement
if event.key == K_RIGHT and playerPos[0] < MAPWIDTH - 1:
playerPos[0] += move
elif event.key == K_LEFT and playerPos[0] > 1/TILESIZE:
playerPos[0] -= move
elif event.key == K_DOWN and playerPos[1] < MAPHEIGHT - 1:
playerPos[1] += move
elif event.key == K_UP and playerPos[1] > 1/TILESIZE:
playerPos[1] -= move
#pick up resource
elif event.key == K_SPACE:
currentTile = tilemap[playerPos[1]][playerPos[0]]
inventory[currentTile] += 1
tilemap[playerPos[1]][playerPos[0]] = DIRT
#place resources
elif event.key == K_1:
currentTile = tilemap[playerPos[1]][playerPos[0]]
if inventory[WATER] > 0:
inventory[WATER] -= 1
tilemap[playerPos[1]][playerPos[0]] = WATER
inventory[currentTile] += 1
elif event.key == K_2:
currentTile = tilemap[playerPos[1]][playerPos[0]]
if inventory[GRASS] > 0:
inventory[GRASS] -= 1
tilemap[playerPos[1]][playerPos[0]] = GRASS
inventory[currentTile] += 1
elif event.key == K_3:
currentTile = tilemap[playerPos[1]][playerPos[0]]
if inventory[COAL] > 0:
inventory[COAL] -= 1
tilemap[playerPos[1]][playerPos[0]] = COAL
inventory[currentTile] += 1
elif event.key == K_4:
currentTile = tilemap[playerPos[1]][playerPos[0]]
if inventory[DIRT] > 0:
inventory[DIRT] -= 1
tilemap[playerPos[1]][playerPos[0]] = DIRT
inventory[currentTile] += 1
elif event.key == K_5:
currentTile = tilemap[playerPos[1]][playerPos[0]]
if inventory[DIAMOND] > 0:
inventory[DIAMOND] -= 1
tilemap[playerPos[1]][playerPos[0]] = DIAMOND
inventory[currentTile] += 1
keys = pygame.key.get_pressed()
if keys[K_LEFT] and playerPos[0] > 1/TILESIZE:
playerPos[0] -= speed
if keys[K_RIGHT] and playerPos[0] < MAPWIDTH - 1:
playerPos[0] += speed
if keys[K_UP] and playerPos[1] > 1/TILESIZE:
playerPos[1] -= speed
if keys[K_DOWN] and playerPos[1] < MAPHEIGHT - 1:
playerPos[1] += speed
for row in range(MAPHEIGHT):
for column in range(MAPWIDTH):
DISPLAYSURF.blit(textures[tilemap[row][column]], (column*TILESIZE, row*TILESIZE))
#DISPLAYSURF.blit(PLAYER, (playerPos[0]*TILESIZE, playerPos[1]*TILESIZE))
DISPLAYSURF.blit(PLAYER, camera.apply(pygame.Rect(playerPos[0],playerPos[1],42,42)))
camera.update(PLAYER.get_rect().move((playerPos[0],playerPos[1])))
pygame.display.update()
fpsClock.tick(10)
print playerPos
First, remove this block of code:
if event.key == K_RIGHT and playerPos[0] < MAPWIDTH - 1:
playerPos[0] += move
elif event.key == K_LEFT and playerPos[0] > 1/TILESIZE:
playerPos[0] -= move
elif event.key == K_DOWN and playerPos[1] < MAPHEIGHT - 1:
playerPos[1] += move
elif event.key == K_UP and playerPos[1] > 1/TILESIZE:
playerPos[1] -= move
You already use pygame.key.get_pressed() for movement, so there's not need to check for a key press (Don't forget to change the following elif to if).
I know I must use the camera's apply method to the map
Yes, you're on the right track.
You already create a variable playerrect, so let's use it to store the position of the player. Also, let's create a Rect to store the size of the map. That will come in handy soon:
playerrect = PLAYER.get_rect(top=50, left=50)
mapsize = pygame.rect.Rect(0, 0, MAPWIDTH*TILESIZE, MAPHEIGHT*TILESIZE)
Now, when keys are hold down to move the player, we can simply use
keys = pygame.key.get_pressed()
if keys[K_LEFT]: playerrect.move_ip(-speed, 0)
if keys[K_RIGHT]: playerrect.move_ip(speed, 0)
if keys[K_UP]: playerrect.move_ip(0, -speed)
if keys[K_DOWN]: playerrect.move_ip(0, speed)
playerrect.clamp_ip(mapsize)
to change the position of the player, and playerrect.clamp_ip(mapsize) makes sure that the player never leaves the map.
As for drawing, you should clear the screen first. To draw the tiles, you have to create a Rect for each tile (maybe later you could create them once and store/reuse them).
DISPLAYSURF.fill(pygame.color.Color('Black'))
for row in range(MAPHEIGHT):
for column in range(MAPWIDTH):
DISPLAYSURF.blit(textures[tilemap[row][column]], camera.apply(pygame.rect.Rect((column*TILESIZE, row*TILESIZE), (TILESIZE, TILESIZE))))
DISPLAYSURF.blit(PLAYER, camera.apply(playerrect))
camera.update(playerrect)

Categories