📄 pushpuzzlecanvas.java
字号:
// Create a mutable image and initialize
themeImage = Image.createImage(cell * 5, cell);
Graphics g = themeImage.getGraphics();
g.setColor(GroundColor0);
g.fillRect((TILE_GROUND - 1 ) * cell, 0, cell*TILE_PUSHER, cell);
g.setColor(PacketColor0);
g.fillRect((TILE_PACKET- 1 ) * cell + 1, 1, cell - 2, cell - 2);
g.setColor(StoreColor0);
g.drawRect((TILE_STORE- 1 ) * cell + 1, 1, cell - 2, cell - 2);
g.setColor(WallColor0);
g.fillRect((TILE_WALL- 1 ) * cell, 0, cell, cell);
g.setColor(PusherColor0);
g.fillArc((TILE_PUSHER- 1 ) * cell, 0, cell, cell, 0, 360);
}
/**
* Setup the theme by reading the images and setting up
* the sprite and picking the tile size.
* Uses the current theme index.
* If the image with the current index can't be found
* retry with theme = 0.
* @param image containing all the frames used for the board.
*/
private void setupTheme() {
if (sprite != null) {
layers.remove(sprite);
sprite = null;
}
if (theme > 0) {
try {
StringBuffer name =
new StringBuffer("/example/pushpuzzle2/images/Theme-");
name.append(theme);
name.append(".png");
themeImage = Image.createImage(name.toString());
// Cells are square using the minimum of the width and height
int h = themeImage.getHeight();
int w = themeImage.getWidth();
cell = (w < h) ? w : h;
} catch (IOException e) {
theme = 0;
setupTheme0();
}
} else {
setupTheme0();
}
sprite = new Sprite(themeImage, cell, cell);
sprite.defineReferencePixel(cell/2, cell/2);
int seq[] = new int[] {TILE_PUSHER-1};
sprite.setFrameSequence(seq);
layers.insert(sprite, 0);
}
/**
* Return the Screen to display scores.
* It returns a screen with the current scores.
* @return a screen initialized with the current score information.
*/
public Screen getScoreScreen() {
Form scoreForm = null; // Temp until form can do setItem
int currPushes = board.getPushes();
int bestPushes = score.getPushes();
int currMoves = board.getMoves();
int bestMoves = score.getMoves();
boolean newbest = solved &&
(bestPushes == 0 || currPushes < bestPushes);
scoreForm = new Form(null);
scoreForm.append(new StringItem(
newbest ? "New Best:\n" : "Current:\n",
currPushes + " pushes\n" +
currMoves + " moves"));
scoreForm.append(new StringItem(
newbest ? "Old Best:\n" : "Best:\n",
bestPushes + " pushes\n" +
bestMoves + " moves"));
String title = "Scores";
if (newbest) {
title = "Congratulations";
}
scoreForm.setTitle(title);
return scoreForm;
}
/**
* Handle a repeated arrow keys as though it were another press.
* @param keyCode the key pressed.
*/
protected void keyRepeated(int keyCode) {
int action = getGameAction(keyCode);
switch (action) {
case Canvas.LEFT:
case Canvas.RIGHT:
case Canvas.UP:
case Canvas.DOWN:
keyPressed(keyCode);
break;
default:
break;
}
}
/**
* Handle a single key event.
* The LEFT, RIGHT, UP, and DOWN keys are used to
* move the pusher within the Board.
* Other keys are ignored and have no effect.
* Repaint the screen on every action key.
*/
protected void keyPressed(int keyCode) {
boolean newlySolved = false;
// Protect the data from changing during painting.
synchronized (board) {
cancelTo();
int action = getGameAction(keyCode);
int move = 0;
switch (action) {
case Canvas.LEFT:
move = Board.LEFT;
break;
case Canvas.RIGHT:
move = Board.RIGHT;
break;
case Canvas.DOWN:
move = Board.DOWN;
break;
case Canvas.UP:
move = Board.UP;
break;
// case 0: // Ignore keycode that don't map to actions.
default:
return;
}
// Tell the board to move the piece
int stored = board.getStored();
int dir = board.move(move);
if (stored < board.getStored()) {
// Play a note if a packet hit the spot.
play(storedTune);
}
int pos = board.getPusherLocation();
updateTilesNear(pos, dir);
updateSprite(dir);
} // End of synchronization on the Board.
}
/**
* Update the scores for the current level if it has
* been solved and the scores are better than before.
*/
private void updateScores() {
if (!solved)
return;
int sp = score.getPushes();
int bp = board.getPushes();
int bm = board.getMoves();
/*
* Update the scores. If the score for this level is lower
* than the last recorded score save the lower scores.
*/
if (sp == 0 || bp < sp) {
score.setLevelScore(bp, bm);
}
}
/**
* Cancel the animation.
*/
private void cancelTo() {
targetx = -1;
targety = -1;
}
/**
* Called when the pointer is pressed.
* Record the target for the pusher.
* @param x location in the Canvas
* @param y location in the Canvas
*/
protected void pointerPressed(int x, int y) {
targetx = (x - tiles.getX()) / cell;
targety = (y - tiles.getY()) / cell;
}
/**
* Add a listener to notify when the level is solved.
* The listener is send a List.SELECT_COMMAND when the
* level is solved.
* @param l the object implementing interface CommandListener
*/
public void setCommandListener(CommandListener l) {
super.setCommandListener(l);
listener = l;
}
/**
* Update the Sprite location from the board supplied position
* @param dir the sprite is moving
*/
private void updateSprite(int dir) {
int loc = board.getPusherLocation();
int x = (loc & 0x7fff) * cell;
int y = ((loc >> 16) & 0x7fff) * cell;
// Update sprite location
sprite.setPosition(tiles.getX() + x, tiles.getY() + y);
dir = Board.RIGHT; // BUG: Graphics.drawRegion doesn't do xofrm
switch (dir & 0x03) {
case Board.LEFT:
sprite.setTransform(Sprite.TRANS_ROT180);
break;
case Board.UP:
sprite.setTransform(Sprite.TRANS_ROT90);
break;
case Board.DOWN:
sprite.setTransform(Sprite.TRANS_ROT270);
break;
default:
sprite.setTransform(Sprite.TRANS_NONE);
break;
}
}
/**
* Queue a repaint for an area around the specified location.
* @param loc an encoded location from Board.getPusherLocation
* @param dir that the pusher moved and flag if it pushed a packet
*/
void updateTilesNear(int loc, int dir) {
int x = loc & 0x7fff;
int y = (loc >> 16) & 0x7fff;
// Update cells if any were moved
if (dir >= 0 && ((dir & Board.MOVEPACKET) != 0)) {
updateTile(x, y);
updateTile(x+1, y);
updateTile(x-1, y);
updateTile(x, y+1);
updateTile(x, y-1);
}
}
/**
* Paint the contents of the Canvas.
* The clip rectangle of the canvas is retrieved and used
* to determine which cells of the board should be repainted.
* @param g Graphics context to paint to.
*/
public void paint(Graphics g) {
flushGraphics();
}
/**
* The canvas is being displayed.
* Stop the event handling and animation thread.
*/
protected void showNotify() {
thread = new Thread(this);
thread.start();
}
/**
* The canvas is being removed from the screen.
* Stop the event handling and animation thread.
*/
protected void hideNotify() {
thread = null;
}
/**
* The main event processor. Events are polled and
* actions taken based on the directional events.
*/
public void run() {
Graphics g = getGraphics(); // Of the buffered screen image
Thread mythread = Thread.currentThread();
// Loop handling events
while (mythread == thread) {
try { // Start of exception handler
boolean newlySolved = false;
if (!solved && board.solved()) {
newlySolved = solved = true;
play(solvedTune);
}
if (newlySolved && listener != null) {
listener.commandAction(List.SELECT_COMMAND, this);
}
if (targetx >= 0 && targety >= 0) {
int dir = board.runTo(targetx, targety, 1);
int pos = board.getPusherLocation();
if (dir < 0) {
targetx = targety = -1; // Cancel target
} else {
updateTilesNear(pos, dir);
updateSprite(dir);
}
}
// Check that the pusher is not to close to the edge
int loc = board.getPusherLocation();
int x = (loc & 0x7fff) * cell;
int y = ((loc >> 16) & 0x7fff) * cell;
int lx = tiles.getX();
int ly = tiles.getY();
int panScale = cell / 4;
if (panScale < 1)
panScale = 1;
// If the sprite is too near the edge (or off) pan
if (lx + x > width - cell - cell ) {
tiles.move(-panScale, 0);
sprite.move(-panScale, 0);
}
if (lx + x < cell) {
tiles.move(panScale, 0);
sprite.move(panScale, 0);
}
if (ly + y > height - cell - cell) {
tiles.move(0, -panScale);
sprite.move(0, -panScale);
}
if (ly + y < cell) {
tiles.move(0, panScale);
sprite.move(0, panScale);
}
// Draw all the layers and flush
layers.paint(g, 0, 0);
if (mythread == thread) {
flushGraphics();
}
// g.drawString("PushPuzzle Level " + level, 0, height,
// Graphics.BOTTOM|Graphics.LEFT);
try {
mythread.sleep(PanRate);
} catch (java.lang.InterruptedException e) {
// Ignore
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Play the simple tune supplied.
*/
void play(byte[] tune) {
try {
if (tonePlayer == null) {
// First time open the tonePlayer
tonePlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
tonePlayer.realize();
toneControl = (ToneControl)tonePlayer.getControl("javax.microedition.media.control.ToneControl");
}
tonePlayer.deallocate();
toneControl.setSequence(tune);
tonePlayer.start();
} catch (Exception ex){
ex.printStackTrace();
}
}
/*
* Close the tune player and release resources.
*/
void closePlayer() {
if ( tonePlayer != null ) {
toneControl = null;
tonePlayer.close();
tonePlayer = null;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -