很详细,但是没有这个全面,现在的很多游戏书籍也很少有关于游戏框架的构建,希望大家可以多借鉴一下,多提提意见! 先上图:
第一个教程就先搭建属于我们的游戏框架: com.mocn.framework中是框架包 com.mocn.airBottle中是游戏包
首先看框架包 中的BaseActivity类,主要用于设置横竖屏,全屏,屏幕的宽高度等等。 ? package com.mocn.framework; http://biao.qqlove7.com 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; http://dudu.qqq23.com 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 框架搭建完成,第二篇就是游戏的绘制篇了,如果大家在框架上有 什么问题可以问我。 现在我们进行第二篇教学,有了框架我们可以自由地在屏幕上绘制我们想要的东西了。背景是用的BackGround组件,人物和子弹,还有精灵都是用的Sprite精灵组件 GameActivity类,游戏的主Activity类,在这里继承基类,只需要将界面替换为GameView就可以了。 ? package com.mocn.airBottle; import android.R; import android.os.Bundle; import com.mocn.framework.BaseActivity; import com.mocn.framework.BaseView; /** * 游戏的Activity类 * * @author Administrator * */ public class PlaneGameActivity extends BaseActivity { public BaseView baseView;// 引用BaseView public GameView gameView;// 引用GameView @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); baseView = new GameView(this);// 得到baseView对象 setContentView(baseView);;// 设置显示界面为baseView } } GameView类,游戏的主界面绘制类,在这里我们要绘制飞机和敌军,判断检测子弹和敌军的碰撞事件 ? package com.mocn.airBottle; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import com.mocn.framework.BackGroundLayer; import com.mocn.framework.BaseView; import com.mocn.framework.Utils; public class GameView extends BaseView implements OnTouchListener { BackGroundLayer backLayer;// 背景组件 Plane plane;// 飞机类 public boolean pressPlane = false; public GameView(Context context) { super(context); setOnTouchListener(this); // 绘制背景 backLayer = new BackGroundLayer(Utils.getBitmap(\"game/bg.png\"), 800, 480); backLayer.setPosition(0, 0); // 绘制飞机 plane = new Plane(Utils.getBitmap(\"game/plane.png\"), 150, 179); plane.setPosition(40, 300); } @Override public void drawSurfaceView(Canvas canvas, Paint paint) { super.drawSurfaceView(canvas, paint); GameData.bulletsAndEnemy();// 判断子弹和敌军的碰撞 GameData.createEnemy();// 创建敌军 } /** * 触摸事件执行的方法 */ @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) {// 按下执行的事件 // 按下点中飞机执行的方法 if (Utils.inRect(plane.x - plane.w / 2, plane.y - plane.h / 2, plane.w, plane.h, event.getX(), event.getY())) { pressPlane = true;// 将飞机可移动设置为true } } else if (event.getAction() == MotionEvent.ACTION_MOVE) {// 拖动执行的事件 if (pressPlane) { plane.setPosition(event.getX(), event.getY());// 将飞机的坐标设置为拖动时的坐标 } } else if (event.getAction() == MotionEvent.ACTION_UP) {// 释放按键时执行的方法 pressPlane = false;// 将飞机可移动设置为false } return true; } } Plane,飞机类,在飞机类中我们给它顺便装上子弹 ? package com.mocn.airBottle; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import com.mocn.framework.LayerManager; import com.mocn.framework.Sprite; import com.mocn.framework.Utils; /** * 飞机类 * * @author Administrator * */ public class Plane extends Sprite { public int timeSpan = 1000;// 飞机的发子弹间隔时间 public long updateTime = 0;// 飞机的更新时间 public Plane(Bitmap bitmap, int w, int h) { super(bitmap, w, h, true); } @Override public void drawSelf(Canvas canvas, Paint paint) { super.drawSelf(canvas, paint); // 给飞机装上子弹 if (System.currentTimeMillis() > updateTime) { // 创建子弹 Bullet b = new Bullet(Utils.getBitmap(\"game/buttle.png\"), 50, 50); b.setPosition(x + w / 2, y);// 设置子弹的位置 b.setAction(\"bb\");// 设置子弹的动作 LayerManager.insert(b, this);// 在飞机层的前面插入子弹层 GameData.bullets.add(b);// 添加一颗子弹 updateTime = System.currentTimeMillis() + timeSpan; } } } Buttle类,子弹类,在这个类中我们要设置子弹的动作和路线 ? package com.mocn.airBottle; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import com.mocn.framework.LayerManager; import com.mocn.framework.Sprite; /** * 子弹类,继承精灵类 * * @author Administrator * */ public class Bullet extends Sprite { public int speed = 10;// 子弹的速度 public Bullet(Bitmap bitmap, int w, int h) { super(bitmap, w, h, false); addAction(\"bb\new int[] { 0, 1, 2, 3, 4, 5 }, new int[] { 50, 50, 50, 50, 50, 50 }); } @Override public void drawSelf(Canvas canvas, Paint paint) { super.drawSelf(canvas, paint); x += speed;// 让子弹移动 // 当子弹超出屏幕移除子弹 if (x >= 800) { LayerManager.deleteLayer(this); GameData.bullets.remove(this); } } } ? Enemy类,敌军类,在这个类中我们要给它设置动作和路线 package com.mocn.airBottle; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import com.mocn.framework.Sprite; /** * 敌军的绘制类 * * @author Administrator * */ public class Enemy extends Sprite { public Enemy(Bitmap bitmap, int w, int h) { super(bitmap, w, h, true); addAction(\"left\new int[] { 0, 1, 2, 3, 4 }, new int[] { 50, 50, 50, 50, 50 });// 设置动作集合 } @Override public void drawSelf(Canvas canvas, Paint paint) { super.drawSelf(canvas, paint); x -= 2;// 敌军往左移动 } } 最后一个,GameData类,游戏数据类,在这里我们有创建敌军的方法和子弹和敌军的碰撞处理 ? package com.mocn.airBottle; import java.util.Vector; import com.mocn.framework.LayerManager; import com.mocn.framework.Utils; /** * 游戏数据类,用于控制敌军的出现和子弹与敌军的碰撞 * * @author Administrator * */ public class GameData { public static Vector 至此,整个游戏教学完成。 这是一个简单的游戏,但是代码量却不少,特别是框架部分,但是这个框架可以说是很基础的,但却囊括了游戏的很多方面,如果以后有机会去游戏公司,框架部分会更复杂,现在的辛苦只是为了以后的轻松而准备,我相信,如果一个人可以克服困难,看懂它的话,那他离真正的游戏大师也差不多远了,真正的机遇留个有准备的人!
因篇幅问题不能全部显示,请点此查看更多更全内容