Faster movement
BlitzMax Forums/BlitzMax Beginners Area/Faster movement
| ||
I've been using Bresenham's line algorithm for player movement, and I am trying to make the player move faster when the basespeed is increased. I tried multiplying the steps by the basespeed, but that ended up with the player passing through the target location entirely. Is there any way to increase the speed of the player's movement using Bresenham's line algorithm? Graphics 640,480,0 x = 250 y = 250 xspeed = 0 yspeed = 0 targetx = x targety = y sx = 0 sy = 0 velocity = 0 angle:Float = 0 basespeed:Int = 1 Repeat Cls distance:Float = Sqr((x-targetx)*(x-targetx) + (y-targety)*(y-targety)) If MouseHit(2) 'Right Click targetx = MouseX() targety = MouseY() dx = Abs(targetx-x) dy = Abs(targety-y) If x < targetx sx = 1 Else sx = -1 EndIf If y < targety sy = 1 Else sy = -1 EndIf err = dx-dy ax = targetx-x ay = targety-y angle = ATan2(ax,ay) * -1 + 90 EndIf If KeyDown(KEY_SPACE) x = 250 y = 250 EndIf If KeyDown(KEY_UP) basespeed :+ 1 EndIf If KeyDown(KEY_DOWN) basespeed :- 1 EndIf If Not(x-targetx=0) Or Not(y-targety=0) e2 = 2*err If e2 >= (-1 * dy) err :- dy x :+ sx EndIf If e2 < dx err :+ dx y :+ sy EndIf EndIf DrawRect(x-4,y-4,8,8) DrawLine(x,y,targetx,targety) 'Draw 30 degree cone splash borders DrawLine(x, y, x + 100 * Cos(angle-15), y + 100 * Sin(angle-15)) DrawLine(x, y, x + 100 * Cos(angle+15), y + 100 * Sin(angle+15)) 'Draw middleline according to angle 'DrawLine(x, y, x + 100 * Cos(angle), y + 100 * Sin(angle)) DrawText("Angle: " + angle, 50, 50) DrawText("Current Coord: " + x + " , " + y, 50, 80) DrawText("Target Coord: " + targetx + " , " + targety, 50, 110) DrawText("dx: " + dx + " dy: " + dy, 50, 140) DrawText("distance: " + distance, 50, 170) DrawText("basespeed: " + basespeed, 50, 210) Flip Until KeyDown(KEY_ESCAPE) Or AppTerminate() End |
| ||
I do not not, whether I understand what you want, but if you want to increase the speed of the player, just do two things: 1. use "Flip 0" instead of "Flip" 2. use Timers to get induvidual turnarounds for the actors: Because it is not the moving algorithm, that wastes time, but the drawing. So, if you reduce the amount of drawing per second, there is more time for the rest of the code. Each "FLIP" waits upto ~15msec for the "VSYNC", until it is turning back to the application. You will have 60 FPS (turnarounds per second). "Flip 0" does not wait! With "Flip 0 " the speed of the program rises dramatically (200fps), so you now have to intervent, that the computer (other apps and OS) keeps operable. The speed now depents on the "bottleneck" in your code. And this is the drawing. There is no use to draw more often than 60 times a second. So add a painting-timer, which allows drawing only every 16msec. (16msec*60times=~960msec). Now the FPS rises upto ~1000! From this moment you cannot longer handle the keyboard! So now add a Keyboard-timer, which allows to check the keyboard only 5 times a second. (=200msec). This is enough. The player gets and individual update rate between 100msec and 1msec. This means 10 times (1000msec:100msec=10 times) upto 1000 times a second. So now he can walk 10 steps in one second upto 1000 steps. Graphics 640,480,0 x = 250 y = 250 xspeed = 0 yspeed = 0 targetx = x targety = y sx = 0 sy = 0 velocity = 0 angle:Float = 0 basespeed:Int = 1 Repeat If KeyTime<MilliSecs() Then KeyTime = MilliSecs()+200 If MouseHit(2) 'Right Click targetx = MouseX() targety = MouseY() dx = Abs(targetx-x) dy = Abs(targety-y) If x < targetx sx = 1 Else sx = -1 EndIf If y < targety sy = 1 Else sy = -1 EndIf err = dx-dy ax = targetx-x ay = targety-y angle = ATan2(ax,ay) * -1 + 90 EndIf If KeyDown(KEY_SPACE) x = 250 y = 250 EndIf If KeyDown(KEY_UP) basespeed :+ 1 EndIf If KeyDown(KEY_DOWN) basespeed :- 1 EndIf PlayerSpeed=(100*0.9^baseSpeed) EndIf If PlayerTime<MilliSecs() Then PlayerTime=MilliSecs()+PlayerSpeed distance:Float = Sqr((x-targetx)*(x-targetx) + (y-targety)*(y-targety)) If Not(x-targetx=0) Or Not(y-targety=0) e2 = 2*err If e2 >= (-1 * dy) err :- dy x :+ sx EndIf If e2 < dx err :+ dx y :+ sy EndIf EndIf EndIf If PaintTime<MilliSecs() Cls PaintTime=MilliSecs()+16 DrawRect(x-4,y-4,8,8) DrawLine(x,y,targetx,targety) 'Draw 30 degree cone splash borders DrawLine(x, y, x + 100 * Cos(angle-15), y + 100 * Sin(angle-15)) DrawLine(x, y, x + 100 * Cos(angle+15), y + 100 * Sin(angle+15)) 'Draw middleline according to angle 'DrawLine(x, y, x + 100 * Cos(angle), y + 100 * Sin(angle)) DrawText("Angle: " + angle, 50, 50) DrawText("Current Coord: " + x + " , " + y, 50, 80) DrawText("Target Coord: " + targetx + " , " + targety, 50, 110) DrawText("dx: " + dx + " dy: " + dy, 50, 140) DrawText("distance: " + distance, 50, 170) DrawText("basespeed: " + basespeed, 50, 210) Flip 0 EndIf Delay 1 ' very important to keep the computer operable Until KeyDown(KEY_ESCAPE) Or AppTerminate() End Try "Basespeed" over 30 to understand what happens. The system is getting faster and faster without side-effects to key-check and drawing-interval. every step +1 at basespeed rises the players speed +10%. If you want to rise it faster, use... ;for 25% increase: PlayerSpeed=(100*0.8^baseSpeed) ;for 100% increase: PlayerSpeed=(100*0.5^baseSpeed) Last edited 2011 |
| ||
You understood me perfectly. You forgot that millisecs() start with a value below 0, so the if conditions are never fulfilled, giving me black screen. So I just multiplied it by -1 and tried running it. It draws once, and does nothing now. So, what now? Thanks. Last edited 2011 |
| ||
Millisecs() does not start with a value below 0! It counts the milliseconds since the computer started and is always positiv. One known bug: You only will have problems with the Millisecs() function, if your computer is a server running 24h/day and 7 days a week without new starts. Restart the computer and try again my code (without multiplying by -1) |
| ||
no, millisecs is not always positive. it all depends on how long the computer has been left running and is the error you mention. when the computer is started it starts at 0 then when it reaches the point to where the last bit in the "Long" counter is reached that bit makes the number a negative. then it continues from -$9fffffff! to $8ffffffff! (or something like that) continually approximately every 7 days. Last edited 2011 |
| ||
I restarted my computer and it works now. But it doesn't get noticeably faster after a certain point. While this is perfectly adequate for player speed, it's too slow for projectiles. Is there any other way to make an accurate RTS-style movement? Btw, kinda off topic, but is it bad for a computer to be left on for a long time? Last edited 2011 |
| ||
if you "remove" the line Delay 1 you will be able to accelerate the Main-Loop, but this can cause a hang of the OP. try it... For a projectil I would do it like this: 'If PlayerTime<MilliSecs() Then PlayerTime=MilliSecs()+PlayerSpeed distance:Float = Sqr((x-targetx)*(x-targetx) + (y-targety)*(y-targety)) For Local I%=0 To 3 ' or try 10 If (x-targetx=0) And (y-targety=0) Exit Else e2 = 2*err If e2 >= (-1 * dy) err :- dy x :+ sx EndIf If e2 < dx err :+ dx y :+ sy EndIf EndIf Next 'EndIf Last edited 2011 |
| ||
My good sir, you are godsend. Many thanks. |