4

I'm trying to learn game programming (and programming in general), therefore im making a simple sidescroller in Python using pygame.

The problem is, when I'm moving the character (a simple cube) to the left it moves faster than when im moving to the right, as shown in console later on.

Here is picture of the game.

The main class with the loop (I've cut out some of it, because it doesn't have relevance, I think, but I can post it if necessary):

player.speed = 135
player = Player.Cube([255,0,0],600, screen.get_height()*0.8-screen.get_height()*0.125,screen.get_height()*0.125,screen.get_height()*0.125)
running = True
clock = pygame.time.Clock()

while running:

    deltaTime = clock.tick(60) / 1000



    screen.blit(background, (0, 0))
    screen.blit(player.image,(player.rect.x,player.rect.y))
    screen.blit(grass,(0,screen.get_height()-grass.get_height()))

    keystate = pygame.key.get_pressed()

    if keystate[K_RIGHT]:
        player.moveRight(deltaTime)
    elif keystate[K_LEFT]:
        player.moveLeft(deltaTime)
    pygame.display.flip()

Cube class:

class Cube(pygame.sprite.Sprite):
    speed = 0
    def __init__(self, color, left,top, width, height):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self)
        self.left = left
        self.top = top
        self.image = pygame.Surface([width,height])
        self.image.fill(color)
        self.rect  = pygame.Rect(left, top, width, height)
    def moveRight(self,deltaTime):
        oldX=self.rect.x
        self.rect.x += self.speed*deltaTime
        print(self.speed*deltaTime)
        print("deltaX: " + str(self.rect.x-oldX))
    def moveLeft(self,deltaTime):
        oldX = self.rect.x
        self.rect.x -= self.speed*deltaTime
        print(self.speed * deltaTime)
        print("deltaX: " + str(self.rect.x-oldX))

As you can see, I'm trying to print out, how many pixels I moved to the right vs how many to the left:

Speed times deltaTime, right: 2.2950000000000004
deltaX, right: 2
exiting game
Speed times deltaTime, left: 2.2950000000000004
deltaX, left: -3

I don't understand one bit of this, does anyone now what the cause of this is? Also, my movement is stuttering a bit, why is that?

skrx
  • 19,980
  • 5
  • 34
  • 48
  • Not directly answering your question but why not define a function called `move`? It takes the direction as a parameter , e.g. left would be -1 and right would be +1. No more need for code duplication – Maximilian Peters May 29 '18 at 17:27
  • True, that would be better, i doubt it fix the problem though... – user8288212 May 29 '18 at 17:30
  • Where are you setting `self.speed`? – Maximilian Peters May 29 '18 at 17:32
  • I can't be certain, I don't see anything obvious, but I think it's got to do with rounding to pixel coords. – user9170 May 29 '18 at 17:32
  • @MaximilianPeters, self.speed is first declared in the Cube class, on the first line, then I change it in the initialisation of the main class – user8288212 May 29 '18 at 17:38
  • It might have something to do with rounding up, would be weird though – user8288212 May 29 '18 at 17:39
  • I am almost sure that this isn't the case, but the fact that it has to check right THEN left might play a role. I don't think that this is the case, but it might be something to think about. What @MaximilianPeters said would resolve this. – Ryan Schaefer May 29 '18 at 17:48
  • Please read the [mcve page](https://stackoverflow.com/help/mcve). We like concise, runnable examples. – skrx May 29 '18 at 17:54
  • Will keep that in mind next time! – user8288212 May 29 '18 at 18:04
  • 1
    Possible duplicate of [Puzzled by my sprite's unequal +/ - velocity](https://stackoverflow.com/questions/39324985/puzzled-by-my-sprites-unequal-velocity) – ndmeiri May 30 '18 at 05:02

1 Answers1

7

That happens because pygame.Rects can only have integers as their coordinates, and if you add or subtract a floating point number the result gets truncated afterwards.

For example if the rect.x is 10 and you add 1.5 to rect.x the new value is 11.5 which is then converted to 11. If you subtract 1.5 from 10 you get 8.5 and after truncating it 8. So in the first case you move 1 px to the right and in the second you move 2 px to the left.

The solution is to store the actual position as a separate variable or attribute, add the speed to it and then assign this value to the rect.

pos_x += speed
rect.x = pos_x

I usually use vectors to store the position and the velocity.

import pygame as pg
from pygame.math import Vector2


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((30, 50))
        self.image.fill(pg.Color('dodgerblue1'))
        self.rect = self.image.get_rect(center=pos)
        self.vel = Vector2(0, 0)
        self.pos = Vector2(pos)

    def update(self):
        self.pos += self.vel
        self.rect.center = self.pos
skrx
  • 19,980
  • 5
  • 34
  • 48