For information about the design and functionality of the MIDlet, see section Design.
The Sudokumaster MIDlet consists of a MIDlet main class and a GameCanvas
. All game widgets are implemented as subclasses
of a custom View
class. Each view has a paint
method that defines how the view is
drawn to the screen. A Layout
view groups the other
views and the canvas has a reference to the layout to draw all the
views. The Sudoku game board is a view and uses a TiledLayer
to draw the game board.
For information about the key aspects of implementing the MIDlet, see:
The whole game engine runs inside a GameCanvas
. While the main thread handles all user events, rendering is done
in a separate thread:
timer = new Timer(); timer.schedule(new TimerTask() { public void run() { render(g); } }, 0, 20);
Updating the value of the elapsed time view is also done in the rendering thread:
timer.scheduleAtFixedRate(new TimerTask() { public void run() { updateElapsed(); } }, 0, 1000);
To keep the interface lag minimal, the render procedure is called every 20 ms, but the screen is redrawn only if there are changes in the views. However, on every call to the render procedure, all the possible animation counters are updated:
private void render(Graphics g) { if(layout.needsRendering()) { layout.render(g); flushGraphics(); } layout.update(); }
The rendering thread is started when the canvas is shown:
protected void showNotify() { // ... startTimer(); }
The thread is stopped when the canvas is hidden:
protected void hideNotify() { stopTimer(); // ... }
The game can be played using either the device keypad or touch screen. When using the touch screen, a number selection dialog is displayed after tapping a cell on the game board:
Figure: Number selection dialog
Touch (pointer) and key events can be captured simply by
overriding the the following Canvas
methods:
For example:
protected void pointerPressed(int x, int y) { handlePointerEvent(View.POINTER_PRESSED, x, y); }
All the views are generated when the canvas is shown:
protected void showNotify() { if(sudoku == null) generateLayout(); // ... }
The positions of the views are also updated when the size of the canvas changes (for example, because of an orientation change):
protected void sizeChanged(int w, int h) { if(timer != null) { stopTimer(); updateLayout(w, h); startTimer(); } }
Bitmap resources are created for two resolutions:
128 x 160 and 240 x 320 pixels. For other resolutions, the game board
bitmap is scaled to fit the screen. The resources are stored to folders
named small
and medium
. In the loadImage
function screen, the resolution determines which
folder is used:
private Image loadImage(String fileName, int w, int h) { Image image = null; if(isSmallScreen(w, h)) { image = ImageLoader.getInstance().loadImage("/small"+fileName); } if(image == null) { image = ImageLoader.getInstance().loadImage("/medium"+fileName); } return image; }
Figure: Game title in different resolutions
The state of the game
is stored using a RecordStore
:
public void saveGameState() { if(sudoku == null) return; try { RecordStore gameState = RecordStore.openRecordStore("GameState", true); if(gameState.getNumRecords() == 0) gameState.addRecord(null, 0, 0); byte[] data = sudoku.getState(); gameState.setRecord(1, data, 0, data.length); } catch (RecordStoreException e) { } } public void loadGameState() { if(sudoku == null) return; try { RecordStore gameState = RecordStore.openRecordStore("GameState", true); if(gameState.getNumRecords() == 0) sudoku.newGame(SudokuGenerator.newPuzzle()); else { sudoku.setState(gameState.getRecord(1)); if(sudoku.isComplete()) showVictoryDialog(); } } catch (RecordStoreException e) { } }
The state is stored when the canvas is hidden:
protected void hideNotify() { // ... if(!main.isClosed()) saveGameState(); }
It is also stored when the MIDlet is destroyed:
public void destroyApp(boolean unconditional) { closed = true; if(sudokuCanvas != null) sudokuCanvas.saveGameState(); }
When the canvas is shown, the state of the game is restored:
protected void showNotify() { // ... loadGameState(); // ... }