Python Pygame changing two positions based on a angle [duplicate] - python

This question already has answers here:
How to set the pivot point (center of rotation) for pygame.transform.rotate()?
(5 answers)
How can you rotate an image around an off center pivot in Pygame
(1 answer)
Closed 4 months ago.
Basically im trying to make a line point out out of the muzzle of this gun.
Picture of player, gun and make shift cross hair for reference (not part of the game)
How i made the gun was by get_rect() the gun surface, and setting the rectangles pos values to the players right side. I also made it so the gun will rotate to always point towards the mouse, but when the cross hair goes past the players right side (the angle goes past 90 or -90) the gun will flip to the players left side. Sorry for very messy code, im still quite new.
gunxposmdl = Player.player_rect.right
gunyposmdl = Player.player_rect.top
gunyposmdl += 20
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - gunxposmdl, mouse_y - gunyposmdl
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
if angle > 90 or angle < -90:
if angle > 0:
angle =-abs(angle)
else:
angle = abs(angle)
rshotgunmdl = pygame.transform.rotate(Weapons.shotgun, int(angle))
rshotgunrect = rshotgunmdl.get_rect(midleft=(gunxposmdl,gunyposmdl))
player_surf_cpy = Player.player_surf.copy()
player_fliped = pygame.transform.flip(player_surf_cpy, False, True)
flipgunxposmdl = Player.player_rect.left
rshotgunmdlcpy = rshotgunmdl.copy()
rshotgunmdlfliped = pygame.transform.flip(rshotgunmdlcpy, False, True )
rshotgunrectfliped = rshotgunmdlfliped.get_rect(midright=(flipgunxposmdl, gunyposmdl))
screen.blit(player_fliped, Player.player_rect)
screen.blit(rshotgunmdlfliped, rshotgunrectfliped)
sg_muzzle_x, sg_muzzle_y = rshotgunrectfliped.midleft[0], rshotgunrectfliped.midleft[1]
else:
rshotgunmdl = pygame.transform.rotate(Weapons.shotgun, int(angle))
rshotgunrect = rshotgunmdl.get_rect(midleft=(gunxposmdl,gunyposmdl))
screen.blit(Player.player_surf, Player.player_rect)
screen.blit(rshotgunmdl, rshotgunrect)
sg_muzzle_x, sg_muzzle_y = rshotgunrect.midright[0], rshotgunrect.midright[1]
#Cast rays
pygame.draw.line(screen, ("Green"), (sg_muzzle_x, sg_muzzle_y), (sg_muzzle_x, sg_muzzle_y), 3)
The problem with this is that when the guns surface is rotated, the rectangle doesnt rotate with it. So when i rotate the gun with the mouse, the line still gets drawn where the rectangles right side is and not where the muzzle is. I need the line to stick out of the muzzle as a visual on where the gun is pointing. Im going to be using this to implement hit casting.
E.g.
Image example (actual in game cross hair this time)
Could somebody please help me make it so the line is coming out of the muzzle in both examples please?
full code:
#!/bin/env python3
import pygame
from sys import exit
import time
import math
pygame.init()
video_infos = pygame.display.Info()
width, height = video_infos.current_w, video_infos.current_h
screen = pygame.display.set_mode((width, height), pygame.FULLSCREEN,
pygame.RESIZABLE)
pygame.display.set_caption('2D Quake')
clock = pygame.time.Clock()
keys = pygame.key.get_pressed()
mousec = pygame.image.load("textures/UI/crossh.png").convert_alpha()
pygame.mouse.set_visible(False)
backround = pygame.Surface((width, height)).convert_alpha()
backround.fill('White')
sbar = pygame.image.load("textures/UI/HUD/SBAR.png").convert_alpha()
class Player:
player_surf = pygame.Surface((50,100))
player_surf.fill('Black')
player_rect = player_surf.get_rect(midbottom = (300, height))
player_gravity = 0
player = {"Inv": [1,1,0], "Hand": 1, "Health": 100}
class Weapons:
shotgun = pygame.image.load("textures/weapons/SHOTGUN.png").convert_alpha()
class Enemies:
esoldier_surf = pygame.Surface((50,100))
esoldier_surf.fill('Black')
esoldier_rect = esoldier_surf.get_rect(midbottom = (800, height))
esoldier = {"Health": 100}
print(width, height)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_h:
Player.player["Health"] -= 1
#Backround
screen.blit(backround,(0,0))
#Enemies
screen.blit(Enemies.esoldier_surf, Enemies.esoldier_rect)
#Player
healthnum = Player.player["Health"]
healthnums = [int(x) for x in str(healthnum)]
Player.player_gravity += 1
Player.player_rect.y += Player.player_gravity
if Player.player_rect.bottom >= height: Player.player_rect.bottom = height
keys = pygame.key.get_pressed()
if keys[pygame.K_d] == 1:
if keys[pygame.K_LCTRL] == 1:
Player.player_rect.x += 9
else:
Player.player_rect.x += 5
if keys[pygame.K_a] == 1:
if keys[pygame.K_LCTRL] == 1:
Player.player_rect.x -= 9
else:
Player.player_rect.x -= 5
if keys[pygame.K_SPACE] == 1 and Player.player_rect.bottom >= height:
Player.player_gravity = -20
gunxposmdl = Player.player_rect.right
gunyposmdl = Player.player_rect.top
gunyposmdl += 20
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - gunxposmdl, mouse_y - gunyposmdl
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
if angle > 90 or angle < -90:
if angle > 0:
angle =-abs(angle)
else:
angle = abs(angle)
rshotgunmdl = pygame.transform.rotate(Weapons.shotgun, int(angle))
rshotgunrect = rshotgunmdl.get_rect(midleft=(gunxposmdl,gunyposmdl))
player_surf_cpy = Player.player_surf.copy()
player_fliped = pygame.transform.flip(player_surf_cpy, False, True)
flipgunxposmdl = Player.player_rect.left
rshotgunmdlcpy = rshotgunmdl.copy()
rshotgunmdlfliped = pygame.transform.flip(rshotgunmdlcpy, False, True )
rshotgunrectfliped = rshotgunmdlfliped.get_rect(midright=(flipgunxposmdl,
gunyposmdl))
screen.blit(player_fliped, Player.player_rect)
screen.blit(rshotgunmdlfliped, rshotgunrectfliped)
sg_muzzle_x, sg_muzzle_y = rshotgunrectfliped.midleft[0],
rshotgunrectfliped.midleft[1]
else:
rshotgunmdl = pygame.transform.rotate(Weapons.shotgun, int(angle))
rshotgunrect = rshotgunmdl.get_rect(midleft=(gunxposmdl,gunyposmdl))
screen.blit(Player.player_surf, Player.player_rect)
screen.blit(rshotgunmdl, rshotgunrect)
sg_muzzle_x, sg_muzzle_y = rshotgunrect.midright[0], rshotgunrect.midright[1]
#Cast rays
pygame.draw.line(screen, ("Green"), (sg_muzzle_x, sg_muzzle_y), (sg_muzzle_x,
sg_muzzle_y), 3)
#UI
mpos = pygame.mouse.get_pos()
sbarxpos = width - 600
sbarxpos = sbarxpos / 2
sbarypos = height - 46
screen.blit(sbar,(sbarxpos,sbarypos))
if len(healthnums) == 3:
hnum1 = pygame.image.load("textures/UI/HUD/NUM_1.png").convert_alpha()
hnum2 = pygame.image.load("textures/UI/HUD/NUM_0.png").convert_alpha()
hnum3 = pygame.image.load("textures/UI/HUD/NUM_0.png").convert_alpha()
if width == 1366:
screen.blit(hnum1,(645,727))
screen.blit(hnum2,(685,727))
screen.blit(hnum3,(727,727))
elif width == 1920:
numypos = height - 44
#screen.blit(hnum1,(, numypos))
#screen.blit(hnum2,(, numypos))
#screen.blit(hnum3,(, numypos))
if len(healthnums) == 2:
numa = healthnums[0]
numb = healthnums[1]
hnum2 = pygame.image.load(f"textures/UI/HUD/NUM_{numa}.png").convert_alpha()
hnum3 = pygame.image.load(f"textures/UI/HUD/NUM_{numb}.png").convert_alpha()
if width == 1366:
screen.blit(hnum2,(685,727))
screen.blit(hnum3,(727,727))
elif width == 1920:
numypos = height - 44
if len(healthnums) == 1:
numb = healthnums[0]
hnum3 = pygame.image.load(f"textures/UI/HUD/NUM_{numb}.png").convert_alpha()
screen.blit(hnum3,(727,727))
screen.blit(mousec, (mpos))
pygame.display.update()
clock.tick(60)
Link to Source files: https://www.dropbox.com/s/4tuk7v675go1urv/2DQuake.zip?dl=0

