Basics of Transparent Blitting, Part 2
Pages: 1, 2
The Blitting Procedure
To really make this useful let’s create a procedure that performs the transparent blit operation. We’re going to stuff all the code from above into this procedure so there is nothing new introduced here.
Remember from the previous example of writing, the hexadecimal conversion procedure that we passed some arguments into the procedure. Our blitting procedure is going to require some arguments to pass in to make it useful.
|
Related Reading Game Coding Complete |
We'll need to know some information about the source image: it’s name, the top-left coordinates we want to blit from, and the width and height of the sprite to blit. We have:
src_image src_x src_y width height
We will need to know the destination image name and the top-left coordinate of the bounding rectangle to blit to. Here we have:
dst_image dst_x dst_y
And won’t we need to know what the value of the transparency pixel is? We will need,
trans_pixel
This should be enough for us to define the procedure. It looks like:
proc transparent_blit { trans_pixel \
src_image src_x src_y width height \
dst_image dst_x dst_y } {
procedure body
}
Cutting and pasting all the code snippets in for our procedure, it looks like this:
# transparent_blit
# ----------------
# Performs a transparent blit operation.
#
# Arguments:
# trans_pixel - transparent pixel value
# src_image - source image to be copied
# src_x - x start of source rectangle
# src_y - y start of source rectangle
# width - width of rectangle
# height - height of rectangle
# src_mask - hex value for transparency pixel
# dst_image - destination image
# dst_x - x start of destination rectangle
# dst_y - y start of destination rectangle
#
# Returns:
# none
proc transparent_blit { trans_pixel \
src_image src_x src_y width height \
dst_image dst_x dst_y } {
# calculate source bounding rectangle
set src_x2 [expr $src_x + $width]
set src_y2 [expr $src_y + $height]
# calculate destination bounding rectangle
set dst_x2 [expr $dst_x + $width]
set dst_y2 [expr $dst_y + $height]
# get source image raw data
set raw_src_data \
[$src_image data -from $src_x $src_y $src_x2 $src_y2]
# get destination image raw data
set raw_dst_data \
[$dst_image data -from $dst_x $dst_y $dst_x2 $dst_y2]
# set src_scan_row
# set dst_scan_row
# raw_image_data is the target buffer
set raw_image_data ""
for {set scan_row_index 0} {$scan_row_index < $height} \
{incr scan_row_index} {
set src_scan_row [lindex $raw_src_data $scan_row_index]
set dst_scan_row [lindex $raw_dst_data $scan_row_index]
# reset raw_scan_row data for a new scan row
set raw_scan_row ""
for {set pixel_index 0} {$pixel_index < $width} \
{incr pixel_index} {
set src_pixel [lindex $src_scan_row $pixel_index]
set dst_pixel [lindex $dst_scan_row $pixel_index]
# check if source pixel is transparent pixel
if {$src_pixel == $trans_pixel} {
# write the destination pixel
set raw_scan_row "$raw_scan_row $dst_pixel"
} else {
# write the source pixel
set raw_scan_row "$raw_scan_row $src_pixel"
}
}
# END for each pixel
puts $raw_scan_row
lappend raw_image_data $raw_scan_row
}
# END for each scan row
# copy the new image to the buffer
# create the Tk temp image buffer
set temp_image \
[image create \
photo -height $height -width $width -format gif]
# copy the raw blit data over to the Tk temp image
$temp_image put $raw_image_data -to 0 0
# copy the Tk temp image to the destination buffer
$dst_image copy $temp_image -from 0 0 $width $height \
-to $dst_x $dst_y $dst_x2 $dst_y2
}
# RGB_convert_decimal_hexadecimal
# ------------------------------
# Convert image pixel values from decimal to hexadecimal
# Arguments:
# transparency_pixel - Tcl list RGB values from
# Tk image library.
# Returns:
# hexadecimal string -formatted RGB values for
# Tk image data analysis.
proc RGB_convert_decimal_hexadecimal { transparency_pixel } {
# convert to hexadecimal
set R_value \
[format "%02x" [lindex $transparency_pixel 0]]
set G_value \
[format "%02x" [lindex $transparency_pixel 1]]
set B_value \
[format "%02x" [lindex $transparency_pixel 2]]
# create the transparency value string
set RGB_value "#$R_value$G_value$B_value"
return $RGB_value
}
# load the art file
set filename "/game_dev/game_art.gif"
set sprites [image create photo -file $filename]
# load the raw pixel data into raw_monster_data
set raw_monster_data [$sprites data -from 265 737 328 800]
set RGB_decimal_pixel [$sprites get 265 737]
set transparent_pixel [RGB_convert_decimal_hexadecimal \
$RGB_decimal_pixel]
# create the offscreen buffer
set video_game_width 640
set video_game_height 480
# create a blank offscreen image
set offscreen [image create photo \
-height $video_game_height -width $video_game_width]
# copy the background mountains image
$offscreen copy $sprites -from 0 0 639 479 -to 0 0 639 479
transparent_blit $transparent_pixel \
$sprites 265 737 63 63 $offscreen 320 303
# create the canvas
canvas .canv -width 640 -height 480 -background black
pack .canv -side top -expand yes -fill both
.canv itemconfigure $offscreen -image $offscreen
.canv create image 0 0 -image $offscreen -anchor nw
![]() |
Conclusion
Now isn’t that more like it? You can create video-game sprite animation just as you see on your Game Boy Advance SP. Tired of playing with those old pocket-monster sprites? Go and make your own game. Play around with the animation cells I provided. You're definitely going to have to go get an art application.
Adobe Photoshop is nice, put nice comes at a hefty price. The next best solution is MacGIMP, which will cost you around $30. So go forth and design that one video game that will change the world!
Michael J. Norton is a software engineer at Cisco Systems.
Return to MacDevCenter.com.



