Why is my pygame application loop not working properly? [duplicate]
I am working on a very rough topdown 2d adventure game after skimming around the pygame documentation. However, I have hit a bit of a roadblock after not being able to find anything on a camera system and found that most tutorials for a camera are 5+ years old and don't seem to work anymore. Can anybody help me build a camera?
This is my main executed script
import sys, pygame
from PlayerObject import Player
pygame.init()
screen_height = 180
screen_width = 320
map_height = 1080
map_width = 1920
num_objects = 5
screen = pygame.display.set_mode((screen_width, screen_height))
player_image = pygame.image.load('models/hero.bmp').convert()
background = pygame.image.load('models/lobby.bmp').convert()
screen.blit(background, (0, 0))
objects = []
# randomly generates 5 entities with the 1st one being the controlled character
for i in range(num_objects):
o = Player(player_image, random.randint(0, screen_width), random.randint(0, screen_height), 10)
objects.append(o)
while 1:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
screen.blit(background, objects[0].pos, objects[0].pos)
objects[0].move_left()
screen.blit(objects[0].image, objects[0].pos)
if keys[pygame.K_RIGHT]:
screen.blit(background, objects[0].pos, objects[0].pos)
objects[0].move_right()
screen.blit(objects[0].image, objects[0].pos)
if keys[pygame.K_UP]:
screen.blit(background, objects[0].pos, objects[0].pos)
objects[0].move_up()
screen.blit(objects[0].image, objects[0].pos)
if keys[pygame.K_DOWN]:
screen.blit(background, objects[0].pos, objects[0].pos)
objects[0].move_down()
screen.blit(objects[0].image, objects[0].pos)
screen.blit(background)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
for o in objects:
screen.blit(background, o.pos, o.pos)
for num in range(num_objects - 1):
objects[num + 1].rand_move()
for o in objects:
screen.blit(o.image, o.pos)
pygame.display.update()
pygame.time.delay(100)
This is my Player class
import random
map_height = 180
map_width = 320
class Player:
def __init__(self, image, width, height, speed):
self.speed = speed
self.image = image
self.pos = image.get_rect().move(width, height)
self.image = image
def set_speed(self, speed):
self.speed = speed
def rand_move(self):
x = random.randint(-self.speed, self.speed)
y = random.randint(-self.speed, self.speed)
self.pos = self.pos.move(x, y)
# keeps player in boundaries
if self.pos.left < 0:
self.pos.left = 0
if self.pos.right > map_width:
self.pos.right = map_width
if self.pos.top < 0:
self.pos.top = 0
if self.pos.bottom > map_height:
self.pos.bottom = map_height
def move_left(self):
speed = self.speed
self.pos = self.pos.move(-speed, 0)
if self.pos.left < 0:
self.pos.left = 0
def move_right(self):
speed = self.speed
self.pos = self.pos.move(speed, 0)
if self.pos.right > map_width:
self.pos.right = map_width
def move_up(self):
speed = self.speed
self.pos = self.pos.move(0, -speed)
if self.pos.top < 0:
self.pos.top = 0
def move_down(self):
speed = self.speed
self.pos = self.pos.move(0, speed)
if self.pos.bottom > map_height:
self.pos.bottom = map_height
Solution 1:
Your basic misunderstanding, is that you try to draw the background at the position of an object, then you move the object and blit
it finally on its new position. That all is not necessary.
In common the entire scene is drawn in each frame in the main application loop. It is sufficient to draw the background to the entire window and blit
each object on top of it. Note, you do not see the changes of the window surface immediately. The changes become visible, when the display is updated by pygame.display.update()
or pygame.display.flip()
:
The main application loop has to:
- handle the events by either
pygame.event.pump()
orpygame.event.get()
. - update the game states and positions of objects dependent on the input events and time (respectively frames)
- clear the entire display or draw the background
- draw the entire scene (
blit
all the objects) - update the display by either
pygame.display.update()
orpygame.display.flip()
e.g.:
while 1:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# update objects (depends on input events and frames)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
objects[0].move_left()
if keys[pygame.K_RIGHT]:
objects[0].move_right()
if keys[pygame.K_UP]:
objects[0].move_up()
if keys[pygame.K_DOWN]:
objects[0].move_down()
for num in range(num_objects - 1):
objects[num + 1].rand_move()
# draw background
screen.blit(background, (0, 0))
# draw scene
for o in objects:
screen.blit(o.image, o.pos)
# update dispaly
pygame.display.update()
pygame.time.delay(100)
Minimal example: repl.it/@Rabbid76/PyGame-MinimalApplicationLoop