📄 ch12.htm
字号:
member list. You can query the width and height of an image, but you cannot change
these values after an image has been created. <B><TT><BR>
<BR>
GD::Image::copy(srcImage,dstX,dstY,srcX,srcY,width,height)</TT></B> The <TT>GD::Image::copy(srcImage,dstX,dstY,srcX,srcY,width,height)</TT>
method enables you to copy one image into another. You call this method on the target
image and specify the source image as <TT>srcImage</TT>. <TT>(dstX,dstY)</TT> specifies
the point in the destination image at which you want to copy to. <TT>(srcX,srcY)</TT>
specifies the point in the source image at which you want to copy from. <TT>width</TT>
and <TT>height</TT> specify the dimensions of the area being copied.</P>
<P>You can also resize or scale an image while copying by using the <TT>copyResized()</TT>
method. In addition to source and destination coordinates, you can specify source
and destination width and height. This way, you can extend or reduce an image as
well as modify the proportions of an image.
<H4 ALIGN="CENTER"><A NAME="Heading5"></A><FONT COLOR="#000077">GD::Polygon Module</FONT></H4>
<P>The <TT>GD::Polygon</TT> module provides an interface to a polygon shape for use
with the <TT>GD::Image::polygon() </TT>and <TT>GD::Image::filledPolygon()</TT> methods.
Polygons consist of vertices that are defined as Cartesian coordinates. You construct
polygon objects by using the <TT>new()</TT> method and the <TT>addPt(x,y)</TT> method.
<TT>addPt(x,y)</TT> adds a vertex to the polygon. A triangle, for example, might
have vertices of (0,0), (10,10), and (10,0). <B><TT>getPt(index), setPt(index,x,y),
and deletePt(index)</TT></B> <TT>getPt()</TT> returns the point corresponding to
the vertex at a given <TT>index</TT>. <TT>setPt()</TT>enables you to modify the vertex
at <TT>index</TT> to contain the new point <TT>(x,y)</TT>. <TT>deletePt()</TT> deletes
a vertex from the polygon. <B><TT>length() and vertices()</TT></B> <TT>length()</TT>returns
the number of vertices in the polygon, and <TT>vertices()</TT>returns a list of those
vertices. The list returned by <TT>vertices()</TT> contains references to arrays
containing the <TT>(x,y)</TT> coordinates of each vertex. <B><TT>bounds()</TT></B>
The <TT>bounds()</TT>method returns the smallest bounding rectangle of the polygon
specified as the list <TT>($left,$top,$right,$bottom)</TT>, where each of these variables
is a reference to an array specifying the <TT>(x,y)</TT> coordinate values. <B><TT>offset(dx,dy)</TT></B>
The <TT>offset(dx,dy)</TT> method enables you to move a polygon by a specified offset
of <TT>dx</TT> and <TT>dy</TT>. Each vertex is offset by these amounts. This method
is useful for the animation of a polygon. <B><TT>map(srcL,srcT,srcR,srcB,destL,destT,destR,destB)</TT></B>
The <TT>map(srcL,srcT,srcR,srcB,destL,destT,destR,destB)</TT> method maps a polygon
from a source rectangle to an equivalent position within a destination rectangle.
The polygon is moved and resized according to the mapping between the two rectangles.
You can use the bounding box of the polygon itself as the <TT>srcL</TT>, <TT>srcT</TT>,
<TT>srcR</TT>, and <TT>srcB</TT> values.
<H4 ALIGN="CENTER"><A NAME="Heading6"></A><FONT COLOR="#000077">GD::Font Module</FONT></H4>
<P>As I mentioned previously, four fonts are available for use within the <TT>GD</TT>
module. These fonts are specified as constants and are exported into your namespace
when you load the <TT>GD</TT> module. This class additionally provides methods for
querying the font. <TT>nchars()</TT> returns the number of glyphs contained in the
font, <TT>offset()</TT> returns the ASCII value of the first character in the font,
and <TT>width()</TT> and <TT>height()</TT> return the width and height of the font.</P>
<P>Currently, you cannot create your own fonts or manipulate the predefined fonts.
Perhaps this support will be added to the GD library one day.</P>
<P>You can find the latest <TT>GD</TT> module in your nearest CPAN location, along
with a more complete reference of the functionality. For more information on the
GD library, refer to <A HREF="javascript:if(confirm('http://www.boutell.com/gd \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.boutell.com/gd'" tppabs="http://www.boutell.com/gd"><TT>http://www.boutell.com/gd</TT></A>.
<H3 ALIGN="CENTER"><A NAME="Heading7"></A><FONT COLOR="#000077">Hangman Using the
GD Module</FONT></H3>
<P>Now you're ready to use the <TT>GD</TT> module to produce a simple game. Hangman
is a game that involves some dynamically drawn graphics. This example contains some
solid filled shapes, outline shapes, lines, and transparency. To create this game,
you combine what you've learned so far about CGI programming with this new concept
of dynamic image creation.</P>
<P>You start by writing the function that draws the entire image. It takes an argument
to determine how much to draw; for example, the value 1 indicates to simply draw
the head. The value 6 indicates to draw the entire body, which, of course, means
that the Hangman game is over. Here's how to get started:</P>
<PRE><FONT COLOR="#0066FF">sub drawMan {
my($level)=@_;
# create the image.
my($image) = new GD::Image(100,100);
my($trans) = $image->colorAllocate(128,128,128);
my($white) = $image->colorAllocate(255,255,255);
my($black) = $image->colorAllocate(0,0,0);
my($red) = $image->colorAllocate(255,0,0);
my($blue) = $image->colorAllocate(0,0,255);
my($green) = $image->colorAllocate(0,255,0);
$image->transparent($trans);
$image->interlaced(1);
$gallows=new GD::Polygon();
$gallows->addPt(10,80);
$gallows->addPt(10,10);
$gallows->addPt(50,10);
$gallows->addPt(50,20);
$gallows->addPt(25,20);
$gallows->addPt(25,80);
$image->filledPolygon($gallows,$blue);
$image->line(50,20,50,30,$green);
$image->line(10,80,80,80,$red);
if ($level>0) {
$image->arc(50,35,10,10,0,360,$black);
if ($level>1) {
$image->line(50,40,50,60,$black);
if ($level>2) {
$image->line(60,35,50,50,$black);
if ($level>3) {
$image->line(40,35,50,50,$black);
if ($level>4) {
$image->line(50,60,60,75,$black);
if ($level>5) {
$image->line(50,60,40,75,$black);
}
}
}
}
}
}
print $image->gif;
}
</FONT></PRE>
<P>You now create the Hangman game around this drawing function. To keep the game
simple, use a small pool of words from which users can choose. To display an image
within your HTML document, you must first store it to a file. Then you can use the
<TT><IMG></TT> tag to embed it into your document. For this example, simply
store the image to a temporary file where the name of the file is determined by the
process ID. Here is how the main program looks:</P>
<PRE><FONT COLOR="#0066FF">#!/usr/local/bin/Perl
use GD;
use CGI::Form;
@wordlist=(`navigator`,`explorer`,`hypertext`,`practical',`extraction`,
`reporting',`language',`portable',`document`,`format`,
`graphic',`interchange',`multimedia',`programming',
`implementation','management');
@letters=(`a',`b',`c',`d',`e',`f',`g',`h',`i',
`j',`k',`l',`m','n',`o',`p',`q',`r',
`s',`t',`u',`v',`w',`x',`y',`z');
$guesses="";
$numguesses=0;
$img_file="/user/bdeng/Web/docs/temp/$$.gif";
$q = new CGI::Form;
print $q->header();
print $q->start_html(-title=>`Hangman!');
print "<H1>Hangman</H1>\n";
if ($q->cgi->var(`REQUEST_METHOD') eq `GET') {
&gameIntro($q);
} else {
$action=$q->param(`Action');
if ($action eq "New Game") {
&gameIntro($q);
} else {
&playGame($q);
}
}
print $q->end_html();
</FONT></PRE>
<P>As you can see from the main program, you have two main subroutines. The first,
which follows, is called <TT>gameIntro()</TT>; it is used to initialize the game.
Initialization involves choosing a random word, drawing the empty gallows, and setting
up some variables used to keep track of the user's progress.</P>
<PRE><FONT COLOR="#0066FF">sub gameIntro {
my($q)=@_;
$numWords=@wordlist;
srand(time|$$);
my($index)=int(rand($numWords));
$word=$wordlist[$index];
$guesses="";
$numguesses=0;
$q->param(`word',$word);
$q->param(`guesses',$guesses);
$q->param(`numguesses',$numguesses);
print "<P>Welcome to Hangman.";
print "Select a letter and click `Guess' to start playing<BR>\n";
&drawHangman($q,$numguesses);
&drawWord($word,$guesses);
&gameForm($q);
}
</FONT></PRE>
<P>You use the <TT>srand()</TT> Perl function to set the seed for generating random
numbers. Using the current time together with the process ID should give you a random
value. This subroutine calls three other subroutines, which are shared with the next
subroutine.</P>
<P>The other main subroutine, which follows, is called <TT>playGame()</TT>; here
you query the letter that the user guesses and fill in the found letters on each
subsequent call. This routine is also responsible for determining when the user wins
or loses. It also makes use of the <TT>drawHangman()</TT>, <TT>drawWord()</TT>, and
<TT>gameForm()</TT> subroutines.</P>
<PRE><FONT COLOR="#0066FF">sub playGame {
my($q)=@_;
$word=$q->param(`word');
$letter=$q->param(`Letter');
$numguesses=$q->param(`numguesses');
$guesses=$q->param(`guesses');
if (index($word,$letter)>=0) {
print "<P>Good Guess!<BR>\n";
} else {
$numguesses++;
$q->param(`numguesses',$numguesses);
if ($numguesses==6) {
print "<P>Sorry! You lose! The word was $word<BR>";
} else {
print "<P>Sorry. Please try again.<BR>";
}
}
$guesses .= $q->param(`Letter');
$q->param(`guesses',$guesses);
$q->param(`word',$word);
if (&guessedFullWord($word,$guesses)) {
print "<P><H3>Congratulations! You Win!</H3><BR>";
}
&drawHangman($q,$numguesses);
&drawWord($word,$guesses);
&gameForm($q);
}
</FONT></PRE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -