It is currently Mon Dec 11, 2017 5:04 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Delta time
PostPosted: Tue Nov 08, 2016 8:05 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 301
Location: France
Hi,

So I wanted to implement delta-time (and global/individual time scale); thought it was easy... I picked up pieces of code here and there, but I'm at the point where I don't fully understand the code, even though it's not (yet) a complete fail.

Here is the code:

Code:
Enumeration 
  #Cursor
EndEnumeration

Structure _fps
  targetFps.f
  fps.f   
  ticksPerSecond.i
  currentTicks.i
  frameDelay.i
  frameRate_real.i
  frameRate_internal.i
  frameStep.f
EndStructure

Structure _world
  delta.f
  timeScale.f
EndStructure

Structure _object
  sprite.i
  timeScale.f
  speed.f
  x.f
  y.f
  destX.f
  destY.f
EndStructure

Structure _xy
  x.f
  y.f
EndStructure

; ------------------------

Global world._world, object1._object
Global fps._fps

Procedure DrawCursor()
  CreateSprite(#Cursor, 2, 2, #PB_Sprite_AlphaBlending)
EndProcedure

Procedure DrawObject(*object._object)
  *object\sprite = CreateSprite(#PB_Any, 4, 4, #PB_Sprite_AlphaBlending)
EndProcedure

Procedure Init()
  InitSprite() : InitKeyboard() : InitMouse()
 
  fps\frameRate_real = 60
  fps\frameRate_internal = 60
  fps\frameStep = fps\frameRate_real * 0.1
EndProcedure

; ------------------------

Procedure InitFPSLimit(target.f)
  fps\targetFps = target
  fps\ticksPerSecond = 1000
  fps\frameDelay = GetTickCount_()
EndProcedure

Procedure SetSpeedFactor()
  fps\currentTicks = GetTickCount_()
  world\delta = (fps\currentTicks - fps\frameDelay) / (fps\ticksPerSecond / fps\targetFps)
  If world\delta <= 0 
    world\delta = fps\targetFps * 0.001
  EndIf
  fps\fps = fps\targetFps / world\delta
  fps\frameDelay = fps\currentTicks
EndProcedure

Procedure.f GetDistance(x1.i, y1.i, x2.i, y2.i)
  Define dx.f = x1 - x2                 
  Define dy.f = y1 - y2                 
  Define dist.f = Sqr(dx*dx + dy*dy)
 
  If dist < 0
    dist * -1
  EndIf
 
  ProcedureReturn dist
EndProcedure

Procedure MoveObject(*object._object, destX.i, destY.i)
  Define direction._xy, distance.f, norm.f
 
  *object\destX = destX
  *object\destY = destY
 
  direction\x = *object\destX - *object\x
  direction\y = *object\destY - *object\y
 
  norm.f = Sqr(Pow(direction\x, 2) + Pow(direction\y, 2))
  If norm
    direction\x / norm
    direction\y / norm
  EndIf
 
  distance = GetDistance(*object\x, *object\y, *object\destX, *object\destY)
 
  If distance < *object\speed
    ;*object\x + direction\x * distance
    ;*object\y + direction\y * distance
    ;*object\x = *object\destX
    ;*object\y = *object\destY
  Else
    *object\x + (direction\x * *object\speed) * world\delta
    *object\y + (direction\y * *object\speed) * world\delta
  EndIf
 
EndProcedure

Procedure InitObject(*object._object)
  DrawObject(*object)
 
  *object\speed = 5
  *object\timeScale = 1
EndProcedure

; ------------------------

Init()
OpenWindow(0, 0, 0, 640, 640, "", #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 640, 640, 0, 0, 0, #PB_Screen_NoSynchronization)

DrawCursor()

InitObject(@object1)

SetFrameRate(fps\frameRate_real)
InitFPSLimit(fps\frameRate_internal / fps\frameStep)

Repeat
 
  While WindowEvent() : Wend
 
  FlipBuffers()
  ClearScreen(0)
   
  ExamineKeyboard() : ExamineMouse()
 
  SetSpeedFactor()
 
  If MouseButton(#PB_MouseButton_Left)
    MoveObject(@object1, MouseX(), MouseY())
  EndIf
 
  DisplayTransparentSprite(#Cursor, MouseX(), MouseY(), 255, #White)
  DisplayTransparentSprite(object1\sprite, object1\x, object1\y, 255, RGB(0, 255, 0))
 
  Delay(1)
 
Until KeyboardPushed(#PB_Key_Escape)


Keep pushing the left mouse button to move the green square. It's supposed to be the same speed at 60 FPS then at 10. By "same speed" I mean that it takes the same amount of time for the object to go from point A to point B. Which is not the case in my code. Any help would be appreciated! :)


Top
 Profile  
Reply with quote  
 Post subject: Re: Delta time
PostPosted: Wed Nov 09, 2016 5:23 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 653
Location: right here
hi.
i did not understand the code, but onestly to me it looks to complicated for what you are trying to do :)
may i suggest another example?
Code:
InitSprite()
InitMouse()

ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget

win=OpenWindow(#PB_Any, 50,100, ww,wh, "", style) :: AddKeyboardShortcut(win, #PB_Shortcut_Escape, 10)
OpenWindowedScreen(WindowID(win), 0,0, ww,wh, 0,0,0)

Repeat
  ExamineMouse()
 
  ; calculate frame rate (updates only twice a second to be 'human readable')
  frame + 1
  If ElapsedMilliseconds() > FRt
    FRt = ElapsedMilliseconds() + 500    ; since we update each half a second
    FR = frame * 2                       ; we multiply counted frames by 2
    frame = 0
  EndIf
 
  If MouseButton(1)
    Delay(100)
  EndIf
 
  Repeat
    event = WindowEvent()
    em = EventMenu()
    Select event
      Case #PB_Event_CloseWindow
        quit = #True
      Case #PB_Event_Menu
        Select em
        Case 10
          quit = #True
        EndSelect
    EndSelect
  Until Not event
 
  ; we want angle to increase 360 degrees per second
  angle.f + Radian(360) * perSecond.f
 
  ; move around screen center with radius 100
  posX = ww/2 + Cos(angle) * 100
  posY = wh/2 + Sin(angle) * 100
 
  StartDrawing(ScreenOutput())
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(200,20,"press left mousebutton for framerate drop")
    DrawText(20,40,"framerate: " + FR)
    DrawText(20,60,"frame duration: " + frameDuration + "ms")
    Circle(posX, posY, 10)
    Circle(MouseX(), MouseY(), 1)
  StopDrawing()
 
  FlipBuffers()
  ClearScreen($333333)
 
  ; get a 'perSecond' factor to be used for movement etc.
  ; if the frame took 500 ms we would have 2 FPS, so our perSecond factor would be 0.5
  ; if the frame took 1000 ms we would have 1 FPS, so our perSecond factor would be 1.0
  ; if the frame took 2000 ms we would have 0.5 FPS, so our perSecond factor would be 2.0
  ; we could also calculate the framerate here (FR.f = 1000.0 / frameDuration), but that's
  ; not suitable for displaying ('number flickering')
 
  perSecond.f = frameDuration / 1000
 
  ; calculate the length of current frame in milliseconds
  frameDuration = ElapsedMilliseconds() - frameFinished
  frameFinished = ElapsedMilliseconds()
 
Until quit

here we calculate the duration of the finished frame which then is available in the next frame as 'frameDuration'.
then we derive a factor 'perSecond' from that which we use in calculations like movement etc.
the framerate calculation at the beginning of the loop is only for display and not used in calculations.


Top
 Profile  
Reply with quote  
 Post subject: Re: Delta time
PostPosted: Wed Nov 09, 2016 6:16 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Sep 18, 2013 11:54 am
Posts: 301
Location: France
Well, thank you very much sir! Your code is way more simple, smooth, and working fine :)

Sometimes I just persevere in crappy code.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye