Python and tile based game: limiting player movement speed
Question: I've been putting together an isometric tile-based RPG using Python and the
Pyglet library. I've run into the following problem, however:

My player movement is based on positions on the three-dimensional array that
consists of tiles. To limit movement speed, I use a global variable:
TILE_TO_TILE_DELAY = 200.

TILE_TO_TILE_DELAY is supposed to be the amount of time in milliseconds it
takes for the player to move from one tile to another. During this time, they
should not be able to make a new movement.

The system I've been using is that I have a timer class, like this:

    
    
    import time
    
    def GetSystemTimeInMS(): #Return system time in milliseconds
        systime = round((time.clock()*1000), 0)
        return systime
    
    class Timer:
    def __init__(self,time):
        #time = time for which the timer runs
        self.time = time
        self.start_time = 0
        self.stop_time  = 0
    
    def StartTimer(self):
        #start_time = time at which the timer was started
        self.start_time = GetSystemTimeInMS()
        self.stop_time  = self.start_time + self.time
    
    def TimerIsStopped(self):
        if GetSystemTimeInMS() >= self.stop_time:
            return True
        else:
            return False
    

The player class has a Timer object:

    
    
    self.MoveTimer = Timer(TILE_TO_TILE_DELAY)
    

When the player presses the W-key, a function is called that checks for
player.MoveTimer.TimerIsStopped(). If it returns True, it calls
player.MoveTimer.StartTimer() and starts a new movement to the next position.

In the even loop, the update(dt) function is set to happen 30 times a second:

    
    
    def update(dt):
        if player.MoveTimer.TimerIsStopped()
            player.UpdatePosition()
    
    pyglet.clock.schedule_interval(update, 1/30)
    

Now, by my logic, update(dt) should check 30 times a second whether or not
enough time has passed to warrant the player a new movement event. However,
for some reason the player moves much faster at lower FPS.

When my FPS is around 30, the player moves much faster than in areas where
there are less tile sprites, pumping the framerate to 60. In areas where FPS
is high, the player indeed by my measurements moves almost twice as slowly.

I just cannot figure it out, nor did I find anything off the internet after a
day of searching. Some help would be much appreciated.

Edit: The code that starts the MoveTimer:

    
    
    def StartMovement(self, new_next_pos):
        self.RequestedMovement = False
        if self.GetCanMoveAgain():
    
            self.SetNextPos(new_next_pos)
            self.SetMoveDirection(self.GetDirection())
    
    
            #Start the timer for the movement
            self.MoveTimer.StartTimer()
            self.SetIsMoving(True)
            self.SetStartedMoving(True)
    
            self.SetWalking(True)
    
            self.SetNeedUpdate(True)
    
            self.MOVE_EVENT_HANDLER.CreateMoveEvent()
    

GetCanMoveAgain() returns the value of player.can_move_again, which is set
back to True by the UpdatePosition() in update(dt)


Answer: Alright, I fixed the problem, how ever I'm still unsure about what caused it.
Maybe it was some sort of a rounding error with milliseconds, having to do
with more checks being made to the clock when the FPS is higher. Anyways, the
solution:

Instead of using the system clock, I decided to use Pyglet's own "dt" argument
in their update functions:

> The dt parameter gives the number of seconds (due to latency, load and timer
> inprecision, this might be slightly more or less than the requested
> interval).

The new timer looks like this:

    
    
    class dtTimer: #A timer based on the dt-paremeter of the pyglet event loop
    def __init__(self,time):
        self.time = time
        self.time_passed = 0
    
    def StartTimer(self):
        self.time_passed = 0
    
    def UpdateTimer(self, dt):
        self.time_passed += dt*1000
    
    def GetTime(self):
        return self.time
    
    def GetTimePassed(self):
        if not self.TimerIsStopped():
            return self.time_passed
        else:
            return 0
    
    def TimerIsStopped(self):
        if self.time_passed > self.time:
            return True
        else:
            return False
    

When the loop attempts to update the player's position, if the TimerIsStopped
returns false, dt is simply added to the Timer's self.time_passed. This has
fixed the issue: the time it takes for the player to move is now constant.

Thanks for looking at my issue.

