Android Open Source - tapdefence Game Thread






From Project

Back to project page tapdefence.

License

The source code is released under:

MIT License

If you think the Android project tapdefence listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.kulinich.tapdefence.engine;
//from w ww . j a v a  2 s  . c  o m
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class GameThread extends Thread {

  Game mGame;
  InputHandler mInput;

  SurfaceHolder mSurfaceHolder;
  Handler mHandler;
  Context mContext;

  int mCanvasWidth;
  int mCanvasHeight;

  boolean mRun;
  int mMode;

  private RectF mScratchRect = new RectF(0, 0, 0, 0);

  public GameThread(SurfaceHolder surfaceHolder, Context context,
      Handler handler) {
    mSurfaceHolder = surfaceHolder;
    mHandler = handler;
    mContext = context;

    // Resources res = context.getResources();

    Constants.initializePaints();
  }

  public void doStart() {
    synchronized (mSurfaceHolder) {
      mGame = new Game(this);
      mInput = new InputHandler(mGame);
    }
    setState(Constants.STATE_RUNNING);
  }

  public void pause() {
    synchronized (mSurfaceHolder) {
      if (mMode == Constants.STATE_RUNNING) {
        setState(Constants.STATE_PAUSE);
      }
    }
  }

  public void unpause() {
    // Move the real time clock up to now
    synchronized (mSurfaceHolder) {
      mGame.mLastTime = System.currentTimeMillis() + 100;
      mGame.mLastTimeEnemySpawned = mGame.mLastTime;
    }
    setState(Constants.STATE_RUNNING);
  }

  public void setRunning(boolean b) {
    mRun = b;
  }

  @Override
  public void run() {
    while (mRun) {
      Canvas c = null;
      try {
        c = mSurfaceHolder.lockCanvas(null);
        synchronized (mSurfaceHolder) {
          if (mMode == Constants.STATE_RUNNING
              || mMode == Constants.STATE_LOSE) {
            update();
            doDraw(c);
          }
        }
      } finally {
        if (c != null) {
          mSurfaceHolder.unlockCanvasAndPost(c);
        }
      }
    }
  }

  private void setState(int mode) {
    synchronized (mSurfaceHolder) {
      setState(mode, 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 == Constants.STATE_RUNNING) {
        // Message msg = mHandler.obtainMessage();
        // mHandler.sendMessage(msg);
      } else {
        if (mMode == Constants.STATE_READY) {

        } else if (mMode == Constants.STATE_PAUSE) {

        } else if (mMode == Constants.STATE_LOSE) {

        }
      }
    }
  }

  public void endGame() {
    setRunning(false);

    Message msg = mHandler.obtainMessage();
    Bundle data = new Bundle();
    data.putLong("score", mGame.calculateScore());
    msg.setData(data);
    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;
    }
  }

  private void doDraw(Canvas canvas) {
    // Clear canvas
    canvas.drawColor(Constants.BG_COLOR_PAINT.getColor(),
        PorterDuff.Mode.CLEAR);
    canvas.save();

    // Rumble
    if (mGame.mRumbleAmount > 0) {
      canvas.translate(
          (float) Math.floor(Math.random()
              * (mGame.mRumbleAmount / 4 + 1))
              - mGame.mRumbleAmount / 8,
          (float) Math.floor(Math.random()
              * (mGame.mRumbleAmount / 4) - mGame.mRumbleAmount
              / 8));
    }

    // Stars
    for (int i = 0; i < mGame.mStars.size(); ++i) {
      Star star = mGame.mStars.get(i);
      canvas.drawCircle(star.x, star.y, star.radius, star.paint);
    }

    if (mMode == Constants.STATE_RUNNING) {
      // Health indicator
      canvas.drawCircle(mGame.mX, mGame.mY,
          Constants.PLAYER_CIRCLE_RADIUS
              + Constants.PLAYER_HEALTH_GLOW_SIZE,
          mGame.makeHealthGradient());

      // Draw player
      canvas.drawCircle(mGame.mX, mGame.mY,
          Constants.PLAYER_CIRCLE_RADIUS, Constants.PLAYER_PAINT);
    }

    // Particles
    Iterator<Particle> particleIter = mGame.mParticles.iterator();
    while (particleIter.hasNext()) {
      Particle particle = particleIter.next();
      if (particle.visible) {
        canvas.drawCircle(particle.point.x, particle.point.y,
            particle.radius, particle.paint);
      } else {
        particleIter.remove();
      }
    }

    // Enemies
    Iterator<Enemy> enemyIter = mGame.mEnemies.iterator();
    while (enemyIter.hasNext()) {
      Enemy enemy = enemyIter.next();
      if (enemy.visible) {
        canvas.drawLine(enemy.a.x, enemy.a.y, enemy.b.x, enemy.b.y,
            Constants.ENEMY_PAINT);
      } else {
        enemyIter.remove();
      }
    }

    // Walls
    Iterator<Wall> wallIter = mGame.mWalls.iterator();
    while (wallIter.hasNext()) {
      Wall wall = wallIter.next();
      if (wall.visible) {
        canvas.drawLine(wall.a.x, wall.a.y, wall.b.x, wall.b.y,
            Constants.WALL_PAINT);
      } else {
        wallIter.remove();
      }
    }

    // Player draws some walls
    for (int i = 0; i < mInput.mCurrentLines.size(); ++i) {
      Line line = mInput.mCurrentLines.valueAt(i);
      canvas.drawLine(line.a.x, line.a.y, line.b.x, line.b.y,
          Constants.DRAW_WALL_PAINT);
    }
    for (int i = 0; i < mInput.mFakeLines.size(); ++i) {
      Line line = mInput.mFakeLines.valueAt(i);
      canvas.drawLine(line.a.x, line.a.y, line.b.x, line.b.y,
          Constants.FAKE_WALL_PAINT);
    }

    // Draw the power gauge
    if (mMode == Constants.STATE_RUNNING) {
      int fuelWidth = (int) ((mCanvasWidth - 8) * mGame.mPower / Constants.POWER_MAX);
      mScratchRect.set(4, 4, 4 + fuelWidth, 4 + Constants.UI_BAR_HEIGHT);
      canvas.drawRect(mScratchRect, Constants.UI_POWER_PAINT);
    }

    // Power gauge ghost
    int fuelGhostWidth = (int) ((mCanvasWidth - 8) * mGame.mPowerGhost / Constants.POWER_MAX);
    mScratchRect.set(4, 4, 4 + (int) (mCanvasWidth - 8),
        4 + Constants.UI_BAR_HEIGHT);
    canvas.drawRect(mScratchRect, Constants.UI_POWER_GHOST_PAINT);

    // Alarm
    if (mGame.mAlarm) {
      mScratchRect.set(0, 0, mCanvasWidth, mCanvasHeight);
      canvas.drawRect(mScratchRect, Constants.ALARM_PAINT);
    }

    // Explosion
    if (mGame.mExploding) {
      mScratchRect.set(0, 0, mCanvasWidth, mCanvasHeight);
      canvas.drawRect(mScratchRect, Constants.EXPLOSION_PAINT);
    }
  }

  private synchronized void update() {
    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 (mGame.mLastTime > now) {
      return;
    }

    double elapsed = (now - mGame.mLastTime) / 1000.0;
    mGame.updateRumble(elapsed);

    if (mMode == Constants.STATE_RUNNING) {
      mGame.mOverallTime += elapsed;

      // Check health
      if (mGame.mHealth <= 0) {
        mGame.shake(Constants.RUMBLE_PLAYER_DESTROYED);
        setState(Constants.STATE_LOSE);
        mGame.makeExplosion();
        Log.d("Game", "Game over");
      }

      // Player draws some walls
      mInput.update();

      // Spawn enemies
      int secondsFromLastSpawn = (int) Math
          .floor((double) (now - mGame.mLastTimeEnemySpawned) / 1000);
      int toSpawn = (int) Math.floor(secondsFromLastSpawn
          / mGame.mEnemyPeriod);
      if (toSpawn > 0) {
        for (int i = 0; i < toSpawn; ++i) {
          mGame.spawnEnemy();
        }
        mGame.mLastTimeEnemySpawned = now;
      }

      mGame.updateDifficulty(elapsed);
      mGame.updateEnemies(elapsed);

      mGame.updateAlarm();

      // Restore health and power
      mGame.updateHealth(Constants.HEALTH_RENEWAL_SPEED * (float) elapsed);
      mGame.updatePower(Constants.POWER_RENEWAL_SPEED * (float) elapsed);
    }

    mGame.updateParticles(elapsed);
    mGame.updateExplosion(elapsed);

    mGame.mLastTime = now;
  }

  void onTouch(MotionEvent e) {
    mInput.onTouch(e);
  }
}




Java Source Code List

com.kulinich.tapdefence.GameActivity.java
com.kulinich.tapdefence.MainActivity.java
com.kulinich.tapdefence.ScoreDialog.java
com.kulinich.tapdefence.engine.Constants.java
com.kulinich.tapdefence.engine.Enemy.java
com.kulinich.tapdefence.engine.GameSurface.java
com.kulinich.tapdefence.engine.GameThread.java
com.kulinich.tapdefence.engine.Game.java
com.kulinich.tapdefence.engine.InputHandler.java
com.kulinich.tapdefence.engine.Line.java
com.kulinich.tapdefence.engine.Particle.java
com.kulinich.tapdefence.engine.Point.java
com.kulinich.tapdefence.engine.Star.java
com.kulinich.tapdefence.engine.Utils.java
com.kulinich.tapdefence.engine.Wall.java