4.3.1.1 AndroidManifest.xml
Android应用程序中,并没有像C++和Java这样有main函数来作为应用程序的入口。Android应用程序提供的是入口Activity,而非入口函数。
AndroidManifest.xml文件中定义了整个Android应用所包含的Activity.在AndroidManifest.xml中将SkyGameStartActivity设置为当前SkyGame启动时,默认加载的Activity,代码如下:
android:launchMode="singleTask">
4.3.1.2 Activity中注册layout
在SkyGameStartActivity的onCreate方法中设置要显示的layout,方法如下所示:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sky_game_start_layout);//设置当前activity调用的layout
//其他操作
}
4.3.1.3 BroadcastReceiver
由于本应用是有多个Activity为了解决多个Activity在其中任意一个Activity结束时都会相应一起退出系统,因此针对每一个Activity设置一个BroadcastReceiver来接收广播,一旦接收到广播当前Activity自动退出。Activity接收到广播后退出的代码如下所示:
private BroadcastReceiver exitReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
SkyGameScreenRollActivity.this.finish();
}
};
4.3.1.4 发送广播
而当前Activity在被按下"EXIT"或者"退出"按钮时,会向外界发送一个广播,
之后结束自己:
Activity activity = (Activity)context;
Intent intent = new Intent(EXIT);
intent.setAction(EXIT);
activity.sendBroadcast(intent);
activity.finish();
4.3.1.5 MediaPlayer(媒体播放器)
本应用使用Android的MediaPlayer来演奏每一个页面的背景音乐。
背景音乐可以存放在两个位置,一个是当前工程的/res/raw目录下,如果是存放在该目录下的话,在install当前Android工程时,需要耗费非常的时间将此类音频文件上传到Android虚拟机中。另一个存放位置是直接将音频文件上传到DDMS的/mnt/sdcard/Music文件夹下,这相当于将该音频文件放入到了Android手机的SD卡上了,相对于存放位置一来说,该方法在加载Android工程时消耗的时间比较少。具体向虚拟机中上传文件如图4-7所示:
图4-7 DDMS向Android虚拟机中上传文件
MediaPlayer使用方法:
private MediaPlayer startSound = null;
startSound = new MediaPlayer();
try {
/*
* 从sdcard中获得音频文件的路径
*/
startSound.setDataSource("/mnt/sdcard/Music/start.mp3");
startSound.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
startSound.setLooping(true) ;//设置循环
由于当前应用针对不同的显示界面(Activity)有不同的背景音乐,因此当前Activity挂起时,对应的背景音乐也要挂起(startSound.pause())。而在当前Activity销毁(destory)时,需要对背景音乐进行停止(startSound.stop())和回收(startSound.release())操作。
4.3.1.6 layout中调用SurfaceView
普通的layout设置与直接调用SurfaceView的layout有所不同,一下列出调用SurfaceView的layout的格式:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
android:id="@+id/skyGameStartPicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
此处使用自定义SurfaceView的绝对路径来编写开始页面的layout文件,使得开始页面直接使用该SurfaceView绘制的Bitmap作为背景图片来显示。
SurfaceView所需要设置下它的SurfaceHolder 和Monitor(实现CallBack接口)属性
holder = getHolder();
monitor = new Monitor();
holder.addCallback(monitor);
Monitor类的方法:
方法surfaceCreated(SurfaceHolder holder)的主要作用是:在surfaceview创建的绘制SurfaceView的内容。
方法surfaceDestroyed(SurfaceHolder holder)的主要作用是:在surfaceview销毁时对于当前SurfaceView中的一些对象做销毁处理。
SurfaceView的方法:
onTouchEvent(MotionEvent event)可以捕获鼠标对于屏幕的触碰事件,在该方法中对于鼠标触碰的区域做出判断如果点击的为按钮图片的位置则会调用图4-4中对应的被按下按钮来显示,如此显示使用户有一个可感受的按钮被按下的动态即视感,用户体验更好。
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
float eventX = event.getX();
float eventY = event.getY();
if((eventX >= START_X)&&
(eventX <= START_X+startButton.getWidth())&&
(eventY >= START_Y)&&
(eventY <= START_Y+startButton.getHeight())){
if(action == MotionEvent.ACTION_DOWN){
startButton = BitmapFactory.decodeResource(getResources(), R.drawable.startbutton2);
drawStartButton();
}
if(action == MotionEvent.ACTION_UP){
startButton = BitmapFactory.decodeResource(getResources(), R.drawable.startbutton1);
drawStartButton();
Intent intent = new Intent(this.context,SkyGameScreenRollActivity.class);
this.context.startActivity(intent);
}
}
else if((eventX >= OPTION_X)&&
(eventX <= OPTION_X+optionButton.getWidth())&&
(eventY >= OPTION_Y)&&
(eventY <= OPTION_Y+optionButton.getHeight())){
if(action == MotionEvent.ACTION_DOWN){
optionButton = BitmapFactory.decodeResource(getResources(), R.drawable.option2);
drawOptionButton();
}
if(action == MotionEvent.ACTION_UP){
optionButton = BitmapFactory.decodeResource(getResources(), R.drawable.option1);
drawOptionButton();
Intent intent = new Intent(this.context,SkyGameOptionButtonOnClickActivity.class);
this.context.startActivity(intent);
}
}
else if((eventX >= SCORE_X)&&
(eventX <= SCORE_X+scoreButton.getWidth())&&
(eventY >= SCORE_Y)&&
(eventY <= SCORE_Y+scoreButton.getHeight())){
if(action == MotionEvent.ACTION_DOWN){
scoreButton = BitmapFactory.decodeResource(getResources(), R.drawable.score2);
drawScoreButton();
}
if(action == MotionEvent.ACTION_UP){
scoreButton = BitmapFactory.decodeResource(getResources(), R.drawable.score1);
drawScoreButton();
Intent intent = new Intent(this.context,SkyGameScoreButtonOnClickActivity.class);
this.context.startActivity(intent);
}
}
else if((eventX >= EXIT_X)&&
(eventX <= EXIT_X +exitButton.getWidth())&&
(eventY >= EXIT_Y)&&
(eventY <= EXIT_Y + exitButton.getHeight())){
if(action == MotionEvent.ACTION_DOWN){
scoreButton = BitmapFactory.decodeResource(getResources(), R.drawable.exit_button_2);
drawExitButton();
}
if(action == MotionEvent.ACTION_UP){
scoreButton = BitmapFactory.decodeResource(getResources(), R.drawable.exit_button_1);
drawExitButton();
Activity activity = (Activity)context;
Intent intent = new Intent(EXIT);
intent.setAction(EXIT);
activity.sendBroadcast(intent);
activity.finish();
}
}
return true;
}
4.3.2游戏界面
本界面与开始界面都是使用SurfaceView绘制的界面,由于本界面相对于开始界面更加复杂在主线程外创建了子线程来负责对于SurfaceView的绘制工作,主线程负责对于各类对象的控制计算等计算工作。
由于游戏界面涉及到的类比较多,且逻辑复杂,所以在这里只介绍下使用的空间、技术以及业务逻辑,粘贴部分技术代码。
绘制的游戏界面如图4-8所示:
图4-8 游戏界面
4.3.2.1 Activity中注册SurfaceView
游戏界面并没有像开始界面那样注册SurfaceView,而是直接在onCreate方法中使用代码注册的自定义SurfaceView,如下:
private SkyGameScreenRollView sr = null;//自定义surfaceview
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
sr = new SkyGameScreenRollView(this);
sr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
sr.setId(0x000101);
setContentView(sr);
}
4.3.2.2 ContextMenu控件
游戏界面使用了Android的ContextMenu,ContextMenu显示的具体效果见图4-9。
图4-9 ContextMenu效果
ContextMenu针对某个控件,一旦为某个控件设置了ContextMenu,那么程序员将不能再实现该控件的长按事件处理了。
ContextMenu的使用步骤:
1. ContextMenu针对的是控件而不是窗体,构建完ContextMenu后需要与一个控件实施绑定。
绑定的代码为:super.registerForContextMenu(控件对象)。
2.构建ContextMenu的方法如下:
a.创建一个res/menu/**_context.xml的菜单(当前应用使用的该方法)。
b.重写onCreateContextMenu()回调函数。
c.super.registerForContextMenu(控件对象)。
3.为每个菜单项编写事件。
具体操作方法重写onCreateMenuItemSelected回调函数。
游戏界面的ContextMenu的playing_game_option_menu.xml内容如下:
在游戏界面的SkyGameScreenRollActivity的方法onCreateOptionsMenu(Menu menu)中注册playing_game_option_menu.xml文件,具体方法如下所示:
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.playing_game_option_menu, menu);
return true;
}
在游戏界面的SkyGameScreenRollActivity的方法onOptionsItemSelected(MenuItem item)中为每个菜单选项编写响应事件,具体使用方法如下所示:
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Intent intent = null;
switch(item.getItemId()){
case R.id.pg_option_exit:
intent = new Intent();
intent.setAction(EXIT);
this.sendBroadcast(intent);
this.finish();
break;
case R.id.pg_option_option:
intent = new Intent(SkyGameScreenRollActivity.this,SkyGameOptionButtonOnClickActivity.class);
this.startActivity(intent);
break;
case R.id.pg_option_score:
intent = new Intent(SkyGameScreenRollActivity.this,SkyGameScoreButtonOnClickActivity.class);
this.startActivity(intent);
break;
case R.id.pg_option_start:
intent = new Intent(SkyGameScreenRollActivity.this,SkyGameStartActivity.class);
this.startActivity(intent);
break;
}
retur
上一篇:
基于android的资源管理器
下一篇:
计算机网络毕业论文