Related

Python PyGame append object on the screen multiple times with different movement

I am trying to make an object with very random movement which is fine, that works. But if I want the same object to append to the screen 10 times then it does not work or i dont know how to do that. The object is called ant. I am sorry if its a bad, unreadable code im still a beginner in pygame. So the ant object(which is a small red square), need to be visible on the screen 10 times, each ant need to move randomly. I appreciate all your answers thanks.
import pygame as pg
import random as rd
import math
import sys
from pygame.time import Clock
pg.init()
screen = pg.display.set_mode((500,500))
title = pg.display.set_caption("TEST")
#REDRAWING SCREEN
def redraw():
screen.fill((0,0,0))
pg.display.update()
#FOOD
def food():
food_x = 200
food_y = 200
FOOD_COLOR = (255,255,255,0)
FWIDTH = 15
fooddraw = pg.draw.circle(screen, FOOD_COLOR, (food_x, food_y), FWIDTH)
#ANT VARIABLES
ant_x = 200
ant_y = 200
COLOR = (220,20,60,0)
ANT_WIDTH = 5
#RANDOM MOVES USING VECTOR
def move():
global ant_x,ant_y
x_boundary = 1000
y_boundary = 1000
pos = pg.math.Vector2(ant_x, ant_y)
ant_x = rd.randrange(0, x_boundary)
ant_y = rd.randrange(0, y_boundary)
speed = 1
maxdist = 1
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 2).rotate(rd.randrange(360))
pos += direction * speed
dist -= speed
ant_x, ant_y = round(pos.x), round(pos.y)
if dist <= 0:
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
if ant_x >= screen.get_width(): #IF ANTS X IS OFF THE SCREEN WIDTH THEN RESET THE X POSITION
ant_x = 200
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
if ant_y >= screen.get_height(): #RESET POSITION IF ANTS Y IS OFF THE SCREEN HEIGHT
ant_x = 200
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
#TRIED TO DUPLICATE ANT 10 TIMES WITH DIFFERENT MOVES BUT DOESNT WORK, I STILL SEE ONLY 1 ANT ON THE SCREEN
ant_spawn = []
for i in range(10):
for j in range(2):
ant_x = 250
ant_y = 250
ant_spawn.append(j)
while True:
FPS = pg.time.Clock()
redraw()
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
#APPEND TO SCREEN
for ants in ant_spawn:
antdraw = pg.draw.rect(screen, COLOR, (ant_x, ant_y,3,3))
#MOVE FUNCTION ACTIVATE
move()
pg.display.update()
FPS.tick(60)
You have to create a list of coordinates instead a list of indices:
ant_spawn = []
for i in range(10):
ant_x = 250
ant_y = 250
ant_spawn.append([ant_x, ant_y])
Move and draw the ants in loops:
for ants in ant_spawn:
move(ants)
for ants in ant_spawn:
pg.draw.rect(screen, COLOR, (*ants, 3, 3))
The move function changes the coordinates of an ant:
def move(ants):
ant_x, ant_y = ants
# change ant_x and ant_y
# [...]
ants[0] = ant_x
ants[1] = ant_y
Complete example (start with space bar)
import pygame as pg
import random as rd
pg.init()
screen = pg.display.set_mode((500,500))
title = pg.display.set_caption("TEST")
ant_x = 200
ant_y = 200
COLOR = (220,20,60,0)
ANT_WIDTH = 5
def move(ants):
ant_x, ant_y = ants
x_boundary = 1000
y_boundary = 1000
pos = pg.math.Vector2(ant_x, ant_y)
c = rd.randrange(0, x_boundary)
ant_y = rd.randrange(0, y_boundary)
speed = 1
maxdist = 1
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 2).rotate(rd.randrange(360))
pos += direction * speed
dist -= speed
ant_x, ant_y = round(pos.x), round(pos.y)
if dist <= 0:
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
if ant_x >= screen.get_width(): #IF ANTS X IS OFF THE SCREEN WIDTH THEN RESET THE X POSITION
ant_x = 200
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
if ant_y >= screen.get_height(): #RESET POSITION IF ANTS Y IS OFF THE SCREEN HEIGHT
ant_x = 200
dist = rd.randrange(maxdist)
direction = pg.math.Vector2(1, 0).rotate(rd.randrange(360))
else:
pass
ants[0] = ant_x
ants[1] = ant_y
ant_spawn = []
for i in range(10):
ant_x = 250
ant_y = 250
ant_spawn.append([ant_x, ant_y])
move_ants = False
run = True
while run:
FPS = pg.time.Clock()
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if event.type == pg.KEYDOWN and event.key == pg.K_SPACE:
move_ants = not move_ants
if move_ants:
for ants in ant_spawn:
ants = move(ants)
screen.fill((0,0,0))
for ants in ant_spawn:
#pg.draw.rect(screen, COLOR, (*ants, 3, 3))
pg.draw.circle(screen, COLOR, ants, 5)
pg.display.update()
FPS.tick(60)
pg.quit()

