To view this site correctly, you need to upgrade your Flash Player. If you know you have Flash installed, you can bypass the detection if you wish, but the site may not work properly unless you are using the latest version. Click here to upgrade.

Site Navigation: Home Page | Products | Rich Media | Partners | About Ikivo

Ikivo Enrich - Enabling rich media services

Tutorial: JSR226 using Netbeans and Ikivo Animator



  • NetBeans IDE 5.5.1 or later
  • NetBeans Mobility Pack 5.5.1
  • Sun Java Wireless Toolkit 2.5
  • Ikivo Animator 2.1
  • Recommended: An editor for static vector graphics. We will use Adobe Illustrator CS2, but any SVG Mobile-compatible editor should work. All the static svg files used in this tutorial are also available for download

    In this tutorial we will create a simple Tic-Tac-Toe game. We'll begin by designing the graphics of the game. If you want to skip this step, you can download the complete board_static.svg and use that in the rest of the tutorial..
  • Open Illustrator and create a new 210x210 pixel document.
  • Drag horizontal and vertical lines, just intersecting the canvas edges, equal distances from each other and the edges. That should be at 70 px and 140 px respectively from the edges.
  • Draw a cross and a circle in each of the squares you just created. Make sure every cross and circle has it's own group and that these two groups in turn are grouped together to form 9 groups each containing two groups: a circle and a cross. Duplicating the same cross-and-circle group can of course speed up this step, but drawing each of the crosses and circles individually will add a nice touch to the game.
  • To easily be able to reference graphics objects later, it's important to use a good naming scheme. Name each circle-and-cross group according to its row and column e.g. square-1-3 is the name of the top right square. Also make sure the cross is always the graphically topmost child of the circle-and-cross group.
  • Save the file in SVG Tiny 1.1 format as board_static.svg in a folder of your choice.
Now we will create a NetBeans project and set up the basic back-bone of the mobile application.
  • Open NetBeans IDE and create a new project. In the New Project dialogue, choose Mobile Application and click Next. Name the project SicVacGoe and uncheck Create Hello MIDlet, click next, select CLDC-1.1 and MIDP-2.0 then click Finish.
  • From the top menu, choose New File... Select VisualMIDlet and click Next. Name the VisualMIDlet SicVacGoe and click Finish
Now we will connect our game graphics to the flow design in this VisualMidlet.
  • Open Ikivo Animator
  • Create a new 220x220 pixel document
  • Navigate to the folder containing board_static.svg using the object browser. Deselect Scale to fit in the object browser and click the import button to place the board centered in your canvas.
  • Save the file as board.svg in the src subfolder of your NetBeans project folder. Make sure you save the file as SVGT 1.1 Animator screenshot #1
  • Return to NetBeans and double click SicVacGoe in the projects view and select Flow Design in the main working area.
  • Drag an SVGAnimatorWrapper from the Palette on the right, into the flow design. Right click it; choose Rename and name it gameStage.
  • Drag your board.svg file from the project view to the newly created gameStage. A new entity called svgImage1 is added to the Inspector to the left. Rename it to svgBoard.
  • Now click and drag from the Start Point of the Mobile Device to the yellow entry point of gameStage NetBeans screenshot #1
  • Save your document
This completes the basic set-up of connections between graphics and logics. NetBeans IDE generates the necessary code and the project can actually be run already although it doesn't do much more than displaying the board.svg-file at the moment. Now we will add some initialization code for referencing svg objects in java code using JSR226.
  • Click the Source tab of the VisualMidlet (SicVacGoe) in the main window.
  • Start by adding some imports that we will use
    import org.w3c.dom.Document;
    import org.w3c.dom.svg.SVGElement;
    import org.w3c.dom.svg.SVGAnimationElement;
    import javax.microedition.m2g.SVGEventListener;
    
  • Declare the following variables in the beginning of the SicVacGoe class definition
  • private SVGElement circles[][];
    private SVGElement crosses[][];
    
  • Add the following code to the initialize() method right after the
    // Insert pre-init code here
    
    comment.
    //Object mapping
    circles = new SVGElement[3][3]; //initialize arrays
    crosses = new SVGElement[3][3];
    Document doc = get_svgBoard().getDocument(); //get the document element
    
    SVGElement el; //temporary reference
    for(int i = 0; i<3; ++i) {
        for(int j=0; j<3; ++j) {
            //get square at row i+1 column j+1
            el = (SVGElement)doc.getElementById("square-"+(i+1)+"-"+(j+1));
            //the circle group is the first child of the square
            circles[i][j] = (SVGElement)el.getFirstElementChild();
            //the cross group is the next sibling after the circle
            crosses[i][j] = (SVGElement) circles[i][j].getNextElementSibling();
        }
    }
    
    resetGame();
    
    Heads up: You may wonder why the circle is assigned to be the first child of the square and the cross the second, even though we in Ikivo Animator tree-view can clearly see that the cross is the top-most element. This is because of the document structure of an svg document. The top-most element graphically, is the bottom-most element in the DOM. If you are not certain where an element is located in the document structure; you can use NetBeans' Navigator to view the document model by double clicking an svg-file in the project view. Clicking an element in the navigator will highlight that object in the graphical representation in the working area.
  • Finally, define the resetGame() method:
    /**
     * This method resets the game engine status and graphics to start values
     */
    private void resetGame() {
        //hide the circles and crosses
        for(int i = 0; i<3; ++i) {
            for(int j = 0; j<3; j++) {
                circles[j][i].setTrait("display", "none");
                crosses[j][i].setTrait("display", "none");
            }
        }
        //TODO:reset game engine here
    }
    
  • Run your NetBeans project by selecting Run>Run Main Project from the top menu or pressing F6. You should see an empty game board. NetBeans screenshot #2
Let us add the game logics.
  • Create a new java file in NetBeans. Name it GameEngine.java and add the following class definition to it. This is pretty straight-forward self-explainable java code and we won't explain it here as it only defines the logics of the game. This separation of user interface and logics is one of the great advantages of SVG drawing using JSR226.
    public class GameEngine {
        //player constants
        public final static int PLAYER_NONE = 0;
        public final static int PLAYER_CIRCLE = 1;
        public final static int PLAYER_CROSS = 2;
        //game state constants
        public final static int STATE_ACTIVE = 1;
        public final static int STATE_POST = 2;
    
        private int board[][];
        private int currentPlayer;
        private int winner;
        private int state;
    
        /** Creates a new instance of GameState */
        public GameEngine() {
            board = new int[3][3];
            reset();
        }
        public void reset() {
            currentPlayer = PLAYER_CROSS;
            for(int i = 0; i<3; ++i) {
                for(int j=0; j<3; ++j) {
                    board[i][j] = PLAYER_NONE;
                }
            }
            state = STATE_ACTIVE;
        }
    
        public int getState() {
            return state;
        }
    
        public void setSquare(int row, int column) throws Exception {
            if(!canSetSquare(row, column))
                throw(new Exception("Marker set on non-empty square!"));
            board[row][column] = currentPlayer;
    
            if(_checkWin(PLAYER_CIRCLE)) //circle wins
            {
                winner = PLAYER_CIRCLE;
                state = STATE_POST;
            } else if(_checkWin(PLAYER_CROSS)) //cross wins
            {
                winner = PLAYER_CROSS;
                state = STATE_POST;
            } else if(_checkStall()) {
                winner = PLAYER_NONE;
                state = STATE_POST;
            } else
                switchPlayer();
        }
    
        public boolean canSetSquare(int row, int column) {
            return (board[row][column]==PLAYER_NONE);
        }
    
        public int getPlayer() {
            return currentPlayer;
        }
    
        public int getWinner() {
            return winner;
        }
    
        private void switchPlayer() {
            if(currentPlayer == PLAYER_CROSS)
                currentPlayer = PLAYER_CIRCLE;
            else
                currentPlayer = PLAYER_CROSS;
        }
    
        private boolean _checkWin(int player) {
            int count3=0, count4=0;
            for(int i = 0; i<3; ++i) {
                if(board[i][i] == player)
                    ++count3;
                if(board[i][2-i] == player)
                    ++count4;
                int count1=0, count2 = 0;
                for(int j = 0; j<3; ++j) {
                    if(board[i][j] == player)
                        count1++;
                    if(board[j][i] == player)
                        count2++;
                }
                if(count1 == 3 || count2 == 3 || count3 == 3 || count4 == 3)
                    return true;
            }
            return false;
        }
    
        private boolean _checkStall() {
            //check if entire board is filled
            for(int i = 0; i<3; ++i) {
                for(int j = 0; j<3; ++j) {
                    if(board[i][j]==PLAYER_NONE)
                        return false;
                }
            }
            return true;
        }
    }
    
Now it's time to connect the logics of the game with the graphics.
  • Declare a gameEngine instance variable of the SicVacGoe class: private GameEngine gameEngine;
  • and initialize the gameEngine variable in the beginning of the initialize() method
    gameEngine = new GameEngine();
  • Make sure the SicVacGoe class implements SVGEventListener press alt-enter to let NetBeans implement empty methods for the inherited abstracts:
    public void startApp() {
    }
    public void destroyApp(boolean unconditional) {
    }
    public void keyPressed(int i) {
    }
    public void keyReleased(int i) {
    }
    public void pointerPressed(int i, int i0) {
    }
    public void pointerReleased(int i, int i0) {
    }
    public void hideNotify() {
    }
    public void showNotify() {
    }
    public void sizeChanged(int i, int i0) {
    }
    protected void pauseApp() {
    }
    
  • Add some code to the keyPressed method:
    public void keyPressed(int i) {
        int key = i;
        int player = gameEngine.getPlayer();
        if(key<get_gameStage().KEY_NUM0 || key>get_gameStage().KEY_NUM9)
            return;
    
        int numberKey = key-get_gameStage().KEY_NUM0;
        if(numberKey == 0) {
            resetGame();
            return;
        }
    
        if(gameEngine.getState() != GameEngine.STATE_ACTIVE) {
            return;
        }
    
        //assuming a regular phone numerical keypad
        int row = (numberKey-1)/3;
        int column = (numberKey-1)%3;
    
        if(gameEngine.canSetSquare(row, column)) {
            try {
                gameEngine.setSquare(row, column);
            } catch (Exception ex) {
                //this really can't happen...
                ex.printStackTrace();
                exitMIDlet();
            }
    
            if(player == GameEngine.PLAYER_CROSS)
                crosses[row][column].setTrait("display", "inherit");
            else
                circles[row][column].setTrait("display", "inherit");
        }
        if(gameEngine.getState() == GameEngine.STATE_POST)
        {
            //game is over
        }
    }
    
  • Replace the //TODO:reset game engine here in resetGame() with gameEngine.reset();
  • Add our application instance as the SVG event listener by adding get_gameStage().setSVGEventListener(this); right before the resetGame(); line in the initialize() method.
That is essentially the game. Run it and try it out.

But shouldn't the players be notified who wins? Using the Ikivo Animator/NetBeans integration, this is a simple thing to do.

  • In NetBeans IDE, right-click the board.svg file in the project view and choose Edit. The file should open in Ikivo Animator.
  • Use the object browser to import the gameover_static.svg we have prepared for you.
  • Drag it so the entire gameoverView is outside and above the stage.
  • Create a new timeline by selecting New in the Timeline menu. Name it gameoverAnimation
  • Make sure gameoverAnimation is the selected timeline and add a position keypoint for the gameoverView at time 0.
  • Drag the time marker to 1 second and drag the gameoverView to align it with the stage.
  • Play the animation in the stage to make sure you are happy with the result. Save the file and return to NetBeans.
  • Add references to the new elements as class instance variables in class SicVacGoe:
    private SVGElement winnerCircle, winnerCross, winnerTie, gameoverView;
    private SVGAnimationElement gameoverAnimation;
    
    And initialize these variables in the initialize() method (below the setting of doc):
    gameoverAnimation = (SVGAnimationElement) doc.getElementById("gameoverAnimation");
    winnerCircle = (SVGElement) doc.getElementById("winnerCircle");
    winnerCross = (SVGElement) doc.getElementById("winnerCross");
    winnerTie = (SVGElement) doc.getElementById("winnerTie");
    gameoverView = (SVGElement) doc.getElementById("gameoverView");
    
  • In the resetGame() method, make sure to hide all elements that are not supposed to be displayed when starting a game.
    gameoverView.setTrait("display", "none");
    winnerCircle.setTrait("display", "none");
    winnerCross.setTrait("display", "none");
    winnerTie.setTrait("display", "none");
  • Replace the //game is over comment with
    gameoverAnimation.beginElementAt(0);
    gameoverView.setTrait("display", "inherit");
    
    to trigger the animation when the game is over. Display the winner using the following code block.
    switch(gameEngine.getWinner())
    {
        case GameEngine.PLAYER_CIRCLE:
            winnerCircle.setTrait("display", "inherit");
            break;
        case GameEngine.PLAYER_CROSS:
            winnerCross.setTrait("display", "inherit");
            break;
        case GameEngine.PLAYER_NONE:
            winnerTie.setTrait("display", "inherit");
            break;
    }
    
There you go. A simple tic-tac-toe game spiced up using a little bit of svg magic.

To try out your new game on a phone you will need a phone supporting JSR-226. For a list of phones supporting JSR-226, please go here.

  • In NetBeans IDE, right-click the Projects tab in the upper left view, and select Deploy Project from the context menu.
  • This will compile the project into the file SicVacGoe.jar and save it into a folder dist in your project folder.
  • Transfer the jar file onto your phone and install it.
  • Enjoy!
Tools: Overview
Animator
  Purchase Online
 Support
 Gallery
 Downloads
 FAQ
 Developers
CDK
IDE


About the tutorial

In this tutorial we will create a simple Tic Tac Toe game. We will use NetBeans to create the game logic in Java and Ikivo Animator to prepare the SVG graphics for the game and the JSR-226 API to let the Java game logic use the SVG graphics in an easy way.

SVG Tools for Mobile Applications