Tuesday 26 February 2013

Android Game Development Tutorial [ Part5 ]


Hi Friends,
            Welcome you all in the Android Game Development Part 5.

In the Part4 we were setting up the Game Architecture. We have created the interfaces. In this part5 we will continue our Game Architecture setup.

Setting Up the Game Architecture:-
           
In the previous part we have completed till step 6. We will continue from there.

7)    Right click on the src directory , New à Package.
Give the package name com.pocogame.framework.implementation
8)    Right click on the package com.pocogame.framework.implementation and create the following classes.
a.     AndroidAudio.java
b.     AndroidFileIO.java
c.      AndroidGame.java
d.     AndroidGraphics.java
e.     AndroidImage.java
f.       AndroidInput.java
g.     AndroidMusic.java
h.     AndroidSound.java
i.        AndoirdView.java
j.       MultiTouchHandler.java
k.     SingleTouchHandler.java
l.        TouchHandler.java
9)    Copy and paste following codes into the respective java file.

a.     /************  AndroidAudio.java  ******************/
package com.pocogame.framework.implementation;

import java.io.IOException;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.SoundPool;
import com.pocogame.framework.Audio;
import com.pocogame.framework.Music;
import com.pocogame.framework.Sound;

public class AndroidAudio implements Audio {
    AssetManager assets;
    SoundPool soundPool;

    public AndroidAudio(Activity activity) {
        activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        this.assets = activity.getAssets();
        this.soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
    }

    @Override
    public Music createMusic(String filename) {
        try {
            AssetFileDescriptor assetDescriptor = assets.openFd(filename);
            return new AndroidMusic(assetDescriptor);
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load music '" + filename + "'");
        }
    }


    @Override
    public Sound createSound(String filename) {
        try {
            AssetFileDescriptor assetDescriptor = assets.openFd(filename);
            int soundId = soundPool.load(assetDescriptor, 0);
            return new AndroidSound(soundPool, soundId);
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load sound '" + filename + "'");
        }
    }
}



b.     /************  AndroidFileIO.java  ******************/
package com.pocogame.framework.implementation;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.os.Environment;
import android.preference.PreferenceManager;

import com.pocogame.framework.FileIO;

public class AndroidFileIO implements FileIO {
 Context context;
    AssetManager assets;
    String externalStoragePath;

    public AndroidFileIO(Context context) {
        this.context = context;
        this.assets = context.getAssets();
        this.externalStoragePath = Environment.getExternalStorageDirectory()
                .getAbsolutePath() + File.separator;
        
 
    
    }

    @Override
    public InputStream readAsset(String file) throws IOException {
        return assets.open(file);
    }

    @Override
    public InputStream readFile(String file) throws IOException {
        return new FileInputStream(externalStoragePath + file);
    }

    @Override
    public OutputStream writeFile(String file) throws IOException {
        return new FileOutputStream(externalStoragePath + file);
    }
    
    public SharedPreferences getSharedPref() {
     return PreferenceManager.getDefaultSharedPreferences(context);
    }
}

c.      /************  AndroidGame.java  ******************/
package com.pocogame.framework.implementation;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;

import com.pocogame.framework.Audio;
import com.pocogame.framework.FileIO;
import com.pocogame.framework.Game;
import com.pocogame.framework.Graphics;
import com.pocogame.framework.Input;
import com.pocogame.framework.Screen;

public abstract class AndroidGame extends Activity implements Game {
    AndroidView renderView;
    Graphics graphics;
    Audio audio;
    Input input;
    FileIO fileIO;
    Screen screen;
    WakeLock wakeLock;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        int frameBufferWidth = isPortrait ? 480: 800;
        int frameBufferHeight = isPortrait ? 800: 480;
        Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
                frameBufferHeight, Config.RGB_565);
        
        float scaleX = (float) frameBufferWidth
                / getWindowManager().getDefaultDisplay().getWidth();
        float scaleY = (float) frameBufferHeight
                / getWindowManager().getDefaultDisplay().getHeight();

        renderView = new AndroidView(this, frameBuffer);
        graphics = new AndroidGraphics(getAssets(), frameBuffer);
        fileIO = new AndroidFileIO(this);
        audio = new AndroidAudio(this);
        input = new AndroidInput(this, renderView, scaleX, scaleY);
        screen = getInitScreen();
        setContentView(renderView);
        
        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MyGame");
    }

    @Override
    public void onResume() {
        super.onResume();
        wakeLock.acquire();
        screen.resume();
        renderView.resume();
    }

    @Override
    public void onPause() {
        super.onPause();
        wakeLock.release();
        renderView.pause();
        screen.pause();

        if (isFinishing())
            screen.dispose();
    }

    @Override
    public Input getInput() {
        return input;
    }

    @Override
    public FileIO getFileIO() {
        return fileIO;
    }

    @Override
    public Graphics getGraphics() {
        return graphics;
    }

    @Override
    public Audio getAudio() {
        return audio;
    }

    @Override
    public void setScreen(Screen screen) {
        if (screen == null)
            throw new IllegalArgumentException("Screen must not be null");

        this.screen.pause();
        this.screen.dispose();
        screen.resume();
        screen.update(0);
        this.screen = screen;
    }
    
    public Screen getCurrentScreen() {

     return screen;
    }
}
d.     /************  AndroidGraphics.java  ******************/
package com.pocogame.framework.implementation;

import java.io.IOException;
import java.io.InputStream;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;

import com.pocogame.framework.Graphics;
import com.pocogame.framework.Image;

public class AndroidGraphics implements Graphics {
    AssetManager assets;
    Bitmap frameBuffer;
    Canvas canvas;
    Paint paint;
    Rect srcRect = new Rect();
    Rect dstRect = new Rect();

    public AndroidGraphics(AssetManager assets, Bitmap frameBuffer) {
        this.assets = assets;
        this.frameBuffer = frameBuffer;
        this.canvas = new Canvas(frameBuffer);
        this.paint = new Paint();
    }

    @Override
    public Image newImage(String fileName, ImageFormat format) {
        Config config = null;
        if (format == ImageFormat.RGB565)
            config = Config.RGB_565;
        else if (format == ImageFormat.ARGB4444)
            config = Config.ARGB_4444;
        else
            config = Config.ARGB_8888;

        Options options = new Options();
        options.inPreferredConfig = config;
        
        
        InputStream in = null;
        Bitmap bitmap = null;
        try {
            in = assets.open(fileName);
            bitmap = BitmapFactory.decodeStream(in, null, options);
            if (bitmap == null)
                throw new RuntimeException("Couldn't load bitmap from asset '"
                        + fileName + "'");
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load bitmap from asset '"
                    + fileName + "'");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }

        if (bitmap.getConfig() == Config.RGB_565)
            format = ImageFormat.RGB565;
        else if (bitmap.getConfig() == Config.ARGB_4444)
            format = ImageFormat.ARGB4444;
        else
            format = ImageFormat.ARGB8888;

        return new AndroidImage(bitmap, format);
    }

    @Override
    public void clearScreen(int color) {
        canvas.drawRGB((color & 0xff0000) >> 16, (color & 0xff00) >> 8,
                (color & 0xff));
    }


    @Override
    public void drawLine(int x, int y, int x2, int y2, int color) {
        paint.setColor(color);
        canvas.drawLine(x, y, x2, y2, paint);
    }

    @Override
    public void drawRect(int x, int y, int width, int height, int color) {
        paint.setColor(color);
        paint.setStyle(Style.FILL);
        canvas.drawRect(x, y, x + width - 1, y + height - 1, paint);
    }
    
    @Override
    public void drawARGB(int a, int r, int g, int b) {
        paint.setStyle(Style.FILL);
       canvas.drawARGB(a, r, g, b);
    }
    
    @Override
    public void drawString(String text, int x, int y, Paint paint){
     canvas.drawText(text, x, y, paint);

     
    }
    

    public void drawImage(Image Image, int x, int y, int srcX, int srcY,
            int srcWidth, int srcHeight) {
        srcRect.left = srcX;
        srcRect.top = srcY;
        srcRect.right = srcX + srcWidth;
        srcRect.bottom = srcY + srcHeight;
        
        
        dstRect.left = x;
        dstRect.top = y;
        dstRect.right = x + srcWidth;
        dstRect.bottom = y + srcHeight;

        canvas.drawBitmap(((AndroidImage) Image).bitmap, srcRect, dstRect,
                null);
    }
    
    @Override
    public void drawImage(Image Image, int x, int y) {
        canvas.drawBitmap(((AndroidImage)Image).bitmap, x, y, null);
    }
    
    public void drawScaledImage(Image Image, int x, int y, int width, int height, int srcX, int srcY, int srcWidth, int srcHeight){
     
     
     srcRect.left = srcX;
        srcRect.top = srcY;
        srcRect.right = srcX + srcWidth;
        srcRect.bottom = srcY + srcHeight;
        
        
        dstRect.left = x;
        dstRect.top = y;
        dstRect.right = x + width;
        dstRect.bottom = y + height;
        
   
        
        canvas.drawBitmap(((AndroidImage) Image).bitmap, srcRect, dstRect, null);
        
    }
   
    @Override
    public int getWidth() {
        return frameBuffer.getWidth();
    }

    @Override
    public int getHeight() {
        return frameBuffer.getHeight();
    }
}

e.     /************  AndroidImage.java  ******************/
package com.pocogame.framework.implementation;

import android.graphics.Bitmap;

import com.pocogame.framework.Image;
import com.pocogame.framework.Graphics.ImageFormat;

public class AndroidImage implements Image {
    Bitmap bitmap;
    ImageFormat format;
    
    public AndroidImage(Bitmap bitmap, ImageFormat format) {
        this.bitmap = bitmap;
        this.format = format;
    }

    @Override
    public int getWidth() {
        return bitmap.getWidth();
    }

    @Override
    public int getHeight() {
        return bitmap.getHeight();
    }

    @Override
    public ImageFormat getFormat() {
        return format;
    }

    @Override
    public void dispose() {
        bitmap.recycle();
    }      
}

f.       /************  AndroidInput.java  ******************/
package com.pocogame.framework.implementation;

import java.util.List;

import android.content.Context;
import android.os.Build.VERSION;
import android.view.View;

import com.pocogame.framework.Input;

public class AndroidInput implements Input {    
    TouchHandler touchHandler;

    public AndroidInput(Context context, View view, float scaleX, float scaleY) {
        if(Integer.parseInt(VERSION.SDK) < 5) 
            touchHandler = new SingleTouchHandler(view, scaleX, scaleY);
        else
            touchHandler = new MultiTouchHandler(view, scaleX, scaleY);        
    }


    @Override
    public boolean isTouchDown(int pointer) {
        return touchHandler.isTouchDown(pointer);
    }

    @Override
    public int getTouchX(int pointer) {
        return touchHandler.getTouchX(pointer);
    }

    @Override
    public int getTouchY(int pointer) {
        return touchHandler.getTouchY(pointer);
    }



    @Override
    public List getTouchEvents() {
        return touchHandler.getTouchEvents();
    }
    
}
/*

*/
g.     /************  AndroidMusic.java  ******************/
package com.pocogame.framework.implementation;

import java.io.IOException;

import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;

import com.pocogame.framework.Music;

public class AndroidMusic implements Music, OnCompletionListener, OnSeekCompleteListener, OnPreparedListener, OnVideoSizeChangedListener {
    MediaPlayer mediaPlayer;
    boolean isPrepared = false;

    public AndroidMusic(AssetFileDescriptor assetDescriptor) {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(assetDescriptor.getFileDescriptor(),
                    assetDescriptor.getStartOffset(),
                    assetDescriptor.getLength());
            mediaPlayer.prepare();
            isPrepared = true;
            mediaPlayer.setOnCompletionListener(this);
            mediaPlayer.setOnSeekCompleteListener(this);
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setOnVideoSizeChangedListener(this);
            
        } catch (Exception e) {
            throw new RuntimeException("Couldn't load music");
        }
    }

    @Override
    public void dispose() {
    
      if (this.mediaPlayer.isPlaying()){
            this.mediaPlayer.stop();
             }
        this.mediaPlayer.release();
    }

    @Override
    public boolean isLooping() {
        return mediaPlayer.isLooping();
    }

    @Override
    public boolean isPlaying() {
        return this.mediaPlayer.isPlaying();
    }

    @Override
    public boolean isStopped() {
        return !isPrepared;
    }

    @Override
    public void pause() {
        if (this.mediaPlayer.isPlaying())
            mediaPlayer.pause();
    }

    
    
    @Override
    public void play() {
        if (this.mediaPlayer.isPlaying())
            return;

        try {
            synchronized (this) {
                if (!isPrepared)
                    mediaPlayer.prepare();
                mediaPlayer.start();
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void setLooping(boolean isLooping) {
        mediaPlayer.setLooping(isLooping);
    }

    @Override
    public void setVolume(float volume) {
        mediaPlayer.setVolume(volume, volume);
    }

    @Override
    public void stop() {
      if (this.mediaPlayer.isPlaying() == true){
        this.mediaPlayer.stop();
        
       synchronized (this) {
           isPrepared = false;
        }}
    }

    @Override
    public void onCompletion(MediaPlayer player) {
        synchronized (this) {
            isPrepared = false;
        }
    }

 @Override
 public void seekBegin() {
  mediaPlayer.seekTo(0);
  
 }


 @Override
 public void onPrepared(MediaPlayer player) {
  // TODO Auto-generated method stub
   synchronized (this) {
            isPrepared = true;
         }
  
 }

 @Override
 public void onSeekComplete(MediaPlayer player) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void onVideoSizeChanged(MediaPlayer player, int width, int height) {
  // TODO Auto-generated method stub
  
 }
}

h.     /************  AndroidSound.java  ******************/
package com.pocogame.framework.implementation;

import android.media.SoundPool;

import com.pocogame.framework.Sound;

public class AndroidSound implements Sound {
    int soundId;
    SoundPool soundPool;

    public AndroidSound(SoundPool soundPool, int soundId) {
        this.soundId = soundId;
        this.soundPool = soundPool;
    }

    @Override
    public void play(float volume) {
        soundPool.play(soundId, volume, volume, 0, 0, 1);
    }

    @Override
    public void dispose() {
        soundPool.unload(soundId);
    }

}

i.        /************  AndoirdView.java  ******************/
package com.pocogame.framework.implementation;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class AndroidView extends SurfaceView implements Runnable {
    AndroidGame game;
    Bitmap framebuffer;
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;
    
    public AndroidView(AndroidGame game, Bitmap framebuffer) {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.holder = getHolder();

    }

    public void resume() { 
        running = true;
        renderThread = new Thread(this);
        renderThread.start();   

    }      
    
    public void run() {
        Rect dstRect = new Rect();
        long startTime = System.nanoTime();
        while(running) {  
            if(!holder.getSurface().isValid())
                continue;           
            

            float deltaTime = (System.nanoTime() - startTime) / 10000000.000f;
            startTime = System.nanoTime();
            
            if (deltaTime > 3.15){
             deltaTime = (float) 3.15;
           }
     

            game.getCurrentScreen().update(deltaTime);
            game.getCurrentScreen().paint(deltaTime);
          
            
            
            Canvas canvas = holder.lockCanvas();
            canvas.getClipBounds(dstRect);
            canvas.drawBitmap(framebuffer, null, dstRect, null);                           
            holder.unlockCanvasAndPost(canvas);
            
            
        }
    }

    public void pause() {                        
        running = false;                        
        while(true) {
            try {
                renderThread.join();
                break;
            } catch (InterruptedException e) {
                // retry
            }
            
        }
    }     
    
  
}
j.       /************  MultiTouchHandler.java  ******************/
package com.pocogame.framework.implementation;

import java.util.ArrayList;
import java.util.List;

import android.view.MotionEvent;
import android.view.View;

import com.pocogame.framework.Pool;
import com.pocogame.framework.Input.TouchEvent;
import com.pocogame.framework.Pool.PoolObjectFactory;

public class MultiTouchHandler implements TouchHandler {
 private static final int MAX_TOUCHPOINTS = 10;
 
 boolean[] isTouched = new boolean[MAX_TOUCHPOINTS];
 int[] touchX = new int[MAX_TOUCHPOINTS];
 int[] touchY = new int[MAX_TOUCHPOINTS];
 int[] id = new int[MAX_TOUCHPOINTS];
 Pool touchEventPool;
 List touchEvents = new ArrayList();
 List touchEventsBuffer = new ArrayList();
 float scaleX;
 float scaleY;

 public MultiTouchHandler(View view, float scaleX, float scaleY) {
  PoolObjectFactory factory = new PoolObjectFactory() {
   @Override
   public TouchEvent createObject() {
    return new TouchEvent();
   }
  };
  touchEventPool = new Pool(factory, 100);
  view.setOnTouchListener(this);

  this.scaleX = scaleX;
  this.scaleY = scaleY;
 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  synchronized (this) {
   int action = event.getAction() & MotionEvent.ACTION_MASK;
   int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
   int pointerCount = event.getPointerCount();
   TouchEvent touchEvent;
   for (int i = 0; i < MAX_TOUCHPOINTS; i++) {
    if (i >= pointerCount) {
     isTouched[i] = false;
     id[i] = -1;
     continue;
    }
    int pointerId = event.getPointerId(i);
    if (event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) {
     // if it's an up/down/cancel/out event, mask the id to see if we should process it for this touch
     // point
     continue;
    }
    switch (action) {
    case MotionEvent.ACTION_DOWN:
    case MotionEvent.ACTION_POINTER_DOWN:
     touchEvent = touchEventPool.newObject();
     touchEvent.type = TouchEvent.TOUCH_DOWN;
     touchEvent.pointer = pointerId;
     touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
     touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
     isTouched[i] = true;
     id[i] = pointerId;
     touchEventsBuffer.add(touchEvent);
     break;

    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_POINTER_UP:
    case MotionEvent.ACTION_CANCEL:
     touchEvent = touchEventPool.newObject();
     touchEvent.type = TouchEvent.TOUCH_UP;
     touchEvent.pointer = pointerId;
     touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
     touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
     isTouched[i] = false;
     id[i] = -1;
     touchEventsBuffer.add(touchEvent);
     break;

    case MotionEvent.ACTION_MOVE:
     touchEvent = touchEventPool.newObject();
     touchEvent.type = TouchEvent.TOUCH_DRAGGED;
     touchEvent.pointer = pointerId;
     touchEvent.x = touchX[i] = (int) (event.getX(i) * scaleX);
     touchEvent.y = touchY[i] = (int) (event.getY(i) * scaleY);
     isTouched[i] = true;
     id[i] = pointerId;
     touchEventsBuffer.add(touchEvent);
     break;
    }
   }
   return true;
  }
 }

 @Override
 public boolean isTouchDown(int pointer) {
  synchronized (this) {
   int index = getIndex(pointer);
   if (index < 0 || index >= MAX_TOUCHPOINTS)
    return false;
   else
    return isTouched[index];
  }
 }

 @Override
 public int getTouchX(int pointer) {
  synchronized (this) {
   int index = getIndex(pointer);
   if (index < 0 || index >= MAX_TOUCHPOINTS)
    return 0;
   else
    return touchX[index];
  }
 }

 @Override
 public int getTouchY(int pointer) {
  synchronized (this) {
   int index = getIndex(pointer);
   if (index < 0 || index >= MAX_TOUCHPOINTS)
    return 0;
   else
    return touchY[index];
  }
 }

 @Override
 public List getTouchEvents() {
  synchronized (this) {
   int len = touchEvents.size();
   for (int i = 0; i < len; i++)
    touchEventPool.free(touchEvents.get(i));
   touchEvents.clear();
   touchEvents.addAll(touchEventsBuffer);
   touchEventsBuffer.clear();
   return touchEvents;
  }
 }
 
 // returns the index for a given pointerId or -1 if no index.
 private int getIndex(int pointerId) {
  for (int i = 0; i < MAX_TOUCHPOINTS; i++) {
   if (id[i] == pointerId) {
    return i;
   }
  }
  return -1;
 }
}
/*

*/
k.     /************  SingleTouchHandler.java  ******************/
package com.pocogame.framework.implementation;

import java.util.ArrayList;
import java.util.List;

import android.view.MotionEvent;
import android.view.View;

import com.pocogame.framework.Pool;
import com.pocogame.framework.Input.TouchEvent;
import com.pocogame.framework.Pool.PoolObjectFactory;

public class SingleTouchHandler implements TouchHandler {
    boolean isTouched;
    int touchX;
    int touchY;
    Pool touchEventPool;
    List touchEvents = new ArrayList();
    List touchEventsBuffer = new ArrayList();
    float scaleX;
    float scaleY;
    
    public SingleTouchHandler(View view, float scaleX, float scaleY) {
        PoolObjectFactory factory = new PoolObjectFactory() {
            @Override
            public TouchEvent createObject() {
                return new TouchEvent();
            }            
        };
        touchEventPool = new Pool(factory, 100);
        view.setOnTouchListener(this);

        this.scaleX = scaleX;
        this.scaleY = scaleY;
    }
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        synchronized(this) {
            TouchEvent touchEvent = touchEventPool.newObject();
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchEvent.type = TouchEvent.TOUCH_DOWN;
                isTouched = true;
                break;
            case MotionEvent.ACTION_MOVE:
                touchEvent.type = TouchEvent.TOUCH_DRAGGED;
                isTouched = true;
                break;
            case MotionEvent.ACTION_CANCEL:                
            case MotionEvent.ACTION_UP:
                touchEvent.type = TouchEvent.TOUCH_UP;
                isTouched = false;
                break;
            }
            
            touchEvent.x = touchX = (int)(event.getX() * scaleX);
            touchEvent.y = touchY = (int)(event.getY() * scaleY);
            touchEventsBuffer.add(touchEvent);                        
            
            return true;
        }
    }

    @Override
    public boolean isTouchDown(int pointer) {
        synchronized(this) {
            if(pointer == 0)
                return isTouched;
            else
                return false;
        }
    }

    @Override
    public int getTouchX(int pointer) {
        synchronized(this) {
            return touchX;
        }
    }

    @Override
    public int getTouchY(int pointer) {
        synchronized(this) {
            return touchY;
        }
    }

    @Override
    public List getTouchEvents() {
        synchronized(this) {     
            int len = touchEvents.size();
            for( int i = 0; i < len; i++ )
                touchEventPool.free(touchEvents.get(i));
            touchEvents.clear();
            touchEvents.addAll(touchEventsBuffer);
            touchEventsBuffer.clear();
            return touchEvents;
        }
    }
}
/*

*/
l.        /************  TouchHandler.java  ******************/
package com.pocogame.framework.implementation;

