Javaone Hands-On Lab: Lab-6400 Create Your Own Mobile Game
Javaone Hands-On Lab: Lab-6400 Create Your Own Mobile Game
1 of 35
2 of 35
Copyright Copyright 2008 Sun Microsystems, Inc. All rights reserved. Sun, Sun the Sun logo, Solaris, Java, the Java Coffee Cup logo, JavaOne, the and all Solaris-based and Java-based marks and logos are trademarks trademarks of Sun Microsystems, Inc. in the United States and other Microsystems, JavaOne logo, or registered countries.
Prerequisites
This hands-on lab assumes you have some basic knowledge or programming experience on the following technologies. MIDP/CLDC development Mobile Media API (JSR 135) Web Services API (JSR 172)
System Requirements
Supported OS: Windows Vista/ XP, Solaris 10 x86/x64,Linux,Ubuntu7.x. Memory requirement: 512MB minimum, 1GB recommended Disk space requirement: 650MB minimum, 1GB recommended Processor requirement: minimum 800 MHz Intel Pentium III workstation, recommended 1.4 GHz Intel Pentium III or equivalent JVM requirement: JDK 1.5_0 or higher
3 of 35
Download and unzip lab file (under a directory of your choice) Read <lab_root>/index.html to proceed
Lab exercises
Exercise Exercise Exercise Exercise Exercise 0: Install and configure the lab environment 1: Creating a MIDP application using visual tools 2: Create the game 3: Logic of the game 4: Make it connected
Resources
Lab presentation Mobile Applications Learning Trail
Where to send questions or feedbacks on this lab and public discussion forums
You can send technical questions via email to the authors of this Hands-on lab (and experts on the subject) or you can post the questions to the web. You can send your other questions to the public mailing lists and forums. Mobility users mailing list archive Forum: Java ME Technologies - CLDC and MIDP JavaOne2008 forum at hands-on-labs.dev.java.net
4 of 35
5 of 35
6 of 35
Figure-1-1: HelloMidlet in the visual designer 5. Select Alert component from the Displayables category in the Palette Window. 6. Drag&Drop the Alert screen from palette to the Visual Designer Flow view. 7. Component named alert appears (Figure-1-2). By this simple operation you just added a screen component to the design.
7 of 35
Figure-1-2: Alert component added to the flow 8. Now change the title of the alert, so it says "Help" - to do so you can simply click on the Title property (in the properties window located in the right-bottom corner of the IDE) and type in the text. 9. The next step is to change the text the alert displays to the user - e.g. "This is Help for Hello Midlet". Switch to the Screen designer (using Screen button). 10. Select the Alert component in combo box at the top of the document window. It will show the alert component in the Device Screen area of the document. 11. Move the mouse over the edit screen, over the < text not specified > area and a blue box should appear, informing you that the text can be edited. Clicking on the blue box. In the editor type the new text and press Enter. 12. Switch back to the flow designer and drag Help Command from the palette and drop it on the form component. Help message is added to form component. 13. The next task is to connect this help command with our help component (alert) you've just created. Select helpCommand in the form component and drag it to the alert component (you should see a line with arrow while dragging) and drop it on the alert component. 14. The components should be now connected together (Figure-1-7 - Alert component is able to automatically return to the component from which it was displayed, thus two lines were actually created - one from form to
8 of 35
Figure-1-3: alert component is linked with Help command on helloForm. Step 2: Build and Running the Project 1. Run the application with Run > Run Main Project or simply by clicking on green arrow or hitting F6 key. This saves all files, builds the project (you should see progress of building in output window) and starts the emulator with the HelloMidlet. 2. Launch the application, and see the Hello form (Figure-1-4), press the Help button. Don't forget to close the emulator when you are done with the application (you can exit the emulator either with close button on the emulator's window or by hitting power-off button in the top-right area, just above the display).
9 of 35
If the emulator doesn't start up then it might be problem with path to the java. Please, look at the FAQ describing the problem - WTK and default java. Step 3: Add Custom Component to the palette. In this step you are going to register a canvas component to the component palette, so it can be used in the visual designer. You can find components provided by MIDP and custom components of the NetBeans Mobility in the palette. The screen components can be used to visualy design a flow of an application. Other components will be used to create user interface of particular screens. You can use your own components to design your application. A custom component has to be added to the palette before it can be used in the visual designer.
10 of 35
11 of 35
5. To add a custom component to the palette select Tools > Palette > MIDP Visual Mobile Designer. This brings up the Palette Manager (Figure-1-6).
Figure-1-6: Palette Manager 6. In the dialog, click on Add to Palette button. A wizard for adding new component to the palette appears. 7. On the first page, select the project from which you'd like to add the component. In our case, MobileGameApp project should be selected. 8. Click Next and select a class to add. By default this dialog shows only components which have sources in the select project, select the class org.netbeans.j1.game.MazeCanvas (Figure-1-7). 9. In this dialog you can also specify the palette category to which the component is going to be added. For custom components, please select the Custom Components node.
12 of 35
Figure-1-7: Registering custom component 10. Close the palette manager. MazeCanvas component is now available for the visual design (Figure-1-8).
13 of 35
Figure-1-8: MazeCanvas component on the Palette Step 4: Define the flow of the game application. In this step you are going to modify the UI of the application that will show a mobile game. When you add/fix the whole game UI and add the logic into the application, the Visual Flow Design of the application should behave in following way. When the user finish to play the game, the application will register his scores and it will require him to enter the userID. It will keep his/her scores and add it into a scores table. This table will display the top10 scores of the best players. If the user decides to improve the score he/she will have the option to update the previous score, in case that it will happened the new score will be reflected in the score table, and return to the main menu, or if he/she decides to exit the application the emulator will be close. For more details about the Visual Flow Design component (and other components) see Javadoc for NetBeans MIDP components and tutorials available on http://www.netbeans.org/kb/trails/mobility.html.
1. Go to the Flow Designer of the GameMIDlet. Drag&Drop the MazeCanvas component from palette to the Flow Designer. Component named MazeCanvas should appear in flow design. By this simple operation you just added a screen component to the design. Create flow of the screens in the application. In the Flow design window, click on the menuItem_0 and drag the arrow to the MazeCanvas component. New transition between screens is created.(Figure 10)
14 of 35
Figure-1-10: Final design of the flow of the MazeCanvas application 2. Select MazeCanvas component in the Flow Design, go to properties window and click on a custom editor button of the midlet(1.contructor-1.parameter defined property (a small button with three dots). This opens a window with embedded editor, which lets you to write a code to be executed. In this editor, you need to change the default value <null> to this value (Figure-1-2)
15 of 35
Figure-1-11: Java expression 3. The next task is to write the code, which will start the game thread. To add this functionality you need to click the Source button at top of GameMIDlet document window. The source-code editor should open Now find method svgMainMenuAction - you can either use CTRL+F or double click the method name in Navigator at left bottom corner of the IDE. If you have problem to find the right place where to write (or paste) the code you can use Window > Tasklist window. Where are listed all TODOs in this hands-on lab. 4. In the method change the code in following way public void svgMainMenuAction() { // enter pre-action user code here String __selectedElement = getSvgMainMenu().getMenuElementID(getSvgMainMenu().getSelectedIndex()); if (__selectedElement != null) { if (__selectedElement.equals("menuItem_0")) { switchDisplayable(null, getMazeCanvas()); // write post-action user code here //TODO: [Exercise1][step4] It starts the game thread myGameThread = new GameThread(getMazeCanvas(), myGameThread.start();//[Exercise1] } else if (__selectedElement.equals("menuItem_1")) {
this);//[Exercise1]
Summary: In this exercise you learned how to rapidly create mobile application from scratch using visual designer. You utilized standard MIDP components as well as additional components supplied by NetBeans Mobility 6.0.1 external project, which included a custom visual component. You learned how to add a Canvas into the custom components. Go on to next exercise
16 of 35
Background information:
Visual editing support for MIDP 2.0 Game API including creation and editing of Sprites, TiledLayers and their arrangement into scenes. The main goal of the Game Builder module is to reduce the effort involved in creating common game components. Sprite Game Builder treats sprites as a collection of animated sequences where each sprite can be contain a number of sequences. The sprite editor allows editing and previewing of multiple animated sequences simultaneously. TiledLayer Grid of cells, each painted with one frame selected from an Image. When a new tiled layer is created it can be edited using the available visual editor. This allows the user to modify the contents of the tiled layer and receive instant visual feedback. The tiled layer editor also includes support for animated tiles. Scene - Scenes are locations within a game enviroment that have distintive visual, and possible audio, characteristics that define the games look and feel. Each level in a game can have several different scenes. Conversely,a simple game may have only one scene for all of its levels. Steps to Follow: Create a new Visual Game Design file Create new Sprites Create new TiledLayer Create new scene for our game Modify the background Step 1: Create a new Visual Game Design file In this step you will create a new Visual Game Design file, which will be developed in the Game Builder. 1. Right click on the package org.netbeans.j1.game and select New > Visual Game Design. A New File wizard for the visual game appears. 2. In this wizard enter the name of the GameDesign (this name will be visible to user when launching the application) for example MazeGameDesign. Click Finish to create the visual game. When created, the file should be opened in Game Builder (Figure-2-1).
17 of 35
Figure-2-1: MazeGameDesign in the Game Builder Step 2: Create new Sprites Sprites are the build brick of any MIDP game. Game Builder treats sprites as a collection of animated sequences where each sprite can be contain a number of sequences. 1. We will create new sprite. You can create it in following ways: Click Create Sprite text in the GameDesign file opened in editor. The Game Builder view has to be active.
Use the /duke.png image. Adjust the tile size to 25 pixels with the sliders for both - width and height. Name the Sprite as dukeS. Click Finish button.
18 of 35
Figure-2-2: Create new sprite New sprite with default sequence opens in the editor.
19 of 35
Figure-2-3: Default duke sprite sequence 2. Change the look of the sprite sequence to look like at Figure-2-4. You can drag and drop images to desired position in the sprite sequence from the down part of the Game Builder view where you can see all the available tiles for the sprite. When you right click a frame in the sequence you can remove the frame.
Figure-2-4: Duke sprite sequence 3. We need to create one more Sprite in our game in the same way as the previous one. This time we will name the sprite jamesS. The image that we will use is bigG. When the jamesS sprite is created it should look like on Figure-2-5.
20 of 35
Figure-2-5: James Gosling sprite 4. We need more sequences for our duke sprite. The duke can walk, he can fall and also jump. We have to create new sequences. Open the dukeS sprite in the Game Builder. Right click on any frame of the default sequence dukeSseq001. 5. Choose Create sequence from the popup menu. Name the sequence dukeSfalling. Create one more sequence with name dukeSjumping.
Figure-2-6: Sequences Step 3: Create new TiledLayer TiledLayer are the build brick of any MIDP game. When a new tiled layer is created it can be edited in the visual editor. This allows the user to modify the contents of the tiled layer and receive instant visual feedback. The tiled layer editor also includes support for animated tiles. 1. Create new TiledLayer. You can invoke the New TiledLayer dialog in different way. Name the TiledLayer as maze1. Use image wall. Adjust the tile size to the maximum heigth and width.
21 of 35
Figure-2-7: New tiled layer 2. Press Finish button. Empty grid appears.
22 of 35
Figure-2-8: Empty tiled layer 3. You can create the tiled layer by drag and drop of images from bottom area to the grid. The IDE will construct the tiled layer table for you. Create a maze of square shape. Build up the walls of the maze. The maze should be square shape.
23 of 35
Figure-2-9: Example of maze walls Step 4: Create new Scene The scene editor is provided to organize all layers (sprites and tiled layers) together into scenes. 1. Create new Scene. Name the Scene as level1. Click Finish button. Empty scene grid appears. 2. Right click the grid. Choose Add tiled layer > maze1 from the popup menu. The maze1 appears on the grid.
24 of 35
Figure-2-10: Maze1 on the scene grid 3. The maze1 tiled layer appears on grid in positions where you right clicked the mouse. We need it in 0,0 position. You can either move it the with mouse or you can set position in Navigator view in right bottom corner of IDE.
Figure-2-11: Setup of position 4. Right click the grid again. Choose Add sprite > jamesS from the popup menu. Add dukeS sprite into the scene too. Place both the sprites to not collide with the maze walls.
25 of 35
Figure-2-12: Final look of the scene When placing the sprites of duke and James into the maze remember the purpose of the game - duke is looking for James. Summary: In this exercise you learned how to create new sprite, tiled layer. Please, note that you can design these sprites and tiled layers in visual tool. The sprites and tiled layer are defined by arrays of positions of a tile in the png image of the sprite. NetBeans Mobility generates these boring arrays for you. If you want to see the generated source code switch to Source of the MazeGameDesign. You also learned how to create sequences of sprite and how to compose the sprites and tiled layers into a scene with NetBeans Mobility. Go on to next exercise
26 of 35
Steps to follow:
Initialize the MazeManager Let the duke move Step 1: Initialize the MazeManager 1. There are following classes created for you in the org.netbeans.j1.game.logic package that take care about processing the game. The GameTread.java class runs in separate thread to not block the game ui. The MazeManager.java class takes care about the interaction among the sprites and tiled layers in the game. At first we have to initialize all the game parts. Copy and paste code in bold to init method of the MazeManager class.
public void init() throws Exception { //TODO: [Exercise 3][step 1] - initialization code. Please, don't forget to fix the missing imports an mazeDesign = new MazeGameDesign(); //[Exercise3] jamesSprite = mazeDesign.getJamesS();//[Exercise3] dukeSprite = mazeDesign.getDukeS();//[Exercise3] dukeSprite.defineReferencePixel(dukeSprite.getWidth() / 2, 0);//[Exerc dukeSpriteAnimator = new SpriteAnimationTask(dukeSprite, false);//[Exe myWalls = mazeDesign.getMaze1();//[Exercise3] mazeDesign.updateLayerManagerForLevel1(this);//[Exercise3] = new Timer();//[Exercise3] timer.scheduleAtFixedRate(dukeSpriteAnimator, // this sets the view screen so that the player is // in the center. myViewWindowX = dukeSprite.getX() - ((DISP_HEIGHT - SQUARE_WIDTH) / 2); myViewWindowY = dukeSprite.getY() - ((DISP_HEIGHT - SQUARE_WIDTH) / 2); System.gc(); } 2. Fix the missing import for MazeGameDesign class. You can use the hint bulb to fix the code. Just press the bulb on the glyph or ALT+ENTER on the line with errors. Hints Figure-3-1: Hints 3. Create new field mazeDesign in the class. You can use the hint again. 4. Now the game is ready to be played. You can run the application. Right click the MobileGameApp project and choose Run. 5. When the emulator window appears launch the application. timer 0,
mazeDesign.dukeSseq
27 of 35
Step 2: Let the duke move We need to set up the right sequence to the duke sprite when he is walking, jumping or falling. 1. It can be done in MazeManager class in method updateSprite. Just uncomment the four lines ending with //TODO: [Exercise 3][step 2]. It will add the code that changes the sequence of tiles for duke sprite. Therefore the duke will either walk or fall or jump. 2. The source code of the updateSprite() method will look in following way. The bold lines are the uncommented ones.
28 of 35
private void updateSprite(int hdirection, int vdirection) { // if the duke is moving left or right, we set // his image to be facing the right direction if (hdirection > 0) { dukeSprite.setTransform(Sprite.TRANS_NONE); } else if (hdirection < 0) { dukeSprite.setTransform(Sprite.TRANS_MIRROR); } //in case that duke is moving, change the showing sprite image if (lastHorDirection != hdirection) { dukeSprite.setFrameSequence(mazeDesign.dukeSseq001); //TODO: [Exercise 3][step 2] Let t } if (lastVertDirection != vdirection) { if (vdirection > 0) { //he's jumping dukeSprite.setFrameSequence(mazeDesign.dukeSfalling);//TODO: [Exercise 3][step 2] } else if (vdirection < 0) { dukeSprite.setFrameSequence(mazeDesign.dukeSjumping);//TODO: [Exercise 3][step 2] } } if ((vdirection != 0) || (hdirection != 0)) { dukeSpriteAnimator.forward(); } else { dukeSpriteAnimator.setMoving(false); dukeSprite.setFrameSequence(mazeDesign.dukeSseq001); } lastHorDirection = hdirection; lastVertDirection = vdirection; }
Summary:
You created necessary logic for the game. You can now play the game. As you can see the work with the Sprites and TiledLayers is quite simple thank to the Game API. The game logic isn't so complicated however the description of it is beyond scope of this hands-on lab class. The source code is well described with comments and javadoc therefore you can study it later. Go on to next exercise Go on to summary
29 of 35
Steps to follow:
Create new configuration Generate stubs Step 1: Create new configuration In this step you will create new configuration in your project. It will allow us to have two version of the same project. First one will be used for the online game and the second one for offline game. 1. Right click the MobileGameApp project. It will open the project Properties. 2. In the project properties dialog, select Add Configuration... from Project configurations the combo box. It will open Add Configuration dialog. 3. Type in the name for new configuration - OnlineGame. Finish the dialog.
Figure-4-1: New configuration dialog 4. In project properties, select Abilities. Uncheck the Use Values from DefaultConfiguration. 5. Click Add button. In Add Ability dialog provide name ONLINE and value true. Click OK to finish dialog.
30 of 35
Figure-4-2: New ability dialog 6. Click OK to close the project properties dialog. Step 2: Generate stubs In this step you will generate a mobile client to the web service. We will use the wizard provided by NetBeans Mobility. 1. Select File > New File... from main menu. In the New File dialog select MIDP category and Java ME Web Service Client. Make sure that MobileGameApp project is selected in Project combo box. Click Next button. 2. You have to specify an URL of webservice's WSDL file in this panel. The WSDL can be either a file stored locally on your hard drive or an URL of a webservice at the internet. Our webservice should be running at following URL : http://193.86.76.42:8080/DukeHighScores/HighScoresService?WSDL If you are not able to access the web service WSDL try to check your network settings. Sometimes a firewall or antivirus shield can protect you from connecting to the web service. If the webservice URL is unreachable you can deploy the webservice to application server by yourself. The project with the webservice is at <lab_root>solutions/solution4 directory. The name of the project is DukeHighScores. 3. Select the Running Web Service radio button. 4. Type the URL of the webservice to WSDL URL text field. Click Retrieve WSDL button and, if the WSDL file name automatically appears in the Local Filename field, the WSDL file is successfully downloaded and validated. The validation of the WSDL is mandatory step. You cannot generate the Java ME Web Service Client to any webservice. There are some restrictions for the webservice defined by the JSR 172. The webservice has to be WS-I Basic Profile compliant. There is no support for asynchronous messaging. No support for SOAP messages with attachments. Support only for the literal representation of messages. No support for extensible type mapping. The wizard will report an error message when you cannot generate the J2ME webservice client for a webservice. 5. The wizard will provide you a default name for the client and package. Change the Package name to org.netbeans.j1.game.client
31 of 35
Figure-4-3: Java ME Web Service Client wizard 6. When you press Finish button the wizard will generate web service client stubs.
Figure-4-4: Generated stubs Step 3: Use mobile client You generated the stubs that will allow you communicate with the web service on a server. It is time to use the web service client in the game source code.
32 of 35
This will add new method for retrieving the webservice stub. 2. Fix the imports. 3. Update the getAddHighScoreTask method to upload the scores to the server.
public SimpleCancellableTask getAddHighScoreTask() { if (addHighScoreTask == null) { // write pre-init user code here addHighScoreTask = new SimpleCancellableTask(); addHighScoreTask.setExecutable(new org.netbeans.microedition.util.Executable() { public void execute() throws Exception { //#if ONLINE == "true" //TODO: [Exercise 4][step 3] set High score //upload the score to WS getMobileClient().setHighScore(getNameTextField().getString(), //get the high scores from WS again to synchronize with server side updateHighScoresTable(getMobileClient().getHighScores());r //#else //# //just add the score to the scores table //# addScoreToScoreTable(lastHighScore, getNameTextField().getString()); //#endif //anyway update the High scores table updateSvgWithHighScores(); } }); // write post-init user code here } return addHighScoreTask; }
4. Update the getHighScoresTask method to download the scores from the server.
public SimpleCancellableTask getHighScoresTask() { if (highScoresTask == null) { // write pre-init user code here highScoresTask = new SimpleCancellableTask(); highScoresTask.setExecutable(new org.netbeans.microedition.util.Executable() { public void execute() throws Exception { // write task-execution user code here //#if (ONLINE == "true") //TODO: [Exercise 4][step 3] get High Scores //connect to WS and get the latest scores updateHighScoresTable(getMobileClient().getHighScores());//down //update the high score table updateSvgWithHighScores();//update the svg image with the lates //#else //# //this code is used when the ONLINE ability value isn't true //# //nothing to do. The high scores are in the highScoresValues array a //# Thread.sleep(500); //#endif
33 of 35
Step 4: Run the game We finished the creation of the game. Even if there is just one source code we created two versions of the game. One is the OnlineGame that connects to server. The other one is the origin source code that works offline. The online version enables you to share the high scores with other players. 1. Switch active configuration to DefaultConfiguration in configuration combobox in middle of toolbar. Switch configuration Figure-4-5: Switch configuration 2. Run the project. It will run the offline version of the game. 3. Switch active configuration to OnlineGame in configuration combobox in middle of toolbar. Switch configuration Figure-4-6: Switch configuration 4. Run the project. It will run the online version of the game.
Summary:
You connected the game with the server side. It is very easy to use the generated stubs. The application is now able to upload your result to server and display the list of best results on your device. We used J2ME Webservices API to achieve this functionality but the J2ME Webservices API is not supported on lot of device in real world. It is easy to change the client calls to solution not using J2ME Webservice API. You can use the second wizard that NetBeans Mobility provides - "Mobile Client to Web Application". The difference between these two solutions is described in "LAB-6340: <Advanced Java ME Programming - Streaming Video From Server to Your Device>" Hands-on lab Go on to summary
34 of 35
Congratulations! You have successfully completed the "LAB-6400: <Create Your Own Mobile Game>" Hands-on Lab.
Where to send questions or feedbacks on this lab and public discussion forums: You can send technical questions via email to the authors of this Hands-on lab (and experts on the subject) or you can post the questions to the web. Please post questions that are relevant only to this hands-on lab. JavaOne2008 forum at hands-on-labs.dev.java.net You can send your other questions to the public mailing lists and forums. Mobility users mailing list archive Forum: Java ME Technologies - CLDC and MIDP
35 of 35