In the main game loop, a movement key press changes the player state:
for event in pygame.event.get():
elif event.type == KEYDOWN:
if event.key == K_w:
player.state = "moving_up"
elif event.type == KEYUP:
if event.key == K_w:
player.state = "stopping_up"
When the player update method is called, it moves according to the state:
def update(self):
if self.state == "idle":
self.displacement = self.displacement
else:
if self.state == "moving_up":
self.displacement[1] = self.displacement[1] - self.speed
if self.state == "stopping_up":
s = self.rect.top % 32
self.displacement[1] = self.displacement[1] - s
self.state = "idle"
new_position = self.rect.move(self.displacement)
self.rect = new_position
When I move the player, the speed seems to be accelerating after each consequent press of the key. e.g. the first time i move the speed is fine, but the next time it is even faster than before and it just snowballs...
Here is a print out of the (speed), (displacement) when moving right:
idle
0.02 [0.7200000000000003, 0]
0.02 [0.7400000000000003, 0]
0.02 [0.7600000000000003, 0]
...
0.02 [1.2400000000000007, 0]
0.02 [1.2600000000000007, 0]
0.02 [19.26, 0]
idle
You can see that on the last movement the displacement increases greatly.
Any idea why this is happening?
update, here is another print out with s:
0.02 [1.1600000000000006, 0]
0.02 [1.1800000000000006, 0]
0.02 [1.2000000000000006, 0]
0.02 [1.2200000000000006, 0]
0.02 [1.2400000000000007, 0]
0.02 [1.2600000000000007, 0]
s: remainder to next tile 18
0.02 [19.2600000000000007, 0]
It looks like s is causing the jump in displacement.
This was intentional as it was supposed to find the distance to the next tile and make the player move there. (tiles are 32x32) and s was the remainder until the next one.
Seems like I need to revise the movement code as it's not resulting in what I expected.
The obvious thing here is that the final value is using s
rather than self.speed
.
As a side note:
In general, in doing physical simulations, it's best to use physical units. By this I mean, think of time in seconds, not loop passes, etc, and work from this. If you want to increment a distance using a speed, do this as dist += dt*speed
, not dist += speed
. Usually this involves and extra multiplication, but it's well worth it. Otherwise, you're effectively using time units so that dt=1.
, which is possible, but trickier than it seems at first.
Here, for example, you're adding self.displacement[1] - self.speed
, and in the next line you do self.displacement[1] = self.displacement[1] - s
, where s
seems to be a distance. Although in numbers these two things look similar, physically they are very different. It's not surprising there was a bug here because the whole thing is hard to understand.