Older Version Newer Version

Alyce Alyce Oct 5, 2011

QCard DLL Lesson 13

Lesson 12

- Alyce Alyce
QCard DLL Lesson 13 | Dealing a Hand | Card Selected? | Removing and Redealing the Hand | DEMO
See Lesson 1 for QCard DLL and WAV files needed for the demo code.

Dealing a Hand

A hand of cards is generally displayed with the cards overlapped horizontally. For demonstration purposes, we'll create a card array and fill it with various cards. The logic of a card game dictates how cards are dealt and keeps track of which cards have been dealt, the hand that contains them, etc.

We're adding a horizontal offset variable to the code to make this "overlap amount" easy to change. We'll use a value of 50.

We'll create a double dimensioned array for our demo hand of cards. The first dimension is the QCard index of the card.
 xOffset=50 'horizontal offset for dealing hand 
dim card(8,2) 'array to hold cards
'fill array with demo hand of cards
'in a game, the logic would dictate how hands are created
'first dimension is card index
card(1,1)=3
card(2,1)=18
card(3,1)=33
card(4,1)=51
card(5,1)=44
card(6,1)=12
card(7,1)=39
card(8,1)=22

We'll deal the cards in a loop, incrementing the x location each time. As we deal each card in our "hand" array, we'll save the x location in the second dimension of the array.
 'set xy location to start deal 
x=10:y=200
for i = 1 to 8
Call DealCard hBox,card(i,1),x,y
'save the x location of each card
card(i,2)=x
x=x+xOffset
scan
next


Card Selected?

There are two ways to retrieve the index of the card selected by the user. The first way was demonstrated in Lesson 4 . Card x,y location is documented in the card array and MouseX and MouseY are compared to the known coordinates of cards to find a match.

The other way to retrieve the index of the selected card is to use the InitDrag function as we did in Lesson 9 . The function returns the index of the card at given coordinates, so we use MouseX and MouseY.

Because the DLL is set up to select the lowest card at a given x,y location, we need to check the x location and see if the mouse click was beyond the x offset for overlap.

 cardIndex=InitDrag(hBox,MouseX,MouseY) 
if cardIndex=0 then wait

'retrieve the index of card in array that matches index returned by DLL
for i = 1 to 8
if cardIndex=card(i,1) then arrayIndex=i
next

If it is beyond that x location, we change the card index to that of the next card in the array. InitDrag returns the index of the card under the mouse, so we can use that value to get the X and Y location of the card.

 if MouseX > card(arrayIndex,2)+xOffset then 

If the MouseX location is greater than the card's x location plus the xOffset value, that means the user actually clicked on the card above the card returned by the DLL. Remember, the DLL always looks for the lowest card at given coordinate. We then change the value of cardIndex to be that of the next card in the hand, which is the next card in our array.

 'Check to see if user clicked the card at an x value 
'greater than the xOffset. If this is true, change
'cardIndex to be the index of the next card in the card array.
if MouseX > card(arrayIndex,2)+xOffset then
cardIndex=card(arrayIndex+1,1)
end if

Removing and Redealing the Hand


Once we have the index of the card clicked, we need to remove all cards in the hand from the display. The QCard DLL keeps a snapshot of the display beneath each card. We need to remove cards before redealing them so that the DLL has the proper snapshot to use when it restores the original display when removing a card.

We also need to call AbortDrag to cause the DLL to stop capturing mouse events.
 call AbortDrag 
for i = 1 to 8
call RemoveCard hBox, card(i,1)
next

Depending upon the order the cards are dealt and our game logic, remnants of cards might be displayed on the desktop because the DLL has saved a snapshot of them. We can easily "erase" the card area with a boxfilled. (Thanks to Janet Terra for this tip!)

 'erase any remnants missed by the DLL before redealing 
#1.g "color 10 190 225; place 10 200; boxfilled 800 400"

A better way to accomplish this!
Thanks to - JackBurman JackBurman
I have found that stepping backwards through the hand removes the cards without leaving any remnants. e.g:
 for i = 8 to 1 step -1 

We deal the cards again. When we deal the card that was selected by the user, we place it a bit higher in the row than the rest of the hand.

 x=10:y=200 
for i = 1 to 8
if cardIndex=card(i,1) then y=140 else y=200
Call DealCard hBox,card(i,1),x,y
x=x+xOffset
scan
next

The program below demonstrates these methods.
handselect.JPG

DEMO

See Lesson 1 for QCard DLL and WAV files needed for the demo code.

 'An open project card game, begun by Alyce Watson, May 27, 2003. 
'Uses Qcard32.dll, a freeware library of playing card images.
'DLL by Stephen Murphy. Qcard32.DLL website:
'http://www.telusplanet.net/public/stevem/

xOffset=50 'horizontal offset for dealing hand
dim card(8,2) 'array to hold cards
'fill array with demo hand of cards
'in a game, the logic would dictate how hands are created
'first dimension is card index
card(1,1)=3
card(2,1)=18
card(3,1)=33
card(4,1)=51
card(5,1)=44
card(6,1)=12
card(7,1)=39
card(8,1)=22

nomainwin
WindowWidth=640:WindowHeight=480
UpperLeftX=1:UpperLeftY=1

menu #1, "&File", "E&xit", [quit]
graphicbox #1.g, 0, 0, 640, 440
open "Cards" for window_nf as #1
#1 "trapclose [quit]"

'get graphicbox handle
hBox=hwnd(#1.g)

'open the dll
open "qcard32.dll" for dll as #qc
'initialize the deck
Call InitializeDeck hBox

[new]
Call SetDefaultValues

'draw a nice background
#1.g "down; fill 10 190 225"
#1.g "backcolor 10 190 225"
'temp message for this demo only
#1.g "place 10 40;\Left-click a card to select it."

'set xy location to start deal
x=10:y=200
for i = 1 to 8
Call DealCard hBox,card(i,1),x,y
'save the x location of each card
card(i,2)=x
x=x+xOffset
scan
next
#1.g "when leftButtonDown [initDrag]"
#1.g "when leftButtonUp [redraw]"
wait

[initDrag]
cardIndex=InitDrag(hBox,MouseX,MouseY)
if cardIndex=0 then wait

'retrieve the index of card in array that matches index returned by DLL
for i = 1 to 8
if cardIndex=card(i,1) then arrayIndex=i
next

'Check to see if user clicked the card at an x value
'greater than the xOffset. If this is true, change
'cardIndex to be the index of the next card in the card array.
if MouseX > card(arrayIndex,2)+xOffset then
cardIndex=card(arrayIndex+1,1)
end if
#1.g "place 10 420;\Selected Card Index is ";cardIndex;space$(100)
wait

[redraw]
if cardIndex=0 then wait
call AbortDrag
for i = 1 to 8
call RemoveCard hBox, card(i,1)
next

'erase any remnants missed by the DLL before redealing
#1.g "color 10 190 225; place 10 200; boxfilled 800 400"

x=10:y=200
for i = 1 to 8
if cardIndex=card(i,1) then y=140 else y=200
Call DealCard hBox,card(i,1),x,y
x=x+xOffset
scan
next
wait


[quit] close #qc:close #1:end


''''''''''''''''''''
'subs and functions:

Function InitDrag(hndle, x, y)
calldll #qc, "InitDrag",_
hndle as ulong, x as long, y as long,_
InitDrag as long
end function

Sub AbortDrag
calldll #qc, "AbortDrag",re as void
end sub

Sub InitializeDeck hndle
calldll #qc, "InitializeDeck",_
hndle as ulong,r as long
End Sub

Sub DealCard hndle,nC,x,y
'places card on window whose handle is hndle at x,y
'nC is number of card - 1-52 in first deck and
'53-104 in second deck, if used
calldll #qc, "DealCard",hndle as ulong,nC as long,_
x as long,y as long,r as void
End Sub

Sub RemoveCard hndle,nC
'removes a card from screen that was
'drawn with DealCard, replacing screen background
calldll #qc, "RemoveCard",hndle as ulong,_
nC as long,r as void
End Sub

Sub SetDefaultValues
'reset all card properties back to their default values.
calldll #qc, "SetDefaultValues",r as void
End Sub

QCard DLL Lesson 13 | Dealing a Hand | Card Selected? | Removing and Redealing the Hand | DEMO
Lesson 12