I am starting an RPG and when the character is running against a wall to either side, I can't get the player to move up and down smoothly. Also, the character can't move left or right smoothly while holding down the up and down key and running against a wall to the north or south.
I've tried different configurations of the 'move' function with no success. I know why the algorithm doesn't work, I just can't figure out how to construct the branch so that when running to the right, it will set 'self.rect.right = p.rect.left' without setting 'self.rect.bottom = p.rect.top' on the next invocation of 'move()' when I start to press down while running against a wall.
def move(self, x, y, platforms):
self.rect.left += x
self.rect.top += y
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
pygame.event.post(pygame.event.Event(QUIT))
if self.x > 0: # Moving right
self.rect.right = p.rect.left
if self.x < 0: # Moving left
self.rect.left = p.rect.right
if self.y > 0: # Moving down
self.rect.bottom = p.rect.top
if self.y < 0: # Moving up
self.rect.top = p.rect.bottom
Here's the complete code you can run to see the unwanted behavior:
#! /usr/bin/python
import pygame, platform, sys
platform.architecture()
from pygame import *
import spritesheet
from sprite_strip_anim import SpriteStripAnim
WIN_W = 1400
WIN_H = 800
HALF_W = int(WIN_W / 2)
HALF_H = int(WIN_H / 2)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class Player(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.x = 0
self.y = 0
self.onGround = False
self.image = Surface((32,32))
self.image.fill(Color("#0000FF"))
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def update(self, up, down, left, right, running, platforms):
if up:
self.y = -5
if down:
self.y = 5
if left:
self.x = -5
if right:
self.x = 5
if not(left or right):
self.x = 0
if not(up or down):
self.y = 0
self.move(self.x, 0, platforms)
self.move(0, self.y, platforms)
def move(self, x, y, platforms):
self.rect.left += x
self.rect.top += y
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
pygame.event.post(pygame.event.Event(QUIT))
if self.x > 0: # Moving right
self.rect.right = p.rect.left
if self.x < 0: # Moving left
self.rect.left = p.rect.right
if self.y > 0: # Moving down
self.rect.bottom = p.rect.top
if self.y < 0: # Moving up
self.rect.top = p.rect.bottom
class Platform(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.image = Surface((32, 32))
self.image.convert()
self.image.fill(Color("#DDDDDD"))
self.rect = Rect(x, y, 32, 32)
def update(self):
pass
class ExitBlock(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image.fill(Color("#0033FF"))
def main():
pygame.init
screen = pygame.display.set_mode((WIN_W, WIN_H), FLAGS, DEPTH)
pygame.display.set_caption("Use arrows to move!")
timer = pygame.time.Clock()
up = down = left = right = running = False
bg = Surface((32,32))
bg.convert()
bg.fill(Color("#000000"))
entities = pygame.sprite.Group()
player = Player(32, 32)
platforms = []
x = y = 0
level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P P",
"P P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P P",
"P P",
"P PPPPPPPP P",
"P P",
"P PPPPPPP P",
"P PPPPPP P",
"P P",
"P PPPPPPP P",
"P P",
"P PPPPPP P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P PPPPPPPPPPP P",
"P P",
"P P",
"P P",
"P P",
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]
# build the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
platforms.append(p)
entities.add(p)
if col == "E":
e = ExitBlock(x, y)
platforms.append(e)
entities.add(e)
x += 32
y += 32
x = 0
total_level_width = len(level[0])*32
total_level_height = len(level)*32
entities.add(player)
while 1:
timer.tick(60)
# draw background
for y in range(32):
for x in range(32):
screen.blit(bg, (x * 32, y * 32))
for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE:
raise SystemExit, "ESCAPE"
if e.type == KEYDOWN and e.key == K_w:
up = True
down = False
if e.type == KEYDOWN and e.key == K_s:
down = True
up = False
if e.type == KEYDOWN and e.key == K_a:
left = True
right = False
if e.type == KEYDOWN and e.key == K_d:
right = True
left = False
if e.type == KEYUP and e.key == K_w:
up = False
if e.type == KEYUP and e.key == K_s:
down = False
if e.type == KEYUP and e.key == K_d:
right = False
if e.type == KEYUP and e.key == K_a:
left = False
# update player, draw everything else
player.update(up, down, left, right, running, platforms)
for e in entities:
screen.blit(e.image, e.rect)
pygame.display.update()
if __name__ == "__main__":
main()