Saturday, January 15, 2011

J2ME 4 WAY SCROLLING GAME
   Part 1
   INTRODUCTION:
Truth be said,i really never had much interest in mobile games until very recently when i had a go at  the mobile version of the call of duty game. The four-way scrolling canvas instantly caught my attention and i decided to develop something similar and by similar i mean just the four-way scrolling concept. There are tons of resources on java me programming and most importantly the GameCanvas package API out there and almost all this content is available for free online.

Getting started is no problem for anyone with prior experience in java programming. I kicked off with the usual hello word!!. The reason i posted this blog is because i could not find a good tutorial anywhere that focused on a four-way scrolling tutorial where the player character walked around in a 2d world in all directions. (I think its called 2.5d ). I f there is such a tutorial maybe i never came across it.
Anyway after lots of trial and error, i have come up with a working example where the player can walk around in all directions in the game world. I used the GameCanvas classes which makes life so much easier...i can't help but wonder why in most commercial games the developers go out of there way to develop  complex custom code to do the same job, maybe its due to performance,compatibility etc. anyway for my purposes i do not think its worth the effort.
Here are some screen shots of the work in progress.
scrolling right    




scrolling up

scrolling left



scrolling down   

I will not go into the details of how to setup the details of how to setup the j2me development environment but for a beginner,it is best to use the netbeans IDE;it has a pretty user friendly mobility pack that is straight forward to use.

Any j2me project must have the startApp(){};pauseApp(){}; and destroyApp(){};
 
Its pretty straight forward and needs no explanation.

import java.io.IOException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.*;

/**
 * @author kimlexson
 */
public class main extends MIDlet
    implements CommandListener {

/**
 * new instance of the GameManager class sets the display to the canvas
 */
   private GameManager game_manager;

    public void startApp() {

        if(game_manager == null)
        try
        {   
             game_manager = new GameManager();
             game_manager.init();

             Command exitCommand = new Command("Exit",Command.EXIT, 0);
             game_manager.addCommand(exitCommand);
             game_manager.setCommandListener(this);
            
        }catch (IOException e) {
        System.out.println(e);
      }
         Display.getDisplay(this).setCurrent(game_manager);
       
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional)
    {
       
    }

    public void commandAction(Command cmnd, Displayable dsplbl)
    {
       if (cmnd.getCommandType() == Command.EXIT) {
      destroyApp(true);
      notifyDestroyed();
    }
    }
}

the GameManager class will implement the Runnable interface meaning that it will have a single thread that will loop continuously as long as the game is alive and it will be alternating sleeping for a few milliseconds and then runs again. It also instantiates the sprites,the tile layer and the layer manager.


import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.TiledLayer;
/**
*
* @author kim
*/
public class GameManager extends GameCanvas implements Runnable {

    private int loop = 50;
    private int width;
    private int height;
    private int speed = 3;
   
    private int offsetx,offsety;

    private boolean isAlive;
    private Thread mainThread = null;
    private LayerManager Lman;
    private TiledLayer tileLay;
    private TiledLayer tileBackGround;

    private levelMaps maps;
    private PlayaSprite pSrite;
    private Enemy eSprite;

   private int []seq_Xaxis = { 0, 1, 2, 3, 4, 5};
   private int []seq_up    = { 6, 7, 8, 9,10,11};
   private int []seq_down  = {12,13,14,15,16,17,};
   private int p1x;
   private int p1y;


    public GameManager() throws IOException
    {
            super(true);
        
            width = getWidth();
            height = getHeight();
            Lman = new LayerManager();

             maps = new levelMaps(1);
             tileLay =  maps.getMap();

             maps = new levelMaps(2);
             tileBackGround = maps.getMap();
     
            pSrite = new PlayaSprite();
            eSprite = new Enemy();

            pSrite.InitPos(width >> 1,height >> 1);
            eSprite.InitPos(400, 250);

            offsetx = pSrite.getX() - width >> 3;
            offsety = pSrite.getY() - width >> 3;

            Lman.append(pSrite);
            Lman.append(eSprite);
            Lman.append(tileLay);
            Lman.append(tileBackGround);
          

    }

    public void init(){

            isAlive = true;

            mainThread = new Thread(this);
            mainThread.start();           
    }

    public void run() {

            Graphics g = getGraphics();
            while (mainThread.isAlive())
            {
            try {
                if (isShown()) {
                    if (isAlive) {
                        controls();
                    }
                    paint(g);
                }
                Thread.sleep(loop);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
                
            }
  }


    public boolean collisionState()
    {  
         return pSrite.collidesWith(tileLay,true);
    }

    public void dead_End()
    {
        if(pSrite.collidesWith(tileLay,true))
            pSrite.setPosition(p1x,p1y);

        if(!collisionState())
        {
            p1x = pSrite.getX();
            p1y = pSrite.getY();
        }
    }

      public void set_frame_seq(int[] seq2)
      {
         
          if(!pSrite.compare_Seq(seq2))
          {
             pSrite.setFrameSequence(seq2);
             pSrite.set_current_Seq(seq2);
  
          }else
         
          pSrite.anim();    
      }

    public void controls()
    {
       int keys = getKeyStates();
            dead_End();
            //left
            if((keys & LEFT_PRESSED) != 0)
            {
               set_frame_seq(seq_Xaxis);
               pSrite.moveLeft(speed * -1);

               if(!collisionState())
               offsetx += -3;
           
            }

            //right
            if((keys & RIGHT_PRESSED) != 0)
            {
                set_frame_seq(seq_Xaxis);
               pSrite.moveRight(speed);

                if(!collisionState())
                offsetx += speed;           
            }

           //up
           if((keys & UP_PRESSED) != 0)
           {
              set_frame_seq(seq_up);
             pSrite.moveUp(speed *-1);

             if(!collisionState())
             offsety += -3;
                
           }

           //down
           if((keys & DOWN_PRESSED) != 0)
           {
                set_frame_seq(seq_down);
                pSrite.moveDown(speed);

                if(!collisionState())
                offsety += speed;
           
           } 
    }

    public void paint(Graphics g){
            g.fillRect(0, 0, width, height);
            Lman.paint(g, 0, 0);
            g.setColor(0x0024B400);
            Lman.setViewWindow(offsetx,offsety, width, height);
            flushGraphics();
    }
}

 Both the terrain objects(buildings) and the background(ground) are maintained on two separate tiled Layers which are added to one LayerManager in order to create the game world. The tile layer class is discussed more in-depth in part two.
 The Sprite class also manages the player and the enemies but am still working on the enemies to be able to collide with player and maybe throw-in some little AI so that they can chase around the player.  For the sprites, i am using the frame sequence to animate the player and this will also be discussed in subsequent parts. 

 



No comments:

Post a Comment