Tweening
Blitz3D Forums/Blitz3D Programming/Tweening
| ||
Please take a look to the following piece of codeConst FPS = 60 Global FramePeriod% ; main game loop timing Global FrameTime% Global FrameElapsed% Global FrameTicks% Global FrameTween# Global ProgramEnd% = False Graphics3D 640, 480, 16, 0 SetBuffer BackBuffer() camera = CreateCamera() : MoveEntity camera, 0, 0, -10 light = CreateLight() cube = CreateCube() Frame_Init() Global dpitch# Global dyaw# Global droll# Global velpitch# = 0 Global velyaw# = 180 Global velroll# = 0 start_time% = -1 While Not ProgramEnd If KeyHit(1) Then ProgramEnd = True Frame_Capture() For FrameLimit = 1 To FrameTicks FrameTime = FrameTime + FramePeriod If FrameLimit = FrameTicks Then CaptureWorld EndIf dpitch = velpitch * 1/FPS dyaw = velyaw * 1/FPS droll = velroll * 1/FPS TurnEntity cube, dpitch, dyaw, droll UpdateWorld Next RenderWorld FrameTween If start_time < 0 Then start_time = MilliSecs() If MilliSecs() - start_time <= 1000 y = EntityYaw(cube) Else velyaw = 0 EndIf Text 0, 0, "Yaw = " + y Flip Wend Function Frame_Init() FramePeriod = 1000 / FPS FrameTime = MilliSecs () - FramePeriod End Function Function Frame_Capture() Repeat FrameElapsed = MilliSecs () - FrameTime Until FrameElapsed FrameTicks = FrameElapsed / FramePeriod FrameTween = Float (FrameElapsed Mod FramePeriod) / Float (FramePeriod) End Function I want to have my entities to move in terms of velocities. The question is: What is the velocity of Y-Axis, velyaw, in order to get the Cube rotated exactly 180 degrees within 1 second? If you run the program you will see that I don't get the desired result setting the velyaw to 180 degrees/sec. OK I know that I am wrong but I don't know where! Thanks |
| ||
I tried running the code a few times and I noticed it doesn't allways end up at the same angle. I don't understand how captureworld and renderworld tween work, so I have trouble understanding what your code does exactly, but I think it doesn't complete the 1000 ms timeperiod exactly enough. There is deltatiming, but I think you know that. You could rotate something 180 deg/sec like this: RotateEntity mesh, 0, Millisecs() * 180 / 1000, 0 |
| ||
Thanks for your time to spend and your advise. The tweening code is not mine. It comes from Blitz castle demo and I have to say that I don't understand its all aspects. For example I don't understand why the program execution exits from the Repeat-Until loop in Frame_Capture() function since FrameElapsed is constantly grow. I suppose the deltatiming is the time that corresponds to 1 Frame Per Second (FPS). That's why I multiply the velocity (velpitch, velyaw, velroll) with the 1/FPS factor (remember this simple formula: distance = velocity * time). I want to avoid the use RotateEntity command because I have already build a whole set of functions based in the TurnEntity command. |
| ||
The point of tweening is that it smooths out _animated_ characters no matter what the framerate at any gven moment. To smoothly rotate a cube a certain amount in a given period you would either have to: a) create an animation of a cube using a bone pivot, or b) if using your own then read the pitch,roll,yaw every frame and calculate ahead how much you need to turn the cube for the next ideal time slice. My own tutorial on tweening is at http://www.blitzbasic.co.nz/codearcs/codearcs.php?code=1497 |
| ||
If you want to use deltatiming with turnentity, try something like this: now = millisecs() elapsed = (now - old) old = now Then use TurnEntity mesh, 0, elapsed * 180 / 1000, 0 The variable 'old' should be global if you are using this in a function. |
| ||
I just returned from my day work. Thank you both. I will follow your guidelines and see... |
| ||
Because of floating point rounding errors, I like b32's suggestion which corrects for such: RotateEntity mesh, 0, Millisecs() * 180 / 1000, 0 I might adjust it a little, though. If you want one 180 degree rotation per second, then you will of course use millisecs(). But, the current amount of ms since you last checked is what you really want, not the ms command itself. So, I would suggest: start = millisecs() ; ms_diff = millisecs() - start if ms_diff > 1000 then start = millisecs():ms_diff=ms_diff-1000 RotateEntity mesh, 0, ms_diff * 180 / 1000, 0 |
| ||
Do you meanRotateEntity mesh, 0, ms_diff * 180 / 1000, 0 or TurnEntity mesh, 0, ms_diff * 180 / 1000, 0 |
| ||
It works!, it works!. Thanks to you! I used the b32's last formula and I made a final touch as Sir Gak noted. I have a function named TransformMeshes (in the main program loop) where I calculate for all my meshes the delta_rotation using a constant angle_velocity delta_rotation = angle_velocity * delta_time TurnEntity myentity, 0, delta_rotation, 0 But what is the delta_time?. Actually is the time between 2 successive calls of TransformMeshes and simply I can't change it. delta_time is not constant!. So If I want to get the total rotation that corresponds to the end of 1000 msecs I have to change the angle_velocity only for the LAST delta_time just before the end of 1000 msecs |