Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
FPS Cap (Tutorial / Question [at the bottom])
#1
First and foremost, I'm not sure where this should have gone, so I placed it in the General Chit Chat section. It's basically an optimization tutorial, but also a question, so I wasn't sure...

There is an FPS cap over the entire client-side MS engine, in the GameLoop Sub. Why the whole GameLoop?
Code:
' Lock fps
    Do While GetTickCount < Tick + 60 '  TickMove + 60 Then
        Call CheckMovement
        TickMove = GetTickCount
    End If

This makes it so your player now moves at the same rate that it did when the FPS was locked.

In order to make it so NPCs and other players move at the same rate as everyone else, make a variable for the action and put the lock around the it as well:
Code:
If GetTickCount > TickNPCMove + 60 Then
        For i = LBound(MapNpc) To UBound(MapNpc)
            If MapNpc(i).Moving = True Then
                TickNPCMove = GetTickCount
                Exit For
            End If
            If MapNpc(i).Num > 0 Then Call ProcessNpcMovement(i)
        Next i
        TickNPCMove = GetTickCount
    End If

Now finish it off by adding it to anything else that needs limiting to the base FPS (16 FPS).

So far all you've done is make it so the framerate increases, and nothing is smooth... would you like your players' movement smooth? Check the question below. (They are still a part of the post, not just a debug section or something of the sort)

Questions:

My players are still really jumpy, and they do not walk smoothly, why?
This tutorial doesn't fix the amount of times that the players appear while walking or running in their animation.

A player presses.. let's say... left once to go left one tile. While a player is walking, the character gets blitted however many times the gameloop sub is called (The same number of times as your FPS), but the player isn't actually shown on each pixel as it moves. It jerks from right to left when walking right by a certain number of pre-determined pixels, WALK_SPEED.

The base MS WALK_SPEED is 4, which means that the player gets shown every four pixels; eight times per tile walk (32 / 4 = 8). Also, every time that a player walks one tile, it takes exactly 480 ticks, or milliseconds.

The base RUN_SPEED is 8, which means that the player gets shown every eight pixels; 4 times per tile run (32 / 8 = 4). Also, every time that a player walks one tile, it takes exactly 240 ticks, or milliseconds.

In order to make the players get shown more times per tile move (instead of jerking over 4 tiles, you can make it jerk over 2, making it look smoother), change the WALK_SPEED and RUN_SPEED to lower numbers. (ie: 2 and 4)

!!BE SURE TO KEEP THE NUMBERS AT LEAST 1 AND AT MOST 32!! The two numbers HAVE to be divisible by 2 (unless the WALK_SPEED is 1 and the RUN_SPEED is 2), and a factor of 32. (1, 2, 4, 8, 16, and 32) This way, XOffset and YOffset don't get thrown off into some weird number, and render your player motionless.

If you change WALK_SPEED to 2, the player will walk half the speed as before because the player is allowed to move by the FPS cap that you set upon him or her. In the GameLoop sub, you'll notice that it is actually limiting the times that "Call ProcessMovement(i)" is called. That's because this is what actually MOVES the player.

Code:
Sub ProcessMovement(ByVal Index As Long)
    ' Check if player is walking, and if so process moving them over
    If Player(Index).Moving = MOVING_WALKING Then
        Select Case GetPlayerDir(Index)
            Case DIR_UP
                Player(Index).YOffset = Player(Index).YOffset - WALK_SPEED
            Case DIR_DOWN
                Player(Index).YOffset = Player(Index).YOffset + WALK_SPEED
            Case DIR_LEFT
                Player(Index).XOffset = Player(Index).XOffset - WALK_SPEED
            Case DIR_RIGHT
                Player(Index).XOffset = Player(Index).XOffset + WALK_SPEED
        End Select
        
        ' Check if completed walking over to the next tile
        If (Player(Index).XOffset = 0) And (Player(Index).YOffset = 0) Then
            Player(Index).Moving = 0
        End If
    End If

    ' Check if player is running, and if so process moving them over
    If Player(Index).Moving = MOVING_RUNNING Then
        Select Case GetPlayerDir(Index)
            Case DIR_UP
                Player(Index).YOffset = Player(Index).YOffset - RUN_SPEED
            Case DIR_DOWN
                Player(Index).YOffset = Player(Index).YOffset + RUN_SPEED
            Case DIR_LEFT
                Player(Index).XOffset = Player(Index).XOffset - RUN_SPEED
            Case DIR_RIGHT
                Player(Index).XOffset = Player(Index).XOffset + RUN_SPEED
        End Select
        
        ' Check if completed walking over to the next tile
        If (Player(Index).XOffset = 0) And (Player(Index).YOffset = 0) Then
            Player(Index).Moving = 0
        End If
    End If
End Sub
When this "Sub ProcessMovement" is called, it moves the player by the number you set as WALK_SPEED or RUN_SPEED. So, if you set WALK_SPEED as 2, the player will walk 2 pixels every 60 ticks (.060 seconds, right?) (This is only if you set the FPS cap as "+ 60" earlier in step 2. -- VERY slow compared to before. When WALK_SPEED was 4, it moved the player 4 pixels every 60 milliseconds / ticks; double the speed than it is now!

To fix the speed that you just changed, change the FPS cap from "+ 60" to "+ 30", resulting in it being called twice as much. The player now moves just as fast as before, but is showed twice as much.


Mathematically this method works, but I'm still having trouble perfecting it.. it's just not perfect yet and I don't know why. Does anyone else?

It sure does makes sense though!


I hope that you all can make heads or tails out of what I've written, and I also hope that this has helped some people. It would be wonderful if someone finds a way to make it better. This may be the best, or worst method to accomplish this task, but it's the only way that I could think of, so comments / questions are welcome and needed.

:: Erik

PS: I really have trouble explaining stuff to people; I'm not a very good teacher. If you see any words that should be changed or rewritten, then just tell me if you're a regular user, or change it for me if you're a mod. Thanks again! Comments are welcome!
Reply
#2
The upper part of the post is just a section explaining how to unlimit how many times the GameLoop sub is allowed to do its events, and instead just limit things that need to be limited.

Now, graphical wise.. yes, there's a big difference in a player walking 1 pixel per ProcessMovement(), or 8.

The player will get displayed differently 4 times if it's 8, and 32 times if it's 1. (That is, if your PIC_X and PIC_Y are both 32..) That makes a big difference on smoothness. I may make a blank MSE with this, a couple screenies, or maybe a video.. hmm.

Dave Wrote:The eye may require more than 16 FPS for other situations, but a MS game would probably look exactly the same at around 8 FPS. There's just not enough going on to notice any difference.

But yes, Dave. You're right. In a blank MSE, if you uncapped GameLoop, then capped all the calls inside to 60 again, then it will, of course, run the same but at a higher framerate, resulting in no noticable difference to the eye.

:: Erik
Reply
#3
Erik Wrote::: Erik

Better stop doing that before Robin copies you :p. Haha JK.
Reply
#4
Most of my games run at 32 capped FPS, but I usually now simply leave it free and restrict everything else.
Quote:Robin:
Why aren't maps and shit loaded up in a dynamic array?
Jacob:
the 4 people that know how are lazy
Robin:
Who are those 4 people?
Jacob:
um
you, me, and 2 others?
Reply
#5
Robin Wrote:Most of my games run at 32 capped FPS, but I usually now simply leave it free and restrict everything else.

Thats what I tend to do, but for ms, I don't think its worth the hassle unless its a final release perfected kinda thing. I don't really notice much difference for it on my computer anyway
Reply
#6
If you're getting better fps by only capping certain calls, (idk how much better), shouldn't advanced features such as alpha blending work better? Or is the fps freed with this method useless ?
Reply
#7
You're not making the FPS higher by uncapping.

Before, the loop wouldn't go above 32fps even though it could theoretically run at 100+

If you add alpha blending then you're going to lose a lot of that 100+ fps, but the game won't use more than 32 of them.
Quote:Robin:
Why aren't maps and shit loaded up in a dynamic array?
Jacob:
the 4 people that know how are lazy
Robin:
Who are those 4 people?
Jacob:
um
you, me, and 2 others?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)