FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

DRAWING

Animate smoothly


What is a simple, reliable way to get a simple object like a ball or letter to move through a window at a reasonably constant speed that can be set by the program?
The following sample code is too fast if I take out the DELAY and too herky-jerky if I use DELAY:

DIM gWinWide%
DIM gWinHigh%
DIM gRect.8
END GLOBALS
CLEAR LOCAL
DIM x
DIM y
DIM dy
DIM radius
LOCAL FN movingBall
  gWinWide% = 300
  gWinHigh% = 400

  WINDOW#1, "Moving Ball", (0,0) - (gWinWide%,gWinHigh%), _docNoGrow
  COORDINATE WINDOW
  TEXT _geneva, _textHeight, 0
  COLOR = _zBlack
  radius = 3 'radius of ball
  x = gWinWide%\2.0 'horizontal center of ball at middle of window
  y = radius 'vertical center of ball near top of window

  CALL SETRECT(gRect,x-radius,y-radius,x+radius,y+radius)' ball
  dy = 1 'pixels dropped each cycle
  CALL FILLOVAL(gRect,#REGISTER(A5)+_black) 'draw ball black
  DO
    DELAY 25 'try to slow ball down
    CALL ERASEOVAL(gRect)
    CALL OFFSETRECT(gRect, 0, dy)
    CALL FILLOVAL(gRect,#REGISTER(A5)+_black)
    y = y + dy
  UNTIL y = gWinHigh% - radius 'stop at bottom of window
END FN

Gary


Just a couple of possibilities.
The screen is only updated once per tick (60 times a second). It's possible that without the delay, your ball is being drawn and erased more than once per screen refresh. Usually 30 times per second is adequate for smooth animation. You could try this to make sure your drawing happens once every two ticks:

DO
nextTime& = FN TICKCOUNT + 2 'Schedule next loop
CALL ERASEOVAL(gRect)
CALL OFFSETRECT(gRect, 0, dy)
CALL FILLOVAL(gRect,#REGISTER(A5)+_black)
y = y + dy
WHILE FN TICKCOUNT < nextTime& 'Delay until tickcount changes twice
WEND
UNTIL y = gWinHigh% - radius 'stop at bottom of window

If your ball moves too slowly at this rate, adjust the size of the moves. It will still appear smooth as long as the drawing happens regularly every 2 ticks. It may even mean fractional moves (i.e. it may drop 2 pixels on one move and 3 the next). You should have plenty of time for a little floating point math if you need to store fractional positions.
Another (unlikely) problem might be that, with the code you posted, screen refreshes could conceiveably happen between

CALL ERASEOVAL(gRect)

and

CALL FILLOVAL(gRect,#REGISTER(A5)+_black)

causing an occasional flash. Offsetrect is quick enough that I doubt it could ever be a problem, especially if you use the code above so it's done right after a tickcount change, but I would probably choose to use two different rects so I had nothing between the erase and the redraw. There are sprite routines available to allow the erase and redraw to happen (on screen) simultaneously, but I doubt this is a major part of your problem.
If you'll permit me one other observation about your code:

x = gWinWide%\2.0 'horizontal center of ball at middle of window

Both "2.0" and "\" are ways of forcing floating point calculation. Once you store the result in your integer variable x, it reverts to an integer. The result will be the same as:

x = gWinWide% / 2 '(much faster)

or

x = gWinWide% >> 1 '(even faster yet)

Not that it matters in this case, but I try to cultivate the habit of avoiding FP calculation except where necessary (as it might be for your y calculations if you decide dy--or dy! in this case--needs to be something like 2.2 pixels per redraw).

Jay