现在的位置: 首页 > 综合 > 正文

实例分析JETBOY

2013年08月23日 ⁄ 综合 ⁄ 共 6618字 ⁄ 字号 评论关闭
实现原理:

启动以个单独的游戏线程,通过主VIEW中的ONCLIK事件中根据不同的线程状态,显示不同的VIEW和按钮状态。

private JetBoyThread mJetBoyThread; //游戏线程

private JetBoyView mJetBoyView; //游戏运行的VIEW

  private Button mButton; //PLAY按钮

  private Button mButtonRetry; //RETRy按钮

  private TextView mTextView; //游戏中显示的帮助文本

  private TextView mTimerView;//游戏时钟

程序入口点:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.android.jetboy" android:versionCode="1"
    android:versionName="1.0.0">
    <application android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar">
        <activity android:name=".JetBoy"

            android:label="@string/app_name"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN
" />
                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3"></uses-sdk>
</manifest>

很明显是JETBOY.JAVA。

main.xml 中使用的是FrameLayout,在其中部署了上诉的VIEW和button。

onCreate中代码很简单,主要是取得VIEW和BUTTON,然后初始化mJetBoyThread和mJetBoyView;

public class JetBoy extends Activity implements View.OnClickListener

请注意这个实现的目的是为了在一个ONCLICK中处理所有按钮事件。主要逻辑都是在onClick(View v)实现。具体看看:

public void onClick(View v) {
        
        if (mJetBoyThread.getGameState() == JetBoyThread.STATE_START) {
            mButton.setText("PLAY!");
            mTextView.setVisibility(View.VISIBLE);

            mTextView.setText(R.string.helpText);
            mJetBoyThread.setGameState(JetBoyThread.STATE_PLAY);

        }
        // we have entered game play, now we about to start running
        else if (mJetBoyThread.getGameState() == JetBoyThread.STATE_PLAY) {
            mButton.setVisibility(View.INVISIBLE);
            mTextView.setVisibility(View.INVISIBLE);
            mTimerView.setVisibility(View.VISIBLE);
            mJetBoyThread.setGameState(JetBoyThread.STATE_RUNNING);

        }
        // this is a retry button
        else if (mButtonRetry.equals(v)) {

            mTextView.setText(R.string.helpText);

            mButton.setText("PLAY!");
            mButtonRetry.setVisibility(View.INVISIBLE);
            // mButtonRestart.setVisibility(View.INVISIBLE);

            mTextView.setVisibility(View.VISIBLE);
            mButton.setText("PLAY!");
            mButton.setVisibility(View.VISIBLE);

            mJetBoyThread.setGameState(JetBoyThread.STATE_PLAY);

        } else {
            Log.d("JB VIEW", "unknown click " + v.getId());

            Log.d("JB VIEW", "state is  " + mJetBoyThread.mState);

        }
    }

很容易读懂。

另外实现两个onKeyDown和onKeyUp事件,处理游戏中按键的事件。

 

核心实现:JetBoyView

1 SurfaceView分析

public class JetBoyView extends SurfaceView implements SurfaceHolder.Callback{}

SurfaceView  在复杂的游戏开发中经常用到,提供一个可直接控制的画图界面,在Canvas可以绘制各种背景、人物、场景。

通过GetHolder()返回SurfaceHolde来实现对SurfaceView  的控制;

SurfaceHolder holder = getHolder();
        holder.addCallback(this);//Add a Callback interface for this holder.

以上是该程序中的代码;

 

SurfaceHolder.Callback 通过这个接口可以获得Surface改变的信息;

   public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}   //在surface的大小发生改变时激发   

   public void surfaceCreated(SurfaceHolder arg0) { }

//在创建时激发,一般在这里调用画图的线程

   public void surfaceDestroyed(SurfaceHolder arg0) { }

//销毁时激发,一般在这里将画图的线程停止、释放

以上是实现的接口方法;

 

2 GameEvent

  程序定义了两个GameEvent 子类KeyGameEvent和JetGameEvent,很容理解。

  KeyGameEvent 来自键盘输入

  JetGameEvent   来自 JetPlayer.

