Hello! I'm a noob at python and pygame, also forgive for possible english mistakes, i'm actually from Brasil.
I'm creating a plataform game using tilemaps and loading it with Richard's Jones tmx library, and i have come across a "bug":
When i'm moving my character around, he goes faster to the left and down directions.
First, i thought it was an error with my code, but after making differents test's using 20-scenes.py, written by Richard Jones, i've realized that this problem ocurrs with his game. If you press both the left and the right arrows together you will see that the caracter has the tendency of going left, also all the objects (Bullet, enemy, Player...) can't have a speed bellow 20 pixels/second (in my game, you can't set a speed bellow 31 pixels/second) otherwize it can't move to the right direction.
What is the source of the problem? How do i fix it?
Here is richard Jones source code:
https://bitbucket.org/r1chardj0n3s/pygame-tutorial/src/91afdcebb0ae?at=default
And here is the code of my enemy object:
import pygame, random
from pygame.locals import *
from Funsoes import *
import resources
class Enemy(pygame.sprite.Sprite):
def __init__(self, location, name, *groups):
super(Enemy, self).__init__(*groups)
self.type = 'Enemy'
self.AllDirection = {'Down': 0, 'Right': 1, 'Up': 2, 'Left': 3}
self.All = {'Lesma': (16, 12, -2, -5, 1, 20)}
self.nome = name
self.originalPosition = location
self.direction = 'Down'
self.number_of_sprite = 0
self.spritesheet = load_sheet('%s.png'%name,'Imagens',
self.All[name][0], self.All[name][1])
self.image = self.spritesheet[self.AllDirection[self.direction]][self.number_of_sprite]
self.rect = pygame.rect.Rect(location, self.image.get_size())
self.deadImage = pygame.image.load(resources.file_path('%sdead.png'%name, 'Imagens')).convert_alpha()
self.collisionRect = pygame.rect.Rect(self.rect.x + self.All[name][2],
self.rect.y + self.All[name][3], 12, 5)
self.life = self.All[name][4]
self.vida = self.life
self.Max = len(self.spritesheet[0])
self.vy = self.All[name][5]
self.vx = 0
self.mask = pygame.mask.from_surface(self.image)
self.alive = True
self.atking = False
self.cont = 0
def update(self, dt, Game):
if not Game.Pause:
if self.alive:
last = self.collisionRect.copy()
self.vx = self.vy = 0
if self.cont >= 4*dt:
self.number_of_sprite += 1
self.cont = 0
if self.number_of_sprite == self.Max:
self.direction = random.choice(['Right', 'Up','Down', 'Left'])
self.number_of_sprite = 0
if self.direction == 'Down':
self.vy = 31
elif self.direction == 'Up':
self.vy = (-1)*self.All[self.nome][5]
elif self.direction == 'Right':
self.vx = 31
else:
self.vx = (-1)*self.All[self.nome][5]
self.collisionRect.centerx += self.vx * dt
self.collisionRect.centery += self.vy * dt
new = self.collisionRect
for cell in Game.tilemap.layers['triggers'].collide(new, 'block'):
blockers = cell['block']
if 'l' in blockers and last.right <= cell.left and new.right > cell.left:
new.right = cell.left
if 'r' in blockers and last.left >= cell.right and new.left < cell.right:
new.left = cell.right
if 't' in blockers and last.bottom <= cell.top and new.bottom > cell.top:
new.bottom = cell.top
if 'b' in blockers and last.top >= cell.bottom and new.top < cell.bottom:
new.top = cell.bottom
self.rect.left = new.left - 2
self.rect.top = new.top - 5
self.cont+= dt
self.image = self.spritesheet[self.AllDirection[self.direction]][self.number_of_sprite]
self.mask = pygame.mask.from_surface(self.image)
else:
if self.cont >= 2*dt:
self.number_of_sprite += 1
self.cont = 0
if self.number_of_sprite == self.Max:
self.kill()
for sprite in Game.sprites:
if sprite.type == 'Player':
sprite.placedPositions.remove(self.originalPosition)
break
self.cont += dt
def draw(self, Surface):
Surface.blit(self.image, self.rect)
if not self.alive:
Surface.blit(self.spritesheet[0][self.number_of_sprite], (self.rect.x, self.rect.y - 8))
Also, i kind of modified the tmx library a bit(only the draw method in the SpriteLayer object):
class SpriteLayer(pygame.sprite.AbstractGroup):
def __init__(self):
super(SpriteLayer, self).__init__()
self.visible = True
def set_view(self, x, y, w, h, viewport_ox=0, viewport_oy=0):
self.view_x, self.view_y = x, y
self.view_w, self.view_h = w, h
x -= viewport_ox
y -= viewport_oy
self.position = (x, y)
[b] def draw(self, screen):
ox, oy = self.position
w, h = self.view_w, self.view_h
OrderedSprites = OrderSprites(self.sprites())
for sprite in OrderedSprites:
sx, sy = sprite.rect.topleft
screen.blit(sprite.image, (sx-ox, sy-oy))
[/b]
The OrderedSprites function:
def OrderSprites(spriteGroup):
OrderedSprites = []
Sprites = spriteGroup
cont = len(spriteGroup)
while len(OrderedSprites) < cont:
MaxY = 0
for sprite in Sprites:
if sprite.rect.bottom > MaxY:
MaxY = sprite.rect.bottom
chosed = sprite
OrderedSprites.append(chosed)
Sprites.remove(chosed)
OrderedSprites.reverse()
return OrderedSprites
I'm creating a plataform game using tilemaps and loading it with Richard's Jones tmx library, and i have come across a "bug":
When i'm moving my character around, he goes faster to the left and down directions.
First, i thought it was an error with my code, but after making differents test's using 20-scenes.py, written by Richard Jones, i've realized that this problem ocurrs with his game. If you press both the left and the right arrows together you will see that the caracter has the tendency of going left, also all the objects (Bullet, enemy, Player...) can't have a speed bellow 20 pixels/second (in my game, you can't set a speed bellow 31 pixels/second) otherwize it can't move to the right direction.
What is the source of the problem? How do i fix it?
Here is richard Jones source code:
https://bitbucket.org/r1chardj0n3s/pygame-tutorial/src/91afdcebb0ae?at=default
And here is the code of my enemy object:
import pygame, random
from pygame.locals import *
from Funsoes import *
import resources
class Enemy(pygame.sprite.Sprite):
def __init__(self, location, name, *groups):
super(Enemy, self).__init__(*groups)
self.type = 'Enemy'
self.AllDirection = {'Down': 0, 'Right': 1, 'Up': 2, 'Left': 3}
self.All = {'Lesma': (16, 12, -2, -5, 1, 20)}
self.nome = name
self.originalPosition = location
self.direction = 'Down'
self.number_of_sprite = 0
self.spritesheet = load_sheet('%s.png'%name,'Imagens',
self.All[name][0], self.All[name][1])
self.image = self.spritesheet[self.AllDirection[self.direction]][self.number_of_sprite]
self.rect = pygame.rect.Rect(location, self.image.get_size())
self.deadImage = pygame.image.load(resources.file_path('%sdead.png'%name, 'Imagens')).convert_alpha()
self.collisionRect = pygame.rect.Rect(self.rect.x + self.All[name][2],
self.rect.y + self.All[name][3], 12, 5)
self.life = self.All[name][4]
self.vida = self.life
self.Max = len(self.spritesheet[0])
self.vy = self.All[name][5]
self.vx = 0
self.mask = pygame.mask.from_surface(self.image)
self.alive = True
self.atking = False
self.cont = 0
def update(self, dt, Game):
if not Game.Pause:
if self.alive:
last = self.collisionRect.copy()
self.vx = self.vy = 0
if self.cont >= 4*dt:
self.number_of_sprite += 1
self.cont = 0
if self.number_of_sprite == self.Max:
self.direction = random.choice(['Right', 'Up','Down', 'Left'])
self.number_of_sprite = 0
if self.direction == 'Down':
self.vy = 31
elif self.direction == 'Up':
self.vy = (-1)*self.All[self.nome][5]
elif self.direction == 'Right':
self.vx = 31
else:
self.vx = (-1)*self.All[self.nome][5]
self.collisionRect.centerx += self.vx * dt
self.collisionRect.centery += self.vy * dt
new = self.collisionRect
for cell in Game.tilemap.layers['triggers'].collide(new, 'block'):
blockers = cell['block']
if 'l' in blockers and last.right <= cell.left and new.right > cell.left:
new.right = cell.left
if 'r' in blockers and last.left >= cell.right and new.left < cell.right:
new.left = cell.right
if 't' in blockers and last.bottom <= cell.top and new.bottom > cell.top:
new.bottom = cell.top
if 'b' in blockers and last.top >= cell.bottom and new.top < cell.bottom:
new.top = cell.bottom
self.rect.left = new.left - 2
self.rect.top = new.top - 5
self.cont+= dt
self.image = self.spritesheet[self.AllDirection[self.direction]][self.number_of_sprite]
self.mask = pygame.mask.from_surface(self.image)
else:
if self.cont >= 2*dt:
self.number_of_sprite += 1
self.cont = 0
if self.number_of_sprite == self.Max:
self.kill()
for sprite in Game.sprites:
if sprite.type == 'Player':
sprite.placedPositions.remove(self.originalPosition)
break
self.cont += dt
def draw(self, Surface):
Surface.blit(self.image, self.rect)
if not self.alive:
Surface.blit(self.spritesheet[0][self.number_of_sprite], (self.rect.x, self.rect.y - 8))
Also, i kind of modified the tmx library a bit(only the draw method in the SpriteLayer object):
class SpriteLayer(pygame.sprite.AbstractGroup):
def __init__(self):
super(SpriteLayer, self).__init__()
self.visible = True
def set_view(self, x, y, w, h, viewport_ox=0, viewport_oy=0):
self.view_x, self.view_y = x, y
self.view_w, self.view_h = w, h
x -= viewport_ox
y -= viewport_oy
self.position = (x, y)
[b] def draw(self, screen):
ox, oy = self.position
w, h = self.view_w, self.view_h
OrderedSprites = OrderSprites(self.sprites())
for sprite in OrderedSprites:
sx, sy = sprite.rect.topleft
screen.blit(sprite.image, (sx-ox, sy-oy))
[/b]
The OrderedSprites function:
def OrderSprites(spriteGroup):
OrderedSprites = []
Sprites = spriteGroup
cont = len(spriteGroup)
while len(OrderedSprites) < cont:
MaxY = 0
for sprite in Sprites:
if sprite.rect.bottom > MaxY:
MaxY = sprite.rect.bottom
chosed = sprite
OrderedSprites.append(chosed)
Sprites.remove(chosed)
OrderedSprites.reverse()
return OrderedSprites