Pygame - Fix issue with pause menu? [duplicate]

I've developed a Python code and am looking for improvements and how to add a pause option.
I repeat the exact same lines one after another although I don't know an easier way to do it.
import math, pygame, random, sys, turtle
from itertools import cycle
from datetime import datetime
from pygame import gfxdraw
from pygame.locals import *
def print_text(surface, font, text, surf_rect, x = 0, y = 0, center = False, color = (255,215,0)):
if not center:
textimage = font.render(text, True, color)
surface.blit(textimage, (x, y))
else:
textimage = font.render(text, True, color)
text_rect = textimage.get_rect()
x = (surf_rect.width // 2) - (text_rect.width // 2 )
surface.blit(textimage, (x, y))
def game_is_over(surface, font, ticks):
timer = ticks
surf_rect = surface.get_rect()
surf_height = surf_rect.height
surf_width = surf_rect.width
print_text(screen, font, "Y O U G O T Y E E T E D (Game Over)", surf_rect, y = 260,\
center = True)
pygame.display.update()
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if ticks > timer + 3000:
break
def next_level(level):
level += 1
if level > 6:
level = 6
return level
#The Level Creator
def load_level(level):
invaders, colors = [], []
start_intx, end_intx, increment_intx = 85, 725, 40
start_inty, end_inty, increment_inty = 60, 60, 30
end_inty = end_inty + level * 30 # 30 being the number of rows / intruders
color_val = 256 / end_inty #For Colour Repetition
for x in range(start_intx, end_intx, increment_intx):
for y in range(start_inty, end_inty, increment_inty):
invaders.append(pygame.Rect(x, y, 30, 15))
colors.append(((x * 0.35) % 256, (y * color_val) % 256))
return invaders, colors, len(invaders)
def draw_title_invader():
rect = Rect(285,247,230,115)#INVATOR
rect2 = Rect(0,0,230,115)
rect3 = Rect(340,120,120,128)#TOP OF HAT
rect4 = Rect(300,200,200,48)#BOT OF HAT
rect5 = Rect(340,182,120,18)#LINE IN HAT
rect_width = 230
a = 175
b = 55
pygame.draw.rect(backbuffer, MGOLD,rect)
#The Left Eye in Title Screen
pygame.draw.circle(backbuffer,(0,255,255), (rect.x+46,rect.y+30), 23)
#The Right Eye in Title Screen
pygame.draw.circle(backbuffer,(0,255,255),(rect.x+rect_width-46,rect.y+30)\
,23)
#The Left Side Mouth in Title Screen
pygame.draw.line(backbuffer, RED, (rect.x+46, rect.y+92),\
(rect.x + 115, rect.y + 61), 2)
#The Right Side Mouth in Title Screen
pygame.draw.line(backbuffer, RED, (rect.x+rect_width-46,\
rect.y+92), (rect.x+rect_width-115,\
rect.y+61), 2)
#The Right Eye
pygame.draw.circle(backbuffer,RED,(rect.x+rect_width-115,rect.y+65)\
,23)
#The Hat
pygame.draw.rect(backbuffer, DIMGRAY,(340,120,120,128))
pygame.draw.rect(backbuffer, DIMGRAY,(300,200,200,48))
pygame.draw.rect(backbuffer, WHITE,(340,182,120,18))
def draw_bonus_invader(i, bonus_color, bx, bonus_x):
x, y = bonus_invader.x, bonus_invader.y
pygame.draw.circle(backbuffer, bonus_color, (x+bx, y+7), 2)
if i == 0:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 1:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 2:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 3:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 4:
pygame.draw.circle(backbuffer, bonus_color,
(bonus_invader.x+bx,bonus_invader.y+7),2)
if i == 5:
bx = next(bonus_x)
def draw_invader(backbuffer, rect, a, b, animate_invaders, ticks,\
animation_time):
invader_width = 30
#THe Intruder In Game
pygame.draw.rect(backbuffer, MGOLD, rect)
#CONSOLE GRAY
pygame.draw.rect(backbuffer, DIMGRAY,(0,510,800,110))
#Left Eye in game
pygame.gfxdraw.filled_circle(backbuffer, rect.x + 6, rect.y + 4, 3, \
RED)
#Right EYe in game
pygame.gfxdraw.filled_circle(backbuffer, rect.x + invader_width - 7,\
rect.y + 4, 3, RED)
#The draw animation (if needed)
if animate_invaders:
pygame.gfxdraw.filled_trigon(backbuffer, rect.x+6, rect.y + 12,\
rect.x + 14, rect.y + 4, rect.x +\
invader_width - 7, rect.y + 12, RED)
else:
#The Left Side of the mouth
pygame.gfxdraw.line(backbuffer, rect.x + 6, rect.y + 12,\
rect.x + 15, rect.y + 8, RED)
#The Right Side of the mouth
pygame.gfxdraw.line(backbuffer, rect.x + invader_width - 7,\
rect.y + 12, rect.x + invader_width - 15,\
rect.y + 8, RED)
if ticks > animation_time + 200:
animate_invaders = False
return animate_invaders
pygame.init()
pygame.mixer.init() # not always called by pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Yeet The Intruders")
fpsclock = pygame.time.Clock()
#get screen metrics
the_screen = screen.get_rect()
screen_width = the_screen.width
screen_height = the_screen.height
backbuffer = pygame.Surface((the_screen.width, the_screen.height))
# fonts
font1 = pygame.font.SysFont(None, 30)
font2 = pygame.font.SysFont("Impact", 54)
font3 = pygame.font.SysFont("Impact", 36)
# User event frequencies
RELOAD_SPEED = 400
MOVE_SIDEWAYS = 1000
MOVE_DOWN = 1000
BONUS_FREQ = 10000
INV_SHOOT_FREQ = 500
# create user events
move_invaders_sideways = pygame.USEREVENT + 1
move_invaders_down = pygame.USEREVENT + 2
reload = pygame.USEREVENT + 3
invader_shoot = pygame.USEREVENT + 4
bonus = pygame.USEREVENT + 5
# event timers
pygame.time.set_timer(move_invaders_down, 0)
pygame.time.set_timer(move_invaders_sideways, MOVE_SIDEWAYS)
pygame.time.set_timer(reload, RELOAD_SPEED)
pygame.time.set_timer(invader_shoot, INV_SHOOT_FREQ)
pygame.time.set_timer(bonus, BONUS_FREQ)
#List of Colours used
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
YELLOW = (255,255,0)
DIMGRAY = (105,105,105)
MGOLD = (212,175,55)
shots, invader_shots, inv_shot_colors, bonus_invaders = [], [], [], []
#MY Space Ship
player = Rect(380,578,42,20)
player_gun = Rect(player.x + 18,player.y - 4, 6, 4)
# make screen rect for purposes of text-centering etc
the_screen = screen.get_rect()
# invader animation variables
animation_time = 0
animate_invaders = False
invader_width = 30
invader_height = 15
# flashing text vars
the_text = cycle(["Press Enter To Play, Yeet Master...", ""])
insert = next(the_text)
flash_timer = 0
# flashing bonus item vars
y1,y2,y3,y4,y5,y6 = (255,255,0), (225,225,0), (195,195,0), (165,165,0),\
(135,135,0), (105,105,0)
bonus_colors = cycle([y1,y2,y3,y4,y5,y6])
bonus_color = next(bonus_colors)
bonus_x = cycle([4,11,18,25,32,39]) # change draw x coord
bonus_timer = 0 # used to control frequency of changes
# vars for moving invaders down
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
invaders = 0 # prevents error until list is created
initial_invaders = 0 # use to manage freq of inv shots as invaders removed
shoot_level = 1 # manage freq of shots
# various gameplay variables
game_over = True
score = 0
lives = 2
level = 0
playing = False
# event loop
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == pygame.K_1 and not game_over:
print("Next level")
if event.type == invader_shoot and not game_over:
i = random.randint(0, len(invaders)-1)
shot_from = invaders[i]
a, b = colors[i]
invader_fired = True
invader_shots.append(Rect(shot_from.x, shot_from.y, 5, 7))
inv_shot_colors.append(RED)
if event.type == reload and not game_over:
reloaded = True
pygame.time.set_timer(reload, 0)
if event.type == move_invaders_sideways and not game_over:
if move_right:
for invader in invaders: invader.move_ip(10,0)
side_steps += 1
else:
for invader in invaders: invader.move_ip(-10,0)
side_steps -= 1
if side_steps == 6 or side_steps == -6:
if vert_steps <= 31: # and not moved_down
pygame.time.set_timer(move_invaders_sideways, 0)
pygame.time.set_timer(move_invaders_down, MOVE_DOWN)
# keep invaders moving horizontally after 31 down movements
else: move_right = not move_right
if event.type == move_invaders_down and not game_over:
#for i in range(20): print("down event")
move_right = not move_right
animate_invaders = True
animation_time = ticks
# reset move_sideways timer
pygame.time.set_timer(move_invaders_sideways, MOVE_SIDEWAYS)
# cancel move_down timer
pygame.time.set_timer(move_invaders_down, 0)
for invader in invaders: invader.move_ip(0,10)
vert_steps += 1
if event.type == bonus and not game_over:
#a = Rect(769,20,45,15)
bonus_invaders.append(Rect(797,20,45,15))
# keyboard polling
pressed = pygame.key.get_pressed()
if pressed[K_ESCAPE]: pygame.quit(), sys.exit()
elif pressed[K_RETURN]:
if game_over: game_over = False
elif pressed[K_d] or pressed[K_RIGHT]:player.move_ip((8, 0))
#player_gun.move_ip((8,0))
elif pressed[K_a] or pressed[K_LEFT]: player.move_ip((-8, 0))
if pressed[K_SPACE]:
if reloaded:
reloaded = False
# create timeout of RELOAD_SPEED
pygame.time.set_timer(reload, RELOAD_SPEED)
# shrink copy of player rect to imitate a missile
missile = player.copy().inflate(-38, -10)
# spawn missile higher to ensure appears missile fired from 'gun'
# when the ship is moving horizontally
missile.y -= 9
shots.append(missile)
#missile_sound.play()
backbuffer.fill(BLACK)
if not game_over:
playing = True
if level == 0:
level = next_level(level)
invaders, colors, initial_invaders = load_level(level)
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
pygame.time.set_timer(invader_shoot, 500)
shoot_level = 1
for shot in invader_shots:
shot.move_ip((0,random.randint(5,11)))
if not backbuffer.get_rect().contains(shot):
i = invader_shots.index(shot)
del invader_shots[i]
del inv_shot_colors[i]
if shot.colliderect(player) and shot.y < the_screen.height -10:
lives -= 1
if lives < 0:
lives = 0
game_over = True
i = invader_shots.index(shot)
del invader_shots[i]
del inv_shot_colors[i]
for shot in shots:
shot.move_ip((0, -8))
for inv_shot in invader_shots:
if inv_shot.colliderect(shot):
shots.remove(shot)
i = invader_shots.index(inv_shot)
del invader_shots[i]
del inv_shot_colors[i]
for b_invader in bonus_invaders:
if b_invader.colliderect(shot):
shots.remove(shot)
i = bonus_invaders.index(b_invader)
del bonus_invaders[i]
score += 1
if not backbuffer.get_rect().contains(shot):
shots.remove(shot)
else:
hit = False
for invader in invaders:
if invader.colliderect(shot):
score += 1
hit = True
i = invaders.index(invader)
del invaders[i]
del colors[i]
if hit: shots.remove(shot)
# move bonus invader
for bonus_invader in bonus_invaders:
bonus_invader.move_ip((-4,0 ))
## if not screen.get_rect().contains(bonus_invader):
## bonus_invaders.remove(bonus_invader)
if bonus_invader.x < -55:
bonus_invaders.remove(bonus_invader)
# check if all invaders killed, if so, move to next level
if len(invaders) == 0:
level = next_level(level)
invaders, colors, initial_invaders = load_level(level)
move_right, move_down, reloaded = True, True, True
vert_steps = 0
side_steps = 0
moved_down = False
invaders_paused = False
pygame.time.set_timer(invader_shoot, 500)
shoot_level = 1
# adjust shot freq when invader numbers decrease
if len(invaders) < initial_invaders*.75 and shoot_level == 1:
pygame.time.set_timer(invader_shoot, 750)
shoot_level = 2
elif len(invaders) < initial_invaders*.5 and shoot_level == 2:
pygame.time.set_timer(invader_shoot, 1000)
shoot_level = 3
elif len(invaders) < initial_invaders*.25 and shoot_level == 3:
pygame.time.set_timer(invader_shoot, 1500)
shoot_level = 4
# draw invaders
for rect, (a, b) in zip(invaders, colors):
animate_invaders = draw_invader(backbuffer, rect, a, b,\
animate_invaders, ticks, \
animation_time)
# draw bonus invaders
if ticks > bonus_timer + 169:
bonus_timer = ticks # change colors every 169ms approx
for bonus_invader in bonus_invaders:
pygame.draw.rect(backbuffer, (0,0,0,0), bonus_invader)
pygame.draw.ellipse(backbuffer,MGOLD,bonus_invader)
for i in range(6):
bonus_color = next(bonus_colors)
bx = next(bonus_x)
draw_bonus_invader(i, bonus_color, bx, bonus_x)
# draw space ship shots
for shot in shots:
pygame.draw.rect(backbuffer, GREEN, shot)
# draw invader shots
for shot, color in zip(invader_shots, inv_shot_colors):
pygame.draw.rect(backbuffer, color, shot)
#update 'gun' position and draw ship/gun
#player_gun = Rect(player.x, player.y, 6, 4)
player_gun.x = player.x+18
pygame.draw.rect(backbuffer, (204,0,255), player)
pygame.draw.rect(backbuffer, (0,204,255), player_gun)
player.clamp_ip(backbuffer.get_rect())
print_text(backbuffer, font1, "Intruders Rekt#: {}".format(score),\
the_screen, x=0, y=520)
print_text(backbuffer, font1, "Hearts#: {}".format(lives), the_screen,\
x=0, y=550)
print_text(backbuffer, font1, "Round#: {}".format(level), the_screen,\
x=0, y=580)
if game_over:
if playing:
game_is_over(backbuffer, font2, ticks)
playing = False
level = 0
lives = 2
score = 0
shots, invader_shots, inv_shot_colors, bonus_invaders = [], [], [], []
print_text(backbuffer, font2, "_/¯Yeet The Intruders¯\_", the_screen, y=5,\
center=True)
draw_title_invader()
if ticks > flash_timer + 800: # "press to play" flashing text
insert = next(the_text)
flash_timer = ticks
print_text(backbuffer, font3, insert, the_screen, y =\
the_screen.height-40, center=True)
screen.blit(backbuffer, (0,0))
pygame.display.update()
fpsclock.tick(30)
Your code is quite large, but to pause the game is very general task:
Add a pause state.
Toggle the pause state on an certain event, e.g. when the p key is pressed.
Skip the game processing if pauseis stated.
e,.g.
pause = False # pause state
while True:
ticks = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYUP:
if event.key == pygame.K_1 and not game_over:
print("Next level")
# toggle pause if "p" is pressed
if event.key == pygame.K_p:
pause = not pause
# [...]
if pause:
# [...] draw pause screen
pass
elif not game_over: # <--- elif is important
playing = True
# [...]
screen.blit(backbuffer, (0,0))
pygame.display.update()
fpsclock.tick(30)

How to fix 'apples' sometimes not appearing in my version of Snake? [duplicate]

I'm currently in the process of creating a Snake game and I want to create a food generator that generates an apple every 10 seconds based on my in-game timer. The timer counts down from 60 to 0(when the game ends) and I want an new apple to generate every 10 seconds, keeping the old one even if it hasn't been eaten. I don't know how to approach this and could use some help. Here is my full program.
Edit: this is a beginner Computer Science school project so the more basic the better.
import random
import pygame
pygame.init()
#---------------------------------------#
#
# window properties #
width = 640 #
height = 480
game_window=pygame.display.set_mode((width,height))
black = ( 0, 0, 0) #
#---------------------------------------#
# snake's properties
outline=0
body_size = 9
head_size = 10
apple_size = 8
speed_x = 8
speed_y = 8
dir_x = 0
dir_y = -speed_y
segx = [int(width/2.)]*3
segy = [height, height + speed_y, height + 2*speed_y]
segments = len(segx)
apple_counter = 0
grid_step = 8
regular_font = pygame.font.SysFont("Andina",18)
blue = [11, 90, 220]
clock = pygame.time.Clock()
time = 60
fps = 25
time = time + 1.0/fps
text = regular_font.render("Time from start: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
apple_x = random.randrange(0, 640, grid_step)
apple_y = random.randrange(0, 480, grid_step)
apple_colour = (255,0,0)
def redraw_game_window():
game_window.fill(black)
for i in range(segments):
segment_colour = (random.randint(1,50),random.randint(100,150),random.randint(1,50))
head_colour = (random.randint(180,220),random.randint(180,220),random.randint(1,15))
apple_colour = (255,0,0)
pygame.draw.circle(game_window, segment_colour, (segx[i], segy[i]), body_size, outline)
pygame.draw.circle(game_window, head_colour, (segx[0], segy[0]), head_size, outline)
game_window.blit(text, (530, 20))
game_window.blit(text2, (30, 20))
pygame.draw.circle(game_window, apple_colour, (apple_x, apple_y), apple_size, outline)
pygame.display.update()
exit_flag = False
print "Use the arrows and the space bar."
print "Hit ESC to end the program."
########################################################## TIMER/CONTROLS
while exit_flag == False:
redraw_game_window()
clock.tick(fps)
time = time - 1.00/fps
text = regular_font.render("Time: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
if time < 0.1:
print "Game Over"
exit_flag = True
pygame.event.get()
keys = pygame.key.get_pressed()
if time ==
if keys[pygame.K_ESCAPE]:
exit_flag = True
if keys[pygame.K_LEFT] and dir_x != speed_x:
dir_x = -speed_x
dir_y = 0
if keys[pygame.K_RIGHT] and dir_x != -speed_x:
dir_x = speed_x
dir_y = 0
if keys[pygame.K_UP] and dir_y != speed_x:
dir_x = 0
dir_y = -speed_y
if keys[pygame.K_DOWN] and dir_y != -speed_x:
dir_x = 0
dir_y = speed_y
############################################################ SNAKE MOVEMENT
for i in range(segments-1,0,-1):
segx[i]=segx[i-1]
segy[i]=segy[i-1]
segx[0] = segx[0] + dir_x
segy[0] = segy[0] + dir_y
############################################################ COLLISION
for i in range(segments-1, 3, -1):
if segments > 3:
if segx[0] == segx[i] and segy[0] == segy[i]:
print "You have collided into yourself, Game Over."
exit_flag = True
############################################################# BORDERS
if segx[0] > 640 or segx[0] < 0:
print "Game Over, you left the borders."
break
if segy[0] > 480 or segy[0] < 0:
print "Game Over, you left the borders."
break
############################################################# APPLE DETECT
for i in range (0 , 13):
if segx[0] == apple_x + i and segy[0] == apple_y + i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
if segx[0] == apple_x - i and segy[0] == apple_y - i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
#############################################################
pygame.quit()
You either
A) use pygame.time.set_timer to call a function every 10 seconds to spawn food, and every 60 seconds to end the round.
or
B) compare get_ticks()
def new_round():
last_apple = pygame.time.get_ticks() + 10*1000
while true:
now = pygame.time.get_ticks()
if now - last_apple >= 1000:
spawn_apple()
last_apple = now
if now - round_start >= 60*1000:
round_end()

Rotating Mask collision in Pygame

So I'm trying to make a game where there are 2 objects and am trying to make it so that my program knows when the 2 objects collide.
if players[0].mask.overlap(players[1].mask, offset):
print("collided")`
My objects both rotate clockwise and counterclockwise and have masks both for the head and the body. (I have 2 images which are both the same size but one contains only the head and another contains only the body, in order to use mask.from_surface().)
def turn(self, event):
self.surface = self.ojSurface
if event == 0:
self.deg -= self.turnSpd
elif event == 1:
self.deg += self.turnSpd
self.surface = pygame.transform.rotate(self.surface, self.deg)
self.newPos = (self.pos[0] - self.surface.get_width() / 2, self.pos[1] - self.surface.get_height() / 2)
self.mask = pygame.mask.from_surface(self.surface)
However, what I find is when I try to check for collision when they are rotated the mask isn't in the same place as the image. It should update the mask every frame through the move function which is called every loop
def move(self):
self.pos[0] = pygame.mouse.get_pos()[0]
self.pos[1] = pygame.mouse.get_pos()[1]
self.newPos = (self.pos[0] - self.surface.get_width() / 2, self.pos[1] - self.surface.get_height() / 2)
self.mask = pygame.mask.from_surface(self.surface)
Faulty Hit Detection
If you want to peruse what I have so far here it is:
import pygame
class Player:
def __init__(self, pos,surface,screen):
self.pos = [pos[0],pos[1]]
self.newPos = (pos[0] - surface.get_width()/2, pos[1] - surface.get_height()/2)
self.deg = 0
self.surface = surface
self.ojSurface = surface
self.screen = screen
self.mask = pygame.mask.from_surface(self.surface)
def turn(self, event):
self.surface = self.ojSurface
#clockwise
if event == 0:
self.deg -= 0.1
#counter clockwise
elif event == 1:
self.deg += 0.1
self.surface = pygame.transform.rotate(self.surface, self.deg)
#resetting pos and mask
self.newPos = (self.pos[0] - self.surface.get_width() / 2, self.pos[1] - self.surface.get_height() / 2)
self.mask = pygame.mask.from_surface(self.surface)
def move(self):
self.pos[0] = pygame.mouse.get_pos()[0]
self.pos[1] = pygame.mouse.get_pos()[1]
self.newPos = (self.pos[0] - self.surface.get_width() / 2, self.pos[1] - self.surface.get_height() / 2)
self.mask = pygame.mask.from_surface(self.surface)
def draw(self):
self.screen.blit(self.surface, self.newPos)
screenRes = (640,480)
screen = pygame.display.set_mode(screenRes)
closed = False
players = [Player((320,240),pygame.image.load("body.png"), screen),Player((480,240),pygame.image.load("body.png"), screen)]
controls = [[pygame.K_a,pygame.K_s],[pygame.K_k,pygame.K_l]]
while not closed:
screen.fill((0, 0, 0))
keys = pygame.key.get_pressed()
offset = (int(players[0].newPos[0] - players[1].newPos[0]), int(players[0].newPos[1] - players[1].newPos[1]))
#collision
if players[0].mask.overlap(players[1].mask, offset):
print("collided")
#controls
for i in range(len(players)):
if keys[controls[i][0]]:
players[i].turn(0)
if keys[controls[i][1]]:
players[i].turn(1)
players[i].draw()
players[0].move()
pygame.display.update()
for event in pygame.event.get():
# standard quit
if event.type == pygame.QUIT:
pygame.display.quit()
closed = True
pygame.quit()
You're calculating the offset in the wrong order. Subtract players[0]'s position from players[1]'s position:
offset = (
int(players[1].newPos[0] - players[0].newPos[0]),
int(players[1].newPos[1] - players[0].newPos[1]),
)
So I've reviewed your GitHub code, and while I'm not completely sure (I skimmed your code, looking for certain methods being called), I believe that you're not updating your masks every frame. Somewhere in your code, you'll have to update the masks every frame/loop, allowing for the collision to work properly. Try to update all the masks, the head, body and the one in the Player class. Hope this helps!

Scrolling in 2D game?

I'm trying to add a scrolling "camera" that follows the player when it moves but can't figure out how to do this. I know that you can just move the level in the opposite direction when you press one of the movement keys but I'd rather not do that as I plan on adding enemies later on and don't want have to keep update their coordinates as the player moves.
I've added my code with a sample level below.
Code:
import pygame, sys, time, random, math
from pygame.locals import *
BACKGROUNDCOLOR = (255, 255, 255)
WINDOWW = 800
WINDOWH = 600
PLAYERW = 66
PLAYERH = 22
FPS = 60
MOVESPEED = 3
YACCEL = 0.13
GRAVITY = 2
BLOCKSIZE = 30
pygame.init()
screen = pygame.display.set_mode((WINDOWW, WINDOWH), 0, 32)
mainClock = pygame.time.Clock()
testLevel = [
(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,),
(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,)]
def createblock(length, height, color):
tmpblock = pygame.Surface((length, height))
tmpblock.fill(color)
tmpblock.convert()
return tmpblock
def terminate(): # Used to shut down the software
pygame.quit()
sys.exit()
def add_level(lvl, bSize): # Creates the level based on a map (lvl) and the size of blocks
bList = [] # List of every block
bListDisp = [] # List of every block to display
bTypeList = [] # List with corresponding type of block(wall, air, etc.)
for y in range(len(lvl)):
for x in range(len(lvl[0])):
if lvl[y][x] == 0: # If the block type on lvl[y][x] is '0', write "air" down in the type list
bTypeList.append("air")
elif lvl[y][x] == 1: # If the block type on lvl[y][x] is '1', write "wall" down in the type list
bTypeList.append("solid")
bList.append(pygame.Rect((bSize * x), (bSize * y), bSize, bSize)) #Append every block that is registered
bListDisp.append(pygame.Rect((bSize * x), (bSize * y), bSize, bSize)) #Append every block to display that is registered
return bList, bListDisp, bTypeList
player = pygame.Rect((WINDOWW/2), (WINDOWH - BLOCKSIZE*3), PLAYERW, PLAYERH)
wallblock = createblock(BLOCKSIZE, BLOCKSIZE,(20,0,50))
lastTime = pygame.time.get_ticks()
isGrounded = False
vx = 0
vy = 0
allLevels = [testLevel] # A list containing all lvls(only one for now)
maxLevel = len(allLevels) # Checks which level is the last
currLevel = allLevels[0] # Current level(start with the first lvl)
blockList, blockListDisp, blockTypeList = add_level(currLevel, BLOCKSIZE) # A list with every block and another list with the blocks types
thrusters = True
jumping = False
falling = True
while True:
"""COLLISION"""
collision = False
for i in range(len(blockTypeList)):
if blockTypeList[i] == "solid":
if player.colliderect(blockList[i]):
collision = True
if vx > 0 and not falling:
player.right = blockListDisp[i].left
vx = 0
print('Collide Right')
if vx < 0 and not falling:
player.left = blockListDisp[i].right
vx = 0
print('Collide Left')
if vy > 0:
player.bottom = blockListDisp[i].top
isGrounded = True
falling = False
vy = 0
print('Collide Bottom')
if vy < 0:
player.top = blockListDisp[i].bottom
vy = 0
print('Collide Top')
else:
player.bottom += 1
if player.colliderect(blockList[i]):
collision = True
#isGrounded = True
#falling = False
player.bottom -= 1
if not collision:
falling = True
isGrounded = False
# Input
pressedKeys = pygame.key.get_pressed() # Checks which keys are being pressed
timeDiff = pygame.time.get_ticks() - lastTime # Calculates time difference
lastTime += timeDiff # Last time checked reset to current time
# Shut-down if the ESC-key is pressed or the window is "crossed down"
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
terminate()
"""X-axis control"""
if pressedKeys[ord('a')]:
vx = -MOVESPEED
if pressedKeys[ord('d')]:
vx = MOVESPEED
if not pressedKeys[ord('d')] and not pressedKeys[ord('a')]:
vx = 0
"""Y-axis control"""
# Controls for jumping
if pressedKeys[ord('w')] and thrusters == True:
vy -= YACCEL * timeDiff; # Accelerate along the y-xis when "jumping", but not above/below max speed
if vy <= -4:
vy = -4
isGrounded = False # You are airborne
jumping = True # You are jumping
if event.type == KEYUP: # If you let go of the "jump"-button, stop jumping
if event.key == ord('w') and vy < 0 and not isGrounded:
jumping = False
falling = True
player.x += vx
player.y += vy
# Gravity
if not isGrounded or falling:
vy += 0.3
if vy > 80:
vy = 80
screen.fill(BACKGROUNDCOLOR)
for i in range(len(blockTypeList)):
if blockTypeList[i] == "solid":
screen.blit(wallblock, (blockListDisp[i].x, blockListDisp[i].y)) #blit the wall-block graphics
pygame.draw.rect(screen, (0, 0, 0), player)
pygame.display.update()
mainClock.tick(FPS)
The trick is to keep track of camera coordinates and use these as an offset in your rendering code. It looks like you're doing you're rendering right at the end of the code you've posted, drawing each block with coord x,y to pixel x,y on the screen.
As you say, shifting the level around isn't great. Instead, have your key inputs (or other camera moving device) change cameraX and cameraY variables, and then add (or subtract, depending which direction you want to go) these values from the block x and y values to change which pixels map to which blocks. I.e. change your rendering to:
screen.blit(wallblock, (blockListDisp[i].x + cameraX, blockListDisp[i].y + cameraY))
This means if your camera moves to (10, 20) then you map your block at (5, 5) to (15, 25) on the screen, shifting your whole level across while your underlying model of the level stays the same. Make sense?
You can also take this slightly further; if your camera is only being moved to follow your character you can make swap cameraX and cameraY in the above for some function of the character position, and have the whole thing just managed directly there.

Categories

Resources