Android Open Source - ShootEmOff World






From Project

Back to project page ShootEmOff.

License

The source code is released under:

Copyright (c) 2011 Andrey Moiseev, http://o2genum.ru Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),...

If you think the Android project ShootEmOff 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.shootemoff.game;
//from   w  ww. ja  v a2s.  co m
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;

import android.content.res.Configuration;

import com.shootemoff.framework.Audio;
import com.shootemoff.framework.Game;
import com.shootemoff.framework.Graphics;
import com.shootemoff.framework.Input.KeyEvent;
import com.shootemoff.framework.Input.TouchEvent;
import com.shootemoff.framework.Sound;

/* I should have used pools for my objects not to make garbage
 * collector angry. As it freezes the game sometimes, 
 * I avoided some object creations. However, it doesn't help.
 */

public class World
{
  Random random = new Random();
  Game game;
  private final int DOTS_COUNT = 15;
  private final int GUN_SHOTS_COUNT = 10;
  // In this case ArrayList is better than LinkedList:
  // list will never be resized.
  public List<Dot> dots = new ArrayList<Dot>(DOTS_COUNT);
  
  public List<Dot> shots = new ArrayList<Dot>(GUN_SHOTS_COUNT);
  
  public Core core = new Core();
  public ControlPad shieldControl = new ControlPad();
  public ControlPad gunControl = new ControlPad();
  public float offScreenRadius;
  private final float SHIELD_HEALTH = 20.0F;
  private final float CORE_HEALTH = 6.0F;
  //private final int[] ALLOWED_ANGLES = {110, 330, 10, 180, 350, 300, 30, 200, -20, 100, 50, 320, 270};
  private final int[] ALLOWED_ANGLES = {30, 200, -20, 100, 50, 320, 270, 0, 70, 340, 45, 20, 190, -80};
     
  public boolean just_aimed = false;
  public double aim_angle;
  public VectorF aim_beam;
  
  public float shield_top_coef = (float)0.65;//0.05;
  public float shield_bottom_coef = (float)0.95;//0.35;
  public float shield_right_coef = (float)0.30;
  public float shield_left_coef = (float)0.06;
  public float shield_top;
  public float shield_bottom;
  public float shield_right;
  public float shield_left;
  
  public float gun_top_coef = (float)0.05;//0.65;
  public float gun_bottom_coef = (float)0.35;//0.95;
  public float gun_right_coef = (float)0.30;
  public float gun_left_coef = (float)0.06;
  public float gun_top;
  public float gun_bottom;
  public float gun_right;
  public float gun_left;
  
  //default base speed
  float base_speed;
  
  private float time = 0.0F; // in seconds
  private float last_shot_time = 0.0F;

  public enum GameState {Ready, Running, Paused, GameOver}

  public GameState state = GameState.Ready;

  private float difficulty = 0.04F; // Max 0.1F

  // Sounds
  // Dot collides with core
  Sound coreHurt;
  Sound coreHealth;
  Sound coreShield;
  // Dot collides with shield
  Sound shieldCollision;

  Sound gameOver;
  Sound gunShot;
  Sound shieldMove;
  Sound gunShotCollision;
  Sound gameOn;

  public World(Game game, int screen_layout)
  {
    this.game = game;
    Graphics g = game.getGraphics();
    
    // Construct core
    core.coords = new VectorF((float) g.getWidth() / 4,
           (float) g.getHeight() / (float) 2);
    core.shieldRadius = (float) g.getWidth() / 4;
    core.maxRadius = core.shieldRadius * 0.7F;
    core.angle = 45.0F;
    core.health = 1.0F;
    core.shieldEnergy = 0.0F;
    
    //Construct shield arc
    shieldControl.angle = 45.0F;
    shieldControl.coords = new VectorF( (float)(g.getWidth() * 0.13),(float)(g.getHeight() * 0.80) );
    shieldControl.ARC_RADIUS = (float)(g.getHeight() * 0.15);
    shieldControl.SHIELD_RADIUS = (float)(shieldControl.ARC_RADIUS * 0.9F);
    
    //Construct gun arc
    gunControl.coords = new VectorF( (float)(g.getWidth() * 0.13),(float)(g.getHeight() * 0.20) );
    gunControl.ARC_RADIUS = (float)(g.getHeight() * 0.15);
    gunControl.SHIELD_RADIUS = (float)(gunControl.ARC_RADIUS * 0.9F);
    
    // Set offScreenRadius
    offScreenRadius = (float) Math.hypot((double) g.getWidth() / 2,
        (double) g.getHeight() / (float) 1.4);
    
    // Max dot radius (when it's energy is 1.0F)
    Dot.maxRadius = core.maxRadius / 8.0F;
    
    DetermineBaseSpeed(screen_layout);
    loadSounds();
  }
  
  //return 1-small, 2-normal, 3-large, 2-other sizes
  private int DetermineScreenSize(int screen_layout)
  {
    int screen_size;
    if ( (screen_layout & Configuration.SCREENLAYOUT_SIZE_MASK ) == Configuration.SCREENLAYOUT_SIZE_LARGE ) {     
          screen_size = 3;
      }
      else if ( (screen_layout & Configuration.SCREENLAYOUT_SIZE_MASK ) == Configuration.SCREENLAYOUT_SIZE_NORMAL ) {     
        screen_size = 2;
      } 
      else if ( (screen_layout & Configuration.SCREENLAYOUT_SIZE_MASK ) == Configuration.SCREENLAYOUT_SIZE_SMALL ) {     
        screen_size = 1;
      }
      else {
        screen_size = 2;
      }
    
    return screen_size;
  }
  
  private void DetermineBaseSpeed(int screen_layout)
  {
    int screen_size = DetermineScreenSize(screen_layout);
    switch(screen_size){
      case 1:
        this.base_speed = 5F;
        break;
      case 2:
        this.base_speed = 15F;
        break;
      case 3:
        this.base_speed = 25F;
        break;
      default:
        this.base_speed = 15F;
    }
    
  }
  
  private void loadSounds()
  {
    Audio a = game.getAudio();
    coreHurt = a.newSound("core_hurt.wav");
    coreHealth = a.newSound("core_health.wav");
    coreShield = a.newSound("core_shield.wav");
    shieldCollision = a.newSound("clash_02.wav");
    gameOver = a.newSound("game_over.wav");
    gunShot = a.newSound("laser_shot.wav");
    shieldMove = a.newSound("shield_move.wav");
    gunShotCollision = a.newSound("clash_01.wav");
    gameOn = a.newSound("saber_on.wav");
  }

  // Restart the game  
  public void renew()
  {
    dots.clear();
    core.health = 1.0F;
    core.shieldEnergy = 0.0F;
    time = 0.0F;
    last_shot_time = 0.0F;
    state = GameState.Ready;
    difficulty = 0.04F;
    generateStartDots(DOTS_COUNT);
  }
  // Add randomness
  private void generateStartDots(int count)
  {
    for(int i = 0; i < count; i++)
    {
      generateNewDot(true);
    }
  }

  private VectorF generateNewDotCoordsInRandomPlace()
  {
    //should stick to predefined angles to make the enemies can from above
    int index = random.nextInt(ALLOWED_ANGLES.length -1 );
    int angle = ALLOWED_ANGLES[ index ];
    
    VectorF coords = new VectorF((float) Math.cos(angle), 
        (float) Math.sin(angle));
    
    coords = coords.multiply(core.shieldRadius + (offScreenRadius -
          core.shieldRadius) * random.nextFloat());
    return coords;
  }

  public void update(float deltaTime)
  {
    if(state == GameState.Ready){
      updateReady(deltaTime);
    }
    if(state == GameState.Running){
      updateRunning(deltaTime);
    }
    if(state == GameState.Paused){
      updatePaused(deltaTime);
    }
    if(state == GameState.GameOver){
      updateGameOver(deltaTime);
    }
  }

  private void doInput()
  {
    if(game.getInput().isTouchDown()){
      
      double touchX = (double) game.getInput().getTouchX();
      double touchY = (double) game.getInput().getTouchY();
      //shield pad controls
      if(touchY >= shield_left && touchX <= shield_right &&
          touchY >= shield_top && touchY <= shield_bottom){
        
        float shield_pad_width = shield_bottom - shield_top;
        float touchPoint = (float)((touchY - shield_top) / shield_pad_width);
        
        core.angle = (270 - (200 * touchPoint)) + 200;
        shieldControl.angle = core.angle;
        shieldMove.play(20);
      }
      else if( touchY >= gun_left && touchX <= gun_right &&
            touchY >= gun_top && touchY <= gun_bottom ){

        //double shot_offset = (int)(time - last_shot_time);
        if(shots.size() < GUN_SHOTS_COUNT){
          
          float gun_pad_width = gun_bottom - gun_top;
          float touchPoint = (float)((touchY - gun_top) / gun_pad_width);
          aim_angle = (270 - (200 * touchPoint)) + 200 + 90;
          double radians = Math.toRadians(aim_angle);
          
          float current_radius = core.maxRadius * 3;
          double x_coord = core.coords.x + (Math.sin(radians) * current_radius);
          double y_coord = core.coords.y + (Math.cos(radians) * current_radius);
          aim_beam = new VectorF((float)x_coord, (float)y_coord);
          just_aimed = true;
          last_shot_time = time;
        }
        /*
          // Y-axis is inverted. See checkCollisionWithShield(...)
          // method
          normAngle(((float) (Math.atan2(-(touchY - core.coords.y), 
              touchX - core.coords.x) / (Math.PI * 2) *
          360.0)) - Core.GAP_ANGLE/2F);
        */
      }
    }
    //remember the aiming angle and sheooooouut...
    if(just_aimed == true && last_shot_time < time){
      double radians = Math.toRadians(aim_angle);
      
      float current_radius = core.maxRadius * core.health;
      double x_coord = core.coords.x + (Math.sin(radians) * current_radius);
      double y_coord = core.coords.y + (Math.cos(radians) * current_radius);
      
      gunShot.play(40);
      generateNewGunShot(x_coord, y_coord, radians);
      just_aimed = false;
    }
    
  }

  private void updateReady(float deltaTime)
  {
    if(checkTouchUp() || checkMenuUp())
      state = GameState.Running;
  }
  
  private boolean checkTouchUp()
  {
    for(TouchEvent event : game.getInput().getTouchEvents())
    {
      if(event.type == TouchEvent.TOUCH_UP)
        return true;
    }
    return false;
  }

  private boolean checkMenuUp()
  {
    for(KeyEvent event : game.getInput().getKeyEvents())
    {
      if(event.keyCode == android.view.KeyEvent.KEYCODE_MENU)
      {
        if(event.type == KeyEvent.KEY_UP)
          return true;
      }

    }
    return false;
  }

  private void updatePaused(float deltaTime)
  {
    if(checkTouchUp() || checkMenuUp())
      state = GameState.GameOver;
  }

  private void updateGameOver(float deltaTime)
  {
    if(checkTouchUp() || checkMenuUp())
      renew();
  }

  private void updateRunning(float deltaTime)
  {
    checkTouchUp(); // Just to clear touch event buffer

    if(checkMenuUp())
      state = GameState.Paused;

    countTime(deltaTime);

    doInput();

    generateNewDots(DOTS_COUNT);

    handleShotPositions();
    handleCollisions();
    moveDots(deltaTime);
    moveShots(deltaTime);
    decreaseShieldEnergy(deltaTime);
  }

  private void decreaseShieldEnergy(float deltaTime)
  {
    if(core.shieldEnergy > 0.0F)
    {
      core.shieldEnergy -= deltaTime / SHIELD_HEALTH;
      if(core.shieldEnergy < 0.0F)
      core.shieldEnergy = 0.0F;
    }
  }

  private void generateNewDots(int neededCount)
  {
    if(neededCount > dots.size())
      generateNewDot(false);
  }

  private void increaseDifficulty()
  {
    difficulty += 0.00005F;
  }
  
  private void generateNewGunShot(double x, double y, double radians)
  {
    float linearSpeed = this.base_speed * difficulty;
    Dot gun_shot = new Dot();
    
    gun_shot.coords = new VectorF((float)x, (float)y);
    
    gun_shot.angle_radians = radians;
    
    VectorF speed  = new VectorF(linearSpeed, linearSpeed);
    gun_shot.speed = speed;
    gun_shot.energy = 1.0F;
    //gun_shot.coords.subtractFromThis(core.coords);
    //gun_shot.coords = generateNewDotCoordsInRandomPlace();
    gun_shot.type = Dot.Type.Gunshot;
    
    shots.add(gun_shot);
  }

  private void generateNewDot(boolean atStart)
  {
    float linearSpeed = this.base_speed * difficulty;
    Dot dot = new Dot();
    if(atStart)
    {
      dot.coords = generateNewDotCoordsInRandomPlace();
    }
    else
    {
      dot.coords = generateNewDotAtOffScreenRadius();
      increaseDifficulty();
    }
    VectorF speed = new VectorF(
        linearSpeed * (-dot.coords.x / dot.coords.length()),
         linearSpeed * (-dot.coords.y / dot.coords.length()));
    dot.speed = speed;
    dot.coords.addToThis(core.coords);
    dot.energy = random.nextFloat();
    if(dot.energy <= 0.3F)
      dot.energy = 0.3F;
    float typeRand = random.nextFloat();
    Dot.Type type;
    if (typeRand >= 0.8){
      type = Dot.Type.Health;
    }
    else{
      type = Dot.Type.Enemy;
    }
    dot.type = type;
    dots.add(dot);
  }

  private void countTime(float deltaTime)
  {
    time += deltaTime;
  }

  public String getTime()
  {
    int seconds = (int) time;
    int minutes = seconds / 60;
    seconds %= 60;
    String result = "";
    if(minutes > 0)
      result += minutes + ":";
    result += String.format("%02d", seconds);
    return result;
  }

  private VectorF generateNewDotAtOffScreenRadius()
  {
    //should stick to predefined angles to make the enemies can from above
    int index = random.nextInt(ALLOWED_ANGLES.length -1 );
    int angle = ALLOWED_ANGLES[ index ];
    
    VectorF coords =
         new VectorF(offScreenRadius * ((float) Math.cos(angle)),
          offScreenRadius * ((float) Math.sin(angle)));
    
    return coords;
  }
  
  private void moveShots(float deltaTime)
  {
    for(Dot dot : shots)
    {
      dot.coords.addToThis((float)(dot.speed.x * deltaTime * 100.0F * Math.sin(dot.angle_radians)),
          (float)(dot.speed.y * deltaTime * 100.0F * Math.cos(dot.angle_radians)));
      
      
    }
  }
  
  private void moveDots(float deltaTime)
  {
    for(Dot dot : dots)
    {
      dot.coords.addToThis(dot.speed.x * deltaTime * 100.0F,
          dot.speed.y * deltaTime * 100.0F);
    }
  }
  
  private void handleShotPositions()
  {
    Iterator<Dot> iterator = shots.iterator();
    while(iterator.hasNext())
    {
      handleShotPosition(iterator.next(), iterator);
    }
  }
  
  private void handleShotPosition(Dot shot, Iterator<Dot> iterator)
  {
    
    Graphics g = game.getGraphics();
    if(shot.coords.x < 0 || shot.coords.y < 0 || shot.coords.x > g.getWidth() || shot.coords.x > g.getHeight()){
      iterator.remove();
    }
  }
  
  private void handleShotCollision(Dot shot, Iterator<Dot> shot_iterator, Dot dot, Iterator<Dot> dot_iterator)
  {
    if(Math.abs(shot.coords.x - dot.coords.x) <= Dot.maxRadius &&
        Math.abs(shot.coords.y - dot.coords.y) <= Dot.maxRadius){
      
      shot_iterator.remove();
      dot_iterator.remove();
      gunShotCollision.play(40);
      game.getVibration().vibrate(30);
    }
  }

  private void handleCollisions()
  {
    Iterator<Dot> iterator = dots.iterator();
    while(iterator.hasNext())
    {
      handleCollision(iterator.next(), iterator);
    }
  }

  private void handleCollision(Dot dot, Iterator<Dot> iterator)
  {
    float lengthToCoreCenter = (float)Math.hypot(
        (double)(dot.coords.x - core.coords.x),
        (double)(dot.coords.y - core.coords.y)); 
    
    if(Math.abs(lengthToCoreCenter - 
          core.shieldRadius) <= dot.maxRadius * dot.energy +
        Core.SHIELD_WIDTH)
    {
      checkCollisionWithShield(dot, iterator);
    }
    else if (lengthToCoreCenter - core.maxRadius * core.health <=
           Dot.maxRadius * dot.energy){
      handleCollisionWithCore(dot, iterator);
    }
    else{
      try{
        if(shots.size() > 0 && dot.type == Dot.Type.Enemy){
          Iterator<Dot> shot_iterator = shots.iterator();
          while(shot_iterator.hasNext()){
            handleShotCollision(shot_iterator.next(), shot_iterator, dot, iterator);
          }
        }
      }
      catch(NoSuchElementException e){
        // just sit this one out
      }
    }
  }

  private void checkCollisionWithShield(Dot dot, Iterator<Dot> iterator)
  {
    // I normalize (move into (0; 360) interval) angles
    // in some places. Don't know if it's needed.
    if(core.shieldEnergy > 0.0F)
    {
      iterator.remove();
      shieldCollision.play(dot.energy);
      game.getVibration().vibrate(30);
    }
    else
    {
    // Pay attention at -v.y! Y-axis is inverted, 
    // because it points downwards.
    float dotAngle = (float) Math.atan2((double) - 
        (dot.coords.y - core.coords.y),
           (double) (dot.coords.x - core.coords.x));
    dotAngle = dotAngle / (((float) Math.PI) * 2.0F) * 360.0F;
    dotAngle = normAngle(dotAngle);
    // For example, dotAngle = 3, and core.angle = 365
    // We need to solve this somehow:
    core.angle = normAngle(core.angle);
    while(dotAngle < core.angle)
    {
      dotAngle += 360.0F;
    }
    // OK, and check if dotAngle is within the gap
    if(!((dotAngle > core.angle) &&
             (dotAngle < core.angle + core.GAP_ANGLE)))
    {
      iterator.remove();
      shieldCollision.play(dot.energy);
      game.getVibration().vibrate(40);
    }
    }
  }

  private float normAngle(float angle)
  {
    float angle2 = angle;
    while(angle2 < 0.0F)
      angle2 += 360.0F;

    while(angle2 > 360.0F)
      angle2 -= 360.0F;

    return angle2;
  }

  private void handleCollisionWithCore(Dot dot, Iterator<Dot> iterator)
  {
    if(dot.type == Dot.Type.Enemy){
      core.health -= dot.energy / CORE_HEALTH;
      if(core.health < 0.0F)
      {
        //state = GameState.GameOver;
        state = GameState.Paused;
        gameOver.play(1F);
        game.getVibration().vibrate(10);
        game.getVibration().vibrate(40);
        game.getVibration().vibrate(100);
        core.health = 0.0F;
      }
      coreHurt.play(dot.energy);
      }
      else if (dot.type == Dot.Type.Health)
      {
      core.health += dot.energy / CORE_HEALTH;
      if(core.health > 1.0F)  
      {
        core.health = 1.0F;
      }
      coreHealth.play(dot.energy);
    }

    iterator.remove();
    game.getVibration().vibrate(30);
  }

}




Java Source Code List

com.shootemoff.framework.Audio.java
com.shootemoff.framework.FileIO.java
com.shootemoff.framework.Game.java
com.shootemoff.framework.Graphics.java
com.shootemoff.framework.Input.java
com.shootemoff.framework.Pool.java
com.shootemoff.framework.Screen.java
com.shootemoff.framework.Sound.java
com.shootemoff.framework.Vibration.java
com.shootemoff.framework.impl.AndroidAudio.java
com.shootemoff.framework.impl.AndroidFastRenderView.java
com.shootemoff.framework.impl.AndroidFileIO.java
com.shootemoff.framework.impl.AndroidGame.java
com.shootemoff.framework.impl.AndroidGraphics.java
com.shootemoff.framework.impl.AndroidInput.java
com.shootemoff.framework.impl.AndroidOrientationHandler.java
com.shootemoff.framework.impl.AndroidSound.java
com.shootemoff.framework.impl.AndroidVibration.java
com.shootemoff.framework.impl.KeyboardHandler.java
com.shootemoff.framework.impl.MultiTouchHandler.java
com.shootemoff.framework.impl.OrientationHandler.java
com.shootemoff.framework.impl.SingleTouchHandler.java
com.shootemoff.framework.impl.TouchHandler.java
com.shootemoff.game.ControlPad.java
com.shootemoff.game.Core.java
com.shootemoff.game.Dot.java
com.shootemoff.game.GameActivity.java
com.shootemoff.game.GameOverActivity.java
com.shootemoff.game.GameScreen.java
com.shootemoff.game.OptionsObject.java
com.shootemoff.game.Point.java
com.shootemoff.game.ScoreBoardActivity.java
com.shootemoff.game.ScoreObject.java
com.shootemoff.game.SettingsActivity.java
com.shootemoff.game.StartScreenActivity.java
com.shootemoff.game.StorageHandler.java
com.shootemoff.game.VectorF.java
com.shootemoff.game.World.java