汉字先生-----初学android时做的小游戏

        12年初,开始接触android,看的书是:[Android.游戏开发入门](美)Mario.Zechner.插图版

        

        一边看一边做了这个小游戏,是以选择两个字形组成一个完整的汉字来进行游戏的。

       目前只有两种模式:

       标准模式:在规定时间内成功组合指定个数的汉字

       渡水模式:游戏中,会有一匹白马一直向前行进,如果白马进水游戏便会失败。玩家需要组合汉字使得白马脚下的木桥延长,木桥覆盖过小河游戏便胜利!共5关。


       画面比较粗糙,毕竟没有那个美工细胞=.=

       整个程序还是有不少问题的, 也有很多用户体验不好的地方,大家也理解 一下哈。


        先看一下截图:

            

        

            


            


        


        下面是工程结构:

        


        游戏中应用 [Android.游戏开发入门](美)Mario.Zechner 一书中介绍的游戏框架,我也对框架进入了适当的修改,以更好地适应自己的游戏。游戏只有一个Activity,继承框架中的 DTGame.java 类,游戏中的界面都是Screen的子类, DTGame 通过调用 getScreen() 获取当前的游戏界面进行绘图。 在游戏中可以调用 DTGame 的setScreen(new Screen())方法来切换界面。整个游戏都只在SurfaceView中更新视图,在框架中 GameSurfaceView.java 继承 SurfaceView 并开启一个线程,调用DTGame 中的 getScreen() 得到当前Screen对象,调用Screen中的 draw() 和update() 方法。


      下面是 自己定义的 Activity,继承DTGame:

        

package cn.dt.mr_cc;

import android.app.ProgressDialog;
import android.app.Service;
import android.os.Handler;
import android.os.Vibrator;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Toast;
import cn.dt.mr_cc.screen.LoadScreen;
import dt.humen.game.GM;
import dt.humen.game.Screen;
import dt.humen.game.core.impl.DTGame;

public class MrCCActivity extends DTGame {
	
	protected WebView webView=null;//加载html的容器
	protected View aboutView;//关于的视图
	protected boolean gameing=true;//是否在游戏界面中
	protected ProgressDialog progressDialog;
	
	private Handler handler=new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch(msg.what){
			case Constant.GAME_EXIT:
				beforeExit();
				break;
			case Constant.SHOW_INFO:
				Toast.makeText(MrCCActivity.this,msg.getData().getString(Constant.MESSAGE), 4000).show();
				break;
			case Constant.ToAbout:
				toAbout();
				break;
			case Constant.ToMenu:
				toGame();
				break;
			case Constant.LOADING_SHOW:
				progressDialog.show();
				break;
			case Constant.LOADING_HIDE:
				progressDialog.hide();
				break;
			case Constant.VIBRATOR_DEF:
				vibrate(300);
				break;
			case Constant.VIBRATOR_LONG:
				vibrate(1000);
				break;
			}
		}
	};
	
	@Override
	protected void onCreate(android.os.Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		startMyGame();
	}
	
	public void startMyGame(){
		//设置进度条
		progressDialog=new ProgressDialog(this);
		progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		progressDialog.setMessage("加载中...");
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(!gameing){
			handler.sendEmptyMessage(Constant.ToMenu);
			return false;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	@Override
	public void onResume() {
		super.onResume();
		if(Asset.bgMusic!=null)
			Asset.bgMusic.play();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		if(Asset.bgMusic!=null)
			Asset.bgMusic.pause();
	}
	
	@Override
	public void finish() {
		if(Asset.bgMusic!=null)
			Asset.bgMusic.stop();
		Asset.bgMusic=null;
		super.finish();
	}

	@Override
	public Screen getStartScreen() {
		return new LoadScreen(this);
	}
	
	@Override
	public void afterCreate() {
		//首先加载背景图片
		Asset.background=GM.loadBitmap("imgs/bg.jpg");
		//设置进度条的颜色
		this.getGameBar().barColor=Constant.CELL_COLOR;
	}
	
	@Override
	public Handler getHandler() {
		return handler;
	}
	
	private void toAbout(){
		if(aboutView==null){
			handler.sendEmptyMessage(Constant.LOADING_SHOW);
			LayoutInflater lif=LayoutInflater.from(MrCCActivity.this);
			aboutView=lif.inflate(R.layout.about, null);
			webView=(WebView)aboutView.findViewById(R.id.webview);
			webView.setWebChromeClient(new WebChromeClient(){
				@Override
				public void onProgressChanged(WebView view, int newProgress) {
					if(newProgress==100)
						handler.sendEmptyMessage(Constant.LOADING_HIDE);
					super.onProgressChanged(view, newProgress);
				}
			});
			webView.loadUrl("file:///android_asset/html/about.html");
		}
		gameView.pause();
		gameing=false;
		setContentView(aboutView);
	}
	
	private void toGame(){
		gameView.resume();
		gameing=true;
		setContentView(gameView);
	}
	
	public void vibrate(long ms){
		if(Setting.vibrateAble){
			Vibrator v=(Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
			v.vibrate(ms);
		}
	}
}


        框架中的 GameSurfaceView类:

package dt.humen.game;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import dt.humen.game.core.impl.DTGame;

/**
 *这个surfaceView 只负责显示
 *
 * @创建者 :集成显卡	1053214511@qq.com
 * @创建日期 :2012-1-26
 * @修改记录 :
 */
public class GameSurfaceView extends SurfaceView implements Runnable{
	public DTGame game;
	public Bitmap gameBuffer;
	public SurfaceHolder holder;
	public Thread thread;
	
	public int sleep=0;//线程间隔
	
	public boolean running=false;//游戏是否在进行
	
	public GameSurfaceView(DTGame game,Bitmap map) {
		super(game);
		this.game=game;
		this.gameBuffer=map;
		this.holder=getHolder();
	}
	
	/**
	 * 游戏恢复时
	 *	
	 *  @date :2012-1-23
	 */
    public void resume() { 
        running = true;
        thread = new Thread(this);
        thread.start();
        System.out.println("线程开启!---->");
    }
    
    /**
     * 游戏暂停时
     *	
     *  @date :2012-1-23
     */
    public void pause() {                        
        running = false;
        System.out.println("线程暂停!---->");
        while(true) {
            try {
                thread.join();
                break;
            } catch (InterruptedException e) {
            }
        }
    }

	@Override
	public void run() {
		Rect rect=new Rect();
		while(running){
			//如果没有可用的外观,就直接跳过
			if(!holder.getSurface().isValid())
				continue;
			//让game的画面更新
			game.getScreen().update();
			game.getScreen().draw();
			
			//将更新后的画布画到屏幕上
			Canvas canvas=holder.lockCanvas();
			canvas.getClipBounds(rect);
			//将gameBuffer 这个 bitmap 画到屏幕上
			canvas.drawBitmap(gameBuffer, null, rect, null);
			holder.unlockCanvasAndPost(canvas);
			try{
				Thread.sleep(sleep);
			}catch(Exception r){}
		}
	}
	
	public void setSleep(int time){
		this.sleep=time;
		if(sleep<0)
			sleep=0;
	}
}

       每个Screen都要重写Screen的 draw 和update 方法,前者是绘图,后者是事件处理,这里贴出游戏主菜单 MenuScreen.java 的代码:

package cn.dt.mr_cc.screen;

import java.util.List;

import cn.dt.mr_cc.Asset;
import cn.dt.mr_cc.Constant;
import cn.dt.mr_cc.Setting;
import dt.humen.game.Screen;
import dt.humen.game.core.Game;
import dt.humen.game.unit.Cell;
import dt.humen.game.unit.Point;
import dt.humen.io.Input;
import dt.humen.io.Input.TouchEvent;

public class MenuScreen extends Screen{
	public int count=0;
	private Cell startCell;
	private Cell exitCell;
	private Cell optionCell;
	private Cell aboutCell;
	
	public MenuScreen(Game game) {
		super(game);
		init();
	}
	
	private void init(){
		startCell=new Cell(120, 360,Asset.startBtn,Asset.selectSound);
		exitCell=new Cell(120, 360, Asset.exitBtn,Asset.selectSound);
		optionCell=new Cell(120,360,Asset.optionBtn,Asset.downSound);
		aboutCell=new Cell(120,360,Asset.aboutBtn,Asset.selectSound);
		
		//开始动画!
		exitCell.getAnimate().setEndPoint(new Point(230,360)).start(350);
		optionCell.getAnimate().setEndPoint(new Point(160,400)).start(350);
		aboutCell.getAnimate().setEndPoint(new Point(10,360)).start(350);
		startCell.getAnimate().setEndPoint(new Point(80,400)).start(350);
	}

	@Override
	public void dispose() {
	}

	@Override
	public void pause() {
	}

	@Override
	public void draw() {
		game.getCanvas().drawBitmap(Asset.background, 0, 0, null);
		game.getCanvas().drawBitmap(Asset.logoPNG, 15, 30, null);
		
		startCell.draw(game.getCanvas());
		exitCell.draw(game.getCanvas());
		optionCell.draw(game.getCanvas());
		aboutCell.draw(game.getCanvas());
	}

	@Override
	public void resume() {
		
	}

	@Override
	public void update() {
		List<TouchEvent> list=game.getInput().getTouchEvents();
		if(list.size()==0)
			return ;
		TouchEvent e=list.get(0);
		if(e.type==Input.TOUCH_DOWN){
			//判断是否按下了菜单按钮
			//说明
			if(aboutCell.isClick(e.x, e.y,Setting.soundAble)){
				toAbout();
			}
			//开始
			else if(startCell.isClick(e.x, e.y,Setting.soundAble)){
				game.setScreen(new SelectScreen(game));
			}
			else if(optionCell.isClick(e.x, e.y,Setting.soundAble)){
				game.setScreen(new SettingScreen(game));
			}
			//退出
			else if(exitCell.isClick(e.x, e.y,Setting.soundAble)){
				/*
				 * 因为是线程里面更新UI,需要使用Looper帮助
				 * 还可以使用handler机制,给Activity传递一个Message然后更新UI
				 * 
				 * ps:
				 * 使用Looper会产生一个bug:当点击退出按钮时,可以成功退出,但是两次打开程序时会失去响应!
				 * 用Handler就没有问题
				 */
				//Looper.prepare();
				game.getHandler().sendEmptyMessage(Constant.GAME_EXIT);
				//Looper.loop();
			}
		}
	}
	
	private void toAbout(){
		game.getHandler().sendEmptyMessage(Constant.ToAbout);
	}
}




        这里就只介绍这么多了。有兴趣的可以下载看看:下载源代码










posted @ 2012-07-09 00:26  集成显卡  阅读(339)  评论(0编辑  收藏  举报