Java手机游戏编程之MIDP图形设计篇03

瞬发一级寒冰箭

瞬发一级寒冰箭

2016-02-19 15:11

下面是个Java手机游戏编程之MIDP图形设计篇03教程,撑握了其技术要点,学起来就简单多了。赶紧跟着图老师小编一起来看看吧!

  5、GameScreen.java

  GameScreen使用了一个低级应用编程接口Canvas屏幕,和Image、Graphics类来绘制游戏面板、棋子,以及游戏的最终结果状态。要获取更详细的信息,请参阅各种绘画方法和drawCircle、drawCross、drawPiece、drawPlayerCursor、drawBoard等方法。这个屏幕使用MIDlet的quit回调方法来指示游戏结束。

  此屏幕可适应各种可用显示性能(高、宽、色彩等)。此外还要注意到可以使用四向导航键,也可以使用双向导航键来移动光标。

  它使用了封装了主游戏程序逻辑的Game类。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  

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 = 0x00000000;
private static final int WHITE = 0x00FFFFFF;
private static final int RED = 0x00FF0000;
private static final int BLUE = 0x000000FF;
private static final int NO_MOVE = -1;
private final TicTacToeMIDlet midlet;
private final Game game;
private final Command exitCommand;
private final Command newGameCommand;
private final Random random = new Random();
private int screenWidth, screenHeight;
private int boardCellSize, boardSize, boardTop, boardLeft;
private boolean playerIsCircle;
private boolean computerIsCircle;
private int preCursorPosition, cursorPosition;
private int computerMove = NO_MOVE;
private int playerMove = NO_MOVE;
private int computerGamesWonTally = 0;
private int playerGamesWonTally = 0;
private boolean isRestart;
public GameScreen(TicTacToeMIDlet midlet, boolean playerIsCircle) {
this.midlet = midlet;
this.playerIsCircle = playerIsCircle;
computerIsCircle = !playerIsCircle;
game = new Game(random);
initializeBoard();
// configure Screen commands
exitCommand = new Command("Exit", Command.EXIT, 1);
newGameCommand = new Command("New", Command.SCREEN, 2);
addCommand(exitCommand);
addCommand(newGameCommand);
setCommandListener(this);
// begin the game play initialize();
}
// Initialize the Game and Game screen. Also used for game restarts.
private void initialize() {
game.initialize();
preCursorPosition = cursorPosition = 0;
playerMove = NO_MOVE;
boolean computerFirst = ((random.nextInt() & 1) == 0);
if (computerFirst) {
computerMove = game.makeComputerMove();
}
else
{
computerMove = 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) {
// clean the canvas
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 = null;
if(game.isComputerWinner()) {
statusMsg = "I win !";
computerGamesWonTally++;
}
else if (game.isPlayerWinner()) {
statusMsg = "You win";
playerGamesWonTally++;
}
else {
statusMsg = "Stalemate";
}
String tallyMsg = "You:" + playerGamesWonTally + " Me:" + computerGamesWonTally;
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
int strHeight = font.getHeight();
int statusMsgWidth = font.stringWidth(statusMsg);
int tallyMsgWidth = font.stringWidth(tallyMsg);
int strWidth = tallyMsgWidth;
if (statusMsgWidth tallyMsgWidth)
{
strWidth = statusMsgWidth;
}
// Get the
{
x, y
}
position for painting the strings. int x = (screenWidth - strWidth) / 2;
x = x 0 ? 0 : x;
int y = (screenHeight - 2 * strHeight) / 2;
y = y 0 ? 0 : y;
// clean the canvas
g.setColor(WHITE);
g.fillRect(0, 0, screenWidth, screenHeight);
// paint the strings' text
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) {
// can't continue playing until the player restarts
if (game.isGameOver()) {
return;
}
int gameAction = getGameAction(keyCode);
switch (gameAction) {
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;
default: break;
}
}
private void doPlayerMove() {
if (game.isFree(cursorPosition)) {
// player move game.
makePlayerMove(cursorPosition);
playerMove = cursorPosition;
// computer move
if (!game.isGameOver()) {
computerMove = game.makeComputerMove();
}
repaint();
}
}
private void doMoveCursor(int dx, int dy) {
int newCursorPosition = cursorPosition + dx + 3 * dy;
if ((newCursorPosition = 0) && (newCursorPosition 9))
{
preCursorPosition = cursorPosition;
cursorPosition = newCursorPosition;
repaint();
}
}
// Draw a CIRCLE or CROSS piece on the board
private void drawPiece(Graphics g, boolean isCircle, int pos) {
int x = ((pos % 3) * boardCellSize) + 3;
int y = ((pos / 3) * boardCellSize) + 3;
if (isCircle) {
drawCircle(g, x, y);
}
else {
drawCross(g, x, y);
}
}
// Draw blue CIRCLE onto the board image
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 - 4 - 8, boardCellSize - 4 - 8, 0, 360);
}
// Draw red CROSS onto the board image
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 - 4 - 4 + i + boardLeft, y + boardCellSize - 5 + boardTop);
g.drawLine(x + 1 + i + boardLeft, y + boardCellSize - 5 + boardTop, x + boardCellSize - 4 - 4 + i + boardLeft, y + boardTop);
}
}
// Visually indicates a Player selected square on the board image
private void drawCursor(Graphics g) {
// draw cursor at selected Player square.
g.setColor(WHITE);
g.drawRect(((preCursorPosition % 3) * boardCellSize) + 2 + boardLeft, ((preCursorPosition/3) * boardCellSize) + 2 + boardTop, boardCellSize - 3, boardCellSize - 3);
// draw cursor at selected Player square.
g.setColor(BLACK);
g.drawRect(((cursorPosition % 3) * boardCellSize) + 2 + boardLeft, ((cursorPosition/3) * boardCellSize) + 2 + boardTop, boardCellSize - 3, boardCellSize - 3);
}
private void drawBoard(Graphics g) {
// clean the board
g.setColor(WHITE);
g.fillRect(0, 0, screenWidth, screenHeight);
// draw the board
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

  这个类封装了九宫格游戏的主要的游戏程序逻辑。前面我们也说过,游戏程序逻辑本身并不在本例程重点讨论的范围之内,本文主要是介绍MIDP图形编程的基础知识。游戏程序逻辑的WINS数组部分来自http://java.sun.com/applets/jdk/1.0/demo/TicTacToe/TicTacToe.java 这个经典例程。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  注意游戏程序逻辑是独立于游戏用户界面的(参见类GameScreen),并且可以使用其它实现方法替代。

  

package example.tictactoe;
import java.util.Random;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
// The game logic for TicTacToe
class Game {
private static final int[] WINS = {
// horizontals
bit(0) | bit(1) | bit(2),
bit(3) | bit(4) | bit(5),
bit(6) | bit(7) | bit(8),
// verticals
bit(0) | bit(3) | bit(6),
bit(1) | bit(4) | bit(7),
bit(2) | bit(5) | bit(8),
// diagonals
bit(0) | bit(4) | bit(8),
bit(2) | bit(4) | bit(6) }
;
private static final int DRAWN_GAME = bit(0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5) | bit(6) | bit(7) | bit(8);
private int playerState;
private int computerState;
private Random random;
Game(Random random) {
this.random = random;
initialize();
}
void initialize() {
playerState = 0;
computerState = 0;
}
boolean isFree(int position) {
int bit = bit(position);
return (((playerState & bit) == 0) && ((computerState & bit) == 0));
}
// The 'Contract' is that caller will always make valid moves.
// We don't check that it's the player's turn.
void makePlayerMove(int position) {
playerState |= bit(position);
}
// The 'Contract' is that we will be called only when there is still
// at least one free square.
int makeComputerMove() {
int move = getWinningComputerMove();
if (move == -1) {
// can't win
move = getRequiredBlockingComputerMove();
if (move == -1) {
// don't need to block
move = getRandomComputerMove();
}
}
computerState |= bit(move);
return move;
}
boolean isGameOver() {
return isPlayerWinner() | isComputerWinner() | isGameDrawn();
}
boolean isPlayerWinner() {
return isWin(playerState);
}
boolean isComputerWinner() {
return isWin(computerState);
}
boolean isGameDrawn() {
return (playerState | computerState) == DRAWN_GAME;
}
// Return a winning move if there is at least one, otherwise return -1
private int getWinningComputerMove() {
int move = -1;
for (int i = 0;
i 9;
++i) {
if (isFree(i) && isWin(computerState | bit(i))) {
move = i;
break;
}
}
return move;
}
// Return a required blocking move if there is at least one (more
// than one and we've inevitably lost), otherwise return -1
private int getRequiredBlockingComputerMove() {
int move = -1;
for (int i = 0;
i 9;
++i) {
if (isFree(i) && isWin(playerState | bit(i))) {
move = i;
break;
}
}
return move;
}
// Return a random move in a free square, // or return -1 if none are available private int getRandomComputerMove() {
int move = -1;
// determine how many possible moves there are int numFreeSquares = 0;
for (int i = 0;
i 9;
++i) {
if (isFree(i)) {
numFreeSquares++;
}
}
// if there is at least one possible move, pick randomly
if (numFreeSquares 0) {
// shift twice to get rid of sign bit, then modulo numFreeSquares
int pick = ((random.nextInt()1)1) % numFreeSquares;
// now find the chosen free square by counting pick down to zero
for (int i = 0;
i 9;
++i) {
if (isFree(i)) {
if (pick == 0) {
move = i;
break;
}
pick--;
}
}
}
return move;
}
private static boolean isWin(int state) {
boolean isWinner = false;
for (int i = 0;
i WINS.length;
++i) {
if ((state & WINS[i]) == WINS[i]) {
isWinner = true;
break;
}
}
return isWinner;
}
private static int bit(int i) {
return 1 i;
}
}

  7、TicTacToe.jad

  下面是九宫格MIDlet的应用程序描述文件。

  

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

展开更多 50%)
分享

猜你喜欢

Java手机游戏编程之MIDP图形设计篇03

编程语言 网络编程
Java手机游戏编程之MIDP图形设计篇03

Java手机游戏编程之MIDP图形设计篇02

编程语言 网络编程
Java手机游戏编程之MIDP图形设计篇02

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Java手机游戏编程之MIDP图形设计篇01

编程语言 网络编程
Java手机游戏编程之MIDP图形设计篇01

Java与XML联合编程之DOM篇

编程语言 网络编程
Java与XML联合编程之DOM篇

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

几个图形(03)

编程语言 网络编程
几个图形(03)

Java网络编程之传输控制协议(一)

编程语言 网络编程
Java网络编程之传输控制协议(一)

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Excel中IPmt函数用法

Excel中IPmt函数用法

剖析JSP与XML的交互编程技巧上

剖析JSP与XML的交互编程技巧上
下拉加载更多内容 ↓