Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Graphics with lots of overlapping

5 views
Skip to first unread message

Karlo Stein

unread,
Feb 11, 2009, 3:17:29 PM2/11/09
to
I am doing something like Mahjong on Vista, and I am in real trouble
because it's so difficult.
These pieces draw over each other, there can be an animation when the
pieces are destroyed, and you can still select the next piece. I am kind
of discouraged because I cannot make up how they do it.
I took a look at the application's dependencies, and they don't use
DirectX, they use SetTimer and KillTimer, redrawing of regions by GDI+
and stuff like that.
Does anybody have any insights on the procedures (I mean the timing when
something happens)?

Thank you very much.

Thorsten Albers

unread,
Feb 11, 2009, 3:38:37 PM2/11/09
to
Karlo Stein <karlo...@gmx.de> schrieb im Beitrag
<usggZXIj...@TK2MSFTNGP03.phx.gbl>...

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

Karlo Stein

unread,
Feb 12, 2009, 5:17:24 AM2/12/09
to
I rather meant the exact procedure.
I am trying to figure out what is the exact "timing"...
Maybe like this? -> (Pseudocode)

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.

Thorsten Albers

unread,
Feb 12, 2009, 7:36:40 AM2/12/09
to
Karlo Stein <karlo...@gmx.de> schrieb im Beitrag
<erjrvsPj...@TK2MSFTNGP02.phx.gbl>...

> I rather meant the exact procedure.
> I am trying to figure out what is the exact "timing"...
> Maybe like this? -> (Pseudocode)
>
> PieceClicked
> DrawPieceInHotState
> if WeHaveAMatch
> Draw2MatchingPiecesInHotState
> SetTimerForAnimation
> End If
>
> TimerProc
> RedrawHotPieces
> If AnimationGoing
> DrawAnimationOverEverything
> End if

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()).

Karlo Stein

unread,
Feb 12, 2009, 4:41:25 PM2/12/09
to
I don't have a message loop, I'm using VB6, so it's event driven :-(
Seems it isn't so easy with VB...

Thorsten Albers

unread,
Feb 12, 2009, 7:24:23 PM2/12/09
to
Karlo Stein <karlo...@gmx.de> schrieb im Beitrag
<OrMu9qVj...@TK2MSFTNGP06.phx.gbl>...

> I don't have a message loop, I'm using VB6, so it's event driven :-(
> Seems it isn't so easy with VB...

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).

Larry Serflaten

unread,
Feb 14, 2009, 12:58:21 AM2/14/09
to

"Karlo Stein" <karlo...@gmx.de> wrote

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


Karlo Stein

unread,
Feb 15, 2009, 4:54:22 PM2/15/09
to
Damn, this is nice!
My application is more complex, but the technique you showed here is good.
Thanks.
0 new messages