他的书上面有介绍游戏框架,而且很详细,但是没有这个全面,现在的很多游戏书籍也很少有关于游戏框架的构建,希望大家可以多借鉴一下,多提提意见!
先上图:
第一个教程就先搭建属于我们的游戏框架:
com.mocn.framework中是框架包
com.mocn.airBottle中是游戏包
首先看框架包 中的BaseActivity类,主要用于设置横竖屏,全屏,屏幕的宽高度等等。
package com.mocn.framework;
import android.R;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Window;
import android.view.WindowManager;
/**
* Activity的基类,本类中只要设置屏幕为竖屏,全屏,得到屏幕的高度和宽度
*
* @author Administrator
*
*/
public class BaseActivity extends Activity {
/**
* Activity创建时执行的方法
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setFullScreen();// 设置全屏
setLandscape();// 设置横屏
Global.context = this;// 获取上下文事件
// 获取屏幕的宽高
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
Global.screenWidth = dm.widthPixels;// 获取屏幕的宽度
Global.screenHeight = dm.heightPixels;// 获取屏幕的高度
}
/**
* 设置为全屏的方法
*/
public void setFullScreen() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
/**
* 设置为竖屏的方法
*/
public void setPortrait() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
/**
* 设置为横屏的方法
*/
public void setLandscape() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
BaseView,主要用于设置线程的开关,游戏界面的绘制
package com.mocn.framework;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
/**
* 游戏界面的基类 SurfaceHolder,线程的开启和关闭,添加組件drawSurfaceView
*
* @author Administrator
*
*/
public abstract class BaseView extends SurfaceView implements Callback,
Runnable {
private SurfaceHolder holder;// SurfaceHolder的引用
private Thread currentThread;// Thread的引用
public int sleepTime = 20;// 设置睡眠时间
public BaseView(Context context) {
super(context);
holder = this.getHolder();// 得到holder对象
holder.addCallback(this);// 得到调函数对象
}
/**
* 开启线程的方法
*/
public void startThread() {
currentThread = new Thread(this);// 得到线程的对象
currentThread.start();// 开启线程
}
/**
* 关闭线程的方法
*/
public void stopThread() {
currentThread = null;// 设置线程为空
}
/**
* 当界面改变时执行的方法
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/**
* 当界面创建时执行的方法
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
startThread();// 开启游戏线程
}
/**
* 当游戏被摧毁时执行的方法
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopThread();// 关闭游戏线程
}
/**
* 绘制界面的方法
*
* @param canvas
* @param paint
*/
public void drawSurfaceView(Canvas canvas, Paint paint) {
LayerManager.drawLayerManager(canvas, paint);// 绘制组件
}
/**
* 线程的控制方法
*/
@Override
public void run() {
Canvas canvas;
Paint paint = new Paint();
while (currentThread != null) {
canvas = holder.lockCanvas();
drawSurfaceView(canvas, paint);
holder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Global类,用于设置一些常量
package com.mocn.framework;
import android.content.Context;
/**
* 得到屏幕的宽度,高度,Context对象
*
* @author Administrator
*
*/
public class Global
{
public static Context context;//得到上下文的引用
public static int screenWidth;//屏幕的宽度
public static int screenHeight;//屏幕的高度
}
Layer类,所以绘制组件的基类,里面包括组件的坐标,宽高,以及绘制的方法等
package com.mocn.framework;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* 层类,组件的父类,添加组件,设置组件位置,绘制自己, 是所有人物和背景的基类
*
* @author Administrator
*
*/
public abstract class Layer {
public float x;// 层的x坐标
public float y;// 层的y坐标
public int w;// 层的宽度
public int h;// 层的高度
public Rect src, dst;// 引用Rect类
public Bitmap bitmap;// 引用Bitmap类
protected Layer(Bitmap bitmap, int w, int h, boolean autoAdd) {
this.bitmap = bitmap;
this.w = w;
this.h = h;
src = new Rect();
dst = new Rect();
if (autoAdd) {
LayerManager.addLayer(this);// 在LayerManager类中添加本组件
}
}
/**
* 设置组件位置的方法
*
* @param x
* @param y
*/
public void setPosition(float x, float y) {
this.x = x;
this.y = y;
}
/**
* 绘制自己的抽象接口
*
* @param canvas
* @param paint
*/
public abstract void drawSelf(Canvas canvas, Paint paint);
}
BackGroundLayer类,主要用于背景的绘制,可以用做静态的绘制
package com.mocn.framework;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* 游戏背景组件,在LayerManager中添加游戏背景组件,绘制自己
*
* @author Administrator
*
*/
public class BackGroundLayer extends Layer
{
public BackGroundLayer(Bitmap bitmap, int w, int h)
{
super(bitmap, w, h, true);
}
@Override
public void drawSelf(Canvas canvas, Paint paint)
{
src.left = 0;
src.top = 0;
src.right = w;
src.bottom = h;
dst.left = (int) x;
dst.top = (int) y;
dst.right = dst.left + w;
dst.bottom = dst.top + h;
canvas.drawBitmap(bitmap, src, dst, paint);
}
}
Sprite类,精灵类,用于绘制动态人物
package com.mocn.framework;
import java.util.Hashtable;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* 精灵组件类,添加精灵组件,设置动作,绘制精灵,添加一个动作序列,精灵动作类
*
* @author Administrator
*
*/
public class Sprite extends Layer {
public int frameIdx;// 当前帧下标
public int currentFrame = 0;// 当前帧
public Hashtable<String, SpriteAction> actions;// 动作集合
public SpriteAction currentAction;// 当前动作
public Sprite(Bitmap bitmap, int w, int h, boolean autoAdd) {
super(bitmap, w, h, autoAdd);
actions = new Hashtable<String, Sprite.SpriteAction>();// 用Hashtable保存动作集合
}
/**
* 设置动作的方法
*
* @param actionName
*/
public void setAction(String actionName) {
currentAction = actions.get(actionName);// 从动作集合中得到该动作
}
/**
* 绘制精灵的方法
*/
@Override
public void drawSelf(Canvas canvas, Paint paint) {
if (currentAction != null) {
currentFrame = currentAction.frames[frameIdx];// 获取当前需要的帧
}
// 截取图片中需要的帧
src.left = currentFrame * w;// 左端宽度:当前帧乘上帧的宽度
src.top = 0;// 上端高度:0
src.right = src.left + w;// 右端宽度:左端宽度加上帧的宽度
src.bottom = h;// 下端高度为帧的高度
// 绘制在界面上,取中心点绘制
dst.left = (int) x - w / 2;
dst.top = (int) y - h / 2;
dst.right = dst.left + w;
dst.bottom = dst.top + h;
canvas.drawBitmap(bitmap, src, dst, paint);// 绘制当前帧
if (currentAction != null) {
currentAction.nextFrame();// 绘制下一帧
}
}
/**
* 添加一个动作集合的方法
*
* @param name
* @param frames
* @param frameTime
*/
public void addAction(String name, int[] frames, int[] frameTime) {
SpriteAction sp = new SpriteAction();// 创建SpiteAction的对象
sp.frames = frames;// 当前帧的数量,用下标表示
sp.frameTime = frameTime;// 每一帧切换的时间
actions.put(name, sp);// 将名字为"name"的动作集合,值为sp的动作集合放进acitons中
}
/**
* 精灵的移动方法
*
* @param dx
* @param dy
*/
public void move(int dx, int dy) {
this.x += dx;
this.y += dy;
}
// 精灵动作类
class SpriteAction {
public int[] frames;// 该动作的帧序列
public int[] frameTime;// 帧序列中每一帧切换对应的时间
private long updateTime;// 记录上次失效时间
/**
* 切换到下一帧的方法
*/
public void nextFrame() {
if (System.currentTimeMillis() > updateTime) {
frameIdx++;// 帧下标增加
frameIdx %= frames.length;
updateTime = System.currentTimeMillis() + frameTime[frameIdx];// 切换下一帧所需要的时间
}
}
}
}
LayerManager类,组件管理类,用于管理组件
package com.mocn.framework;
import java.util.Vector;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* 组件的管理类,用于存放组件,绘制所有组件,添加一个组件,删除一个组件,插入一组件
*
*
* @author Administrator
*
*/
public class LayerManager {
public static Vector<Layer> vec = new Vector<Layer>(); // Vector对象用于存放所有组件
/**
* 绘制所有组件的方法
*
* @param canvas
* @param paint
*/
public static void drawLayerManager(Canvas canvas, Paint paint) {
for (int i = 0; i < vec.size(); i++) {
vec.elementAt(i).drawSelf(canvas, paint);// 把存在于Vector对象中的组件绘制出来
}
}
/**
* 添加一个组件的方法
*
* @param layer
*/
public static synchronized void addLayer(Layer layer) {
vec.add(layer);// 在Vector对象中添加此组件
}
/**
* 删除一个组件的方法
*
* @param layer
*/
public static synchronized void deleteLayer(Layer layer) {
vec.remove(layer);// 在Vector对象中删除此组件
}
/**
* 在before指定的位置插入layer,原来对象以及此后的对象依次往后顺延。
*
* @param layer
* @param before
*/
public static void insert(Layer layer, Layer before) {
for (int i = 0; i < vec.size(); i++) {// 遍历Vector对象
if (before == vec.elementAt(i)) {
vec.insertElementAt(layer, i);// 在before对象前面插入layer,该对象位于before之上
return;
}
}
}
}
最后一个,Utilsl类,工具类,包含各种取得图片,碰撞事件的检测等方法
package com.mocn.framework;
import java.io.IOException;
import java.io.InputStream;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
* 工具类 获得一张图片,判断两个矩形是否相交,判断一个点是否在矩形内
*
* @author Administrator
*
*/
public class Utils {
/**
* 获取一张图片的方法
*
* @param path
* @return
*/
public static Bitmap getBitmap(String path) {
try {
InputStream is = Global.context.getAssets().open(path);
return BitmapFactory.decodeStream(is);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 判断两个矩形是否相交的方法
*
* @param x
* @param y
* @param w
* @param h
* @param x2
* @param y2
* @param w2
* @param h2
* @return
*/
public static boolean colliseWidth(float x, float y, float w, float h,
float x2, float y2, float w2, float h2) {
if (x > x2 + w2 || x2 > x + w || y > y2 + h2 || y2 > y + h) {
return false;
}
return true;
}
/**
* 判断 一个点是否在矩形内的方法
*
* @param x
* @param y
* @param w
* @param h
* @param px
* @param py
* @return
*/
public static boolean inRect(float x, float y, float w, float h, float px,
float py) {
if (px > x && px < x + w && py > y && py < y + h) {
return true;
}
return false;
}
}
框架搭建完成,第二篇就是游戏的绘制篇了,如果大家在框架上有什么问题可以问我。