import java.util.List;

import android.view.View.OnTouchListener;

import com.pocogame.framework.Input.TouchEvent;

public interface TouchHandler extends OnTouchListener {
    public boolean isTouchDown(int pointer);
    
    public int getTouchX(int pointer);
    
    public int getTouchY(int pointer);
    
    public List getTouchEvents();
}
/*

*/


In the next part we are going to see how we can re-use our old java game code for android game development.

Stay Tuned ………….            


Game Development "Part 4"


Friday 22 February 2013

Android Game Development tutorial [ Part 4 ]

Hello Friends,
            Welcome you all in the Android Game Development tutorial [part 4].

Let’s take a quick review of what we have learnt in the part3.
1)    How to setup the ADT (Android Development Tool)
2)    We have created our first Android Application.
3)    We have learnt how to run the application on Android Emulator.
4)    We have learnt how to port the android application on an Android Device.

Let’s have a look what we are going to learn in this part.
1)    Directory structure of the android application.
2)    AndroidManifest.xml file
3)    Setup the Game Architecture.

Let’s start with the Directory Structure of an Android Application.


Directory Structure of an Android Application:-

Android project are get build into the .apk file. You can install this file onto your Android Device.
The following directories and files comprise android project:-
·        src/
It contains your source code.
·        bin/
This is the output directory of build. Here you can find all the compiled files and .apk file.
·        jni/
It contains the native code developed using the Android NDK.
·        gen/
It contains the java file generated by the ADT such as R.java. The R.java file assigns a numerical value to the each resource what we use in our project.
·        assets/
This is an empty directory. We can use this directory to store the files which we need in our game development.
·        res/
It contains the application resources such as layout files, string values etc.
·        libs/
It contains the various dependent libraries required by the application.


AndroidManifest.xml :-

         This is the very important file of the Android Application.
Every application must have an AndroidManifest.xml file.
This file contains the essential information about the application like version number of the application, minimum SDK version, Main Activity, permissions etc.

Main Activity is like a main method of our application.
You can modify all these information provided by the AndroidManifest.xml file also according to your need.

The AndroidManifest.xml file looks like as follows :-



The AndroidManifest.xml file xml version look like as follows :-



Setup the Game Architecture :-
            There are the following steps you have to follow :-

            1)    Create new Android Application Project.
File à New à Android Application Project.
Give the project name PocoGame, package name com.pocogame.gamecode and click next.

  2)    Unchecked the create custom launcher icon and create activity. We are going to create it later manually.


3)    Right click on the src directory  à New à package.
Give the package name,  com.pocogame.framework

You can give any name whatever you would like to give.
4)    Right Click on the package directory com.pocogame.framework  à New à Interface.
Give the interface name Audio.java

Like that you have to create the following interface class.
a.     Audio.java
b.     FileIO.java
c.      Game.java
d.     Graphics.java
e.     Image.java
f.       Input.java
g.     Music.java
h.     Pool.java
i.        Sound.java

5)    Right Click on the package directory com.pocogame.framework  à New à Class.
Create an abstract class, give Screen.java to this class.


         6)    Copy paste the code into the respective java file.
         
/********************************************************/
          a.     Audio.java 
 /*********************************************************/
package com.pocogame.framework;

public interface Audio {
    public Music createMusic(String file);

    public Sound createSound(String file);
}


    /********************************************************/
          b.     FileIO.java
/********************************************************/
package com.pocogame.framework;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.SharedPreferences;

public interface FileIO {
    public InputStream readFile(String file) throws IOException;

    public OutputStream writeFile(String file) throws IOException;
    
    public InputStream readAsset(String file) throws IOException;
    
    public SharedPreferences getSharedPref();
}


/********************************************************/
          c.      Game.java
/********************************************************/
package com.pocogame.framework;

public interface Game {

    public Audio getAudio();

    public Input getInput();

    public FileIO getFileIO();

    public Graphics getGraphics();

    public void setScreen(Screen screen);

    public Screen getCurrentScreen();

    public Screen getInitScreen();
}

/********************************************************/
          d.     Graphics.java
/********************************************************/
package com.pocogame.framework;


import android.graphics.Paint;

public interface Graphics {
 public static enum ImageFormat {
  ARGB8888, ARGB4444, RGB565
 }

 public Image newImage(String fileName, ImageFormat format);

 public void clearScreen(int color);

 public void drawLine(int x, int y, int x2, int y2, int color);

 public void drawRect(int x, int y, int width, int height, int color);

 public void drawImage(Image image, int x, int y, int srcX, int srcY,
   int srcWidth, int srcHeight);

 public void drawImage(Image Image, int x, int y);

 void drawString(String text, int x, int y, Paint paint);

 public int getWidth();

 public int getHeight();

 public void drawARGB(int i, int j, int k, int l);

}

          e.     Image.java
/********************************************************/
package com.pocogame.framework;

import com.kilobolt.framework.Graphics.ImageFormat;

public interface Image {
    public int getWidth();
    public int getHeight();
    public ImageFormat getFormat();
    public void dispose();
}




/********************************************************/
          f.       Input.java
/********************************************************/
package com.pocogame.framework;

import java.util.List;

public interface Input {
    
    public static class TouchEvent {
        public static final int TOUCH_DOWN = 0;
        public static final int TOUCH_UP = 1;
        public static final int TOUCH_DRAGGED = 2;
        public static final int TOUCH_HOLD = 3;

        public int type;
        public int x, y;
        public int pointer;


    }

    public boolean isTouchDown(int pointer);

    public int getTouchX(int pointer);

    public int getTouchY(int pointer);

    public List getTouchEvents();
}
 

/********************************************************/
          g.     Music.java
/********************************************************/
package com.pocogame.framework;

public interface Music {
    public void play();

    public void stop();

    public void pause();

    public void setLooping(boolean looping);

    public void setVolume(float volume);

    public boolean isPlaying();

    public boolean isStopped();

    public boolean isLooping();

    public void dispose();

    void seekBegin();
}


/********************************************************/
          h.     Pool.java
/********************************************************/
package com.pocogame.framework;

import java.util.ArrayList;
import java.util.List;

public class Pool {
    public interface PoolObjectFactory {
        public T createObject();
    }

    private final List freeObjects;
    private final PoolObjectFactory factory;
    private final int maxSize;

    public Pool(PoolObjectFactory factory, int maxSize) {
        this.factory = factory;
        this.maxSize = maxSize;
        this.freeObjects = new ArrayList(maxSize);
    }

    public T newObject() {
        T object = null;

        if (freeObjects.size() == 0)
            object = factory.createObject();
        else
            object = freeObjects.remove(freeObjects.size() - 1);

        return object;
    }

    public void free(T object) {
        if (freeObjects.size() < maxSize)
            freeObjects.add(object);
    }
}
//

/********************************************************/
          i.        Sound.java
/********************************************************/
package com.pocogame.framework;

public interface Sound {
    public void play(float volume);

    public void dispose();
}


/********************************************************/
          j.   Screen.java
/********************************************************/
package com.pocogame.framework;

public abstract class Screen {
    protected final Game game;

    public Screen(Game game) {
        this.game = game;
    }

    public abstract void update(float deltaTime);

    public abstract void paint(float deltaTime);

    public abstract void pause();

    public abstract void resume();

    public abstract void dispose();
    
 public abstract void backButton();
}
           
In the next part we are going to create java classes that will use these interfaces. 

Stay tuned ....

Saturday 16 February 2013

Android Game Development Tutorial [ Part3 ]


Hi Friends,
            Welcome you all in the Android Game Development [Part3].

            Let’s take a quick review of what we have learnt in the Android Game Development [Part2].
1)    We have learnt about how to put Emotions.
2)    We have learnt about how to create Game Level.
3)    We have learnt about how to handle Collision Detection.
4)    We have learnt how to put these things all together to create a full game.

Let’s have a look what we are going to learn in this part.
1)    How to setup Development environment for Android.
2)    How to create a “Hello World” application.
3)    How to run the application on an Android Simulator.
4)    How to port the application on an Android Device.

First of all we will setup our development environment for Android.
For that you need to download the ANDROID DEVELOPER TOOL (ADT).

You can use the following link to download the ADT :-
http://developer.android.com/sdk/installing/bundle.html

            This single bundle gives everything you need for developing apps.
1)    Eclipse + ADT plugin
2)    Android SDK Tools
3)    Android Platform-tools
4)    Simulator

Setting up the Developer Tool:-
1)    Unzip the zip file named adt-bunlde-<os-platform>.zip and save it to some location where you want to save.
2)    Move to adt-bundle-<os-platform>/eclipse/ directory and run the eclipse exe.


Create our first Android Project:-

The steps for creating a new Android Application are as follows:-

1)    Go to File à New  and click on Android Application Project.






2)    Write your application name in the Application Name.
a.     Project Name: is the name of your project directory.
b.     Package Name: is the name package namespace.
c.      Minimum Required SDK: is the lowest version of Android that your app support.
d.     Target SDK: is the highest version of Android what your app support.
e.     Compile With: is the platform version against which your app will compile.
f.       Theme specifies: the Android UI style apply for your app.
3)    Click on the next button.
4)    Leave the next screen default and click on the next button.
5)    Next screen is the launcher icon screen. You can customize also. Leave this screen as default , click on the next button.
6)    Next screen belongs to the activity template. For this project select BlankActivity and click next button.
7)    Leave the next screen default and do Finish.
                      
   Now your first android application is ready with some default files.





How to Run on the Emulator:-

            First of all before running our application on the Emulator, we need to create an Android Virtual Device (AVD).
            
1)    Click on the Android Virtual Device Manager.
    The following image shows how AVD manager look like.


2)    Click on New Button. Type AVD name. I have given Galaxy Nexus. Select Device, choose Galaxy Nexus device. We will try to run our application on Galaxy Nexus emulator.







3)    Click on the OK button.
4)    Select your AVD device and click on the start button.
5)    Click on the Launch Button.


6)    You might get some error like the following image.


7)    To fix this error, select your AVD device and click on the edit button, change the ram size to 512.
8)    Start your AVD once again. This will take some long time.
9)    Then unlock your emulator screen.
10)           Click Run Button from the toolbar. 
         This will run your first application on the Emulator.

Your application on the Emulator will look like this.






Porting of the application on an Android Device:-
1)    Plug in your device to the development machine with a USB cable.
2)    Enable USB DEBUGGING on your device.
a.     On device Android 3.2 or older,  you can find this option under Settings à Applications à Development.
b.     On Android 4.0 and newer, it’s in Settings à Developer options.
On Android 4.2 and newer versions, Developer options is hidden by default. To make it available go to Setting à About phone and tap Build number seven times.
Return to previous screen to find the Developer option.

If you are developing on Windows then you might need to install a proper USB drive for you device.
If you are connected with net windows 7 will automatically install the proper driver.
The following link helps to install driver related things.


3)    Open your first application project and click on the RUN menu and select Run Configuration.
4)    Go to Target Tab.


5)    Select Always prompt to pick device and click on the run button
6)    Then choose a running Android device.
7)    Click ok.
Then you will see some messages on console window like Uploading FirstApp.apk on device.
Installing FirstApp.apk
Success!

Check it out your android device; you will be seeing the application running.

Enjoy your First Android Application buddies. 


In the next tutorial we will learn about:-
1) Android Directory Structure.
2) AndroidManifest.xml
3) Setup the Game Architecture.


Do comments, ask questions, and don't forgot to share it with your buddies.



Game Development "Part 2"