如何构建自己的游戏框架并且制作游戏
這個教程就讓我們學習怎么用這個游戲框架開發(fā)一個簡單的空戰(zhàn)游戲吧!由于素材有限,都是用的網(wǎng)上的素材。這個游戲可以改造成為空戰(zhàn)或者植物大戰(zhàn)僵尸等的養(yǎng)成類型游戲或者更多,原理都差不多。 ? ?一個出類拔萃的人總是一個有耐心的人! 一個游戲的制作經(jīng)常會出現(xiàn)小意外,一個不耐心的人往往會不知所措,我看過李華明他的書上面有介紹游戲框架,而且很詳細,但是沒有這個全面,現(xiàn)在的很多游戲書籍也很少有關于游戲框架的構建,希望大家可以多借鑒一下,多提提意見!
先上圖:
??第一個教程就先搭建屬于我們的游戲框架:
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創(chuàng)建時執(zhí)行的方法 ?????????*/ ????????@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);// 得到調(diào)函數(shù)對象 ????????} ????????/** ?????????* 開啟線程的方法 ?????????*/ ????????public?void?startThread() { ????????????????currentThread = new?Thread(this);// 得到線程的對象 ????????????????currentThread.start();// 開啟線程 ????????} ????????/** ?????????* 關閉線程的方法 ?????????*/ ????????public?void?stopThread() { ????????????????currentThread = null;// 設置線程為空 ????????} ????????/** ?????????* 當界面改變時執(zhí)行的方法 ?????????*/ ????????@Override ????????public?void?surfaceChanged(SurfaceHolder holder, int?format, int?width, ????????????????????????int?height) { ????????} ????????/** ?????????* 當界面創(chuàng)建時執(zhí)行的方法 ?????????*/ ????????@Override ????????public?void?surfaceCreated(SurfaceHolder holder) { ????????????????startThread();// 開啟游戲線程 ????????} ????????/** ?????????* 當游戲被摧毀時執(zhí)行的方法 ?????????*/ ????????@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類,主要用于背景的繪制,可以用做靜態(tài)的繪制
| 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類,精靈類,用于繪制動態(tài)人物
| 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();// 創(chuàng)建SpiteAction的對象 ????????????????sp.frames = frames;// 當前幀的數(shù)量,用下標表示 ????????????????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; /** ?* 工具類 獲得一張圖片,判斷兩個矩形是否相交,判斷一個點是否在矩形內(nèi) ?* ?* @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; ????????} ????????/** ?????????* 判斷 一個點是否在矩形內(nèi)的方法 ?????????* ?????????* @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; ????????} } |
框架搭建完成,第二篇就是游戲的繪制篇了,如果大家在框架上有什么問題可以問我。
總結
以上是生活随笔為你收集整理的如何构建自己的游戏框架并且制作游戏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 皇室战争:暗夜女巫重做,去掉亡语机制后,
- 下一篇: 在安卓上,微信公众号无法分享到QQ的解决