Author: yinowl January 2005 Introduction This is the first work after my learning j2me introductory course, this is a very simple work (no computer AI, only two people play against), and now I have written in this time of design ideas Article document, I hope to get a friend who wants to get the J2ME in J2ME process, button response, drawing, etc., and I hope that everyone will point out errors and improved procedures. Note that the code lists the explanation of the "J2ME Game Programming" book, and the relevant code is given according to the programming function, and the code of a file will be given according to the function, and the article is over, the code is complete. This is different from the code in the usual book, which is all given in the unit. I think this more helps you understand a program from design to the last finish. Design data structure: Because Wuzi is a two-dimensional chess game, all the first thought is to define a chest class to represent the chess pieces, and chesses has a Boolean type variable isplayer1 to distinguish which players are under, then use a chess type Two-dimensional arrays to include all chess pieces on the board. Considering the limited resources of mobile devices, minimize system resource occupation, I consider that you don't generate every object of an array after the array is established, but put every chess pieces in the game's progress, that is, When the game is carried out, the player generates the object of the chess pieces every step in the array, which avoids the chess pieces that have not yet, take up the system memory process at the beginning: the game is drawn according to the two-dimensional array of chess pieces. After players play chess, the program modifies the array corresponding position, sets the isplayer1 value, and resets (repaint), update the board interface. Due to the simple function of the game, in order to make the operation of the game as easy as possible, I don't enter the design menu when the game is entitled, but directly on the battle, in the battle interface, set the restart and exit button. That is, running, just play, one button starts, one key, one button exits. Player handover: There is a problem with the chess game. It is to pay attention to the presentation. In order to save the interface space, simplify the game interface, I added a three pixel wide box outside the chessboard, the color of the box is currently the current The color of the chess party, as shown: Application Class: GoBang.java Next, start completing every class in the game, first is a MIDlet class. The Gobang class inherits from the MIDLET class, the Application Manager for connecting the device, notifies the start, pause, and destruction of the game by methods startapp, pauseapp, design, to notify the game. The source code is as follows:
Package com.occo.j2me.game.gobang;
Import javax.microedition.lcdui.display;
Import javax.microedition.midlet.midlet; public class gobang extends MIDlet {Gobangcanvas Gobang; / / Define Game Interface Canvas Class Gobangcanvas Object Gobang Public GoBang () {
Super ();
Gobang = New GoBangcanvas (this); // Generate objects of Gobangcanvas class Gobang
} Protected void startapp () {
Display.getdisplay (this) .Setcurrent (Gobang);
// Pain the game on the screen Gobang
} Protected void pauseapp () {
} Protected void destroyApp (boolean arg0) {
}}} Game Interface Class: Gobangcanvas.javagobangcanvas class is the core class of the game, inherits from CANVAS, such will complete all functions such as logic, drawing, control, interaction, etc., such framework code as follows:
Package com.occo.j2me.game.gobang; import javax.microedition.lcdui.canvas;
Import javax.microedition.lcdui.command;
Import javax.microedition.lcdui.commandlistener;
Import javax.microedition.lcdui.displayable;
Import javax.microedition.lcdui.graphics; public class gobangcanvas extends canvas imports CommandListener {Protected GoBang Gobang;
Public Gobangcanvas () {
} Public gobangcanvas (gobang gobang) {
THIS.GOBANG = GoBang;
} Protected void paint (graphics g) {
}}} Chess: Chess.java defines a piece of chess pieces, every chess piece on the board corresponds to a chesses object, the entire chessboard is a two-dimensional array of chesses type, the source code is as follows:
Package com.occo.j2me.game.gobang; public class chesses {boolean isplayer1;
Public chesses () {
} Public chesses (boolean isplayer1) {
THIS.IsPlayer1 = isplayer1;
}} Add graphic image to now, we have completed a basic framework of the game. Next, we can draw some initial settings for each part of the game, add some initial settings of the five daughter, add the following code to GoBangcanvas.java
...
INT Empty; // Game interface to leave the blank on the edge of the screen
Int canvasw, canvash; // long and wide
INT CHESSLENGTH; // Diameter of the chess pieces
Int Chessmaplength, ChessmapGrid, ChessGridLength
// Board of the chessboard, the number of chessboards, the width per grid
INT CHESSMAPX, CHESSMAPY; / / Chessboard left upper corner X, Y coordinate
INT selectedX, selectedEDY; // Select the X, Y position on the board pattern
Boolean isplayer1; // Is it a player 1
Chess [] Chesses; // chess pieces array
Boolean newgame; // Is it a new game Public Gobangcanvas (GoBang Gobang) {
Newgame = true;
EMPTY = 10;
CANVASW = getWidth () - EMPTY; Canvash = GetHeight () - EMPTY
Chessmapgrid = 15;
Chess = new chesses [chessmapgrid 1] [chessmapgrid 1];
IF (canvasw> canvash) {
Chessmaplength = canvash-canvash% chessmapgrid;
Chessmapx = (canvasw-chessmaplength) / 2 EMPTY / 2; chessmapy = (canvash% chessmapgrid) / 2 EMPTY / 2;
}
Else {
Chessmaplength = canvasw-canvasw% chessmapgrid;
Chessmapx = (canvasw% chessmapgrid) / 2 EMPTY / 2;
ChessMapy = (canvash-chessmaplength) / 2 EMPTY / 2;
}
ChessGridlength = chessmaplength / chessmapgrid;
Chesslength = chessgridLength-1;
SELECTEDX = SELECTEDY = CHESSMAPGRID / 2;
Isplayer1 = true;
} The first thing to draw is the chessboard. The chessboard is square, but the screen has a rectangle, so the board is long to press the short side, but the short side is not necessarily the number of checkerboard lattice, so the board side length = Short side - short The number of lattices is in the case of the chessboard, so it is necessary to divide the blank (EMPTY) by 2, the following is the code of the painting board:
Protected void PaintMap (Graphics g) {
For (int i = 0; i For (int J = 0; j G.SetColor (128, 128, 128); g.drawRect (Chessmapx J * ChessGridlength, ChessMapy i * chessgridlength, Chessgridlength, ChessGridlength; } } } Then draw the selection box, note: Select the selectedX, SELECTEDY is not the X, Y coordinates on the canvas, but in the position of the chess pieces, the source code is as follows: Protected Void PaintSelected (Graphics G) { G.SetColor (0,0,255); g.drawRect (Chessmapx Selectedx * ChessGridLength-ChessGridLength / 2, ChessMapy Selectedy * ChessGridLength-ChessGridLength / 2, Chessgridlength, ChessGridlength; } Then the chess pieces that have been drawn according to the two-dimensional number of chess pieces. Every time the player will modify the array, you can draw it when you re-draw, the source code is as follows: Protected void Paintchesses (graphics g) { For (INT i = 0; i <= chessmapgrid; i ) { For (int J = 0; j <= chessmapgrid; j ) { IF (chesses [i] [j]! = null) { IF (chesses [i] [j] .isplayer1) G.SetColor (255, 255, 255); Else G.SetColor (255, 0, 0); G.fillarc (Chessmapx J * ChessGridLength-Chesslength / 2, ChessMapy i * chessgridlength-insplayne / 2, Chesslength, Chesslength, 0, 360); } } } } Finally, the player prompt box is drawn, and the drawing of all parts is summarized in the Paint () method, pay attention to the order of drawing, obvious, you should draw the prompt box - Chessboard - Select box - Chess: Protected Void PaintPlayer (Graphics G, Boolean Isplayer1) { IF (Isplayer1) G.SetColor (255, 255, 255); Else G.SetColor (255, 0, 0); G. DrawRect (1, 1, getWidth () - 2, GetHeight () - 2); G.drawRect (2, 2, getwidth () - 4, getHeight () - 4); G.drawRect (3, 3, getWidth () - 6, GetHeight () - 6); } Protected Void Paint (Graphics G) { g.setcolor (0x00000000); G.fillRect (0, 0, getWidth (), getHeight ()); PaintPlayer (g, isplayer1); PaintMap (g); PaintSelected (g); PainTchesses (g); } Responding to the player's operation Next, you should add a command button and game operation control. We need two buttons in the game, restart and exit, and must also receive the operation of the player control selection box and chess, add code to GoBangcanvas.Java: Command exitcmd; Command RestartCmd; Public GoBangcanvas (Gobang Gobang) { ... RestartCMD = New Command ("Restart", Command.Screen, 0); EXITCMD = New Command ("Exit", Command.exit, 0); Addcommand (RestartCMD); Addcommand (exitcmd); SetcommandListener (this); Private vidinit () { IF (newgame) { Chess = new chesses [chessmapgrid 1] [chessmapgrid 1]; Isplayer1 = true; SELECTEDX = SELECTEDY = CHESSMAPGRID / 2; } } Public void CommandAction (Command C, Displayable D) { IF (c == exitcmd) { Gobang.destroyApp (False); GoBang.NotifyDestroyed (); } else if (c == restartCMD) { Init (); // Initialize the chessboard, empty the chessboard, restart the game Repaint (); } } Protected synchronized void keypressed (int keycode) { Int action = getGameAction (keycode); IF (Action == canvas.left) { SELECTEDX = (- SELECTEDX CHESSMAPGRID 1)% (CgestmapGrid 1); } Else if (action == canvas.right) { SelectEdx = ( selectedX)% (CHESSMAPGRID 1); } Else if (action == canvas.up) { SELECTEDY = (- SELECTEDY CHESSMAPGRID 1)% (checkmapgrid 1);} Else IF (action == canvas.down) { SELECTEDY = ( selectedy)% (CgestmapGrid 1); } Else IF (action == canvas.fire) { IF (chesses [selectedy] [selectedX] == null) { Chess [selectedy] [selectedX] = new chesses (this.isplayer1); // checkwin (); this.isplayer1 =! this.isplayer1; // Switch the chess party } } Repaint (); } private void checkwin () { } To this, all the drawings of the game give it, one thing to point out, double buffer display technology, because some mobile phones have directly built-in double buffer, here we are not detailed, interested, you can consult the relevant documentation. The game will finally say that it is to determine the game's losing, in the game's response to the player operation section, I have a way to checkwin (), you can think about the calculation method to determine the game's loss, don't don't care, because it is two Personal categories will look at the game and lose. The game will win the final say that it is to determine the game's loss. My idea is that each time player pace (5), judge the losing wins of the chess game, then use an Alert to show the current score, return to the new game. The logic of judgment is, in the current under the top of the chess pieces, 90/270 degrees, 45/225 degrees, 135/315 degrees four directions, respectively, respectively, according to the near-to-far order, 5 chess pieces Whether it is a chess piece of the chess party, if it is accumulated to a variable, if "NO" before arriving 5, the determination of this direction or this angle is stopped, and the variable is started 1 (the current The chess pieces are definitely the chess pieces after the current chess) and carry out the next direction or angle. When it is judged whether it is the current part, the ISPLAYER1 variable of the current IsPlayer1 variable and the chess pieces are used. The source code is as follows: INT Player1win, Player2win; Protected synchronized void keypressed (int keycode) { ... Else IF (action == canvas.fire) { IF (chesses [selectedy] [selectedX] == null) { Chess [selectedy] [selectedX] = new chesses (this.isplayer1); IF (Checkwin ()) { String Winner; IF (isplayer1) { Winner = "Bai Fang Victory"; Player1win ; } Else { Winner = "Red Cover"; Player2win ; } Try { Thread.sleep (3000); } catch (exception e) { } Alert Winalert = New Alert ("", Winner "/ N white" Player1win ":" Player2win "Red Part", NULL, ALERTTYPE.INFO; Winalert.SetTimeout (Alert.Forever); Display.GetDisplay (GoBang) .SetCurrent (Winalert, this) INIT (); Repaint (); } this.isplayer1 =! this.isplayer1; // Switch the chess party } } Repaint (); } Private boolean checkwin () { INT NUM = 1; IF (Num <5) { Num = 1; For (int i = 1; i <= 4; i ) { IF (Isplayer1 (SelectEer1 (SELECTEDX-I, SELECTEDY) { Num ; } Else Break; } For (int i = 1; i <= 4; i ) { IF (IsPlayer1 (SELECTEDX I, SELECTEDY) { Num ; } Else Break; } } IF (Num <5) { Num = 1; For (int i = 1; i <= 4; i ) { IF (IsPlayer1 (SELECTEDX, SELECTEDY-I)) { Num ; } Else Break; } For (int i = 1; i <= 4; i ) { IF (Isplayer1 (SELECTEDX, SELECTEDY I)) Num ; Else Break; } } IF (Num <5) { Num = 1; For (int i = 1; i <= 4; i ) { IF (IsPlayer1 (SELECTEDX-I, SELECTEDY-I)) Num ; Else Break; } For (int i = 1; i <= 4; i ) { IF (IsPlayer1 (SELECTEDX I, SELECTEDY I)) Num ; Else Break; } } IF (Num <5) { Num = 1; For (int i = 1; i <= 4; i ) { IF (IsPlayer1 (SELECTEDX I, SELECTEDY-I)) Num ; Else Break; } For (int i = 1; i <= 4; i ) { IF (Isplayer1 (SELECTEDX-I, SELECTEDY I)) Num ; Else Break; } } IF (Num> = 5) Return True; Else Return False; } Private Boolean Isplayer1 (int y, int x) { IF (x <= 15 && x> = 0 && y <= 15 && y> = 0 && chesses [x] [y]! = null) { IF (chesses [x] [y] .isplayer1 == this.isplayer1) Return True; Else Return False; } Else Return False; }