⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lunarview.scala

📁 JAVA 语言的函数式编程扩展
💻 SCALA
📖 第 1 页 / 共 2 页
字号:
            if (speed <= mGoalSpeed) {      mScratchRect.set(4 + BAR + 4, 4, 4 + BAR + 4 + speedWidth, 4 + BAR_HEIGHT)      canvas.drawRect(mScratchRect, mLinePaint)    } else {      // Draw the bad color in back, with the good color in front of it      mScratchRect.set(4 + BAR + 4, 4, 4 + BAR + 4 + speedWidth, 4 + BAR_HEIGHT)      canvas.drawRect(mScratchRect, mLinePaintBad)      val goalWidth = (BAR * mGoalSpeed / SPEED_MAX)      mScratchRect.set(4 + BAR + 4, 4, 4 + BAR + 4 + goalWidth, 4 + BAR_HEIGHT)      canvas.drawRect(mScratchRect, mLinePaint)    }    // Draw the landing pad    canvas.drawLine(mGoalX, 1 + screenHeight - PAD_HEIGHT,                    mGoalX + mGoalWidth, 1 + screenHeight - PAD_HEIGHT,  mLinePaint)    // Draw the ship with its current rotation    canvas.save()    canvas.rotate(mHeading.toFloat, mX.toFloat, screenHeight - mY.toFloat)    if (mMode == 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)    }    /*     * Our animation strategy is that each draw() does an invalidate(),     * so we get a series of draws. This is a known animation strategy     * within Android, and the system throttles the draws down to match     * the refresh rate.     */    if (mMode == RUNNING) {      // Invalidate a space around the current lander + the bars at the top.      // Note: invalidating a relatively small part of the screen to draw      // is a good optimization. In this case, the bars and the ship      // may be far apart, limiting the value of the optimization.      invalidate(xLeft-20, yTop-20, xLeft+mLanderWidth+20, yTop+mLanderHeight+20)      invalidate(0, 0, screenWidth, 4 + BAR_HEIGHT)    }            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.   */  def updatePhysics() {    val 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            val elapsed = (now - mLastTime) / 1000.0            // mRotating -- update heading    if (mRotating != 0) {      mHeading += mRotating * (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    var ddx = 0.0    var ddy = -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      var elapsedFiring = elapsed      var fuelUsed = elapsedFiring * 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      val accel = FIRE_ACCEL_SEC * elapsedFiring                  val radians = 2 * Math.Pi * mHeading / 360      ddx = Math.sin(radians) * accel      ddy += Math.cos(radians) * accel    }    val dxOld = mDX    val 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    checkLanding()  }  def checkLanding() {    val yLowerBound = PAD_HEIGHT + mLanderHeight/2 - BOTTOM_PADDING    if (mY <= yLowerBound) {      mY = yLowerBound      val res = getContext.getResources      val speed = Math.sqrt(mDX*mDX + mDY*mDY)      val 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 > SPEED_HYPERSPACE) {        mWinsInARow += 1        doStart()      } else {        val (result, message) =           if (!onGoal)             (LOSE, res.getText(R.string.message_off_pad))          else if (!(mHeading <= mGoalAngle || mHeading >= 360 - mGoalAngle))            (LOSE, res.getText(R.string.message_bad_angle))          else if (speed  > mGoalSpeed)             (LOSE, res.getText(R.string.message_too_fast))          else {            mWinsInARow += 1            (WIN, "")          }        setMode(result, message)      }    }  }  /**   * Sets if the engine is currently firing.   */  def isFiring_=(firing: Boolean) { mEngineFiring = firing }  def isFiring = mEngineFiring  /**   * Sets the game mode, RUNNING, PAUSED, etc.   * @param mode RUNNING, PAUSED, ...   */  def mode_=(mode: Int) { setMode(mode, null) }  def mode = mMode    /**   * Sets the game mode, RUNNING, PAUSED, etc.   * @param mode RUNNING, PAUSED, ...   * @param message string to add to screen or null   */  def setMode(mode: Int, message: CharSequence) {    mMode = mode    invalidate()	    if (mMode == RUNNING) {      mStatusText.setVisibility(View.INVISIBLE)    } else {      mRotating = 0      mEngineFiring = false      val res = getContext.getResources      var str = mMode match {        case READY => res.getText(R.string.mode_ready)        case PAUSE => res.getText(R.string.mode_pause)        case LOSE => mWinsInARow = 0; res.getText(R.string.mode_lose)        case WIN => res.getString(R.string.mode_win_prefix)          + mWinsInARow + " " + res.getString(R.string.mode_win_suffix)        case _ => ""      }      mStatusText setText (if (message != null) message + "\n" + str else str)      mStatusText setVisibility View.VISIBLE    }  }  /**   * Starts the game, setter parameters for the current   * difficulty.   */  def doStart() {    // First set the game for Medium difficulty    mFuel = FUEL_INIT    mEngineFiring = false    mGoalWidth = (mLanderWidth * TARGET_WIDTH).toInt    mGoalSpeed = TARGET_SPEED    mGoalAngle = TARGET_ANGLE    var speedInit = SPEED_INIT            // Adjust difficulty params for EASY/HARD    if (mDifficulty == EASY) {      mFuel = mFuel * 3 / 2      mGoalWidth = mGoalWidth * 4 / 3      mGoalSpeed = mGoalSpeed * 3 / 2      mGoalAngle = mGoalAngle * 4 / 3      speedInit = speedInit * 3 / 4    } else if (mDifficulty == HARD) {      mFuel = mFuel * 7 / 8      mGoalWidth = mGoalWidth * 3 / 4      mGoalSpeed = mGoalSpeed * 7 / 8      speedInit = speedInit * 4 / 3    }            mX = getWidth/2    mY = getHeight - 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    do {      mGoalX = (Math.random * (getWidth - mGoalWidth)).toInt    } while (Math.abs(mGoalX - (mX - mLanderWidth/2)) <= getWidth/6)            mLastTime = System.currentTimeMillis + 100    mode = RUNNING  }  /**   * Resumes from a pause.   */  def doResume() {    // Move the real time clock up to now    mLastTime = System.currentTimeMillis + 100    mode = RUNNING  }  /**   * Pauses from the running state.   */  def doPause() { if (mMode == RUNNING) mode = PAUSE }      /**   * Standard override to get key events.   */  override def onKeyDown(keyCode: Int, msg: KeyEvent): Boolean = {    var handled = false    val okStart = keyCode == KeyEvent.KEYCODE_DPAD_UP ||                  keyCode == KeyEvent.KEYCODE_DPAD_DOWN ||                  keyCode == KeyEvent.KEYCODE_S    val center = keyCode == KeyEvent.KEYCODE_DPAD_UP    // ready-to-start -> start    if (okStart && (mMode == READY || mMode == LOSE || mMode == WIN)) {      doStart()      handled = true    }    // paused -> running    else if (mMode == PAUSE && okStart) {      doResume()      handled = true    } else if (mMode == RUNNING) {      // center/space -> fire      if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER  ||          keyCode == KeyEvent.KEYCODE_SPACE) {        isFiring = true        handled = true        // left/q -> left      } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT ||                 keyCode == KeyEvent.KEYCODE_Q) {        mRotating = -1        handled = true        // right/w -> right      } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||                 keyCode == KeyEvent.KEYCODE_W) {        mRotating = 1        handled = true        // up -> pause      } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {        doPause()        handled = true      }    }    handled  }  /**   * Standard override for key-up. We actually care about these,   * so we can turn off the engine or stop rotating.   */  override def onKeyUp(keyCode: Int, msg: KeyEvent): Boolean =     if (mMode == RUNNING) {      if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||          keyCode == KeyEvent.KEYCODE_SPACE) {        isFiring = false        true      } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT ||                 keyCode == KeyEvent.KEYCODE_Q ||                  keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ||                 keyCode == KeyEvent.KEYCODE_W) {        mRotating = 0        true      } else false    } else false  def difficulty_=(d: Int) { mDifficulty = d }  def difficulty = mDifficulty}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -