📄 tumbleweedgame.java
字号:
setFrameSequence(FRAME_SEQUENCE);
}
//---------------------------------------------------------
// game methods
/**
* If the cowboy has landed on a tumbleweed, we decrease the score.
*/
int checkCollision(Tumbleweed tumbleweed) {
int retVal = 0;
if (collidesWith(tumbleweed, true)) {
retVal = 1;
// once the cowboy has collided with the tumbleweed,
// that tumbleweed is done for now, so we call reset
// which makes it invisible and ready to be reused.
tumbleweed.reset();
}
return (retVal);
}
/**
* set the cowboy back to its initial position.
*/
void reset() {
myIsJumping = myNoJumpInt;
setRefPixelPosition(myInitialX, myInitialY);
setFrameSequence(FRAME_SEQUENCE);
myScoreThisJump = 0;
// at first the cowboy faces right:
setTransform(TRANS_NONE);
}
//---------------------------------------------------------
// graphics
/**
* alter the cowboy image appropriately for this frame..
*/
void advance(int tickCount, boolean left) {
if (left) {
// use the mirror image of the cowboy graphic when
// the cowboy is going towards the left.
setTransform(TRANS_MIRROR);
move(-1, 0);
} else {
// use the (normal, untransformed) image of the cowboy
// graphic when the cowboy is going towards the right.
setTransform(TRANS_NONE);
move(1, 0);
}
// this section advances the animation:
// every third time through the loop, the cowboy
// image is changed to the next image in the walking
// animation sequence:
if (tickCount % 3 == 0) { // slow the animation down a little
if (myIsJumping == myNoJumpInt) {
// if he's not jumping, set the image to the next
// frame in the walking animation:
nextFrame();
} else {
// if he's jumping, advance the jump:
// the jump continues for several passes through
// the main game loop, and myIsJumping keeps track
// of where we are in the jump:
myIsJumping++;
if (myIsJumping < 0) {
// myIsJumping starts negative, and while it's
// still negative, the cowboy is going up.
// here we use a shift to make the cowboy go up a
// lot in the beginning of the jump, and ascend
// more and more slowly as he reaches his highest
// position:
setRefPixelPosition(getRefPixelX(), getRefPixelY()
- (2 << (-myIsJumping)));
} else {
// once myIsJumping is negative, the cowboy starts
// going back down until he reaches the end of the
// jump sequence:
if (myIsJumping != -myNoJumpInt - 1) {
setRefPixelPosition(getRefPixelX(), getRefPixelY()
+ (2 << myIsJumping));
} else {
// once the jump is done, we reset the cowboy to
// his non-jumping position:
myIsJumping = myNoJumpInt;
setRefPixelPosition(getRefPixelX(), myInitialY);
// we set the image back to being the walking
// animation sequence rather than the jumping image:
setFrameSequence(FRAME_SEQUENCE);
// myScoreThisJump keeps track of how many points
// were scored during the current jump (to keep
// track of the bonus points earned for jumping
// multiple tumbleweeds). Once the current jump is done,
// we set it back to zero.
myScoreThisJump = 0;
}
}
}
}
}
/**
* makes the cowboy jump.
*/
void jump() {
if (myIsJumping == myNoJumpInt) {
myIsJumping++;
// switch the cowboy to use the jumping image
// rather than the walking animation images:
setFrameSequence(null);
setFrame(0);
}
}
/**
* This is called whenever the cowboy clears a tumbleweed so that more
* points are scored when more tumbleweeds are cleared in a single jump.
*/
int increaseScoreThisJump() {
if (myScoreThisJump == 0) {
myScoreThisJump++;
} else {
myScoreThisJump *= 2;
}
return (myScoreThisJump);
}
}
/**
* This class contains the loop that keeps the game running.
*
* @author Carol Hamer
*/
class TumbleweedThread extends Thread {
//---------------------------------------------------------
// fields
/**
* Whether or not the main thread would like this thread to pause.
*/
private boolean myShouldPause;
/**
* Whether or not the main thread would like this thread to stop.
*/
private boolean myShouldStop;
/**
* A handle back to the graphical components.
*/
private Tumbleweed[] myTumbleweeds;
/**
* Random number generator to randomly decide when to appear.
*/
private Random myRandom = new Random();
//----------------------------------------------------------
// initialization
/**
* standard constructor, sets data.
*/
TumbleweedThread(JumpCanvas canvas) throws Exception {
myTumbleweeds = canvas.getTumbleweeds();
}
//----------------------------------------------------------
// actions
/**
* pause the thread.
*/
void pauseGame() {
myShouldPause = true;
}
/**
* restart the thread after a pause.
*/
synchronized void resumeGame() {
myShouldPause = false;
notify();
}
/**
* stops the thread.
*/
synchronized void requestStop() {
myShouldStop = true;
notify();
}
/**
* start the thread..
*/
public void run() {
myShouldStop = false;
myShouldPause = false;
while (true) {
if (myShouldStop) {
break;
}
synchronized (this) {
while (myShouldPause) {
try {
wait();
} catch (Exception e) {
}
}
}
// wait a random length of time:
int waitTime = (1 + getRandomInt(10)) * 100;
synchronized (this) {
try {
wait(waitTime);
} catch (Exception e) {
}
}
if (!myShouldPause) {
// randomly select which one to set in motion and
// tell it to go. If the chosen tumbleweed is
// currently visible, it will not be affected
int whichWeed = getRandomInt(myTumbleweeds.length);
myTumbleweeds[whichWeed].go();
}
}
}
//----------------------------------------------------------
// randomization utilities
/**
* Gets a random int between zero and the param upper (exclusive).
*/
public int getRandomInt(int upper) {
int retVal = myRandom.nextInt() % upper;
if (retVal < 0) {
retVal += upper;
}
return (retVal);
}
}
/**
* This class represents the tumbleweeds that the player must jump over.
*
* @author Carol Hamer
*/
class Tumbleweed extends Sprite {
//---------------------------------------------------------
// dimension fields
/**
* The width of the tumbleweed's bounding square.
*/
static final int WIDTH = 16;
//---------------------------------------------------------
// instance fields
/**
* whether or not this tumbleweed has been jumped over. This is used to
* calculate the score.
*/
private boolean myJumpedOver;
/**
* whether or not this tumbleweed enters from the left.
*/
private boolean myLeft;
/**
* the Y coordinate of the tumbleweed.
*/
private int myY;
/**
* the leftmost visible pixel.
*/
private int myCurrentLeftBound;
/**
* the rightmost visible pixel.
*/
private int myCurrentRightBound;
//---------------------------------------------------------
// initialization
/**
* constructor initializes the image and animation.
*
* @param left
* whether or not this tumbleweed enters from the left.
*/
public Tumbleweed(boolean left) throws Exception {
super(Image.createImage("/images/tumbleweed.png"), WIDTH, WIDTH);
myY = JumpManager.DISP_HEIGHT - WIDTH - 2;
myLeft = left;
if (!myLeft) {
setTransform(TRANS_MIRROR);
}
myJumpedOver = false;
setVisible(false);
}
//---------------------------------------------------------
// game actions
/**
* Set the tumbleweed in motion if it is not currently visible.
*/
synchronized boolean go() {
boolean retVal = false;
if (!isVisible()) {
retVal = true;
//System.out.println("Tumbleweed.go-->not visible");
myJumpedOver = false;
setVisible(true);
// set the tumbleweed's position to the point
// where it just barely appears on the screen
// to that it can start approaching the cowboy:
if (myLeft) {
setRefPixelPosition(myCurrentRightBound, myY);
move(-1, 0);
} else {
setRefPixelPosition(myCurrentLeftBound, myY);
move(1, 0);
}
} else {
//System.out.println("Tumbleweed.go-->visible");
}
return (retVal);
}
//---------------------------------------------------------
// graphics
/**
* move the tumbleweed back to its initial (inactive) state.
*/
void reset() {
setVisible(false);
myJumpedOver = false;
}
/**
* alter the tumbleweed image appropriately for this frame..
*
* @param left
* whether or not the player is moving left
* @return how much the score should change by after this advance.
*/
synchronized int advance(Cowboy cowboy, int tickCount, boolean left,
int currentLeftBound, int currentRightBound) {
int retVal = 0;
myCurrentLeftBound = currentLeftBound;
myCurrentRightBound = currentRightBound;
// if the tumbleweed goes outside of the display
// region, set it to invisible since it is
// no longer in use.
if ((getRefPixelX() - WIDTH >= currentRightBound) && (!myLeft)) {
setVisible(false);
}
if ((getRefPixelX() + WIDTH <= currentLeftBound) && myLeft) {
setVisible(false);
}
if (isVisible()) {
// when the tumbleweed is active, we advance the
// rolling animation to the next frame and then
// move the tumbleweed in the right direction across
// the screen.
if (tickCount % 2 == 0) { // slow the animation down a little
nextFrame();
}
if (myLeft) {
move(-3, 0);
// if the cowboy just passed the tumbleweed
// (without colliding with it) we increase the
// cowboy's score and set myJumpedOver to true
// so that no further points will be awarded
// for this tumbleweed until it goes offscreen
// and then is later reactivated:
if ((!myJumpedOver) && (getRefPixelX() < cowboy.getRefPixelX())) {
myJumpedOver = true;
retVal = cowboy.increaseScoreThisJump();
}
} else {
move(3, 0);
if ((!myJumpedOver)
&& (getRefPixelX() > cowboy.getRefPixelX()
+ Cowboy.WIDTH)) {
myJumpedOver = true;
retVal = cowboy.increaseScoreThisJump();
}
}
}
return (retVal);
}
}
/**
* This is the class that plays a little tune while you play the game. This
* version uses the Player and Control interfaces.
*
* @author Carol Hamer
*/
class ToneControlMusicMaker implements PlayerListener {
//---------------------------------------------------------
// fields
/**
* The player object that plays the tune.
*/
private Player myPlayer;
/**
* Whether or not the player wants to pause the music.
*/
private boolean myShouldPause;
/**
* Whether or not the system wants to pause the music.
*/
private boolean myGamePause;
/**
* The tune played by the game, stored as an array of bytes in BNF notation.
*/
private byte[] myTune = {
// first set the version
ToneControl.VERSION, 1,
// set the tempo
ToneControl.TEMPO, 30,
// define the first line of the song
ToneControl.BLOCK_START, 0, 69, 8, 69, 8, 69, 8, 71, 8, 73, 16, 71,
16, 69, 8, 73, 8, 71, 8, 71, 8, 69, 32, ToneControl.BLOCK_END, 0,
// define the other line of the song
ToneControl.BLOCK_START, 1, 71, 8, 71, 8, 71, 8, 71, 8, 66, 16, 66,
16, 71, 8, 69, 8, 68, 8, 66, 8, 64, 32, ToneControl.BLOCK_END, 1,
// play the song
ToneControl.PLAY_BLOCK, 0, ToneControl.PLAY_BLOCK, 0,
ToneControl.PLAY_BLOCK, 1, ToneControl.PLAY_BLOCK, 0, };
//----------------------------------------------------------
// actions
/**
* call this when the game pauses. This method does not affect the field
* myShouldPause because this method is called only when the system pauses
* the music, not when the player pauses the music.
*/
void pauseGame() {
try {
myGamePause = true;
myPlayer.stop();
// when the application pauses the game, resources
// are supposed to be released, so we close the
// player and throw it away.
myPlayer.close();
myPlayer = null;
} catch (Exception e) {
// the music isn't necessary, so we ignore exceptions.
}
}
/**
* call this when the game resumes. This method does not affect the field
* myShouldPause because this method is called only when the system reusmes
* the music, not when the player pauses the music.
*/
synchronized void resumeGame() {
try {
myGamePause = false;
if (!myShouldPause) {
// if the player is null, we create a new one.
if (myPlayer == null) {
start();
}
// start the music.
myPlayer.start();
}
} catch (Exception e) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -