📄 lunarview.java
字号:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.lunarlander;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.KeyEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.TextView;/** * View that draws, takes keystrokes, etc. for a simple LunarLander game. * * Has a mode which RUNNING, PAUSED, etc. Has a x, y, dx, dy, ... capturing the * current ship physics. All x/y etc. are measured with (0,0) at the lower left. * updatePhysics() advances the physics based on realtime. draw() renders the * ship, and does an invalidate() to prompt another draw() as soon as possible * by the system. */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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -