Previous |
| Next |
We've done simple animation on the canvas for flipping the cards. We can also make the cards move slowly from one location to another.
When you (or the computer) finds a pair, the cards are moved from where they were on the board to your stack of matched cards.
Right now, the matchCards
procedure just resets the
coordinates of the card images, and presto, the cards teleport to
the new location.
The Tk canvas
command has a subcommand named move
that will move an item on the canvas to a new location.
The syntax for the canvas move
command is similar to the
other canvas commands:
canvasName
| The name of the canvas to search |
move
| Move items on the canvas |
id
| An identifier for the item (or items) to move. This can be a canvas id number or a tag. |
xDistance
| How far to move in the X dimension |
yDistance
| How far to move in the Y dimension |
That's the only new command we need to move things on the canvas.
The tricky part (and it's not that tricky) is the geometry.
The easiest way to move the cards is to figure out the distance
we need to move them, divide that by how many steps we want to use
to move the cards, and then use a for
loop to move the
cards by the step distance for N steps.
We can use the coords
to find out where the card is,
and we know where we want it to go because we have that information
in the global concentration
array.
The canvas coords
command will give us a two value list
for the location of a card. This list is the X and then the Y coordinate.
We can use the foreach
command to split that list into
two values like this:
foreach {c1x c1y} [.game coords $id1] {break}
foreach {c2x c2y} [.game coords $id2] {break}
The next step is to calculate the distance to the end point. Because
the coordinates have both X and Y values, and the move
command uses X and Y, we need to calculate an X and Y distance separately
like this:
set d1x [expr $concentration($prefix,x) - $c1x ]
set d1y [expr $concentration($prefix,y) - $c1y ]
In this game, we'll move the cards in 10 steps, and pause for 1/10 of a second between steps. That means it will take a second to move a card to the score pile, whether the card is moving across the board, or just a single card width.
The step size will be 1/10th the distance in the X and Y dimensions,
which we can calculate using the expr
command:
set step1x [expr $d1x / 10]
And finally, the loop to move the cards. Notice the update idle
that tells Tk to update the screen now instead of waiting until
everything is done, and the after 100
that pauses for 100
milliseconds (1/10 second) between passes through the loop.
for {set i 0} {$i < 10} {incr i} {
.game move $id1 $step1x $step1y
.game move $id2 $step2x $step2y
update idle
after 100
}
The complete new procedure looks like this:
proc moveCards {id1 id2 prefix} {
global concentration
.game raise $id1
.game raise $id2
# Get the X and Y coordinates for the two cards
foreach {c1x c1y} [.game coords $id1] {break}
foreach {c2x c2y} [.game coords $id2] {break}
# Calculate the distance that this card is from where
# it needs to go. Do this for both the X and Y dimensions.
# Do it for both cards.
set d1x [expr $concentration($prefix,x) - $c1x ]
set d1y [expr $concentration($prefix,y) - $c1y ]
set d2x [expr $concentration($prefix,x) - $c2x ]
set d2y [expr $concentration($prefix,y) - $c2y ]
# We'll take 10 steps to move the cards to the new location.
# Figure out 1/10 the distance to the score pile for each card.
set step1x [expr $d1x / 10]
set step1y [expr $d1y / 10]
set step2x [expr $d2x / 10]
set step2y [expr $d2y / 10]
# Loop 10 times, moving the card 1/10'th the distance to the
# new location. Pause 1/10 of a second (100 ms) between movements.
# It will take 1 second to move a card from the current location to
# the desired location.
for {set i 0} {$i < 10} {incr i} {
.game move $id1 $step1x $step1y
.game move $id2 $step2x $step2y
update idle
after 100
}
# Set the matched card location to stack the next card
# a bit lower than the previous cards.
incr concentration($prefix,y) 30
}
moveCards
procedure. Presto, now it shows the cards
moving.
Right now, the cards move at different speeds, so that they always
take one second to reach the destination. Rework the moveCards
procedure so that the cards move at the same speed, but take a different
length of time to reach the match stack.
You can change the step1x and step1y values inside the loop. To be really tricky, make the cards speed up as they move, and then slow down again as they approach their destination.
move
command.
Previous | Next |