Thank you very much.
One can use a or >the< message loop for this. A rough sketch:
Do
Is there any message out there?
Yes:
Let the message event, if any, be processed
No:
Do what shell be done while the application is 'idle'
Loop
To build this up you can use one or a mixture of VB procedures (DoEvents,
which is the least preferrable) and Windows API procedures (PeekMessage()).
Another approcach would be the use of threads. As far as I remember VB
shipps with a sample screen saver which uses threads to move a lot of IE
logos more or less simultaneously over the screen.
--
Thorsten Albers
albers (a) uni-freiburg.de
PieceClicked
DrawPieceInHotState
if WeHaveAMatch
Draw2MatchingPiecesInHotState
SetTimerForAnimation
End If
TimerProc
RedrawHotPieces
If AnimationGoing
DrawAnimationOverEverything
End if
Well, something like that. I cannot figure out how exactely they do it.
Do
Piece clicked? (PeekMessage())
Yes: Marke piece as to be redrawn
Do what has to be done if a piece has been clicked
Any piece to be redrawn?
Yes:
Redraw any piece which has to be redrawn, and redraw it in its current
state
Loop
Now you can use a state value which tells if and how a piece has to be
redrawn. e.g.
0 Not to be redrawn
1 ...
2 ...
100-150 Animation sequence picture #1, #2, #3, ...
To make the animation nice looking you have to time somehow the drawing of
the animation sequence picture drawing (e.g. by using GetTickCount() or
QueryPerformanceCounter()).
The sketch I gave you is not for >the< message loop (your VB app has one
but you can't access it because it is handled by VB internally) but for >a<
message loop. Because this isn't the main message loop it doesn't use
GetMessage() but PeekMessage() (see MSDN documentation) which doesn't wait
for a message. To allow VB to perform its default message processing you
have to use this additional message loop in combination with DoEvents (see
VB help).
First thing about animation is that you need a re-occuring event to
facilitate drawing the animated frames. You can use the API (SetTimer,
KillTimer) or you can use the VB Timer control. I am just going to call
it a timer event, and leave up to you on what method to use.
Second, it helps to have the animated items somewhat autonomous. That
means, once you set it in motion, it knows where to go, what to do, and
whatever else, so that your main program code need not manage the
animation. One way to do that is to have a group (array, collection, etc)
of static items (still) and another group of animated items. Your main
program simply moves a still item to the animated group, for the animation
to begin. Code in the timer event animates all the items from the
animated group.
Third, in your case, you have stages, (or game states), where you are
either waiting for the user to select the first block, or select the second
block. You progress through the game states as the user makes their
selections. After two tiles are selected you either move the matching
tiles to the animated group (for removal) or you mark them as wrong
(however you indicate that) and then reset the stage counter.
Lastly, you need a method to draw the gameboard in its current state
(0, 2, 4, or more tiles missing). When the user correctly selects
two matching tiles, you'll need to remove those tiles from the board
and redraw the board. You immediately (without flicker) redraw the
two selected tiles, only this time they are from the animated group.
They look like they are still in place, but they will be animated when
you start the timer.
Animation often looks better when you use an off screen image to
do the work of building each frame, and copy that off screen image
to the screen, for each frame. It slows down the animation process
but eliminates flicker. Its one of those give and take areas where you
have to decide which is the better route in your specific circumstance.
Instead of copying an entire image for each frame, some will record
and copy over only those 'regions' that actually changed from one
frame to the next. That is an optimization technique that speeds up the
back buffer approach....
So assuming you have a Tile() array that holds the tiles and their values.
locations, and whatnot, you are likely to determine the user's selection
in a MouseDown event. Such an event might look similar to:
' Module level variables
Dim Tiles() As Tile
Dim Picked(0 To 1) as Long
Dim Selecting as Boolean
Dim Stage as Long
Private Sub Board_MouseDown(Button, Shift, X, Y) ' condensed for newsgroup
Dim idx As Long
If Selecting Then
idx = GetTileIndex(X, Y)
If idx < UBound(Tiles) Then 'Test just to be sure
HighlightTile idx ' Mark as selected
Picked(Stage) = idx ' Save user selection
Stage = Stage + 1 ' Increment stage counter
If Stage = 2 Then ' Second selection made....
Selecting = False
If Tiles(Picked(0)).Value = Tiles(Picked(1)).Value Then
StartAnimation ' Moves Picked tiles to animated group, draws board, etc.
Else
MarkAsWrong ' Un-Highlights tiles, or whatever....
End If
Stage = 0 ' Start over with first selection
End If
End If
End If
End Sub
Note that Selecting is left false so that the user cannot select more
tiles until the program is ready to accept selections again. For example,
the StartAnimations routine needs to move the Picked tiles into the
animated groups, so the user must not be allowed to change selections
until that happens. Once the animations have begun, or the Wrong tile
indications are over, Selecting can be returned to True so that the user
can again select tiles.
This is a rough outline, and it could get complicated fast, so my advice
would be to start with getting the basics into place. The drawing of the
board, handling of the game states, and very simple animation just to get
it working. With a framework in place, (and debugged) you can then
go back and add details.
Be sure to save your work as you go. You may find you need to go
a different direction on something and have to start from an earlier
working version. So, at significant milestones, save all your files off to
a different directory (or otherwise back them up) until you have
completed the project. You can then build and back up the final version
and delete all the earlier versions.
Good Luck!
LFS