Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android:如何用一天時間,寫出“飛機大戰”這樣的游戲!(無框架-SurfaceView繪制)

android:如何用一天時間,寫出“飛機大戰”這樣的游戲!(無框架-SurfaceView繪制)

編輯:關於Android編程

序言
作為一個android開發者,時常想開發一個小游戲娛樂一下大家,今天就說說,我是怎麼樣一天寫出一個簡單的“飛機大戰”的.
體驗地址:http://www.wandoujia.com/apps/edu.njupt.zhb.planegame
游戲分析
玩過“飛機大戰”游戲的都知道,飛機大戰中的主要“角色”有:
1.玩家飛機
2.敵方飛機
3.玩家飛機發送的子彈
4.敵方Boss飛機發送的子彈
我們需要控制的有
1.繪制屏幕內的角色
2.控制角色的邏輯,比如:敵方飛機與我方飛機的碰撞檢測,我方飛機發射的子彈與敵方飛機之間的碰撞檢測,敵方Boss飛機發射的子彈與我方飛機直接的碰撞檢測等等。
資源:
要完成一個游戲,還要有資源的加載,比如飛機,子彈等圖片的加載等,音效的加載。
游戲背景的繪制
其實是一張圖,這張圖可以首尾相接,也即是“卷軸”,原理就是卡馬克卷軸算法的原理。
下面分析代碼區

其實,拋開android平台,任何一個平台,做這樣一個游戲,都需要這些邏輯。針對android平台,我們看一下,SurfaceView的繪制框架。直接貼代碼:

package edu.njupt.zhb.game.view;

/**
 * 
 * @author Zheng Haibo
 * @webset: http://www.mobctrl.net
 * @android開發聯盟QQ群:272209595
 */
public class PlaneView extends SurfaceView implements Callback, Runnable {

	private SurfaceHolder surfaceHolder;
	private long sleep_time = 16;//繪制周期
	private int screenHeight;
	private int screenWidth;
	private Thread thread;
	private Canvas canvas;
	private Paint paint;
	private GameScreen currentScreen;
	private int level = 0;
	private int backgroundSpeed = 1;

	public PlaneView(Context context) {
		super(context);
		System.out.println("debug:PlaneView()");
		surfaceHolder = this.getHolder();
		surfaceHolder.addCallback(this);
		surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
		paint = new Paint();
		paint.setAntiAlias(true);
		paint.setDither(true);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		System.out.println("debug:surfaceCreated");
		setZOrderOnTop(false);
		isGameOver = false;
		if (isPause) {
			return;
		}
		screenHeight = this.getHeight();
		screenWidth = this.getWidth();
		initPlane();
		thread = new Thread(this);
		thread.start();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		System.out.println("debug:surfaceChanged");
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		System.out.println("debug:surfaceDestroyed");
		if (lift > 0) {
			planeViewCallback.onGamePause();
		}
		isPause = true;
	}

	@Override
	public void run() {
		while (!isGameOver) {//控制繪制周期
			if (isPause) {
				try {
					Thread.sleep(sleep_time);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				continue;
			}
			long starttime = System.currentTimeMillis();
			drawScreen();
			long time = System.currentTimeMillis() - starttime;
			if (time < sleep_time) {
				try {
					Thread.sleep(sleep_time - time);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 繪制場景
	 */
	private void drawScreen() {
		canvas = surfaceHolder.lockCanvas();
		if (null == canvas) {
			return;
		}
		//清除
		canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
		paint.setAlpha(255);
		gameLogic();
		gameDraw();
		if (null != canvas) {
			surfaceHolder.unlockCanvasAndPost(canvas);
		}
	}

	/**
	 * 游戲邏輯
	 */
	private void gameLogic() {
		//TO DO 控制游戲邏輯
		...
	}

	private void gameDraw() {
	    //先繪制游戲背景
		drawBackground(backgroundSpeed * frameSeq);
		if (currentScreen == GameScreen.NORMAL) {
			synchronized (planes) {
				drawPlanes();
				drawBullets();
				drawMasterPlane();
			}
		} else if (currentScreen == GameScreen.BOSS) {
			drawBullets();
			drawBossPlane();
			drawBossBullets();
			drawMasterPlane();
		}
	}

	private void drawBossPlane() {
		if (null != bossPlane) {
			if (bossPlane.isClicked()) {// draw blast img
				bossPlane.onBlastDraw(canvas, paint);
				if (bossPlane.isBlastFrameEnd()) {
					bossPlane.setClicked(false);
				}
			}
			bossPlane.onDraw(canvas, paint);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		System.out.println("debug:onDraw");
	}

	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		System.out.println("debug:onDetachedFromWindow...");
		isPause = false;
		isGameOver = true;
		//釋放資源
		for (PlaneRes plane : planesRes) {
			plane.getBitmap().recycle();
		}
		for (BulletRes bulletRes : bulletsRes) {
			bulletRes.getBitmap().recycle();
		}
	}

	/**
	* 用戶交互
	*/
	@Override
	public boolean onTouchEvent(MotionEvent e) {
		int x = (int) e.getX();
		int y = (int) e.getY();
		switch (e.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (masterPlane.isContainPoint(x, y)) {
				isMove = true;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (isMove) {
				synchronized (masterPlane) {
					masterPlane.updatePosition(x, y);//控制玩家飛機的移動
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			isMove = false;
			break;
		}
		return true;
	}
}

對於背景的繪制,其實是循環繪制一張圖:本游戲的繪制邏輯:

private void drawBackground(int yOffset) {
		yOffset %= screenHeight;
		if (yOffset == 0) {
			canvas.drawBitmap(backgroundBmp, 0, 0, paint);
		} else {
			canvas.drawBitmap(backgroundBmp, new Rect(0,
					screenHeight - yOffset, screenWidth, screenHeight),
					new Rect(0, 0, screenWidth, yOffset + 1), paint);
			canvas.drawBitmap(backgroundBmp, new Rect(0, 0, screenWidth,
					screenHeight - yOffset), new Rect(0, yOffset, screenWidth,
					screenHeight), paint);
		}
	}

然後,我們只需要在一個布局上,將PlaneView添加進去即可:

如:

planeView = new PlaneView(this);
		planeView.setPlaneViewCallback(this);
		planeView.setGameOverCallback(this);
		planeView.isMediaOpen = this.isMediaOpen;
		LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		rl_plane.addView(planeView, lp);

未完待續。。。。。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved