📄 lunarview.scala
字号:
/* * Copyright (C) 2007 Google Inc. * * 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.google.android.lunarlanderimport _root_.android.content.{Context, Resources}import _root_.android.graphics.{Canvas, Paint, RectF}import _root_.android.graphics.drawable.Drawableimport _root_.android.os.Bundleimport _root_.android.util.AttributeSetimport _root_.android.view.{KeyEvent, View}import _root_.android.widget.TextViewimport java.util.Mapobject LunarView { final val READY = 0 final val RUNNING = 1 final val PAUSE = 2 final val LOSE = 3 final val WIN = 4 final val EASY = 0 final val MEDIUM = 1 final val HARD = 2 // Parameters for how the physics works. final val FIRE_ACCEL_SEC = 80 final val DOWN_ACCEL_SEC = 35 final val FUEL_SEC = 10 final val SLEW_SEC = 120 // degrees/second rotate final val FUEL_INIT = 60d final val FUEL_MAX = 100 final val SPEED_INIT = 30 final val SPEED_MAX = 120 final val SPEED_HYPERSPACE = 180 // Parameters for landing successfully (MEDIUM difficulty). final val TARGET_SPEED = 28 final val TARGET_WIDTH = 1.6 // how much wider than lander final val TARGET_ANGLE = 18 /** * Pixel height of the fuel/speed bar. */ final val BAR_HEIGHT = 10 /** * Pixel width of the fuel/speed bar. */ final val BAR = 100 /** * Height of the landing pad off the bottom. */ final val PAD_HEIGHT = 8 /** * Extra pixels below the landing gear in the images */ final val BOTTOM_PADDING = 17}/** * 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(context: Context, attrs: AttributeSet, inflateParams: Map) extends View(context, attrs, inflateParams) { import LunarView._ // companion object /** * The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */ private var mMode = READY /** * Current difficulty -- amount of fuel, allowed angle, etc. * Default is MEDIUM. */ private var mDifficulty = MEDIUM /** * Velocity dx. */ private var mDX = 0.0 /** * Velocity dy. */ private var mDY = 0.0 /** * Lander heading in degrees, with 0 up, 90 right. * Kept in the range 0..360. */ private var mHeading = 0.0 /** * Currently rotating, -1 left, 0 none, 1 right. */ private var mRotating = 0 /** * X of the landing pad. */ private var mGoalX = 0 /** * Allowed speed. */ private var mGoalSpeed = 0 /** * Allowed angle. */ private var mGoalAngle = 0 /** * Width of the landing pad. */ private var mGoalWidth = 0 /** * Number of wins in a row. */ private var mWinsInARow = 0 /** * Fuel remaining */ private var mFuel = FUEL_INIT /** * Is the engine burning? */ private var mEngineFiring = true /** * Used to figure out elapsed time between frames */ private var mLastTime: Long = _ /** * Paint to draw the lines on screen. */ private val mLinePaint = new Paint mLinePaint setAntiAlias true mLinePaint.setARGB(255, 0, 255, 0) /** * "Bad" speed-too-high variant of the line color. */ private val mLinePaintBad = new Paint mLinePaintBad setAntiAlias true mLinePaintBad.setARGB(255, 120, 180, 0) /** * What to draw for the Lander in its normal state */ private val mLanderImage = context.getResources getDrawable R.drawable.lander_plain /** * What to draw for the Lander when the engine is firing */ private val mFiringImage = context.getResources getDrawable R.drawable.lander_firing /** * What to draw for the Lander when it has crashed */ private val mCrashedImage = context.getResources getDrawable R.drawable.lander_crashed /** * Pixel width of lander image. */ var mLanderWidth = mLanderImage.getIntrinsicWidth /** * Pixel height of lander image. */ var mLanderHeight = mLanderImage.getIntrinsicHeight /** * X of lander center. */ private var mX: Double = mLanderWidth /** * Y of lander center. */ private var mY: Double = mLanderHeight * 2 /** * Pointer to the text view to display "Paused.." etc. */ private var mStatusText: TextView = _ /** * Scratch rect object. */ private val mScratchRect= new RectF(0, 0, 0, 0) setBackground(R.drawable.earthrise) // Make sure we get keys setFocusable(true) /** * Save game state so that the user does not lose anything * if the game process is killed while we are in the * background. * * @return Map with this view's state */ def saveState(): Bundle = { val map = new Bundle map.putInteger("mDifficulty", mDifficulty) map.putDouble("mX", mX) map.putDouble("mY", mY) map.putDouble("mDX", mDX) map.putDouble("mDY", mDY) map.putDouble("mHeading", mHeading) map.putInteger("mLanderWidth", mLanderWidth) map.putInteger("mLanderHeight", mLanderHeight) map.putInteger("mGoalX", mGoalX) map.putInteger("mGoalSpeed", mGoalSpeed) map.putInteger("mGoalAngle", mGoalAngle) map.putInteger("mGoalWidth", mGoalWidth) map.putInteger("mWinsInARow", mWinsInARow) map.putDouble("mFuel", mFuel) map } /** * Restore game state if our process is being relaunched * * @param icicle Map containing the game state */ def restoreState(icicle: Bundle) { mode = PAUSE mRotating = 0 mEngineFiring = false mDifficulty = icicle.getInteger("mDifficulty").intValue mX = icicle.getDouble("mX").doubleValue mY = icicle.getDouble("mY").doubleValue mDX = icicle.getDouble("mDX").doubleValue mDY = icicle.getDouble("mDY").doubleValue mHeading = icicle.getDouble("mHeading").doubleValue mLanderWidth = icicle.getInteger("mLanderWidth").intValue mLanderHeight = icicle.getInteger("mLanderHeight").intValue mGoalX = icicle.getInteger("mGoalX").intValue mGoalSpeed = icicle.getInteger("mGoalSpeed").intValue mGoalAngle = icicle.getInteger("mGoalAngle").intValue mGoalWidth = icicle.getInteger("mGoalWidth").intValue mWinsInARow = icicle.getInteger("mWinsInARow").intValue mFuel = icicle.getDouble("mFuel").doubleValue } /** * Installs a pointer to the text view used * for messages. */ def setTextView(textView: TextView) { mStatusText = textView } /** * Standard window-focus override. * Notice focus lost so we can pause on focus lost. * e.g. user switches to take a call. */ override def windowFocusChanged(hasWindowFocus: Boolean) { if (!hasWindowFocus) doPause() } /** * Standard override of View.draw. * Draws the ship and fuel/speed bars. */ override def onDraw(canvas: Canvas) { super.onDraw(canvas) if (mMode == RUNNING) updatePhysics() val screenWidth = getWidth val screenHeight = getHeight val yTop = screenHeight - (mY.toInt + mLanderHeight/2) val xLeft = mX.toInt - mLanderWidth/2 // Draw fuel rect val fuelWidth = (BAR * mFuel / FUEL_MAX).toInt mScratchRect.set(4, 4, 4 + fuelWidth, 4 + BAR_HEIGHT) canvas.drawRect(mScratchRect, mLinePaint) val speed = Math.sqrt(mDX*mDX + mDY*mDY) val speedWidth = (BAR * speed / SPEED_MAX).toInt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -