千家信息网

Android游戏开发中SurfaceView类的应用实例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇文章给大家分享的是有关Android游戏开发中SurfaceView类的应用实例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。大
千家信息网最后更新 2026年11月01日Android游戏开发中SurfaceView类的应用实例分析

本篇文章给大家分享的是有关Android游戏开发中SurfaceView类的应用实例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

大家可以把此工程导入到Eclipse,然后编译运行,试玩一下。最后对应着看代码,这样更容易理解。下面上代码:

class LunarView extends SurfaceView implements SurfaceHolder.Callback {        class LunarThread extends Thread {            /*            * Difficulty setting constants            */           public static final int DIFFICULTY_EASY = 0;            public static final int DIFFICULTY_HARD = 1;            public static final int DIFFICULTY_MEDIUM = 2;            /*            * Physics constants            */           public static final int PHYS_DOWN_ACCEL_SEC = 35;            public static final int PHYS_FIRE_ACCEL_SEC = 80;            public static final int PHYS_FUEL_INIT = 60;            public static final int PHYS_FUEL_MAX = 100;            public static final int PHYS_FUEL_SEC = 10;            public static final int PHYS_SLEW_SEC = 120; // degrees/second rotate            public static final int PHYS_SPEED_HYPERSPACE = 180;            public static final int PHYS_SPEED_INIT = 30;            public static final int PHYS_SPEED_MAX = 120;            /*            * State-tracking constants            */           public static final int STATE_LOSE = 1;            public static final int STATE_PAUSE = 2;            public static final int STATE_READY = 3;            public static final int STATE_RUNNING = 4;            public static final int STATE_WIN = 5;               /*            * Goal condition constants            */           public static final int TARGET_ANGLE = 18; // > this angle means crash            public static final int TARGET_BOTTOM_PADDING = 17; // px below gear            public static final int TARGET_PAD_HEIGHT = 8; // how high above ground            public static final int TARGET_SPEED = 28; // > this speed means crash            public static final double TARGET_WIDTH = 1.6; // width of target            /*            * UI constants (i.e. the speed & fuel bars)            */           public static final int UI_BAR = 100; // width of the bar(s)            public static final int UI_BAR_HEIGHT = 10; // height of the bar(s)            private static final String KEY_DIFFICULTY = "mDifficulty";            private static final String KEY_DX = "mDX";               private static final String KEY_DY = "mDY";            private static final String KEY_FUEL = "mFuel";            private static final String KEY_GOAL_ANGLE = "mGoalAngle";            private static final String KEY_GOAL_SPEED = "mGoalSpeed";            private static final String KEY_GOAL_WIDTH = "mGoalWidth";               private static final String KEY_GOAL_X = "mGoalX";            private static final String KEY_HEADING = "mHeading";            private static final String KEY_LANDER_HEIGHT = "mLanderHeight";            private static final String KEY_LANDER_WIDTH = "mLanderWidth";            private static final String KEY_WINS = "mWinsInARow";               private static final String KEY_X = "mX";            private static final String KEY_Y = "mY";               /*            * Member (state) fields            */           /** The drawable to use as the background of the animation canvas */           private Bitmap mBackgroundImage;               /**            * Current height of the surface/canvas.            *             * @see #setSurfaceSize            */           private int mCanvasHeight = 1;               /**            * Current width of the surface/canvas.            *             * @see #setSurfaceSize            */           private int mCanvasWidth = 1;               /** What to draw for the Lander when it has crashed */           private Drawable mCrashedImage;               /**            * Current difficulty -- amount of fuel, allowed angle, etc. Default is            * MEDIUM.            */           private int mDifficulty;               /** Velocity dx. */           private double mDX;               /** Velocity dy. */           private double mDY;               /** Is the engine burning? */           private boolean mEngineFiring;               /** What to draw for the Lander when the engine is firing */           private Drawable mFiringImage;               /** Fuel remaining */           private double mFuel;               /** Allowed angle. */           private int mGoalAngle;               /** Allowed speed. */           private int mGoalSpeed;               /** Width of the landing pad. */           private int mGoalWidth;               /** X of the landing pad. */           private int mGoalX;               /** Message handler used by thread to interact with TextView */           private Handler mHandler;               /**            * Lander heading in degrees, with 0 up, 90 right. Kept in the range            * 0..360.            */           private double mHeading;               /** Pixel height of lander image. */           private int mLanderHeight;               /** What to draw for the Lander in its normal state */           private Drawable mLanderImage;               /** Pixel width of lander image. */           private int mLanderWidth;               /** Used to figure out elapsed time between frames */           private long mLastTime;               /** Paint to draw the lines on screen. */           private Paint mLinePaint;               /** "Bad" speed-too-high variant of the line color. */           private Paint mLinePaintBad;               /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */           private int mMode;               /** Currently rotating, -1 left, 0 none, 1 right. */           private int mRotating;               /** Indicate whether the surface has been created & is ready to draw */           private boolean mRun = false;               /** Scratch rect object. */           private RectF mScratchRect;               /** Handle to the surface manager object we interact with */           private SurfaceHolder mSurfaceHolder;               /** Number of wins in a row. */           private int mWinsInARow;               /** X of lander center. */           private double mX;               /** Y of lander center. */           private double mY;               public LunarThread(SurfaceHolder surfaceHolder, Context context,                    Handler handler) {                // get handles to some important objects                mSurfaceHolder = surfaceHolder;                mHandler = handler;                mContext = context;                   Resources res = context.getResources();                // cache handles to our key sprites & other drawables                mLanderImage = context.getResources().getDrawable(                        R.drawable.lander_plain);                mFiringImage = context.getResources().getDrawable(                        R.drawable.lander_firing);                mCrashedImage = context.getResources().getDrawable(                        R.drawable.lander_crashed);                   // load background image as a Bitmap instead of a Drawable b/c                // we don't need to transform it and it's faster to draw this way                mBackgroundImage = BitmapFactory.decodeResource(res,                        R.drawable.earthrise);                   // Use the regular lander image as the model size for all sprites                mLanderWidth = mLanderImage.getIntrinsicWidth();                mLanderHeight = mLanderImage.getIntrinsicHeight();                   // Initialize paints for speedometer                mLinePaint = new Paint();                mLinePaint.setAntiAlias(true);                mLinePaint.setARGB(255, 0, 255, 0);                   mLinePaintBad = new Paint();                mLinePaintBad.setAntiAlias(true);                mLinePaintBad.setARGB(255, 120, 180, 0);                   mScratchRect = new RectF(0, 0, 0, 0);                   mWinsInARow = 0;                mDifficulty = DIFFICULTY_MEDIUM;                   // initial show-up of lander (not yet playing)                mX = mLanderWidth;                mY = mLanderHeight * 2;                mFuel = PHYS_FUEL_INIT;                mDX = 0;                mDY = 0;                mHeading = 0;                mEngineFiring = true;            }               /**            * Starts the game, setting parameters for the current difficulty.            */           public void doStart() {                synchronized (mSurfaceHolder) {                    // First set the game for Medium difficulty                    mFuel = PHYS_FUEL_INIT;                    mEngineFiring = false;                    mGoalWidth = (int) (mLanderWidth * TARGET_WIDTH);                    mGoalSpeed = TARGET_SPEED;                    mGoalAngle = TARGET_ANGLE;                    int speedInit = PHYS_SPEED_INIT;                       // Adjust difficulty params for EASY/HARD                    if (mDifficulty == DIFFICULTY_EASY) {                        mFuel = mFuel * 3 / 2;                        mGoalWidth = mGoalWidth * 4 / 3;                        mGoalSpeed = mGoalSpeed * 3 / 2;                        mGoalAngle = mGoalAngle * 4 / 3;                        speedInit = speedInit * 3 / 4;                    } else if (mDifficulty == DIFFICULTY_HARD) {                        mFuel = mFuel * 7 / 8;                        mGoalWidth = mGoalWidth * 3 / 4;                        mGoalSpeed = mGoalSpeed * 7 / 8;                        speedInit = speedInit * 4 / 3;                    }                       // pick a convenient initial location for the lander sprite                    mX = mCanvasWidth / 2;                    mY = mCanvasHeight - mLanderHeight / 2;                       // start with a little random motion                    mDY = Math.random() * -speedInit;                    mDX = Math.random() * 2 * speedInit - speedInit;                    mHeading = 0;                       // Figure initial spot for landing, not too near center                    while (true) {                        mGoalX = (int) (Math.random() * (mCanvasWidth - mGoalWidth));                        if (Math.abs(mGoalX - (mX - mLanderWidth / 2)) > mCanvasHeight / 6)                            break;                    }                       mLastTime = System.currentTimeMillis() + 100;                    setState(STATE_RUNNING);                }            }               /**            * Pauses the physics update & animation.            */           public void pause() {                synchronized (mSurfaceHolder) {                    if (mMode == STATE_RUNNING) setState(STATE_PAUSE);                }            }               /**            * Restores game state from the indicated Bundle. Typically called when            * the Activity is being restored after having been previously            * destroyed.            *             * @param savedState Bundle containing the game state            */           public synchronized void restoreState(Bundle savedState) {                synchronized (mSurfaceHolder) {                    setState(STATE_PAUSE);                    mRotating = 0;                    mEngineFiring = false;                       mDifficulty = savedState.getInt(KEY_DIFFICULTY);                    mX = savedState.getDouble(KEY_X);                    mY = savedState.getDouble(KEY_Y);                    mDX = savedState.getDouble(KEY_DX);                    mDY = savedState.getDouble(KEY_DY);                    mHeading = savedState.getDouble(KEY_HEADING);                       mLanderWidth = savedState.getInt(KEY_LANDER_WIDTH);                    mLanderHeight = savedState.getInt(KEY_LANDER_HEIGHT);                    mGoalX = savedState.getInt(KEY_GOAL_X);                    mGoalSpeed = savedState.getInt(KEY_GOAL_SPEED);                    mGoalAngle = savedState.getInt(KEY_GOAL_ANGLE);                    mGoalWidth = savedState.getInt(KEY_GOAL_WIDTH);                    mWinsInARow = savedState.getInt(KEY_WINS);                    mFuel = savedState.getDouble(KEY_FUEL);                }            }               @Override           public void run() {                while (mRun) {                    Canvas c = null;                    try {                        c = mSurfaceHolder.lockCanvas(null);                        synchronized (mSurfaceHolder) {                            if (mMode == STATE_RUNNING) updatePhysics();                            doDraw(c);                        }                    } finally {                        // do this in a finally so that if an exception is thrown                        // during the above, we don't leave the Surface in an                        // inconsistent state                        if (c != null) {                            mSurfaceHolder.unlockCanvasAndPost(c);                        }                    }                }            }               /**            * Dump game state to the provided Bundle. Typically called when the            * Activity is being suspended.            *             * @return Bundle with this view's state            */           public Bundle saveState(Bundle map) {                synchronized (mSurfaceHolder) {                    if (map != null) {                        map.putInt(KEY_DIFFICULTY, Integer.valueOf(mDifficulty));                        map.putDouble(KEY_X, Double.valueOf(mX));                        map.putDouble(KEY_Y, Double.valueOf(mY));                        map.putDouble(KEY_DX, Double.valueOf(mDX));                        map.putDouble(KEY_DY, Double.valueOf(mDY));                        map.putDouble(KEY_HEADING, Double.valueOf(mHeading));                        map.putInt(KEY_LANDER_WIDTH, Integer.valueOf(mLanderWidth));                        map.putInt(KEY_LANDER_HEIGHT, Integer                                .valueOf(mLanderHeight));                        map.putInt(KEY_GOAL_X, Integer.valueOf(mGoalX));                        map.putInt(KEY_GOAL_SPEED, Integer.valueOf(mGoalSpeed));                        map.putInt(KEY_GOAL_ANGLE, Integer.valueOf(mGoalAngle));                        map.putInt(KEY_GOAL_WIDTH, Integer.valueOf(mGoalWidth));                        map.putInt(KEY_WINS, Integer.valueOf(mWinsInARow));                        map.putDouble(KEY_FUEL, Double.valueOf(mFuel));                    }                }                return map;            }               /**            * Sets the current difficulty.            *             * @param difficulty            */           public void setDifficulty(int difficulty) {                synchronized (mSurfaceHolder) {                    mDifficulty = difficulty;                }            }               /**            * Sets if the engine is currently firing.            */           public void setFiring(boolean firing) {                synchronized (mSurfaceHolder) {                    mEngineFiring = firing;                }            }               /**            * Used to signal the thread whether it should be running or not.            * Passing true allows the thread to run; passing false will shut it            * down if it's already running. Calling start() after this was most            * recently called with false will result in an immediate shutdown.            *             * @param b true to run, false to shut down            */           public void setRunning(boolean b) {                mRun = b;            }               /**            * Sets the game mode. That is, whether we are running, paused, in the            * failure state, in the victory state, etc.            *             * @see #setState(int, CharSequence)            * @param mode one of the STATE_* constants            */           public void setState(int mode) {                synchronized (mSurfaceHolder) {                    setState(mode, null);                }            }               /**            * Sets the game mode. That is, whether we are running, paused, in the            * failure state, in the victory state, etc.            *             * @param mode one of the STATE_* constants            * @param message string to add to screen or null            */           public void setState(int mode, CharSequence message) {                /*                * This method optionally can cause a text message to be displayed                * to the user when the mode changes. Since the View that actually                * renders that text is part of the main View hierarchy and not                * owned by this thread, we can't touch the state of that View.                * Instead we use a Message + Handler to relay commands to the main                * thread, which updates the user-text View.                */               synchronized (mSurfaceHolder) {                    mMode = mode;                       if (mMode == STATE_RUNNING) {                        Message msg = mHandler.obtainMessage();                        Bundle b = new Bundle();                        b.putString("text", "");                        b.putInt("viz", View.INVISIBLE);                        msg.setData(b);                        mHandler.sendMessage(msg);                    } else {                        mRotating = 0;                        mEngineFiring = false;                        Resources res = mContext.getResources();                        CharSequence str = "";                        if (mMode == STATE_READY)                            str = res.getText(R.string.mode_ready);                        else if (mMode == STATE_PAUSE)                            str = res.getText(R.string.mode_pause);                        else if (mMode == STATE_LOSE)                            str = res.getText(R.string.mode_lose);                        else if (mMode == STATE_WIN)                            str = res.getString(R.string.mode_win_prefix)                                    + mWinsInARow + " "                                   + res.getString(R.string.mode_win_suffix);                           if (message != null) {                            str = message + "\n" + str;                        }                           if (mMode == STATE_LOSE) mWinsInARow = 0;                           Message msg = mHandler.obtainMessage();                        Bundle b = new Bundle();                        b.putString("text", str.toString());                        b.putInt("viz", View.VISIBLE);                        msg.setData(b);                        mHandler.sendMessage(msg);                    }                }            }               /* Callback invoked when the surface dimensions change. */           public void setSurfaceSize(int width, int height) {                // synchronized to make sure these all change atomically                synchronized (mSurfaceHolder) {                    mCanvasWidth = width;                    mCanvasHeight = height;                       // don't forget to resize the background image                    mBackgroundImage = mBackgroundImage.createScaledBitmap(                            mBackgroundImage, width, height, true);                }            }               /**            * Resumes from a pause.            */           public void unpause() {                // Move the real time clock up to now                synchronized (mSurfaceHolder) {                    mLastTime = System.currentTimeMillis() + 100;                }                setState(STATE_RUNNING);            }               /**            * Handles a key-down event.            *             * @param keyCode the key that was pressed            * @param msg the original event object            * @return true            */           boolean doKeyDown(int keyCode, KeyEvent msg) {                synchronized (mSurfaceHolder) {                    boolean okStart = false;                    if (keyCode == KeyEvent.KEYCODE_DPAD_UP) okStart = true;                    if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) okStart = true;                    if (keyCode == KeyEvent.KEYCODE_S) okStart = true;                       boolean center = (keyCode == KeyEvent.KEYCODE_DPAD_UP);                       if (okStart                            && (mMode == STATE_READY || mMode == STATE_LOSE || mMode == STATE_WIN)) {                        // ready-to-start -> start                        doStart();                        return true;                    } else if (mMode == STATE_PAUSE && okStart) {                        // paused -> running                        unpause();                        return true;                    } else if (mMode == STATE_RUNNING) {                        // center/space -> fire                        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER                                || keyCode == KeyEvent.KEYCODE_SPACE) {                            setFiring(true);                            return true;                            // left/q -> left                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT                                || keyCode == KeyEvent.KEYCODE_Q) {                            mRotating = -1;                            return true;                            // right/w -> right                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT                                || keyCode == KeyEvent.KEYCODE_W) {                            mRotating = 1;                            return true;                            // up -> pause                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {                            pause();                            return true;                        }                    }                       return false;                }            }               /**            * Handles a key-up event.            *             * @param keyCode the key that was pressed            * @param msg the original event object            * @return true if the key was handled and consumed, or else false            */           boolean doKeyUp(int keyCode, KeyEvent msg) {                boolean handled = false;                   synchronized (mSurfaceHolder) {                    if (mMode == STATE_RUNNING) {                        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER                                || keyCode == KeyEvent.KEYCODE_SPACE) {                            setFiring(false);                            handled = true;                        } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT                                || keyCode == KeyEvent.KEYCODE_Q                                || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT                                || keyCode == KeyEvent.KEYCODE_W) {                            mRotating = 0;                            handled = true;                        }                    }                }                   return handled;            }               /**            * Draws the ship, fuel/speed bars, and background to the provided            * Canvas.            */           private void doDraw(Canvas canvas) {                // Draw the background image. Operations on the Canvas accumulate                // so this is like clearing the screen.                canvas.drawBitmap(mBackgroundImage, 0, 0, null);                   int yTop = mCanvasHeight - ((int) mY + mLanderHeight / 2);                int xLeft = (int) mX - mLanderWidth / 2;                   // Draw the fuel gauge                int fuelWidth = (int) (UI_BAR * mFuel / PHYS_FUEL_MAX);                mScratchRect.set(4, 4, 4 + fuelWidth, 4 + UI_BAR_HEIGHT);                canvas.drawRect(mScratchRect, mLinePaint);                   // Draw the speed gauge, with a two-tone effect                double speed = Math.sqrt(mDX * mDX + mDY * mDY);                int speedWidth = (int) (UI_BAR * speed / PHYS_SPEED_MAX);                   if (speed <= mGoalSpeed) {                    mScratchRect.set(4 + UI_BAR + 4, 4,                            4 + UI_BAR + 4 + speedWidth, 4 + UI_BAR_HEIGHT);                    canvas.drawRect(mScratchRect, mLinePaint);                } else {                    // Draw the bad color in back, with the good color in front of                    // it                    mScratchRect.set(4 + UI_BAR + 4, 4,                            4 + UI_BAR + 4 + speedWidth, 4 + UI_BAR_HEIGHT);                    canvas.drawRect(mScratchRect, mLinePaintBad);                    int goalWidth = (UI_BAR * mGoalSpeed / PHYS_SPEED_MAX);                    mScratchRect.set(4 + UI_BAR + 4, 4, 4 + UI_BAR + 4 + goalWidth,                            4 + UI_BAR_HEIGHT);                    canvas.drawRect(mScratchRect, mLinePaint);                }                   // Draw the landing pad                canvas.drawLine(mGoalX, 1 + mCanvasHeight - TARGET_PAD_HEIGHT,                        mGoalX + mGoalWidth, 1 + mCanvasHeight - TARGET_PAD_HEIGHT,                        mLinePaint);                      // Draw the ship with its current rotation                canvas.save();                canvas.rotate((float) mHeading, (float) mX, mCanvasHeight                        - (float) mY);                if (mMode == STATE_LOSE) {                    mCrashedImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop                            + mLanderHeight);                    mCrashedImage.draw(canvas);                } else if (mEngineFiring) {                    mFiringImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop                            + mLanderHeight);                    mFiringImage.draw(canvas);                } else {                    mLanderImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop                            + mLanderHeight);                    mLanderImage.draw(canvas);                }                canvas.restore();            }               /**            * Figures the lander state (x, y, fuel, ...) based on the passage of            * realtime. Does not invalidate(). Called at the start of draw().            * Detects the end-of-game and sets the UI to the next state.            */           private void updatePhysics() {                long now = System.currentTimeMillis();                   // Do nothing if mLastTime is in the future.                // This allows the game-start to delay the start of the physics                // by 100ms or whatever.                if (mLastTime > now) return;                   double elapsed = (now - mLastTime) / 1000.0;                   // mRotating -- update heading                if (mRotating != 0) {                    mHeading += mRotating * (PHYS_SLEW_SEC * elapsed);                       // Bring things back into the range 0..360                    if (mHeading < 0)                        mHeading += 360;                    else if (mHeading >= 360) mHeading -= 360;                }                   // Base accelerations -- 0 for x, gravity for y                double ddx = 0.0;                double ddy = -PHYS_DOWN_ACCEL_SEC * elapsed;                   if (mEngineFiring) {                    // taking 0 as up, 90 as to the right                    // cos(deg) is ddy component, sin(deg) is ddx component                    double elapsedFiring = elapsed;                    double fuelUsed = elapsedFiring * PHYS_FUEL_SEC;                       // tricky case where we run out of fuel partway through the                    // elapsed                    if (fuelUsed > mFuel) {                        elapsedFiring = mFuel / fuelUsed * elapsed;                        fuelUsed = mFuel;                           // Oddball case where we adjust the "control" from here                        mEngineFiring = false;                    }                       mFuel -= fuelUsed;                       // have this much acceleration from the engine                    double accel = PHYS_FIRE_ACCEL_SEC * elapsedFiring;                       double radians = 2 * Math.PI * mHeading / 360;                    ddx = Math.sin(radians) * accel;                    ddy += Math.cos(radians) * accel;                }                   double dxOld = mDX;                double dyOld = mDY;                   // figure speeds for the end of the period                mDX += ddx;                mDY += ddy;                   // figure position based on average speed during the period                mX += elapsed * (mDX + dxOld) / 2;                mY += elapsed * (mDY + dyOld) / 2;                   mLastTime = now;                   // Evaluate if we have landed ... stop the game                double yLowerBound = TARGET_PAD_HEIGHT + mLanderHeight / 2                       - TARGET_BOTTOM_PADDING;                if (mY <= yLowerBound) {                    mY = yLowerBound;                       int result = STATE_LOSE;                    CharSequence message = "";                    Resources res = mContext.getResources();                    double speed = Math.sqrt(mDX * mDX + mDY * mDY);                    boolean onGoal = (mGoalX <= mX - mLanderWidth / 2 && mX                            + mLanderWidth / 2 <= mGoalX + mGoalWidth);                       // "Hyperspace" win -- upside down, going fast,                    // puts you back at the top.                    if (onGoal && Math.abs(mHeading - 180) < mGoalAngle                            && speed > PHYS_SPEED_HYPERSPACE) {                        result = STATE_WIN;                        mWinsInARow++;                        doStart();                           return;                        // Oddball case: this case does a return, all other cases                        // fall through to setMode() below.                    } else if (!onGoal) {                        message = res.getText(R.string.message_off_pad);                    } else if (!(mHeading <= mGoalAngle || mHeading >= 360 - mGoalAngle)) {                        message = res.getText(R.string.message_bad_angle);                    } else if (speed > mGoalSpeed) {                        message = res.getText(R.string.message_too_fast);                    } else {                        result = STATE_WIN;                        mWinsInARow++;                    }                       setState(result, message);                }            }        }           /** Handle to the application context, used to e.g. fetch Drawables. */       private Context mContext;           /** Pointer to the text view to display "Paused.." etc. */       private TextView mStatusText;           /** The thread that actually draws the animation */       private LunarThread thread;           public LunarView(Context context, AttributeSet attrs) {            super(context, attrs);               // register our interest in hearing about changes to our surface            SurfaceHolder holder = getHolder();            holder.addCallback(this);               // create thread only; it's started in surfaceCreated()            thread = new LunarThread(holder, context, new Handler() {                @Override               public void handleMessage(Message m) {                    mStatusText.setVisibility(m.getData().getInt("viz"));                    mStatusText.setText(m.getData().getString("text"));                }            });               setFocusable(true); // make sure we get key events        }           /**        * Fetches the animation thread corresponding to this LunarView.        *         * @return the animation thread        */       public LunarThread getThread() {            return thread;        }           /**        * Standard override to get key-press events.        */       @Override       public boolean onKeyDown(int keyCode, KeyEvent msg) {            return thread.doKeyDown(keyCode, msg);        }           /**        * Standard override for key-up. We actually care about these, so we can        * turn off the engine or stop rotating.        */       @Override       public boolean onKeyUp(int keyCode, KeyEvent msg) {            return thread.doKeyUp(keyCode, msg);        }           /**        * Standard window-focus override. Notice focus lost so we can pause on        * focus lost. e.g. user switches to take a call.        */       @Override       public void onWindowFocusChanged(boolean hasWindowFocus) {            if (!hasWindowFocus) thread.pause();        }           /**        * Installs a pointer to the text view used for messages.        */       public void setTextView(TextView textView) {            mStatusText = textView;        }           /* Callback invoked when the surface dimensions change. */       public void surfaceChanged(SurfaceHolder holder, int format, int width,                int height) {            thread.setSurfaceSize(width, height);        }           /*        * Callback invoked when the Surface has been created and is ready to be        * used.        */       public void surfaceCreated(SurfaceHolder holder) {            // start the thread here so that we don't busy-wait in run()            // waiting for the surface to be created            thread.setRunning(true);            thread.start();        }           /*        * Callback invoked when the Surface has been destroyed and must no longer        * be touched. WARNING: after this method returns, the Surface/Canvas must        * never be touched again!        */       public void surfaceDestroyed(SurfaceHolder holder) {            // we have to tell thread to shut down & wait for it to finish, or else            // it might touch the Surface after we return and explode            boolean retry = true;            thread.setRunning(false);            while (retry) {                try {                    thread.join();                    retry = false;                } catch (InterruptedException e) {                }            }        }    }

以上就是Android游戏开发中SurfaceView类的应用实例分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

实例 实例分析 分析 应用 开发 更多 知识 篇文章 e.g. 实用 上代 代码 就是 工作会 工程 文章 看吧 知识点 行业 试玩 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网是第几次科技革命的成果 互联网科技公司起名 中关村互联网 科技集团 科技和互联网公司 金诺互联网科技 金融科技创新监管互联网金融 易互联网科技有限公司 奇酷互联网络科技 天津摩尔互联网科技 顺玮阁互联网科技 卓越科技互联网 招聘 联恩商钥互联网科技有限公司 哈尔滨新华互联网科技 南山科技园互联网公司有哪些 和信科技工业互联网 深圳育鹏互联网科技有限公司招聘 互联网金融科技公司的优势 张召忠谈中国互联网科技 2021世界互联网领先科技成果发布 唐山双旺合互联网科技产业园 互联网金融科技 科技与互联网 中国最先进互联网科技公司 浙江互联网科技研学营 科技赋能视角下互联网保险发展 恒生互联网科技业指数调整周期 锡山区互联网智能科技产品供应 广州互联网高科技取餐柜 科技互联网经济论坛 悟空问答互联网科技
0