📄 pushpuzzlecanvas.java
字号:
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/pushpuzzle/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) { /* * After MIDP 2.0 clarification was implemented, keyRepeated() * method is normally called by system immediately after keyPressed() * method is called thus the keyRepeated() should not call keyPressed() * here for now. * 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) { System.out.println(ex.getMessage()); } } /* * 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 + -