Programming Java 2 Micro Edition for Symbian OS 2004 (779882), страница 28
Текст из файла (страница 28)
The paint() methodmust be implemented to render the CustomItem. In the example codeabove we have produced a minimal button, leaving it as an exerciseto the reader to add the embellishments. We must also implement thegetPrefContentWidth(), getPrefContentHeight(), getMinContentWidth() and getMinContentHeight() methods inheritedfrom CustomItem; here we have provided trivial implementations. Anattractive feature of CustomItem is the optional support for pointerinput, via the protected pointerPressed(), pointerDragged()and pointerReleased() methods. The Button class redefines thepointerPressed() method to provide support for touch screen userinterfaces such as Symbian’s UIQ.Of course, we could have adopted a simpler approach to our keypad.Instead of providing a custom Button class extending CustomItem wecould have simply used StringItem instances with appearanceModeset to Item.BUTTON:public StringItem (String label, String text, int appearanceMode)We would then add a Command to the StringItem to take appropriate action when it is selected and implement an ItemCommandListener on each StringItem instance, as shown below:public class KeyPad extends MIDlet implements CommandListener,ItemCommandListener{...public KeyPad() {...StringItem button1 = new StringItem(null, “1”, Item.BUTTON);MIDP 2.0131button1.setDefaultCommand(new Command(“Select 1”,Command.Item, 1));button1.setItemCommandListener(this);...form.append(button1);...}...public void commandAction(Command command, Item item) {StringItem button = (StringItem)item;setString(button.getText());}...}We adopted the CustomItem approach for our keypad examplefor two reasons: it provides an opportunity to illustrate the use ofCustomItem, and its inherent support for touch screens; and the particular variant of StringItem shown above was subject to a defecton the original Nokia 6600 firmware release (but should be fixed infuture upgrades).3.3.7 The Game API3.3.7.1 IntroductionThe MIDP 1.0 specification, though limited in many respects, proved abig hit with the gaming fraternity.
The vast majority of MIDlets developedso far are games.As mentioned briefly in Chapter 2, the MIDP 2.0 specification extendssupport for games developers with the introduction of the javax.microedition.lcdui.game package. We will now discuss programmingthis API in more detail. The aim of the API is to facilitate richer gamingcontent by providing a set of APIs, targeted at games developers, thatmap directly to native functionality, taking advantage of the performanceenhancements offered by native code and minimizing the amount ofwork required in pure Java code.The game package contains the following classes:• GameCanvas• LayerManager• Layer• Sprite• TiledLayer.In the next few sections we shall look at the functionality offered by theseclasses, illustrating some of the key concepts with sample code.132MIDP 2.0 AND THE JTWI3.3.7.2 GameCanvasA basic game user interface class extending javax.microedition.lcdui.Canvas, GameCanvas provides an offscreen buffer as part ofthe implementation even if the underlying device doesn’t support doublebuffering.
The Graphics object obtained from the getGraphics()method is used to draw to the screen buffer. The contents of the screenbuffer can then be rendered to the display synchronously by calling theflushGraphics() method.The GameCanvas class also provides the ability to query key statesand return an integer value in which each bit represents the state of aspecific key on the device:public int getKeyStates()If the bit representing a key is set to 1 then this key is pressed orhas been pressed at least once since the last invocation of the method.The returned integer can be ANDed against a set of predefined constants(shown below), each representing the appropriate bit for a specific keyset to 1 (support for the last four values is optional).publicpublicpublicpublicpublicpublicpublicpublicpublicstaticstaticstaticstaticstaticstaticstaticstaticstaticfinalfinalfinalfinalfinalfinalfinalfinalfinalintintintintintintintintintUP_PRESSEDDOWN_PRESSEDLEFT_PRESSEDRIGHT_PRESSEDFIRE_PRESSEDGAME_A_PRESSEDGAME_B_PRESSEDGAME_C_PRESSEDGAME_D_PRESSEDWe would use these values to ascertain the state of a key in the mannershown below.if ( getKeyStates() & FIRE_PRESSED != 0 ) {// FIRE key is down or has been pressed// take appropriate action}3.3.7.3 TiledLayerThe abstract Layer class is the parent class of TiledLayer and Sprite.A TiledLayer consists of a grid of cells each of which can be filledwith an image tile.
An instance of TiledLayer is created by invokingthe constructor of the TiledLayer class:public TiledLayer(int columns, int rows, Image image, int tileWidth,int tileHeight)MIDP 2.0133The columns and rows arguments represent the number of columnsand rows in the grid. The tileWidth and tileHeight argumentsrepresent the width and height of a single tile in pixels. The imageargument represents the image used for creating the set of tiles that willbe employed to populate the TiledLayer. Naturally, the dimensionof the image in pixels must be an integral multiple of the dimensionof an individual tile. The use of TiledLayer is best illustrated withan example.The image in Figure 3.8 (taken with a Symbian OS phone) is apanoramic view of Prague.
The dimensions of the image are 560 × 140pixels and we will use it to provide the tile set for our TiledLayer.We will use a TiledLayer to pan through this view. To fit comfortablyin the display of a phone we will display samples of the image on aTiledLayer of 140 × 140 pixels, consisting of a 7 × 7 grid, as shownin Figure 3.9.Note that cells are identified by their column and row number, thetop left cell having coordinates (0, 0) and the bottom right (7, 7).
Thedimensions of the TiledLayer and the number of cells it containsdictates that the individual tile dimensions are 20 × 20 pixels in thisexample and that the image can be treated as a 28 × 7 matrix of tiles (seeFigure 3.10).A given tile is specified by its tile index.
Tile indices in this examplerun from 1 for the top left tile to 196 for the bottom right tile.Figure 3.8Basic image for use by a TiledLayer.Figure 3.9Example of a 7 × 7 TiledLayer.134MIDP 2.0 AND THE JTWIFigure 3.10 Dividing our image into tiles.Figure 3.11Panning through a panoramic view using TiledLayer.To pan through the whole image we simply shift each column of tilesone position left within the TiledLayer, as shown in Figure 3.11.The source code for the TiledLayerCanvas class, which rendersthe panned view, is listed below:importimportimportpublicjavax.microedition.lcdui.*;javax.microedition.lcdui.game.*;java.io.*;class TiledLayerCanvas extends Canvas implements Runnable {private Image image;private int x;private int y;MIDP 2.0135private TiledLayer layer;public TiledLayerCanvas(String imageName)throws ApplicationException {//create the imagetry {image = Image.createImage(imageName);layer = new TiledLayer(7, 7, image, 20, 20);x = (getWidth() - layer.getHeight())/2;y = (getHeight() - layer.getWidth())/2;layer.setPosition(x, y);}catch(IOException ioe) {throw new ApplicationException("Unable to create image");}}public void paint(Graphics g) {layer.paint(g);}public void run() {int n = 0;while ( n <= 21) {for(int i = 0; i < 7; i++) {for(int j = 0; j < 7; j++) {layer.setCell(i, j, (i + 1) + n +(j*28));}}repaint();try {Thread.sleep(100);}catch(InterruptedException ie) {}n++;}}}The TiledLayerCanvas constructor creates an instance of Imagefrom a resource file containing the panoramic view.
This is then used tocreate the TiledLayer instance:layer = new TiledLayer(7, 7, image, 20, 20);This consists of a 7 × 7 grid, to be populated with tiles of dimensions20 × 20 pixels. The position of the TiledLayer relative to the containingCanvas is defined by the setPosition() method of the parent Layerclass. To render the TiledLayer, we call its paint() method fromthe Canvas paint() method. We pan through the image using awhile loop that increments a counter running from 0 to 21 for eachnew tile set. Each iteration of the while loop sets the tile set and thencalls repaint (and increments the counter). The TiledLayer grid ispopulated with a tile set by multiple calls to setCell from within nestedfor loops:136MIDP 2.0 AND THE JTWIfor(int i = 0; i < 7; i++) {for(int j = 0; j < 7; j++) {layer.setCell(i, j, (i + 1) + n +(j*28));}}repaint();The setCell() method of TiledLayer takes integers representingthe row and column of the TiledLayer grid (which in this case run from0 to 6 for a 7 × 7 grid) in which the tile is to be placed, and an integerrepresenting the index of the tile within the image (which in this exampleruns from 1 to 196 for an image consisting of 28 × 7 tiles) as arguments.public void setCell(int col, int row, int tileIndex)The full source code and JAR and JAD files for the Panorama MIDletcan be downloaded from the Symbian website at www.symbian.com/books.One of the principal uses of TiledLayer is the creation of largescrolling backgrounds from relatively few tiles.
Consider the rather simplistic, but nonetheless illustrative, example in Figure 3.12.We have built up a background TiledLayer from just four tiles.By changing the arrangement of the four tiles within the TiledLayergrid we can convey the impression of an infinite scrolling background.For more information on using TiledLayer to create backgrounds,including the use of animation, consult the MIDP 2.0 documentationwhich includes a comprehensive example.Figure 3.12A simple background TiledLayer built up from four tiles.3.3.7.4 SpriteSprite is a basic visual element suitable for creating animations.A Sprite consists of an image composed of several smaller images(frames). The Sprite can be rendered as one of the frames.