?? the java game programming tutorial part iv.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0057)http://www.intergate.bc.ca/personal/iago/javatut/jtp4.htm -->
<HTML><HEAD><TITLE>The Java Game Programming Tutorial: Part IV</TITLE>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
<META content="Garry Morse" name=Author>
<META content="MSHTML 5.00.2614.3500" name=GENERATOR>
<META content="An expanding tutorial on Java 2D/3D game programming"
name=Description>
<META
content=Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java,Java
name=KeyWords></HEAD>
<BODY aLink=#ff0000 bgColor=#ffdfdf link=#0000ee text=#000000 vLink=#551a8b>
<H1><A href="http://www.intergate.bc.ca/personal/iago/javatut/index.htm"><IMG
align=ABSCENTER border=0 height=85
src="The Java Game Programming Tutorial Part IV_ficheiros/coffee.gif"
width=116></A><FONT color=#804040><FONT size=+2><A
href="http://www.intergate.bc.ca/personal/iago/javatut/index.htm">The Java Game
Programming Tutorial</A></FONT></FONT></H1>
<H1>
<HR width="100%">
</H1>
<H2>Part IV: What about Double Buffering?</H2>
<UL>
<P>Now we have images loaded and doing something the next topic<BR>on the
agenda is flicker. Although simplistic animations or<BR>slideshows run fairly
well, as more drawing is done to the<BR>viewing window in advanced applets,
one can begin to see the<BR>screen refresh causing a flicker. </P></UL>
<UL>
<P>I would say this is the bane of the animator or game developer<BR>because
many solutions exist on a variety of platforms to speed<BR>up rendering.
Either built into the hardware or programmed in<BR>the software, the most
common solution is double buffering. </P>
<P>Double buffering is the process of storing a copy of the screen<BR>in a
section of memory and doing all drawing to this canvas as<BR>if it were the
screen. Since all drawing is being done off the<BR>screen, the only drawing
onscreen is the actual copying of the<BR>buffer to the screen which can be
timed to avoid the refresh. </P>
<P>Some systems or environments have automatic buffering which<BR>means little
or no programming. My experience in low level<BR>DOS has taught me this can
mean extensive coding for speedy<BR>animation. Thankfully, in Java it is
really only a matter of<BR>redirection from what we've doing so far. </P>
<P>These lessons are compressed to be building blocks for bigger<BR>and better
applets. Otherwise, there might be ten versions of<BR>Hello world (yikes!) and
I refuse to insult your intelligence<BR>this way. At this juncture, I must
cram more information about<BR>sprite images relevant to the example. </P>
<P>A good thing about gif files is that you can make transparent<BR>gifs quite
easily using many paint programs and image utilities.<BR>This fact allows gif
images which aren't rectangular to keep<BR>their fine figure and blend in with
whatever background we like. </P>
<P>In <A href="http://www.intergate.bc.ca/personal/iago/javatut/jtp3.htm">Part
3</A>, an image array was created to load in each sketch<BR>or picture. This
is alright for a slideshow of variable images<BR>but bad in the case of small
identical images. Bad because each<BR>image requires an established HTTP
connection which can be slow.<BR>A good solution is to store your images side
by side like so: </P>
<UL>
<P><IMG height=40
src="The Java Game Programming Tutorial Part IV_ficheiros/guy.gif"
width=64></P></UL>
<P>Only a single image connection is required for this image strip<BR>which
can be drawn easily with a slight adjustment. Since the<BR>previous tutorial
sections cover applet structure and graphics<BR>techniques, I will just
elaborate on new or changed code. </P><PRE> <B>Image offscreenImage;
Graphics offscreenGraphics;</B></PRE>
<P>These two objects are added to the applet to implement double<BR>buffering.
The first is the familiar image object which serves<BR>as the image buffer
itself. The second is a graphics context<BR>or handle for reference to the
image buffer. </P><PRE> <B>Image imageBackground;
Image spriteStrip;</B></PRE>
<P>These are just less important images for drawing. The first is<BR>a
background image to make a backdrop for the sprite. The next<BR>is the sprite
image strip. I've decided to omit explaining the<BR>init method. Image loading
was discussed in <A
href="http://www.intergate.bc.ca/personal/iago/javatut/jtp3.htm">Part 3</A>.
</P><PRE> <B>offscreenImage = createImage(this.size().width,
this.size().height);
offscreenGraphics = offscreenImage.getGraphics();</B></PRE>
<P>This conditional initialization code is added to the paint method.<BR>The
method createImage is used to create an offscreen buffer image<BR>the size of
the applet window. The image method getGraphics is used<BR>to get a graphics
context. This is excellent because we can draw to<BR>the double buffer exactly
as if it were the screen. </P><PRE> <B>spriteWidth = spriteStrip.getWidth(this) / spriteCount;
spriteHeight = spriteStrip.getHeight(this);</B></PRE>
<P>Here, the variable spriteCount is used to calculate the
independent<BR>image width, assuming each is the same width. The height is
the<BR>same as the strip height because it is a row of images. </P><PRE> <B>offscreenGraphics.drawImage(imageBackground,0,0,this);</B></PRE>
<P>This is the same method used in <A
href="http://www.intergate.bc.ca/personal/iago/javatut/jtp3.htm">Part 3</A>
but note how our own graphics<BR>context is used. We could draw lines or
circles, etc. In this case,<BR>our background image is copied into the
offscreen buffer. Redrawing<BR>the background every frame is rather
inefficient but I'll go over a<BR>better design later. For this purpose, it's
okay. </P><PRE> <B>offscreenGraphics.clipRect(spriteX,spriteY,
spriteWidth,spriteHeight);</B></PRE>
<P>This code above makes a clipping window in our offscreen buffer in<BR>the
position of our sprite image. We want it to be the size of only<BR>a single
image frame. This way, the picture we want is drawn and not<BR>the entire
image strip. </P><PRE> <B>offscreenGraphics.drawImage(spriteStrip,
spriteX+(-spriteIndex * spriteWidth),
spriteY,this);</B></PRE>
<P>Drawing the sprite is the same as drawing any image. Note above that<BR>the
only difference is the x coordinate. We are shifting the strip of<BR>images
left to get the image we want. If we didn't create a clipping<BR>rectangle
first, the image would just move left. The image strip is<BR>like a large
banner being carried back and forth behind a small window.<BR>Considering the
image download speed increases, this is worthwhile. </P><PRE> <B>g.drawImage(offscreenImage,0,0,this);</B></PRE>
<P>And finally, here is the only call to the screen graphics context
which<BR>draws the updated offscreen buffer just like any normal image. </P>
<P>Here's the HTML parameters:</P></UL>
<UL>
<UL>
<P><B><APPLET CODE="DBuffer.class" WIDTH=104 HEIGHT=64><BR><PARAM
NAME="SPRITEDELAY" VALUE="200"><BR><PARAM NAME="SPRITEX"
VALUE="45"><BR><PARAM NAME="SPRITEY" VALUE="20"><BR><PARAM
NAME="SPRITECOUNT" VALUE="4"><BR><PARAM NAME="SPRITENAME"
VALUE="guy"><BR><PARAM NAME="BACKGROUNDNAME"
VALUE="skullbg"><BR></APPLET></B></P></UL>
<P>The example applet parameters allow you to insert your own
background<BR>image and animated character at an (x,y) position within the
applet<BR>window. If you alter the applet, you can make your character
walk<BR>around in front of a logo by changing spriteX and spriteY in
the<BR>run method infinite loop. Below is the entire Java code. Enjoy! </P><PRE><B>// DBuffer.java
// by Garry Morse
import java.awt.*;
import java.applet.*;
public class DBuffer extends Applet implements Runnable {
Thread spriteThread;
MediaTracker tracker;
Image offscreenImage;
Graphics offscreenGraphics;
Image imageBackground;
Image spriteStrip;
int spriteDelay=0, spriteCount=0, spriteIndex=0;
int spriteWidth=0,spriteHeight=0;
int spriteX=0,spriteY=0;
String paramString;
public void init() {
// create a media tracker object for this applet
tracker = new MediaTracker(this);
// get parameter for wait spriteDelay between images
paramString = getParameter("SPRITEDELAY");
spriteDelay = Integer.parseInt(paramString);
// get parameter for number of separate images in strip
paramString = getParameter("SPRITECOUNT");
spriteCount = Integer.parseInt(paramString);
// get parameter for x position of sprite
paramString = getParameter("SPRITEX");
spriteX = Integer.parseInt(paramString);
// get parameter for y position of sprite
paramString = getParameter("SPRITEY");
spriteY = Integer.parseInt(paramString);
// get parameter for sprite image file and load strip
paramString = getParameter("SPRITENAME");
spriteStrip = getImage(getCodeBase(),paramString + ".gif");
// get parameter for background image file and load image
paramString = getParameter("BACKGROUNDNAME");
imageBackground = getImage(getCodeBase(),paramString + ".gif");
// add images to monitored images with IDs
tracker.addImage(spriteStrip,0);
tracker.addImage(imageBackground,1);
// load images into memory
tracker.checkID(0,true);
tracker.checkID(1,true);
repaint();
}
public void start() {
if(spriteThread==null) {
spriteThread = new Thread(this);
spriteThread.start();
}
}
public void stop() {
if(spriteThread!=null) {
spriteThread.stop();
spriteThread = null;
}
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// if images not loaded yet, inform user
if(!tracker.checkAll()) {
g.drawString("loading images...",
20,this.size().height/2);
}
else {
if(offscreenImage==null) {
// set up double buffer
offscreenImage = createImage(this.size().width,
this.size().height);
offscreenGraphics = offscreenImage.getGraphics();
}
// get dimensions of sprite
spriteWidth = spriteStrip.getWidth(this) / spriteCount;
spriteHeight = spriteStrip.getHeight(this);
// draw background and sprite in offscreen buffer
offscreenGraphics.drawImage(imageBackground,0,0,this);
offscreenGraphics.clipRect(spriteX,spriteY,
spriteWidth,spriteHeight);
offscreenGraphics.drawImage(spriteStrip,
spriteX+(-spriteIndex * spriteWidth),
spriteY,this);
// copy offscreen buffer to screen
g.drawImage(offscreenImage,0,0,this);
}
}
public void run() {
while(true) {
repaint();
// reloop through list of images to display
if(++spriteIndex >= spriteCount) spriteIndex=0;
// try to shut down spriteThread for milliseconds
try {
spriteThread.sleep(spriteDelay+1);
}
catch(InterruptedException e) { }
}
}
}</B></PRE></UL>
<P><FONT size=+1><A
href="http://www.intergate.bc.ca/personal/iago/javatut/dbuffer.htm">Click here
to see the Double Buffer applet in action!</A></FONT></P>
<P><FONT color=#ffb5b5><FONT size=-2>The Java Game Programming Tutorial and all
tutorials within are created by Garry Morse, Copyright 1997</FONT></FONT></P>
<P><BR></P></BODY></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -