1. Trang chủ
  2. » Công Nghệ Thông Tin

Black Art of Java Game Programming PHẦN 8 pdf

98 347 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 98
Dung lượng 6,16 MB

Nội dung

Black Art of Java Game Programming:WordQuest bounds = r; x = bounds.x; y = bounds.y; } public void setID(int id) { this.id = id; } public int queryID() { return id; } public void setSpeed( double X, double Y) { speedX=X; speedY=Y; } public void setSpeed( double factor) { speedX=factor; speedY=factor; } public int getSpeed() { if( speedY!=0) return warp*(int)(speedX/speedY); else return warp*(int)(speedX+.5); } Previous Table of Contents Next file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/656-659.html (4 von 4) [13.03.2002 13:19:33] Black Art of Java Game Programming:WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next Defining the Sprite Images Next comes the tedious job of defining each type of Sprite’s default “look”. This is used in the absence of an animation array of Images. To speed things up, rather than actually drawing the Sprite every time it is required, we will have the program generate an offscreen Image and put it in the animation array. Subsequent calls can simply make use of the default Image. Besides raw speed, the advantage of this is that the same code can be used whether the Sprite is preanimated or not. Here’s the method that will take care of creating the default Image: public synchronized void generateImage() { if( im==null) return; Graphics blah = im.getGraphics(); anim = new Image[1]; switch( id) { case ENEMY: { theColor = new Color( (int)(Math.random()*255),(int)(Math.ran- dom()*255),(int)(Math.random()*255)); blah.setColor( theColor); blah.fillRect( 0,0,bounds.width,bounds.height); break; } case BULLET: { theColor = Color.green; blah.setColor( theColor); blah.fillRoundRect( 0,0,bounds.width,bounds.height,5,5); break; } case USER: { theColor = Color.blue; blah.setColor( Color.black); blah.fillRect( 0,0,bounds.width,bounds.height); blah.setColor( Color.white); blah.drawOval( 0,0, bounds.width, bounds.height); blah.setColor( theColor); blah.fillOval( 0,0, bounds.width, bounds.height); break; } file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/659-664.html (1 von 4) [13.03.2002 13:19:34] Black Art of Java Game Programming:WordQuest } anim[0]=im; animIndex=0; animMax=1; } This takes care of all of our default IDs except MESSAGE, which we will handle later. We declare this method to be synchronized because we don’t want the Sprite to try to draw the Image before it is finished being created. Next, let’s actually create the drawing methods: public void paintSprite( Graphics g) { g.setColor( Color.black); if( lastX!=x || lastY!=y) g.fillRect( lastX,lastY,bounds.width,bounds.height); if( anim == null) generateImage(); g.drawImage(anim[animIndex],x,y,null); } Animating the Sprites Notice how this method works just fine whether or not we have given this Sprite a nifty animation array. However, if there is an animation array, we need a method that will advance it as necessary. This method should also move the Sprite to its new location based on the speed attributes: public void advance() { if( anim != null) { animIndex++; if( animIndex >= animMax ) animIndex = 0; } lastX=x; lastY=y; x += warp*(int)(speedX+.5); y += warp*(int)(speedY+.5); bounds.move(x,y); } Be sure to understand that a negative speedX or speedY value is totally legitimate, and is used to move the Sprite in the left or up directions, respectively. The last method required for a fully functional Sprite class is the one that makes it actually do something. If you remember that Sprite extends Thread, you should realize it needs a run() method: file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/659-664.html (2 von 4) [13.03.2002 13:19:34] Black Art of Java Game Programming:WordQuest public void run() { while(true) { try{ sleep(DELAY); } catch(Exception e); paintSprite( theG); advance(); } } Scrolling the Background The scrolling background is best accomplished in two parts: the terrain (foreground) and the star field (background). Because the Terrain uses some pretty wacky methods to achieve great speed, we will write it as its own class, and not as a subclass of Sprite. However, just to demonstrate how useful the Sprite class is, we will write the StarField class as an extension of it. Understanding the Terrain Class How does one write a scrolling foreground? Many games use a graphic that is longer than the active playing field and that looks exactly the same at both ends. This can then be scrolled at high speeds past the user, and when it “runs out,” another copy of it (or another compatible graphic) is added. This works pretty well, but the repetitive nature of it can be quite annoying to the user if the graphic is not large enough. Of course, the drawback to a large graphic is that it requires large amounts of memory to store, and time to develop. To avoid the drawbacks associated with predrawn terrains, we are going to create a “dynamic” terrain that is continuously generated by a Thread specifically written for this task. A “terrain” looks something like Figure 16-2. Figure 16-2 Terrain to be scrolled This may seem complicated to draw. However, if you look at the terrain as a series of polygons, each with four sides, a way of creating it should become clear. Figure 16-3 gives an example. Figure 16-3 Same terrain divided into quadrilaterals To create this effect we will call upon the Polygon class. The terrain will be composed of a series of Polygons, each the same width, that have at least two points in common. This is highlighted in Figure 16-4. Every time the terrain is “scrolled,” the leftmost Polygon is removed and a new one is generated at the far right. At high speeds, this gives the illusion that the user is whizzing by a landscape tremendously fast. Figure 16-4 Terrain coordinate system file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/659-664.html (3 von 4) [13.03.2002 13:19:34] Black Art of Java Game Programming:WordQuest Coding the Terrain Class The Terrain class will use a Vector to store the number of Polygons of a specified width. In order to avoid using double-buffered graphics (which are just too slow for this) and to also avoid much flicker (which would ruin the high-speed effect), we will be using some tricky Graphics methods. Declaring Variables To begin with, we start with some simple variable declarations. Notice that many of them are similar to ones we used in the Sprite class. import java.awt.*; import java.util.*; import java.lang.*; import Sprite; public class Terrain extends Thread { Vector v; // stores the Polygons int WIDTH; // pixel width of one Polygon Rectangle bounds; // Rectangle bounding the entire Terrain Graphics theG; // Graphics to draw on int lasty=0; // the y-coordinate of the "last" Polygon created } Previous Table of Contents Next file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/659-664.html (4 von 4) [13.03.2002 13:19:34] Black Art of Java Game Programming:WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next Initializing Now we initialize the Terrain. To do this, we require that the creating class pass along three things: the width of each Polygon, the Terrain’s bounding Rectangle, and the Graphics context to be used. Then, we calculate the size of the Vector needed to store the Polygons (the number of Polygons of the requested width that would fit within the bounding Rectangle). Then we actually create the first set of Polygons needed to draw the Terrain: Terrain( int w, Rectangle r, Graphics g) { WIDTH = w; bounds = r; theG = g.create(); int num = (int) (r.width/WIDTH); v = new Vector(num); while( num >= 0) v.addElement(nextPoly()); } Creating the nextPoly() Method Of course, we haven’t written the nextPoly() method, so let’s do that next. It creates a Polygon of random height starting with the Y coordinate of the last Polygon created: Polygon nextPoly() { Polygon p = new Polygon(); p.addPoint( (int)(WIDTH/2), (int)(bounds.height * Math.random())); p.addPoint( 0, lasty); p.addPoint( 0, bounds.height); p.addPoint( WIDTH, bounds.height); p.addPoint( WIDTH, lasty = (int)(bounds.height * Math.random())); return p; } Notice that we create the Polygon using x and y coordinates that are relative to an X coordinate of zero. When we draw the actual Polygon onto the screen, we are going to need to shift it over before it is drawn, and for that we need a new method: file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/664-667.html (1 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming:WordQuest void paintPolyXY(Graphics g, Polygon p, int x, int y) { for(int i=0;i<p.npoints;i++) { p.xpoints[i]+=x; p.ypoints[i]+=y; } g.fillPolygon(p); } Drawing Terrain onto the Screen Next, let’s write the method that actually draws the entire Terrain onto the screen. For this, we must take each Polygon out of the Vector and make a copy of it, because the method we just wrote for painting the Polygon actually changes its X and Y coordinates. We then send the copy to be painted, and leave the original alone: public void paintAll( Graphics g, Rectangle r) { g.setColor(Color.black); g.fillRect(bounds.x,bounds.y,bounds.width,bounds.height); g.setColor( Color.yellow); for(int x=0;x<v.size();x++) { Polygon p2 = (Polygon) v.elementAt(x); Polygon p = new Polygon(p2.xpoints,p2.ypoints,p2.npoints); paintPolyXY(g,p,r.x+x*WIDTH,r.y); } } Using copyArea() to Enhance Performance Although we could go ahead now and write the Thread code that makes the Terrain go, the result would be horrendously slow. Even if we used double-buffered graphics to draw each successive frame of the Terrain, the method is simply not fast enough, especially when there are many Threads running simultaneously (as there will be in the final product). The key to solving this problem is to recognize that 90 percent of the Terrain (all but one Polygon) doesn’t change each time. Therefore, it is wasteful and inefficient (not to mention slow) to have to redraw the entire Terrain for each frame. Rather, we can take advantage of a Graphics method called copyArea(), which actually copies a rectangular set of bits from one location on a Graphics context to another. Using this method, we can easily copy the majority of the Terrain to the left, and then only draw the one remaining Polygon right next to it. Here’s the code: public void paintChange( Graphics g, Rectangle r) { g.copyArea( r.x,r.y,r.width,r.height,-WIDTH,0); g.setColor(Color.black); g.fillRect( r.x+r.width-WIDTH,r.y,WIDTH,r.height); g.setColor(Color.yellow); paintPolyXY(g, (Polygon)v.lastElement(), r.x+r.width-WIDTH,r.y); } Finishing the Thread Methods file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/664-667.html (2 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming:WordQuest Now it’s time to finish up the Thread-related methods of Terrain.class. First, there is a method that will be called each frame to dispose of the oldest Polygon and to add a new one: public void advance() { v.removeElementAt(0); v.addElement( nextPoly()); } Next, we add a new variable and method that will allow the applet to request that the entire Terrain (and not just the new Polygon) be redrawn at the next available instant. This method also makes reference to the Sprite class “warp” factor that is used to increase the drawing frequency of the Terrain when necessary. This, of course, assumes that the applet using Terrain is also using Sprite. If this is not the case, you can always give Terrain a separate “warp” variable (or just leave this feature out altogether). boolean repaint=true; … public void repaint() { repaint=true; } Adding Functionality And last but not least, we create the run() method in order to actually give this class some functionality! public void run() { while(true) { if( repaint) { paintAll(theG,bounds); repaint = false; } else paintChange(theG,bounds); advance(); try{ sleep(200/Sprite.warp); } catch(Exception e); } } Terrain is finished! I would recommend writing up a simple applet to prove this to yourself, or if you wish, you can proceed straight to the rest of our background drawing. Previous Table of Contents Next file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/664-667.html (3 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming:WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next Coding the StarField Class The StarField is quite simple, really. All we have to do is keep track of a big array of X and Y coordinates. At each coordinate, we draw a tiny little white line, on a black background, to represent a star. Because we will make StarField an extension of Sprite, we can use its “speed” to determine not only the amount each star will move, but also the length of each star. Thus, when the Sprite “warp” factor is set to a large number, the stars will appear to streak by at amazing warp speeds! Like the Sprite class, this first version of StarField will use simple onscreen graphics, but eventually we will convert it to double-buffered form. We begin with two integer arrays for the X and Y coordinates. We initialize the arrays so that they are full of - 1. The method we will write for creating new stars will search the array for a star that is off the screen (that is, one with an X or Y coordinate that is less than zero). Let’s get started: import java.awt.*; import java.lang.*; public class StarField extends Sprite { int x[],y[]; int NUM_STARS; Graphics g; StarField( int num, Rectangle r, Image im) { this.im=im; // we’ll use this later for double-buffered graphics DELAY = 300; NUM_STARS = num; bounds = r; x = new int[num]; y = new int[num]; for(int i=0;i<NUM_STARS;i++) { x[i]=-1; y[i]=-1; addStar(i); } } file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/667-669.html (1 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming:WordQuest The initialization method makes a call to a method that adds a star to the array at position i, so let’s code that: public void addStar(int min) { int i,j; for(i=0;i<NUM_STARS;i++) if(x[i]==-1 && y[i]==-1) { x[i] = bounds.x+min+(int)((bounds.width-min)*Math.[return] random()); y[i] = bounds.y+(int)(bounds.height*Math.random()); } } This picks a random Y position and a random X position (near the right edge) and adds the “star” to the coordinate arrays. Next let’s write a little method to “kill” a star that is no longer needed (i.e., one that has scrolled off the screen): public void killStar(int i) { x[i]=-1; y[i]=-1; } The default advance method for Sprite will obviously not work for StarField, so let’s code that next: public void advance() { int i, spd = (int)(speedX+.5); for(i=0;i<NUM_STARS-1;i++) { x[i]-=spd; if( !bounds.inside(x[i],y[i])) { killStar(i); addStar(bounds.width-50); } } } Of primary importance is the painting method. We can safely assume that the applet will start with a nice black background, so all we have to do is erase the previous stars’ locations and then draw the new ones. As previously mentioned, we use Sprite’s default getSpeed() method to determine the length of each star (remember that getSpeed() takes the “warp” factor into account): public void paintSprite(Graphics g) { int i; Rectangle r=bounds; g.setColor( Color.black); g.fillRect( r.x,r.y,r.width,r.height); for(i=0;i<NUM_STARS;i++) file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch16/667-669.html (2 von 3) [13.03.2002 13:19:35] [...]... file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/676-679.html (4 von 5) [13.03.2002 13:19:37] Black Art of Java Game Programming: WordQuest boolean playing = false; // start with high scores Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/676-679.html (5 von 5) [13.03.2002 13:19:37] Black Art of Java Game Programming: WordQuest Black Art of Java. .. s.im=createImage(s.WIDTH,s.HEIGHT); s.start(); s.suspend(); } group.resume(); T.resume(); } Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/ 683 - 686 .html (4 von 4) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents... Game Programming: WordQuest Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/679- 683 .html (5 von 5) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next Handling the Rules Arguably... referee, scorekeeper, and line judge To accomplish all of this, we should start by creating some new classes to help with the task Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/667-669.html (3 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming: WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing... d) { super(p,d); data=d; } Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/673-675.html (3 von 3) [13.03.2002 13:19:37] Black Art of Java Game Programming: WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next The statusBar Class Even... needed in the final product Previous Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/669-673.html (4 von 4) [13.03.2002 13:19:36] Black Art of Java Game Programming: WordQuest Black Art of Java Game Programming by Joel Fan Sams, Macmillan Computer Publishing ISBN: 1571690433 Pub Date: 11/01/96 Previous Table of Contents Next Writing the Prompt Frame... bar.setPriority(Thread.MIN_PRIORITY); bar.start(); PF = new promptFrame(); PF.resize(d.width,d.height); PF.show(); file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/679- 683 .html (1 von 5) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest And last, but not least, get the “kicker” started: kicker = new Thread(this); kicker.setPriority(Thread.MAX_PRIORITY); kicker.start(); } Using Double-Buffered... flag = true; } while( flag); dataArray[x]=temp; } file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/ 683 - 686 .html (3 von 4) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest Once we have the text of the answers, we can create the enemy Sprites themselves Once we have them started, we suspend them immediately Once they are all created and in the appropriate... methods, start() and stop(): public void start() { questions = new Vector(); try{ URL theURL = new URL(getCodeBase(), "data.txt"); new dataThread( questions, theURL).start(); } catch (Exception e); } public void stop() { everything.stop(); } file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/679- 683 .html (4 von 5) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest... window); this is left as an exercise Next, we do all of the Sprite checking Whenever a collision occurs, we call the collision() method in the affected Sprites In order to save processing time, we only check those file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/ 683 - 686 .html (1 von 4) [13.03.2002 13:19: 38] Black Art of Java Game Programming: WordQuest Sprites that have an effect . Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/656-659.html (4 von 4) [13.03.2002 13:19:33] Black Art of Java Game Programming: WordQuest Black. Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/659-664.html (4 von 4) [13.03.2002 13:19:34] Black Art of Java Game Programming: WordQuest Black. Table of Contents Next file:///D|/Downloads/Books/Computer /Java/ Blac 2 0Java% 2 0Game% 2 0Programming/ ch16/667-669.html (3 von 3) [13.03.2002 13:19:35] Black Art of Java Game Programming: WordQuest Black

Ngày đăng: 12/08/2014, 09:21

TỪ KHÓA LIÊN QUAN