[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pygame] Rects and subpixel values



I've run into a little problem with my game, and I wonder if anyone
has an idea...

I'm trying to implement proper frame-rate handling code - I'm trying
to measure the length of time between frames, then scale all actor
speeds by that duration for the rest of the frame. The idea is that if
the player speed is 100 pixels per second, and the frame is 1/50th of
a second long, the player will move 2 pixels. If the frame is later
1/100th of a second long, the player moves 1 pixel during that frame.

The code is simple:

class Timer:
    def __init__(self):
        self.last_frame_ms = 0
        self.this_frame_ms = 0
        self.frame_duration = 0.000

    def calculate_frame_duration(self):
        self.this_frame_ms = pygame.time.get_ticks()
        self.frame_duration = ((self.this_frame_ms - self.last_frame_ms) / 1000.000)
        self.last_frame_ms = self.this_frame_ms
        return

then...

player.delta_x = Player.speed * timer.frame_duration

an my player should move smoothly at a constant rate as the framerate
changes. In theory this works great.

The problem I'm running into is that for slow-moving objects, or for
high-framerate situations, delta_x is less than one. When I then do:

player.rect.left += player.delta_x

rounding dominates. In other words, at some point, rect.left is being
cast to an int, and I'm losing the information after the decimal
place. The result is what you'd expect - I can move left or up at the
rate of one pixel per frame, and I can't move right or down at
all. It's a shame, because I'm starting to use rects for _everything_
- that's a great little class there, Pete :)

What's the solution? Should Rect.left be able to hold a float, but
only pass an int to SDL?

Ugh. Ever notice that when you type out a problem you're having, the
solution seems obvious? The solution, I suppose, is to keep track of
the 'real' x and y coordinates in an extra pair of variables -
player.x and player.y (both as floats), and only do:

player.rect.topleft = (int(player.x), int(player.y))

before drawing and collision detection. Hmmm... that should work.

Any thoughts? Has anyone tried this stuff before?
 

-- 
David "Futility [D!]" Clark  |  How can this mean anything to me, when |
silenus@telus.net            |  I really don't feel anything at all?   |
------------------------------------------------------------------------

____________________________________
pygame mailing list
pygame-users@seul.org
http://pygame.seul.org