这里涉及到JetPlayer是什么?开发过游戏的应该很熟悉,我查了帮助,才搞清楚是做什么的。这里会涉及到一系列Jet的概念,从相关资料中得知:

JET 一个在嵌入式设备上的音乐播放器,包括那些运行机器人平台小的嵌入式设备。它允许应用程序在响应中的 MIDI 格式中包含交互式音乐音轨实时游戏事件和用户交互。

JET ENGINE 一个控制游戏声音特效的引擎,其使用MIDI格式,并可以控制游戏的时间进度(一个精确的时钟是一个游戏必不可少)

JetPlayer 提供了对JET content的访问

JetCreator 是一盒可以创建JET content的工具;

 

稍后会详细说明;

 

3 关键线程JetBoyThread

整个游戏的主线程,首先看看定义

class JetBoyThread extends Thread implements OnJetEventListener

它实现了OnJetEventListener接口,用来获取JetPlayer的事件;

先看看该线程主要完成什么功能:

  • 处理JetPlayer和KEY事件;
  • 2 绘制各种动画SurfaceView中的显示;
  • 3 游戏状态的设置;
  • 4 用户游戏数据的保存;

程序的逻辑

在仔细分析代码前,有必要看看程序的逻辑是如何实现的?线程是如何启动和运行的?

 

首先jetBoy:onCreate

JetBoyView:JetBoyView(Context context, AttributeSet attrs{

   thread = new JetBoyThread(holder, context, new Handler();//创建线程并在线程构造函数中初始化游戏状态;mState=STATE_START;setRunning(TRUE);

}

surfaceCreated 中启动线程thread.start();

开始执行JetBoyThread:run()//进入游戏状态集;这是执行的主体;会根据不同的游戏状态执行相应的操作。直到setRunning(false);

这时候等待用户操作;

jetBoy的onKeyDown,onKeyUp会触发JetBoyThread的doKeyDown和doKeyUp,将事件放到队列中,然后在updateGameState,检查mEventQueue,进行事件处理:

@Override
    public boolean onKeyDown(int keyCode, KeyEvent msg) {

        if (keyCode == 4)
            super.onKeyDown(keyCode, msg);

        return mJetBoyThread.doKeyDown(keyCode, msg);
    }

 

public boolean doKeyDown(int keyCode, KeyEvent msg) {
            mEventQueue.add(new KeyGameEvent(keyCode, false, msg));

            return true;
        }

 

protected void updateGameState() {
            // Process any game events and apply them
            while (true) {
                GameEvent event = mEventQueue.poll();
                if (event == null)
                    break;

                // Log.d(TAG,"*** EVENT = " + event);

                // Process keys tracking the input context to pass in to later
                // calls
                if (event instanceof KeyGameEvent) {
                    // Process the key for affects other then asteroid hits
                    mKeyContext = processKeyEvent((KeyGameEvent)event, mKeyContext);

                    // Update laser state. Having this here allows the laser to
                    // be triggered right when the key is
                    // pressed. If we comment this out the laser will only be
                    // turned on when updateLaser is called
                    // when processing a timer event below.
                    updateLaser(mKeyContext);

                }
                // JET events trigger a state update
                else if (event instanceof JetGameEvent) {
                    JetGameEvent jetEvent = (JetGameEvent)event;

                    // Only update state on a timer event
                    if (jetEvent.value == TIMER_EVENT) {
                        // Note the time of the last beat
                        mLastBeatTime = System.currentTimeMillis();

                        // Update laser state, turning it on if a key has been
                        // pressed or off if it has been
                        // on for too long.
                        updateLaser(mKeyContext);

                        // Update explosions before we update asteroids because
                        // updateAsteroids may add
                        // new explosions that we do not want updated until next
                        // frame
                        updateExplosions(mKeyContext);

                        // Update asteroid positions, hit status and animations
                        updateAsteroids(mKeyContext);
                    }

                   
processJetEvent(jetEvent.player, jetEvent.segment, jetEvent.track,
jetEvent.channel, jetEvent.controller, jetEvent.value);
                }
            }
        }

逻辑应该很清楚了吧。

抱歉!评论已关闭.