Recent

Author Topic: Simple animation with TTimer  (Read 1842 times)

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Simple animation with TTimer
« on: May 27, 2022, 10:10:25 pm »
Hi all,

I'm trying to do a very simple animation that slides one box off the screen when the user presses a button, and simultaneously slides in a set of several other boxes.  Have tried various different configurations and also some other fancy timer, and I keep having the same problem.  Sometimes it works and sometimes it doesn't - when it doesn't, the screen appears to just freeze for a second and then the boxes are in their final position, without me seeing any of the animation. 

The following script worked well for a while and then just suddenly stopped, for reasons I cannot detect.  The only changes I made were adding one more item to the list of controls moving in, and after the final "if PPBoxDB.Left < -400", I added one final piece of code to move all the controls into their final position at Left :=520.  That's it.  Of course, I added the final move to 520 as part of the "if" clause.  And even after removing those items, the code no longer works.

The OnTimer event of my TTimer is the following, and my interval is 5.   PPBox is the original box, which is slid off to the left, to be replaced by the other boxes.

Code: Pascal  [Select][+][-]
  1. if PPNickNameLabel.Left > -400 then
  2. begin
  3. PPBoxDB.Left := (PPBoxDB.Left - 12);
  4.  PPNicknameLabel.Left := (PPNicknameLabel.Left -12);
  5. PPNickName.Left := (PPNickName.Left -12);
  6. PPCharacteristicsLabel.Left := (PPCharacteristicsLabel.Left -12);
  7. PPCharacteristics.Left := (PPCharacteristics.Left -12);
  8. PPBarriersLabel.Left := (PPBarriersLabel.Left -12);
  9. PPBarriers.Left := (PPBarriers.Left -12);
  10. PPUserNotesLabel.Left := (PPUserNotesLabel.Left -12);
  11. PPUserNotes.Left := (PPUserNotes.Left -12);
  12. end;
  13. if PPBoxDB.Left < -400 then KillPPBox.Enabled :=false;
  14.                                                          
  15.  

Any ideas?  Or is there a better way to do this? Thanks!
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Simple animation with TTimer
« Reply #1 on: May 27, 2022, 10:52:21 pm »
A compilable project would be more helpful.
But a timer interval of 5 ms for so much successive screen redrawing (and no Application.ProcessMessages) may be unrealistic for your hardware.

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Re: Simple animation with TTimer
« Reply #2 on: May 28, 2022, 03:10:26 am »
I can't possibly conceive how any modern hardware would choke on moving 9 simple items across the screen, but in any case I've tried with all sorts of different intervals and it makes no difference.  You'd also expect the pattern to be more random, whereas this works perfectly for long stretches at a time and then a slight breeze causes it to permanently break until I try something else.
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Simple animation with TTimer
« Reply #3 on: May 28, 2022, 05:25:48 am »
For issues 'why my code doesn't run as what I think', usually is very helpful if the user can provide the compile-able source code, so others can run and inspect the problem.

In the link below, you can find many simple animation demos:
https://wiki.freepascal.org/Portal:HowTo_Demos

Click the link above and find these names:
- Moving an Object by pressing a key
- Control an Object's direction using the keyboard
- Simple animation
- Move a shape with a mouse
- Button with animation

I can't possibly conceive how any modern hardware would choke on moving 9 simple items across the screen

LCL components are build for compatibility not optimized for performance, you won't get the performance the hardware can offer. If performance is important, you should consider other graphics libraries that are hardware accelerated.

TTimer is okay for simple animations. But it won't give you any difference if the interval is too small. I am not sure, but I usually won't use interval < 16.

If time precision is important, you should use different technique. Like EpikTimer + delta time method.

For animating several components with same direction and speed, you should put them in a container, TPanel for example. Like the demo:
simple transition effect (in User Interface category, in the link above)

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Re: Simple animation with TTimer
« Reply #4 on: May 28, 2022, 10:44:47 pm »
Thanks for the input.  For some reason, it has started working when I up the interval to 16. Doesn't make a lot of sense because I've had the interval set even higher before and still had problems.  Anyway, 16 interval is too slow, so I just set 2 simultaneous timers running, both doing the same thing.  For some reason this works.

Thanks for the link, too.  I will check those out if I need to do any more of this stuff.
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

RayoGlauco

  • Full Member
  • ***
  • Posts: 176
  • Beers: 1567
Re: Simple animation with TTimer
« Reply #5 on: May 28, 2022, 11:22:13 pm »
I think you may need to insert Application.ProcessMessages after each timer interval, to make sure the current move shows up before doing another move.
To err is human, but to really mess things up, you need a computer.

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: Simple animation with TTimer
« Reply #6 on: May 29, 2022, 04:38:49 am »
... so I just set 2 simultaneous timers running, both doing the same thing.  For some reason this works.

Don't use multiple timers. For some cases, it may seem better to use more than 1 TTimer but actually it hurts more than what you think.  It can be easily to run into unexpected result because programmers usually couldn't understand how to handle multiple running timers.

https://forum.lazarus.freepascal.org/index.php/topic,54535.msg405050.html#msg405050

Doesn't make a lot of sense because I've had the interval set even higher before and still had problems.

TTimer is working good, I has been using it for a very long time. Please provide the source code, so we can tell you where you did it wrong.
« Last Edit: May 29, 2022, 04:42:13 am by Handoko »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Simple animation with TTimer
« Reply #7 on: May 29, 2022, 01:51:17 pm »
The attached simple project (based on what I could gather of OP's code) even "works" with a timer interval of 1ms on my hardware, though the effect is unpleasant.
Use the spacebar to start and stop the animation

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Simple animation with TTimer
« Reply #8 on: May 29, 2022, 09:51:25 pm »
I can't possibly conceive how any modern hardware would choke on moving 9 simple items across the screen, but in any case I've tried with all sorts of different intervals and it makes no difference.

Hold on there. an "item" isn't simple these days: you're not talking about a sprite on a home computer or an area on a workstation screen being bitblted: if you dug down a bit deeper you'd find that most components are actually abstractions wrapping some sort of operating system object, and as such something that appears simple is in actual fact far from it.

Quote
You'd also expect the pattern to be more random, whereas this works perfectly for long stretches at a time and then a slight breeze causes it to permanently break until I try something else.

To be brutally frank, if you're seeing that sort of thing then there's something badly wrong in your code. I'd hardly call myself an accomplished graphics programmer, but from my experience the most alluring mistakes are (a) putting things in the wrong place (i.e. stuff that's in an event shouldn't be, or vice-versa) and (b) accidentally getting code reentry. There's also the perpetual problem that people have when they reference a GUI property or entry point in code which is actually being run by a background thread.

However until you post an example of what you're actually doing it's not going to be possible to give you more detailed help. And I'm not the first to point that out.

MarkMLl

MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

heebiejeebies

  • Full Member
  • ***
  • Posts: 127
Re: Simple animation with TTimer
« Reply #9 on: June 12, 2022, 07:05:39 am »
Thanks for all the input guys!  The sample project was helpful too.  To avoid getting growled at I went back to one timer and it seems to work fine with the   Application.ProcessMessages added.

 :D
Fedora 38/Lazarus 2.2.4- FPC 3.3.1

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Simple animation with TTimer
« Reply #10 on: June 12, 2022, 10:05:04 am »
Thanks for all the input guys!  The sample project was helpful too.  To avoid getting growled at I went back to one timer and it seems to work fine with the   Application.ProcessMessages added.

Just be careful not to overdose on the APMs, they can really slow you down.

Take a guess at how long a loop will take, and put in enough APMs that one will be called somewhere between 10 and 100 times a second.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018