汉字先生-----初学android时做的小游戏
16lz
2021-01-23
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;}}};@Overrideprotected void onCreate(android.os.Bundle savedInstanceState) {super.onCreate(savedInstanceState);startMyGame();}public void startMyGame(){//设置进度条progressDialog=new ProgressDialog(this);progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);progressDialog.setMessage("加载中...");}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if(!gameing){handler.sendEmptyMessage(Constant.ToMenu);return false;}return super.onKeyDown(keyCode, event);}@Overridepublic void onResume() {super.onResume();if(Asset.bgMusic!=null)Asset.bgMusic.play();}@Overrideprotected void onPause() {super.onPause();if(Asset.bgMusic!=null)Asset.bgMusic.pause();}@Overridepublic void finish() {if(Asset.bgMusic!=null)Asset.bgMusic.stop();Asset.bgMusic=null;super.finish();}@Overridepublic Screen getStartScreen() {return new LoadScreen(this);}@Overridepublic void afterCreate() {//首先加载背景图片Asset.background=GM.loadBitmap("imgs/bg.jpg");//设置进度条的颜色this.getGameBar().barColor=Constant.CELL_COLOR;}@Overridepublic 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(){@Overridepublic 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 只负责显示 * * @创建者 :集成显卡[email protected] * @创建日期 :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) { } } }@Overridepublic 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);}@Overridepublic void dispose() {}@Overridepublic void pause() {}@Overridepublic 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());}@Overridepublic void resume() {}@Overridepublic 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);}}
这里就只介绍这么多了。有兴趣的可以下载看看: 下载源代码
更多相关文章
- Android小项目--2048小游戏
- html5游戏移植到android并打包成apk,加广告《一》
- 简单的Android游戏测试
- Chapter3-运行cocos2dx游戏在android设备上
- 十五开源的Android(2D或3D)Android开发游戏引擎