首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

Java 手機遊戲開發:MIDP 圖形設計實戰(下)

     編輯:J2ME

5. GameScreen.java 完整實現

GameScreen 繼承 Canvas,使用 Image、Graphics 繪製棋盤、棋子、結果。關鍵點:

  • 適配各種螢幕尺寸、色彩能力
  • 支援四向與雙向導航鍵移動光標
  • 封裝遊戲邏輯於獨立 Game 類
package example.tictactoe;
import java.util.Random;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

class GameScreen extends Canvas implements CommandListener {
    private static final int BLACK = 0x000000, WHITE = 0x00FFFFFF, RED = 0x00FF0000, BLUE = 0x000000FF;
    private static final int NO_MOVE = -1;
    private final TicTacToeMIDlet midlet;
    private final Game game;
    private final Command exitCommand, newGameCommand;
    private final Random random = new Random();
    private int screenWidth, screenHeight, boardCellSize, boardSize, boardTop, boardLeft;
    private boolean playerIsCircle, computerIsCircle;
    private int preCursorPosition, cursorPosition, computerMove = NO_MOVE, playerMove = NO_MOVE;
    private int computerGamesWonTally = 0, playerGamesWonTally = 0;
    private boolean isRestart;

    public GameScreen(TicTacToeMIDlet midlet, boolean playerIsCircle) {
        this.midlet = midlet; this.playerIsCircle = playerIsCircle;
        computerIsCircle = !playerIsCircle;
        game = new Game(random);
        initializeBoard();
        exitCommand = new Command("Exit", Command.EXIT, 1);
        newGameCommand = new Command("New", Command.SCREEN, 2);
        addCommand(exitCommand); addCommand(newGameCommand); setCommandListener(this);
        initialize();
    }
    private void initialize() {
        game.initialize(); preCursorPosition = cursorPosition = 0; playerMove = NO_MOVE;
        boolean computerFirst = ((random.nextInt() & 1) == 0);
        computerMove = computerFirst ? game.makeComputerMove() : NO_MOVE;
        isRestart = true; repaint();
    }
    public void paint(Graphics g) {
        if (game.isGameOver()) paintGameOver(g); else paintGame(g);
    }
    private void paintGame(Graphics g) {
        if (isRestart) { g.setColor(WHITE); g.fillRect(0,0,screenWidth,screenHeight); drawBoard(g); isRestart=false; }
        drawCursor(g);
        if (playerMove != NO_MOVE) drawPiece(g, playerIsCircle, playerMove);
        if (computerMove != NO_MOVE) drawPiece(g, computerIsCircle, computerMove);
    }
    private void paintGameOver(Graphics g) {
        String statusMsg, tallyMsg = "You:" + playerGamesWonTally + " Me:" + computerGamesWonTally;
        if (game.isComputerWinner()) { statusMsg = "I win!"; computerGamesWonTally++; }
        else if (game.isPlayerWinner()) { statusMsg = "You win"; playerGamesWonTally++; }
        else statusMsg = "Stalemate";
        Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        int strHeight = font.getHeight(), statusW = font.stringWidth(statusMsg), tallyW = font.stringWidth(tallyMsg);
        int strWidth = Math.max(statusW, tallyW);
        int x = Math.max(0, (screenWidth - strWidth) / 2);
        int y = Math.max(0, (screenHeight - 2 * strHeight) / 2);
        g.setColor(WHITE); g.fillRect(0,0,screenWidth,screenHeight);
        g.setColor(BLACK);
        g.drawString(statusMsg, x, y, Graphics.TOP | Graphics.LEFT);
        g.drawString(tallyMsg, x, y + 1 + strHeight, Graphics.TOP | Graphics.LEFT);
    }
    public void commandAction(Command c, Displayable d) {
        if (c == exitCommand) midlet.quit(); else if (c == newGameCommand) initialize();
    }
    private void initializeBoard() {
        screenWidth = getWidth(); screenHeight = getHeight();
        if (screenWidth > screenHeight) {
            boardCellSize = (screenHeight - 2) / 3;
            boardLeft = (screenWidth - boardCellSize * 3) / 2; boardTop = 1;
        } else {
            boardCellSize = (screenWidth - 2) / 3;
            boardLeft = 1; boardTop = (screenHeight - boardCellSize * 3) / 2;
        }
    }
    protected void keyPressed(int keyCode) {
        if (game.isGameOver()) return;
        int action = getGameAction(keyCode);
        switch (action) {
            case FIRE: doPlayerMove(); break;
            case RIGHT: doMoveCursor(1,0); break;
            case DOWN: doMoveCursor(0,1); break;
            case LEFT: doMoveCursor(-1,0); break;
            case UP: doMoveCursor(0,-1); break;
        }
    }
    private void doPlayerMove() {
        if (game.isFree(cursorPosition)) {
            makePlayerMove(cursorPosition); playerMove = cursorPosition;
            if (!game.isGameOver()) computerMove = game.makeComputerMove();
            repaint();
        }
    }
    private void doMoveCursor(int dx, int dy) {
        int newPos = cursorPosition + dx + 3 * dy;
        if (newPos >= 0 && newPos < 9) { preCursorPosition = cursorPosition; cursorPosition = newPos; repaint(); }
    }
    private void drawPiece(Graphics g, boolean isCircle, int pos) {
        int x = (pos % 3) * boardCellSize + 3, y = (pos / 3) * boardCellSize + 3;
        if (isCircle) drawCircle(g, x, y); else drawCross(g, x, y);
    }
    private void drawCircle(Graphics g, int x, int y) {
        g.setColor(BLUE);
        g.fillArc(x+boardLeft, y+boardTop, boardCellSize-4, boardCellSize-4, 0, 360);
        g.setColor(WHITE);
        g.fillArc(x+4+boardLeft, y+4+boardTop, boardCellSize-12, boardCellSize-12, 0, 360);
    }
    private void drawCross(Graphics g, int x, int y) {
        g.setColor(RED);
        for (int i=0;i<4;i++) {
            g.drawLine(x+1+i+boardLeft, y+boardTop, x+boardCellSize-8+i+boardLeft, y+boardCellSize-5+boardTop);
            g.drawLine(x+1+i+boardLeft, y+boardCellSize-5+boardTop, x+boardCellSize-8+i+boardLeft, y+boardTop);
        }
    }
    private void drawCursor(Graphics g) {
        g.setColor(WHITE);
        g.drawRect((preCursorPosition%3)*boardCellSize+2+boardLeft, (preCursorPosition/3)*boardCellSize+2+boardTop, boardCellSize-3, boardCellSize-3);
        g.setColor(BLACK);
        g.drawRect((cursorPosition%3)*boardCellSize+2+boardLeft, (cursorPosition/3)*boardCellSize+2+boardTop, boardCellSize-3, boardCellSize-3);
    }
    private void drawBoard(Graphics g) {
        g.setColor(WHITE); g.fillRect(0,0,screenWidth,screenHeight);
        g.setColor(BLACK);
        for (int i=0;i<4;i++) {
            g.fillRect(boardLeft, boardCellSize*i+boardTop, boardCellSize*3+2, 2);
            g.fillRect(boardCellSize*i+boardLeft, boardTop, 2, boardCellSize*3);
        }
    }
}

6. Game.java 遊戲邏輯封裝

獨立於 UI 的邏輯類,使用位運算高效判定勝負:

package example.tictactoe;
import java.util.Random;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

class Game {
    private static final int[] WINS = {
        0x007, 0x038, 0x1C0, 0x124, 0x092, 0x049, 0x111, 0x054
    };
    private static final int DRAWN_GAME = 0x1FF;
    private int playerState, computerState; private Random random;
    Game(Random random) { this.random = random; initialize(); }
    void initialize() { playerState = 0; computerState = 0; }
    boolean isFree(int pos) { int bit = 1<>>1) % free;
        for (int i=0;i<9;i++) if (isFree(i)) { if (pick==0) return i; pick--; }
        return -1;
    }
    private static boolean isWin(int state) {
        for (int w: WINS) if ((state & w) == w) return true; return false;
    }
}

7. 應用描述文件 TicTacToe.jad

MIDlet-Name: TicTacToe
MIDlet-Vendor: Forum Nokia
MIDlet-Version: 1.1.1
MIDlet-Jar-Size: 11409
MIDlet-Jar-URL: TicTacToe.jar
MIDlet-1: TicTacToe, /tictactoe.png, example.tictactoe.TicTacToeMIDlet
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved