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

Black Art of Java Game Programming PHẦN 7 docx

98 346 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,15 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Black Art of Java Game Programming:Building the JAVAroids Game// handle keyDown events by setting the appropriate // field in the key buffer // field in the key buffer... Black Art of Ja

Trang 1

Black Art of Java Game Programming:Building the JAVAroids Game

// key bindings

static final int LEFTINDEX = 0;

static final int LEFT = 'q'; // rotate left

static final int RIGHTINDEX = 1;

static final int RIGHT = 'w'; // rotate right

static final int THRUSTINDEX = 2;

static final int THRUST = 'o'; // thrust

static final int FIREINDEX = 3;

static final int FIRE = 'p'; // fire

static final int SHIELDINDEX = 4;

static final int SHIELD = ' '; // shield

/////////////////////////////////////////////////////////////////// update Ship and Fire sprites based on key buffer

///////////////////////////////////////////////////////////////// public void update() {

// update fire sprites

for ( int i=0 ; i<MAX_SHOTS; i++) {

Trang 2

// otherwise, the ship's not alive!

else {

// if the waiting period's over,

// initialize a new Ship sprite

if (!gameOver && (waitPeriod <= 0)) {

Trang 3

Black Art of Java Game Programming:Building the JAVAroids Game

// handle keyDown events by setting the appropriate

// field in the key buffer

// field in the key buffer

Trang 4

private void updateShield() {

///////////////////////////////////////////////////////////////// private void handleFire() {

for (int i=0; i<MAX_SHOTS; i++) {

Trang 5

Black Art of Java Game Programming:Building the JAVAroids Game

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 Enemy Manager

By now, you should be getting a better idea of how these managers are organized! The

EnemyManager class is responsible for the Enemy sprites and their Fire sprites, which it initializes in its constructor The update() method checks for collisions between the enemy objects and the ship (and this code is really similar to the AstManager’s update()) In addition, update() starts new enemy ships, using the method NewEnemy(), and initiates enemy firing at random intervals Finally, the paint() method cycles through all enemy ship sprites and enemy fire sprites, and tells each one to paint itself

Listing 13-16 shows the EnemyManager class

Listing 13-16 EnemyManager class

///////////////////////////////////////////////////////////////////

// EnemyManager responsible for controlling the

// Enemy alien sprites, and Enemy Fire

//

/////////////////////////////////////////////////////////////////public class EnemyManager extends Object {

// constants to define two sizes of enemy ships

static final int LARGE = 0;

static final int SMALL = 1;

static final int SRATX = 3; // x-ratio of large to small

static final int SRATY = 2; // y-ratio of large to small

// the enemy ship templates

Trang 6

static final int tpy[][] = {

{0,3,6,6,3,0,-4,-4,0,0},

{0/SRATY,3/SRATY,6/SRATY,6/SRATY,3/SRATY,0/SRATY,-4/SRATY, -4/SRATY,0/SRATY,0/SRATY} } ;

// screen boundaries

static int width,height;

// constants parameters for enemy ships

static final int MAX_ENEMIES = 3;

static final int MAX_SHOTS_PER_ENEMY = 2;

static final int MAX_SHOTS = MAX_ENEMIES*MAX_SHOTS_PER_ENEMY;

// arrays for color, length, and value of various enemy ships static final Color ENEMY_COLOR[] =

{Color.green,Color.red,Color.orange};

static final int ENEMY_LENGTH[] = {14,14,5};

static final int VALUE[] = {500,750,1000};

// maximum speed

static final int MAX_VX = 9, MAX_VY = 9;

// how often enemies appear, and how often they fire

static double enemy_freq = 0.995 ;

static double fire_freq = 0.995;

// array of Enemy sprites

private Enemy e[] = new Enemy[MAX_ENEMIES];

// array of Fire sprites

private Fire f[] = new Fire[MAX_SHOTS_PER_ENEMY*MAX_ENEMIES];

// references to other game objects

Trang 7

Black Art of Java Game Programming:Building the JAVAroids Game

GameManager g) {

ship = sm.getShip(); // get ship needed for // collision detection

shipfire = sm.getFire(); // get ship's fire for

this.sm = sm; // collision detection

this.efm = efm;

game = g;

// initialize the three enemy sprites

e[0] = new Enemy(tpx[0],tpy[0],tpx[0].length, // template

0,0, // initial loc ENEMY_COLOR[0], // color

width,height, // screen bounds ENEMY_LENGTH[0],VALUE[0]); // length,value

e[1] = new Enemy(tpx[0],tpy[0],tpx[0].length,

// suspend the three enemy sprites

for (int i=0; i<MAX_ENEMIES; i++) {

e[i].suspend();

}

// create and suspend the Fire sprites

for ( int i=0 ; i<MAX_SHOTS; i++) {

f[i] = new Fire(ENEMY_COLOR[i/MAX_SHOTS_PER_ENEMY],

///////////////////////////////////////////////////////////////// public void newGame() {

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/570-575.html (3 von 7) [13.03.2002 13:19:19]

Trang 8

}

for (int i=0 ; i<MAX_SHOTS; i++) {

f[i] = new Fire(ENEMY_COLOR[i/MAX_SHOTS_PER_ENEMY],

// CHECK FOR COLLISIONS WITH SHIP OR SHIP FIRE

///////////////////////////////////////////////////////////////// public void update() {

// check if any of the fire sprites hit the Player's ship // If so, tell the ShipManager to destroy the ship

for ( int i=0 ; i<MAX_SHOTS; i++) {

for ( int i=0 ; i<MAX_ENEMIES; i++) {

// place a new enemy on the screen at random intervals

Trang 9

Black Art of Java Game Programming:Building the JAVAroids Game

// tell sm to destroy ship

// check if enemy intersect's ship's fire

for (int j=0; j<shipfire.length; j++) {

if (e[i].intersect(shipfire[j])) {

sm.stopFire(j); // stop fire sprite

e[i].suspend(); // stop enemy sprite

Trang 10

private void NewEnemy(int i) {

// set the enemy speed

e[i].setVelocity(GameMath.getRand(2*MAX_VX)-MAX_VX,

GameMath.getRand(2*MAX_VY)-MAX_VY);

// set the enemy position

int px = (Math.random() > 0.5) ? 0 : width;

/////////////////////////////////////////////////////////////////

private void Fire(int i) {

for (int j = i*MAX_SHOTS_PER_ENEMY;

j < (i+1)*MAX_SHOTS_PER_ENEMY;

j++) {

// if there's a slot in enemy fire array,

// initialize and restore the fire sprite

///////////////////////////////////////////////////////////////// public void paint(Graphics g) {

for ( int i=0 ; i<MAX_ENEMIES; i++) {

Trang 11

Black Art of Java Game Programming:Building the JAVAroids Game

}

}

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/570-575.html (7 von 7) [13.03.2002 13:19:19]

Trang 12

by Joel Fan

Sams, Macmillan Computer Publishing

ISBN: 1571690433 Pub Date: 11/01/96

Previous Table of Contents Next

The Effect Manager

For the effect manager, we’re going to depart from our policy of avoiding object instantiations during game play This is because the number of explosions is tricky to judge beforehand, so it’s easier to keep a Vector of explosions, and insert new explosions when the other manager classes detect

collisions Thus, EffManager provides the public methods addShipExplosion(),

addEnemyExplosion(), and addAstExplosion(), which the other managers can invoke These methods create new Explosion objects that are added to the explosions Vector

Listing 13-17 contains the complete effect manager class

Listing 13-17 EffManager class

///////////////////////////////////////////////////////////////////

// EffManager: handles effects, such as explosions and sound

//

/////////////////////////////////////////////////////////////////public class EffManager extends Object {

Vector explosions;

AudioClip expsound;

/////////////////////////////////////////////////////////////////// EffManager constructor

/////////////////////////////////////////////////////////////////

public EffManager(AudioClip expsound) {

explosions = new Vector();

this.expsound = expsound;

}

/////////////////////////////////////////////////////////////////// make a ship explosion at x,y

/////////////////////////////////////////////////////////////////file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/575-577.html (1 von 3) [13.03.2002 13:19:20]

Trang 13

Black Art of Java Game Programming:Building the JAVAroids Game

public void addShipExplosion(int x,int y) {

Explosion exp = new Explosion(Color.red,x,y,20);

Explosion exp1 = new Explosion(Color.yellow,x+2,y+2,25);

///////////////////////////////////////////////////////////////// public void addAstExplosion(int x,int y) {

Explosion exp = new Explosion(Color.white,x,y,15);

///////////////////////////////////////////////////////////////// public void addEnemyExplosion(int x,int y) {

Explosion exp = new Explosion(Color.orange,x,y,15);

///////////////////////////////////////////////////////////////// public void addExplosion(Color c,int x, int y, int u) {

Explosion exp = new Explosion(c,x,y,u);

// explosions Vector

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/575-577.html (2 von 3) [13.03.2002 13:19:20]

Trang 14

// explosions Vector

///////////////////////////////////////////////////////////////// public void update() {

Trang 15

Black Art of Java Game Programming:Building the JAVAroids Game

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 Game Manager

The GameManager class contains the top-level structure of JAVAroids The game opens with an introductory screen, which lists the point values of the objects in the game After this, the player can test drive his ship, and learn the controls Then, the player can start the game The transition between these screens is triggered by a mouseUp event

GameManager implements the Runnable interface by defining a method called run() The heart of the run() method is the Video Game Loop, which we covered back in Chapter 5, Building a Video Game This loop coordinates the sequence of actions that take place in Figure 13-17 GameManager also defines handlers for key events, which it passes along to the ShipManager

Finally, the GameManager source is presented in Listing 13-18 JAVAroids is finished!

Listing 13-18 GameManager class

///////////////////////////////////////////////////////////////////

// GameManager:

// responsible for tracking status of game and keeping score

//

/////////////////////////////////////////////////////////////////public class GameManager extends Applet implements Runnable {

// variables for double buffering and animation

Thread animation;

Graphics gbuf;

Image im;

static final int REFRESH_RATE = 72; // in ms

// size of the game applet: change as needed

static final int MAX_HEIGHT = 400;

static final int MAX_WIDTH = 400;

// game parameters

file:///D|/Downloads/Books/Computer/Java/Bla 0Java%20Game%20Programming/ch13/578-588.html (1 von 12) [13.03.2002 13:19:21]

Trang 16

private boolean gameOver; // is game over

private int intro_screen; // which screen

static final int EXTRA_SHIP = 10000; // #pts for extra ship private int current_extra = 0; // counts extras

// constants for the introduction part of the game

static final int INSTRUCTIONS = 1;

static final int TEST_DRIVE = 2;

static final int INTRO_OVER = 3;

// references to manager classes

AstManager am; // asteroids

ShipManager sm; // ship

EnemyManager em; // enemy ships

EffManager efm; // effects

// sound

URL codebase;

AudioClip expsound = null;

// variables to monitor performance during game

Date time;

long t1,t2,dt;

// fonts

static Font bigfont = new Font("TimesRoman", Font.BOLD,24);

static Font medfont = new Font("TimesRoman", Font.PLAIN,18); static Font smallfont = new Font("TimesRoman", Font.PLAIN,12);

/////////////////////////////////////////////////////////////////// initialize applet

///////////////////////////////////////////////////////////////// public void init() {

Trang 17

Black Art of Java Game Programming:Building the JAVAroids Game

///////////////////////////////////////////////////////////////// public void start() {

// load sound

try {

expsound = getAudioClip(getCodeBase(),"Explosion.au");

}

catch (Exception exc) {

System.out.println("Sound not loaded");

};

// initialize manager classes

efm = new EffManager(expsound);

/////////////////////////////////////////////////////////////////

file:///D|/Downloads/Books/Computer/Java/Bla 0Java%20Game%20Programming/ch13/578-588.html (3 von 12) [13.03.2002 13:19:21]

Trang 18

///////////////////////////////////////////////////////////////// public void setGameOver() {

gameOver = true;

}

/////////////////////////////////////////////////////////////////// start a new game

///////////////////////////////////////////////////////////////// private void newGame() {

// tell managers to start a new game

Trang 19

Black Art of Java Game Programming:Building the JAVAroids Game

sm.getShip().restore();

}

// else restart the game

else if (intro_screen == TEST_DRIVE) {

// pass key events to the ShipManager

public boolean keyDown(Event e, int k) {

sm.keyDown(e,k);

return true;

}

// pass key events to the ShipManager

public boolean keyUp(Event e, int k) {

sm.keyUp(e,k);

return true;

}

/////////////////////////////////////////////////////////////////// the game driver

///////////////////////////////////////////////////////////////// public void run() {

em.update(); // update enemies

am.update(); // update asteroids

efm.update(); // update effects

Trang 20

Thread.sleep (REFRESH_RATE);// sleep

} catch (Exception exc) { };

}

}

}

/////////////////////////////////////////////////////////////////// initialize the AstManager and EnemyManager for the

// INSTRUCTIONS screen

///////////////////////////////////////////////////////////////// private void startInstructions() {

Asteroid a[] = am.getAsts();

Trang 21

Black Art of Java Game Programming:Building the JAVAroids Game

// set enemies for intro screen

Enemy e[] = em.getEnemy();

///////////////////////////////////////////////////////////////// private void updateOpening() {

// (every EXTRA_SHIP points) give an extra ship!

///////////////////////////////////////////////////////////////// public void updateScore(int val) {

score += val;

if ((score / EXTRA_SHIP) > current_extra) {

sm.extraShip(); // give extra ship

current_extra = score/EXTRA_SHIP;

}

}

/////////////////////////////////////////////////////////////////// override update() to eliminate flicker

/////////////////////////////////////////////////////////////////file:///D|/Downloads/Books/Computer/Java/Bla 0Java%20Game%20Programming/ch13/578-588.html (7 von 12) [13.03.2002 13:19:21]

Trang 22

}

/////////////////////////////////////////////////////////////////// return a string of n that is 0-padded with the given length///////////////////////////////////////////////////////////////// public String PadNumber(int n,int len) {

///////////////////////////////////////////////////////////////// // Strings used in INSTRUCTIONS screen

String javaroidsString = new String("JAVAroids!");

String galleryString = new String("The Lineup ");

new String("extra shield strength:");

// Strings used in the TEST_DRIVE screen

String shipControlString =

new String("Test Drive your ship NOW -> ");

String rotLeftString = new String("Press 'q' to Rotate Left"); String rotRightString =

file:///D|/Downloads/Books/Computer/Java/Bla 0Java%20Game%20Programming/ch13/578-588.html (8 von 12) [13.03.2002 13:19:21]

Trang 23

Black Art of Java Game Programming:Building the JAVAroids Game

new String("Press 'w' to Rotate Right");

String thrustString = new String("Press 'o' to Thrust");

String fireString = new String("Press 'p' to Fire");

new String("Click mouse to begin!");

String byMeString = new String("by Joel Fan");

String gameOverString = new String("GAME OVER");

String clickMouseString2 =

new String("Click mouse to play again!");

/////////////////////////////////////////////////////////////////// paint to the screen, depending on mode of game

///////////////////////////////////////////////////////////////// public void paint(Graphics g) {

// clear offscreen buffer

Trang 24

// tell other manager classes to paint themselves

em.paint(gbuf); // paint enemies

am.paint(gbuf); // paint asteroids

efm.paint(gbuf); // paint effects

// draw the score

// coordinates are hardcoded for simplicity

///////////////////////////////////////////////////////////////// public void paintInstructions(Graphics g) {

Trang 25

Black Art of Java Game Programming:Building the JAVAroids Game

// coordinates are hardcoded for simplicity

///////////////////////////////////////////////////////////////// public void paintTestDrive(Graphics g) {

Trang 26

Recommended Applet Tag to Run JAVAroids

<applet code=“GameManager.class” width=400 height=400>

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Bl Java%20Game%20Programming/ch13/578-588.html (12 von 12) [13.03.2002 13:19:21]

Trang 27

Black Art of Java Game Programming:Building the JAVAroids Game

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

Suggestion Box

This game’s only a starting point Here are a few ideas for further extensions and improvements to the game:

• Make the enemy ships more intelligent For example, they could follow the player’s ship, or

exhibit different behaviors You can use a state machine to implement multiple behaviors, as you’ve seen in Chapter 5, Building a Video Game

• Change the way the game objects move One change you can implement almost immediately

is to bounce the sprites off the edges of the screen, instead of wrapping them around to the other side Just modify the updatePosition() method of MoveablePolygon, and you can alter the dynamic of the game dramatically!

• Another way of handling explosions and sound effects is by incorporating this functionality

in the Sprite subclasses themselves Thus, the sprites would be responsible for the sounds that occur when they collide, and the way that they explode In this scenario, the effect manager might tell the individual sprites when to make sounds or explode, but the actual sound or

explosion is the responsibility of the sprite itself Think about the benefits of encapsulating explosion and sound effects in the Sprite subclasses, and implement it

• Optimize the game Here are some ways of doing this First, precompute the coordinates of

the rotated polygons, and store them in a lookup table This way, you can avoid the point multiplications while the game is playing Secondly, use final methods whenever

floating-possible (such as accessor methods) to eliminate the overhead from dynamic method binding

A third optimization is to flatten the inheritance hierarchy, and reduce unnecessary method calls by inlining functions as much as possible

• Allow multiple players to compete, either in alternation or at the same time (You’ll need a

big keyboard!)

Summary

You’ve constructed a fairly intricate video game in this chapter However, you’ve built the game, and managed its complexity, by making use of inheritance- and responsibility-driven design These are concepts you can take with you in designing any object-oriented application, whether it’s a game or not!

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/588-590.html (1 von 2) [13.03.2002 13:19:21]

Trang 28

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch13/588-590.html (2 von 2) [13.03.2002 13:19:21]

Trang 29

Black Art of Java Game Programming:Daleks!

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

In developing this applet, I paid a lot of attention to the issues of bandwidth and processor speed The sounds, graphics, and animations used are simple but effective The result is a program that loads and runs quickly—features that are easy to overlook with Java In addition, many game parameters are customizable from HTML, meaning the game board, images, and intro screen can be modified to incorporate different themes and challenges

Playing the Game

When the applet first runs, the player is greeted with an animated intro screen and a bar showing the progress of loading images When the images are done loading, the player can press any key to begin the game Figure 14-1 shows a typical board setup on level 1 The player’s character always begins in the center of the screen The Daleks are scattered randomly around the board and move one square in the direction of the player every turn The numeric keypad is used to control movement (diagonal movement is allowed) The player may press “S” to activate a sonic screwdriver to destroy adjacent Daleks The number of remaining screwdrivers is displayed in the info bar at the bottom of the screen The player may teleport at any time by pressing “T” This will move the player to a random space on the board, which may be adjacent to one of the Daleks, resulting in the player’s capture and the end of the game Finally, the player can press “L” to make a “last stand,” allowing the Daleks to move

continuously until the player or all the Daleks are destroyed

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/591-596.html (1 von 4) [13.03.2002 13:19:22]

Trang 30

Figure 14-1 The Daleks! board

Setting Up the Game

The applet is contained in two classes, daleks14 and animatedIntroClass A daleks14 object contains all the game routines and directs the traffic throughout the game An animatedIntroClass object contains the methods necessary to create the title screen shown between games Listing 14-1 shows the init() method of the daleks14 class, which is automatically called when the applet is loaded

Listing 14-1 The daleks14.init() method

public void init() {

// get parameters from the calling HTML file

getHTMLParameters();

// initialize dalek arrays

dalX = new int[maxEnemies];

dalY = new int[maxEnemies];

dalF = new int[maxEnemies];

Trang 31

Black Art of Java Game Programming:Daleks!

to resize(int, int) ensures that the game graphics will fit in the applet window The method then

assigns each graphic image to the appropriate Image object The various Images contained in the

doctorPic array are needed because the player’s appearance changes at certain levels (mimicking Dr

Who’s ability to regenerate on the TV show) Each player and Dalek has a right- and left-facing

Image All the Image objects are given to a newly created MediaTracker object tracker, which

handles loading the graphics and reports on their progress The nextScreen variable is basically a

worksheet Image where we build each successive game screen, which can be accessed by using

offScreenGC, its graphics context The call to prepareScreen() draws the current game status on the

offscreen Image Finally, the animatedIntroClass object is initialized and run

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/591-596.html (3 von 4) [13.03.2002 13:19:22]

Trang 32

Java addresses some of the complexity of C++ by eliminating the ability to dynamically allocate memory After an array is initialized, it cannot be extended, which can greatly reduce the flexibility

of Java applets Daleks! avoids this problem by waiting to initialize the Dalek arrays until the

maximum number of Daleks allowed is determined (this can be set through an HTML <param> tag)

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/591-596.html (4 von 4) [13.03.2002 13:19:22]

Trang 33

Black Art of Java Game Programming:Daleks!

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

Animating the Title Screen

The animated intro screen displays a cloud of question marks flying from the middle to the edges of the screen, as shown in Figure 14-2 It displays the applet title, version number, author, and an info bar on the bottom of the screen If the animatedIntroClass object is running for the first time, it will display a progress bar that grows as the Image variables are loaded When loading is complete, the progress bar is replaced with the standard info bar showing the player status (i.e., last score, screwdrivers, level number, and so on)

Figure 14-2 The animated intro screen

Before the title screen is run, however, a new Thread must be created This allows the daleks14 object to monitor the keyboard while another Thread loops continuously to create the animation effect of the title screen

Preparing to Animate

The title screen features a number of customizable items, and so we cannot assume anything about the applet title, screen size, and flying widgets (question marks by default) We need to have a procedure to ensure that when displayed, the graphics and text on the intro screen will be properly aligned and displayed To do this, the setInfo(…) method examines the dimensions of the String objects to be displayed and determines their horizontal and vertical positions Listing 14-2 shows a portion of the setInfo(…) method, which determines how to center the game title on the screen

Listing 14-2 The animatedIntroClass.setInfo(…) method

// handle Font creation and sizing

int halfWayX = maxX * imgW / 2;

int totalHeight = maxY * imgH;

titleFont = new Font("Helvetica", Font.PLAIN, 36);

offScreenGC.setFont(titleFont);

titleX = halfWayX - offScreenGC.getFontMetrics().stringWidth(gameTitle) ⇐

/ 2;

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/596-599.html (1 von 3) [13.03.2002 13:19:23]

Trang 34

The value of halfWayX is the horizontal center of the applet window in pixels (number of horizontal board squares * horizontal width of game pieces / 2) The totalHeight variable is the height of the game board in pixels The code creates a new Font object titleFont, which defines the display characteristics of the String object gameTitle To calculate dimensions, the procedure must make titleFont the current font, which is done

by setting it on the offscreen graphics context offScreenGC The variable titleX is then given the value for center of the screen minus half the width (in pixels) of the gameTitle String The procedure also calculates a

new vertical position for the text, 30 percent of the way down from the top of the applet window (remember both the height and width of the intro screen are customizable!).

Another preparation involves initializing the arrays for the flying String objects on the title screen The

trajectory and speed of each question mark is predetermined Listing 14-3 shows a portion of code that may seem a rather roundabout way of animating a number of randomly moving objects This code was chosen because it minimizes the number of calculations done in the animation loop itself, and therefore increases the speed at which the animation runs.

Listing 14-3 The animatedIntroClass.start() method

public void start() {

// determine question mark trajectory, velocity, and color

// *before* they are ever drawn

for (int j=0; j<numQmarks; j++) {

int angle = (int)(Math.random()*360);

int numSteps = (int)(Math.random()*30) + 20;

qMarkSteps[j] = numSteps;

int bright = 255 - numSteps * 3;

qMarkColor[j] = new Color(85, bright, 85);

qMarkXinc[j] = (int)(Math.cos(angle) * radius / numSteps); qMarkYinc[j] = (int)(Math.sin(angle) * radius / numSteps); qMarkCnt[j] = 0 - (int)(j/2);

qMarkX[j] = maxX * 8 + 2 + qMarkXinc[j];

qMarkY[j] = maxY * 8 + 2 + qMarkXinc[j];

}

}

As will be seen later, the number of question marks on the title screen is variable, and can be changed within

the source code or from HTML The for loop determines a trajectory, velocity, and Color object for each

question mark (later referred to as “flying widgets,” because they can be any valid String object) The total number of steps needed for each question mark to go from the center of the screen to the screen’s edge is

placed in qMarkSteps[x] (this is technically a measure of velocity) The fewer the steps needed to reach the

edge, the faster the question mark will move Based on this velocity, faster question marks are displayed using

brighter Color objects The arrays qMarkXinc[x] and qMarkYinc[x] are determined based on velocity and a

randomly determined trajectory (angle) calculated for each question mark These values represent the amount the question mark will be moved horizontally and vertically from its last position.

What is the end result? The question marks can be drawn and moved with a minimum of logical steps The

qMarkCnt[x] array tracks how many steps each question mark has taken When this becomes larger than the

value of qMarkSteps[x], the question mark is simply returned to the middle of the screen and sent right back

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/596-599.html (2 von 3) [13.03.2002 13:19:23]

Trang 35

Black Art of Java Game Programming:Daleks!

along the same path Because of the large number of question marks being displayed, the animation still retains a random feel, even though it really just continually shows the same thing.

Creating a New Thread

Because the daleks14 class is implemented as Runnable, a method called start() is called when the applet is run, as shown in Listing 14-4 This method handles the creation of the new Thread for animation

Listing 14-4 The daleks14.start() method

public void start() {

The kicker Thread can be controlled using its start() and stop() methods The Thread object also contains

methods for adjusting its priority, or its share of CPU resources This allows applet programmers to adjust performance and distribute processing power to the methods or objects that need it most.

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/596-599.html (3 von 3) [13.03.2002 13:19:23]

Trang 36

Sams, Macmillan Computer Publishing

ISBN: 1571690433 Pub Date: 11/01/96

Previous Table of Contents Next

The Animation Loop

Now that two Thread objects are active, one can be concentrated on the animation loop while the other waits for keyboard input (a keypress indicates it is time for the game to begin) Nothing fancy is required

here The update() procedure will call the animatedIntro object whenever animIntro (a boolean variable) is set to true Therefore, the animation loop will start whenever repaint() is called and animIntro is true, as

demonstrated in Listing 14-5.

Listing 14-5 The daleks14.update(…) method

public synchronized void update(Graphics g) {

// draw between-move animations and repaint the game board, or // call the intro screen’s drawing routine

This is the portion of the update() procedure that comprises the animation loop Notice that the loop will

only continue so long as animIntro remains true When a key is pressed and image loading is complete, the keyDown() method sets animIntro to false and stops the second Thread object, effectively ending the

animation loop.

Notice that the actual drawing routine is handled by the animateIntro object Its drawIntroScreen() method

is called with arguments for the current graphics context (telling it where to draw!), Image loading status,

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/599-602.html (1 von 3) [13.03.2002 13:19:23]

Trang 37

Black Art of Java Game Programming:Daleks!

and the number of the picture currently being loaded.

The last important point of the animation loop is the use of the MediaTracker object tracker As a picture is loaded, the value for currentPic is incremented The value of currentPic is passed to the animateIntro()

method and is used to determine the length of the progress bar on the bottom of the screen, as shown in

Figure 14-3 When the last Image file is loaded, doneLoading becomes true, and the progress bar is

replaced by the normal status bar.

Figure 14-3 The progress bar while an image is loading

The Game Begins

Once the game begins, nothing happens in the Daleks! applet until the player presses a key In a real-time game this would be unacceptable, but it is perfect for turn-based games A large number of boolean

variables are used in the daleks14 object to help direct traffic, but we will only examine the important ones

to get a feel for the structure of the game itself

Starting a Turn

A new turn begins when the player presses a key, which automatically calls the keyDown() method, shown

in Listing 14-6

Listing 14-6 The daleks14.keyDown(…) method

public synchronized boolean keyDown(Event evt, int x) {

if (doneLoading)

handleKeyPress(x);

return false;

}

Notice that nothing will happen unless doneLoading is true This variable will not become true until the

tracker object is done loading all the Image files necessary to play the game Ideally, the audio files would

also be tracked, but Java’s beta API does not currently implement this function As a result, the game will pause to load audio files the first time they are played.

Directing Traffic

Now that a new turn has started, what should be done? The game can be in many states–we could be

waiting to start a new level (if all the Daleks have been destroyed), in the middle of a level, or waiting to reanimate the title screen (if the player has been captured) Each of these possibilities requires an additional boolean variable to help the handleKeyPress(int) method decide what to do Listing 14-7 gives the skeleton

of this procedure

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/599-602.html (2 von 3) [13.03.2002 13:19:23]

Trang 38

public void handleKeyPress(int whichKey)

The if statement checks the current status of the game and calls the appropriate methods Let’s examine

what happens if we are in the middle of a level and the player has pressed a key In this case, the boolean

variables animIntro, levelComplete, and playerDead are false, and the code in the final else clause will be

executed.

Previous Table of Contents Next

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/599-602.html (3 von 3) [13.03.2002 13:19:23]

Trang 39

Black Art of Java Game Programming:Daleks!

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

Making the Right Moves

We can only hope for the player’s sake that he or she has made a wise move Fortunately, the applet’s only job is to analyze the player’s input and update the game board according to the rules of the game The final

else clause (with the comment “analyze keypress and execute the next turn”) is where the entire turn

unfolds, shown in Listing 14-8.

Listing 14-8 Executing player’s move in handleKeyPress(int whichKey); executing next turn in

// analyze keypress and execute the next turn

char ASCIImove = (char)whichKey;

boolean validMove = movePlayer(ASCIImove);

Trang 40

First, the player’s move is converted from an integer to an ASCII character for simplification Then the

movePlayer(char) method is called This method returns a boolean value—true if the player’s move was valid and false otherwise If the player’s move checks out, several things can happen If the player has

chosen to make a last stand (by pressing “L”), the repaint() procedure is called This will be examined in a later section.

Analyzing Input

The movePlayer(char) method shown in Listing 14-9 takes care of the gritty details of keyboard processing The end result of this method is a boolean value indicating whether or not the player’s move is a valid one

Listing 14-9 The daleks14.movePlayer(…) method

public boolean movePlayer(char input) {

int newX = drX;

int newY = drY;

int newF = drF;

boolean pass = false;

// player may elect to not move (hit '5')

boolean teleport = false;

// player may teleport (hit 'T' or 't')

boolean validMove = true;

switch (input) {

// numeric keypad movement options

case '1': newX ; newY++; newF = faceLeft; break; case '2': newY++; break; case '3': newX++; newY++; newF = faceRight; break; case '4': newX ; newF = faceLeft; break; case '5': pass = true; break; case '6': newX++; newF = faceRight; break; case '7': newX ; newY ; newF = faceLeft; break; case '8': newY ; break; case '9': newX++; newY ; newF = faceRight; break;

file:///D|/Downloads/Books/Computer/Java/Blac 20Java%20Game%20Programming/ch14/602-605.html (2 von 4) [13.03.2002 13:19:24]

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

TỪ KHÓA LIÊN QUAN