Page 1 of 5

smooth animation in a window - not possible?

Posted: Fri Apr 20, 2007 12:00 pm
by mp303
Is it impossible to get completely smooth animation in a window, or am I doing something wrong?

Below is an example...

On line 1, you can switch between windowed mode or full screen by setting windowed.l to 0 (full screen) or 1 (windowed).

In full screen mode, the animation is completely smooth. But in windowed mode, there's a small "jump" in the animation every second or so.

Why?

Isn't FlipBuffers supposed to wait for vertical refresh? It seems it sometimes doesn't, or perhaps it waits too long... (I can't tell if it's skipping a frame or painting a frame too late)

My monitor is running at 60 FPS, and my system has loads of CPU power and plenty of RAM to go around... I've tried on three different systems, and this frame skipping/doubling occurs on all of them...

Any ideas?

thanks! :)

(code below...)

Code: Select all

windowed.l = 1

width.l = 512
height.l = 288

boxw.l = 30
boxh.l = 30

maxx.l = width - boxw
maxy.l = height - boxh

If InitSprite() = 0
  MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
  End
EndIf

If Windowed
  If OpenWindow(0, 0, 0, width, height, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If Not OpenWindowedScreen(WindowID(0), 0, 0, width, height, 0, 0, 0)
      MessageRequester("Error", "Can't open windowed screen!", 0)
      End
    EndIf
  EndIf
Else
  SetRefreshRate(60)
  If Not OpenScreen(640,480,32,"Screen")
    MessageRequester("Error", "Can't open screen!", 0)
    End
  EndIf
EndIf


If Not InitKeyboard()
  MessageRequester("Error", "Can't init keyboard!", 0)
  End
EndIf

CreateSprite(0, 30, 30)
If StartDrawing(SpriteOutput(0))
  Box(0, 0, 30, 30, RGB(255, 0, 0))
  Box(5, 5, 20, 20, RGB(0, 255, 0))
  Box(10, 10, 10, 10, RGB(0, 0, 255))
  StopDrawing()
EndIf

If Not windowed : SetFrameRate(60) : EndIf

dx.f = 2
dy.f = 1

Repeat

  FlipBuffers(1) 
  
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape) : End : EndIf
  
  If windowed
  Repeat
    Event = WindowEvent()
    Select Event 
      Case #PB_Event_CloseWindow
        End 
    EndSelect
  Until Event = 0
  EndIf

  ClearScreen(RGB(0, 0, 0))

  x = x + dx
  y = y + dy
  
  If x > maxx : x = maxx : dx = -dx : EndIf
  If x < 0 : x = 0 : dx = -dx : EndIf
  
  If y > maxy : y = maxy : dy = -dy : EndIf
  If y < 0 : y = 0 : dy = -dy : EndIf

  DisplaySprite(0, x, y)
  
ForEver
[/code]

Posted: Sat Apr 21, 2007 4:47 am
by netmaestro
The trick is to set a high framerate and counterbalance it with a delay in the display loop. However, you can't finetune the timing closely enough with the default Windows timing resolution. You have to set it up higher while the screen is active and set it back when you're done. This (windowed only) version is moving perfectly smooth here:

Code: Select all

ExamineDesktops()
framerate = DesktopFrequency(0) * 3 ; *** change *** // Choose a nice high framerate
              
maxx.l = 482
maxy.l = 258

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Can't open screen & sprite enviroment!", 0) 
  End 
EndIf 


If OpenWindow(0, 0, 0, 512, 288, "A screen in a window...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
  If Not OpenWindowedScreen(WindowID(0), 0, 0, 512, 288, 0, 0, 0) 
    MessageRequester("Error", "Can't open windowed screen!", 0) 
    End 
  Else 
    SetFrameRate(framerate) ; *** change  *** // Set framerate up 
  EndIf 
EndIf 

CreateSprite(0, 30, 30) 
If StartDrawing(SpriteOutput(0)) 
  Box(0, 0, 30, 30, RGB(255, 0, 0)) 
  Box(5, 5, 20, 20, RGB(0, 255, 0)) 
  Box(10, 10, 10, 10, RGB(0, 0, 255)) 
  StopDrawing() 
EndIf 

dx = 2 : dy = 1 

timeGetDevCaps_(@tc.TIMECAPS, SizeOf(TIMECAPS)) 
res = tc\wPeriodMin 

timeBeginPeriod_(res) ; *** change  *** // Raise timer resolution for added Delay()
                      ;                 // (counterbalances the high framerate) 

Repeat 

  FlipBuffers(1) 
  
  ExamineKeyboard() 
  If KeyboardPushed(#PB_Key_Escape) : End : EndIf 
  
  If WindowEvent() = #WM_CLOSE:End:EndIf
  
  Delay(11) ; *** change  *** // Add a finetuned Delay() to counter high framerate
  
  ClearScreen(#Black) 

  x = x + dx 
  y = y + dy 
  
  If x > maxx : x = maxx : dx = -dx : EndIf 
  If x < 0 : x = 0 : dx = -dx : EndIf 
  
  If y > maxy : y = maxy : dy = -dy : EndIf 
  If y < 0 : y = 0 : dy = -dy : EndIf 

  DisplaySprite(0, x, y) 
  
ForEver 

timeEndPeriod_(res) ; *** change  *** // Reset timer res to normal
Another advantage to this method is the low cpu usage provided by the Delay(). It's only using 3% here, compared to 100% with your code.

Posted: Sun Apr 22, 2007 7:19 pm
by mp303
thanks, that's perfectly smooth! and without blocking while waiting, that's a big bonus.

kinda makes you wonder why the standard functions don't implement it this way? seems like the proper way to implement it...

Posted: Mon Apr 23, 2007 12:05 am
by Kaeru Gaman
because it's a standard implementation,
wich means it has all the disadvantages of the original DX7 solution...

Posted: Mon Apr 23, 2007 7:31 am
by mp303
uh. and using 50% CPU to get half-descent synchronization is supposed to somehow be better?

I don't get it...

Posted: Mon Apr 23, 2007 10:37 am
by Kaeru Gaman
PB does nothing else than the standard solution of DX7 does.
PB is just calling DX7 functionallities.

the effect you complained about would occur in any program that uses standard DX7 functionalities,
no matter if it was written in C++, Delphi or whatever.

Posted: Mon Apr 23, 2007 10:44 am
by mp303
yeah, "everybody else does it".

right on.

Posted: Mon Apr 23, 2007 10:51 am
by Kaeru Gaman
HELLO
is there anybody in there?

it is just a CALL of functions of the grafic subsystem!

the problem is caused by DirectX7, not by PureBasic!

Posted: Mon Apr 23, 2007 11:06 am
by mp303
Maybe I'm not making myself clear.

OpenWindowedScreen(), SetFrameRate(), FlipBuffers() ... are these not PB commands?

What I'm asking you is, why do these commands not implement it the way you just showed me in your example?

I know it may not be the "standard" way to implement it, but the "standard" way is obviously not very good, so why force every PB programmer to implement this workaround in every application over and over again?

Posted: Mon Apr 23, 2007 11:15 am
by Kaeru Gaman
you made yourself perfectly clear, you just don't get the point.

I will explain it once again....

OpenWindowedScreen(), SetFrameRate(), FlipBuffers()
are PB commands that use functionallities of the Graphical Subsystem DirectX.

the example you saw is a WORKAROUND that uses a lot of additional functionallities to work this way.

netmaestro changes the timer resolution and applicates a very precisely precalculated Delay to make it work that way.
that is nothing connected with the graphical subsystem in any way,
that is something that is connected with the handling of the process.

sure an interface for the graphical subsystem should not mess with the process-timing, shouldn't it?

there is no way to implement a FlipBuffers that way, because it's not a Buffer issue but a process-timing issue.

...I hope that finally made it clear...

Posted: Mon Apr 23, 2007 12:55 pm
by mp303
The manual states, "Waiting for the screen synchronization allows the flip to be perfect (no 'tearing' or other visible artifacts) because the flip is performed when the screen has been fully drawed".

Having read the manual, I was expecting FlipBuffers() to do a properly synchronized flip without further intervention on my part.

I would expect FlipBuffers() to do whatever it has to do to ensure that it functions.

If that means changing process timing, or some other technical workaround that most people probably wouldn't even understand, so be it.

If for some reason a few users need to tinker with process timing themselves, of course it might be nice if the command had a parameter to bypass this functionality.

But for the average user, I think this is what you would expect - a properly timed flip, without having to do a bunch of platform-specific workarounds to get it up and running.

I didn't need a workaround in AMOS or Blitz Basic on my Amiga in the 90s - I guess I expected things that were possible 15 years ago to be possible still today...

I guess it's a matter of difference in what people expect.[/i]

Posted: Mon Apr 23, 2007 1:15 pm
by Kaeru Gaman
well, feel free to go to Silicon Vallay and kick Billies Ass for what sideeffects his so called OperatingSystem has.

a Screen and a Window are two completely different surfaces,
and it causes problems when you want to mix them both up,
that's just reality.

flipbuffers will flip "perfectly" in that way, that it is syncronized to avoid flipping buffers
in the middle of the disply-process of the monitor, which would lead to half-picture display.

you seem to have not the merest idea what the differences of an Amiga and a PC are.
go ahead and program PB on an Amiga, it's avaliable, don't you know?

if you want some special bypass timer-handling within a former simple flipbuffers,
go ahead, construct it, program it, write the code it would need.

perhaps after a long period of going into that materia you will see how it can work
and maybe you'll find some functionable solution,
but I rather expect you to learn that it's not worth sweating about the task to get it universal functional.

I wanted to explain to you, why anything is the way it is.
if you don't get it, I just stop bothering with you right here.
I have better ways to waste my time than explaning obvious things to someone who won't listen.


> I guess it's a matter of difference in what people expect.

sure I could expect Windows to be a super-duper Operating-System,
but to fill my needs I better should buy a UNIX-workstation.

If I can't efford a real computer, I have to cope with what I can afford.

Posted: Mon Apr 23, 2007 1:33 pm
by mp303
heh, it seems I always manage to brush someone the wrong way here, whenever I point out anything that doesn't work.

anyway, what you're saying, basically, is that Windows is a crummy operating system, and therefore you should not expect anything to work correctly on it.

(at least not without quirky workarounds)

is that about it? :)

Posted: Mon Apr 23, 2007 2:24 pm
by Dare
mp303 wrote:heh, it seems I always manage to brush someone the wrong way here, whenever I point out anything that doesn't work.
Probably because of the way that you point it out. :P

Come on, 'fess up. You enjoy stirring it don't you. :wink:

Posted: Mon Apr 23, 2007 2:55 pm
by mp303
Dare wrote:Probably because of the way that you point it out. :P
read through the thread - I tried to play nice from the start, didn't I? :)

if you notice, my smart-ass remarks usually start around the time somebody gives me an explanation like "PB does nothing else than the standard solution of DX7 does". Gee, well, maybe it should? Maybe the standard solution isn't good enough?

I don't do anything "half" - a vertical sync that sometimes synchronizes, or sometimes drops a frame, is not good enough ... it's half-done, and I don't care if half-done is the "standard" for Windows or DirectX or the universe in general - if it can be done better, it should be.

I'm pretty uncompromising that way - I don't cut corners or accept "sort of" solutions to problems that I know can be solved properly, and I get terribly frustrated with people who try to convince me that less than perfect is "normal".

If it's worth doing, it's worth doing it right.