最近在看一本不错的Android的入门书《ProAndroidGame》
没有使用多么厉害的游戏引擎
而是依靠浅显易懂的java +Android SDK来完成几个小游戏项目
个人觉得这是一本不错的Android游戏开发入门书籍
读完逾三分之一后 感悟良多
由于这是一本英语书籍
所以个人就凭借羞涩的英语水平来解释一下其中奥义吧
/
前面的一些基础知识跳过
进入到第三章 Building a Java Game from Scratch
先看游戏布局文件 main.xml
写Android程序的布局文件常用Layout格式有2种
LinearLayout RelativeLayout
这两种都是Android SDK中定义的
而作者使用的是SpaceBlasterGame的布局格式
这个其实是作者从LinearLayout继承而来的
在后面会详细描述SpaceBlasterGame类的
这里主要声明了一个SpaceBlasterGame类的对象
其id为ll_absolute
<?xml version="1.0" encoding="utf-8"?>
<!-- User Defined Linear Layout -->
<ch03.game.sb.SpaceBlasterGame
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_absolute"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF000000">
</ch03.game.sb.SpaceBlasterGame>
///
接下来作者就开始介绍主Activity类SpaceBlaster
同样是继承自Activity但是有所不同的是
setContentView方法参数只有一个View对象
调用的是一个LayoutInflater 类生成的对象factory
factory生成出一个带有R.layout.main资源参数的view
再调用setContentView 使程序显示出该view
view是通过main.xml布局文件生成
由于在前面的中写明了main.xml带有一个SpaceBlasterGame类
根据作者编写的类的继承结构LinearLayout->ArcadeGame->SpaceBlasterGame
所以又在一些触发事件中 加入了view强制转换
使得调用ArcadeGame类中的方法
这里需要注意的地方是加载自定义的Layout 需要使用到LayoutInfalter类
public class SpaceBlaster extends Activity {
private View view;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater factory = LayoutInflater.from(this);
// Set game layout
view = factory.inflate(R.layout.main, null);
setContentView(view);
// Enable view key events
view.setFocusable(true);
view.setFocusableInTouchMode(true);
}
@Override
protected void onStop() {
super.onStop();
((ArcadeGame) view).halt();
}
@Override
protected void onPause() {
super.onPause();
onStop();
}
@Override
protected void onRestart() {
super.onRestart();
((ArcadeGame) view).resume();
}
}
根据作者的设计 ArcadeGame类被定义成游戏基础架构类
如时间计时器 生成图像方法 生成音效方法
都被定义到ArcadeGame类中
同时还定义有一些虚方法 可供子类实现
比较重要的虚方法有
initialize() 可供子类填写游戏初始化数据的代码
updatePhysics() 可供子类填写逻辑部分的代码
由于代码比较冗余 这里就不全写出
解释一些重要的部分
计时器对象mUpdateTimer
ArcadeGame类中还带有一个mPeriod 字段
用户可定义更新周期
mUpdateTimer是Timer类的对象
这样mUpdateTimer可以使用schedule方法定制TimerTask对象
作者已经自定义一个UpdateTask 类 继承自TimerTask类
因此可以解释成在固定周期中调用UpdateTask对象中的run方法
run方法中只有两句代码
一个执行游戏逻辑的虚方法updatePhysics()
一个更新视图的方法 postInvalidate()
其实作者编写的代码主要是在mUpdateTimer与TimerTask对象之间来回调用
先生成mUpdateTimer 并定制其UpdateTask类的对象
使其执行run方法
而UpdateTask类中又定义有halt() resume() 方法
halt() 调用的是ArcadeGame类中的stopUpdateTimer()
resume()调用的是ArcadeGame类中的initialize()和startUpdateTimer()
当暂停时 halt()方法撤销掉mUpdateTimer
当恢复时 resume()方法生成新的mUpdateTimer
private Timer mUpdateTimer;
public void setUpdatePeriod(long period) {
mPeriod = period;
}
protected void startUpdateTimer() {
mUpdateTimer = new Timer();
mUpdateTimer.schedule(new UpdateTask(), 0, mPeriod);
}
protected void stopUpdateTimer() {
if (mUpdateTimer != null) {
mUpdateTimer.cancel();
}
}
private class UpdateTask extends TimerTask {
@Override
public void run() {
updatePhysics();
postInvalidate();
}
}
public void halt() {
stopUpdateTimer();
}
public void resume() {
initialize();
startUpdateTimer();
}
}
//
最后再介绍一下音效的AudioClip类
AudioClip是作者自己编写的一个音效类
个人觉得作者在因为出于时间考虑
这部分代码编写得比较简单
实现音效主要功能的mPlayer字段
里面只有一个表示资源名的name 字段
表示状态的2个字段mPlaying 和mLoop
在AudioClip类的构造方法中
通过Android SDK中的MediaPlayer类和getResources()方法
很容易就创建出一个MediaPlayer 对象
重点部分放在匿名内部类中
定义了一个监听事件OnCompletionListener
表示在完成播放音效后触发的事件
这里用于设置音效的mPlaying状态
并且判断mLoop 以实现音效的循环播放功能
public class AudioClip {
private MediaPlayer mPlayer;
private String name;
private boolean mPlaying = false;
private boolean mLoop = false;
public AudioClip(Context ctx, int resID){
// clip name
name = ctx.getResources().getResourceName(resID);
// Create a media player
mPlayer = MediaPlayer.create(ctx, resID);
// Listen for completion events
mPlayer.setOnCompletionListener(
new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mPlaying = false;
if (mLoop) {
mp.start();
}
}
});
}
由于时间关系 今天只能叙述到此
明天将把第三章的SpaceBlasterGame类进行详细的说明