Using scrolling camera in pygame - python

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)

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

I do not know how to end game when specific block is touched in pygame

I want to make it so when my character touches the "v" block the game quits. What I tried was to find all blocks that are "v" and put them in the list. If player colliderect with any in list of "v" game will quit.
I think this should work although it does not seem to be working. Whenever I run it when I touch the "v" block nothing happens.
Here is my code
import pygame
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
WINDOW_SIZE = (600, 400)
pygame.display.set_caption("Game")
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)
display = pygame.Surface((300, 200))
player_image = pygame.image.load("Jacques clone-1.png (1).png").convert()
player_image.set_colorkey((255,255,255))
location = [50, 50]
#boolean for movement
moving_right = False
moving_left = False
scroll = [0, 0]
Stay_right = True
game_map1 = """
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
-----------------------------------------------------
xx----------x----------------------------------------
----------vvvv---------------------xxx----------------
---------xooo----------------------------------------
xxxxxxxxxooooxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooooooooo
""".splitlines()
game_map = [list(lst) for lst in game_map1]
tl = {}
tl["v"] = spike_img = pygame.image.load('dirt.png')
tl["o"] = dirt_img = pygame.image.load('grass.png')
tl["x"] = grass_img = pygame.image.load('grass.png')
player_rect = pygame.Rect(50, 50, 25, 25)
momentum = 0
air_timer = 0
#adding tiles list that are hit for movement
def collision_test(rect, tiles):
hit_list = []
for tile in tiles:
if rect.colliderect(tile):
hit_list.append(tile)
#print(hit_list)
return hit_list
def move(rect, movement, tiles):
collision_types = {'top': False, 'bottom': False, 'right': False, 'left': False}
rect.x += movement[0]
hit_list = collision_test(rect, tiles)
for tile in hit_list:
if movement[0] > 0:
rect.right = tile.left
collision_types['right'] = True
elif movement[0] < 0:
rect.left = tile.right
collision_types['left'] = True
rect.y += movement[1]
hit_list = collision_test(rect, tiles)
for tile in hit_list:
if movement[1] > 0:
rect.bottom = tile.top
collision_types['bottom'] = True
elif movement[1] < 0:
rect.top = tile.bottom
collision_types['top'] = True
return rect, collision_types
run = True
while run:
display.fill((146, 244, 255))
scroll[0] += (player_rect.x - scroll[0] - 130)
tile_rects = []
y = 0
for line_of_symbols in game_map:
x = 0
for symbol in line_of_symbols:
if symbol in tl:
display.blit(tl[symbol], (x * 16 - scroll[0], y * 16 - scroll[1]))
if symbol != "-":
tile_rects.append(pygame.Rect(x * 16, y * 16, 16, 16))
x += 1
y += 1
list_ofspike = []
y2 = 0
for lineofsymbols in game_map:
x2 = 0
for symbols in lineofsymbols:
if symbols == "v":
list_ofspike.append(pygame.Rect(x2 * 16, y2 * 16, 16, 16))
x2 += 1
y2 += 1
for spike in list_ofspike:
if player_rect.colliderect(spike):
pygame.quit()
player_movement = [0, 0]
if moving_right:
player_movement[0] += 2
if moving_left:
player_movement[0] -= 2
player_movement[1] += momentum
momentum += 0.3
if momentum > 3:
momentum = 3
player_rect, collisions = move(player_rect, player_movement, tile_rects)
if collisions['bottom']:
air_timer = 0
momentum = 0
else:
air_timer += 1
if Stay_right:
display.blit(player_image, (player_rect.x - scroll[0], player_rect.y - scroll[1]))
else:
display.blit(pygame.transform.flip(player_image, 1, 0 ),(player_rect.x - scroll[0], player_rect.y - scroll[1]))
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == KEYDOWN:
if event.key == K_RIGHT:
moving_right = True
Stay_right = True
if event.key == K_LEFT:
moving_left = True
Stay_right = False
if event.key == K_SPACE:
if air_timer < 6:
momentum = -5
if event.type == KEYUP:
if event.key == K_RIGHT:
moving_right = False
if event.key == K_LEFT:
moving_left = False
screen.blit(pygame.transform.scale(display, (WINDOW_SIZE)), (0, 0))
pygame.display.update()
clock.tick(60)
pygame.quit()
You do not detect a collision with the spikes, because your collision detection works too perfectly.
When you move the player then you ensure, that the player does not intersect any object, thus the player does not intersect a spike, too.
You have to test if the player touches a spike. Increase the player rectangle by 1 in direction and use the increased rectangle to do the collision test with the spikes:
while run:
# [...]
test_rect = pygame.Rect(player_rect.left-1, player_rect.top-1,
player_rect.width+2, player_rect.height+2)
for spike in list_ofspike:
if test_rect.colliderect(spike):
pygame.quit()
# [...]

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

Pygame Multiple bullets not spawning

So im new at pygame and coding my first project- a side scrolling shooter. The issue im having is with my bullets: when i press the space key, some of the bullets will show up but there are times when nothing happens, and no bullets spawn when i jump. Not quite sure how to go about fixing this issue- any ideas would be greatly appreciated.
Code is as follows:
import pygame
import math, random, sys, pygame.mixer
from pygame.locals import *
pygame.init()
pygame.mixer.pre_init(44100, -16, 2, 8192)
pygame.mixer.init()
jump = False
jump_offset = 0
jump_height = 250
k = pygame.key.get_pressed()
def events():
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
def do_jumping():
global jump_height
global jump
global jump_offset
if jump:
jump_offset += 3
if jump_offset >= jump_height:
jump = False
elif jump_offset > 0 and jump == False:
jump_offset -= 3
#Defining colours
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
#Window Settings
w = 1280
h = 720
half_w = w /2
half_h = h /2
AREA = w*h
#Initialising the window
pygame.init()
display = pygame.display.set_mode((w,h)) #Sets the size of the window
pygame.display.set_caption("Cattleman") #Sets the title of the window
Clock = pygame.time.Clock() #clockspeed for the game ie. 60fps
FPS = 600
#pygame.mouse.set_visible(True) #Allows the mouse to be shown in the game window.
background = pygame.image.load("background.png").convert()
backgroundWidth, backgroundHeight = background.get_rect().size
stageWidth = backgroundWidth*2 #sets the area which the player can move in
stagePosX = 0 #Records position of stage as the player moves
startScrollPosX = half_w
circleRadius = 25
circlePosX = circleRadius
playerPosX = circleRadius
playerPosY = 602
playerVelocityX = 0
playersprite = pygame.image.load("player_spriteR2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
bullets = []
bulletSprite = pygame.image.load("Bullet1.png").convert_alpha()
bulletSprite = pygame.transform.scale(bulletSprite, (20,10))
#Sounds
#gunSounds = ["pew1.wav", "pew2.wav", "pew3.wav", "pew4.wav"]
#SOUNDS
shot = pygame.mixer.Sound("pew1.wav")
#------------------------MAIN PROGRAM LOOP------------------------#
while True:
events()
do_jumping()
k = pygame.key.get_pressed()
if k[K_RIGHT]:
playerVelocityX = 2 #Moves the player right
playersprite = pygame.image.load("player_spriteR2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
if k[K_LEFT]:
playerVelocityX = -2 #Moves the player left
playersprite = pygame.image.load("player_spriteL2.png").convert_alpha()
playersprite = pygame.transform.scale(playersprite, (130,130))
if k[K_UP] and jump == False and jump_offset == 0:
jump = True
if not k[K_RIGHT] and not k[K_LEFT]:
playerVelocityX = 0 #If no input detected, the player does not move
if k[K_SPACE]:
for event in pygame.event.get():
bullets.append([circlePosX-100, playerPosY-20])
shot.play()
playerPosX += playerVelocityX
if playerPosX > stageWidth - circleRadius-25: playerPosX = stageWidth - circleRadius-25 #Checks if the player trie to go past the right boundary
if playerPosX < circleRadius+55:playerPosX = circleRadius+55 #Checks if the player tries to go past the left boundary
if playerPosX < startScrollPosX: circlePosX = playerPosX
elif playerPosX > stageWidth - startScrollPosX: circlePosX = playerPosX - stageWidth + w
else:
circlePosX = startScrollPosX
stagePosX += -playerVelocityX
for b in range(len(bullets)):
bullets[b][0] -= 3
for bullet in bullets[:]:
if bullet[0] < 0:
bullets.remove(bullet)
rel_x = stagePosX % backgroundWidth
display.blit(background,(rel_x - backgroundWidth, 0))
if rel_x < w:
display.blit(background, (rel_x, 0))
for bullet in bullets:
display.blit(bulletSprite, pygame.Rect(bullet[0], bullet[1], 0, 0,))
#pygame.draw.circle(display,WHITE, (int(circlePosX),playerPosY - jump_offset), circleRadius, 0)
display.blit(playersprite, (int(circlePosX-80),playerPosY-100 - jump_offset))
pygame.display.update()
Clock.tick(FPS)
display.fill(BLACK)
I have done this in my code that leaves multiple balls similar like bullets :
class Bullet():
def __init__(self, x, y):
# self.image = pygame.image.load("SingleBullet.png")
self.image = pygame.image.load("ball.png")
self.image = pygame.transform.scale(self.image, (25, 25))
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
self.is_alive = True
# --------------------
def update(self):
self.rect.y -= 15
if self.rect.y < 0:
self.is_alive = False
# --------------------
def draw(self, screen):
screen.blit(self.image, self.rect.topleft)
for getting keyboard :
def event_handler(self, event):
if event.type == KEYDOWN:
if event.key == K_LEFT:
self.move_x = -5
elif event.key == K_RIGHT:
self.move_x = 5
elif event.key == K_SPACE:
if len(self.shots) < self.max_shots:
self.shots.append(Bullet(self.rect.centerx, self.rect.top))
if event.type == KEYUP:
if event.key in (K_LEFT, K_RIGHT):
self.move_x = 0

How to make Pacman's ghost randomly move around in 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

Categories