Android Open Source - DivisionByZero Level Manager






From Project

Back to project page DivisionByZero.

License

The source code is released under:

Apache License

If you think the Android project DivisionByZero 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.ggstudios.divisionbyzero;
//from   w w w  .ja va  2 s  . c  om
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.ggstudios.divisionbyzero.Button.OnClickListener;
import com.ggstudios.divisionbyzero.Game.OnGameReadyListener;
import com.ggstudios.divisionbyzero.MessageDialog.OnDismissListener;
import com.ggstudios.utils.DebugLog;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;

public class LevelManager implements Updatable{
  private final String TAG = "LevelManager";

  /**  
   * Outlined here is a list of special commands...
   */
  enum Command{
    SPAWN_UNIT,
    SLEEP,
    START,
    MESSAGE,
    SPECIAL,
    NULL
  };

  private static final char
  TYPE_INIT_LIVES  = 'l',
  TYPE_INIT_GOLD  = 'g',
  TYPE_SPAWN     = 's',
  TYPE_SPAWN_BOSS = 'b',
  TYPE_SLEEP     = 'p',  // pause
  TYPE_MESSAGE   = 'm',
  TYPE_MAP    = 'a',
  TYPE_SPECIAL  = '!',
  TYPE_DIFFICULTY = '#',
  TYPE_LEVEL_NAME = '$'
  ;

  /**
   * An Event is a class that stores information
   * about a game event. This game event can vary from
   * a spawn event to a wait or message event.
   */
  class Event {
    Command cmd = Command.NULL;

    Object args;
  }
  
  static class Group {
    int groupNumber = 0;
    int memberCount = 0;
    SpawnEvent groupLeader;
  }

  static class SpawnEvent {
    int waveNumber;
    int index;
    int numUnits;
    int pathIndex;    // which starting point to spawn from
    float spawnRate;  // in seconds...
    int hp, gold;

    float approxTime;
    float elapsed = 0f;
    
    Group group;

    public int enemyType;
  }
  
  public static interface WaveChangeListener {
    public void onWaveChange(int currentWave);
  }

  private List<Event> events = new ArrayList<Event>();
  private int mapType;
  private boolean customMap;
  private int customMapW, customMapH;
  private List<String> customMapArgs = new ArrayList<String>();
  private HashMap<Character, List<Character>> symbolMap = new HashMap<Character, List<Character>>();
  private int pathCount = 0;
  private int curEventIndex = 0;
  private boolean waitingForEventToFinish = false;
  private int initGold, initLives;
  private float sleepTime;
  private boolean paused = true;
  private int waveCount;
  private int curWave = 0;
  private SpawnEvent lastSpawnEvent;
  private int difficulty;
  private String levelName;
  private int spriteCount;
  private boolean mock = false;
  private StateManager stateMgr;
  private int totalSpriteGold = 0;
  private float sleepModifier = 1f;

  private WaveChangeListener waveChangeListener = null;
  
  public LevelManager(){
    stateMgr = StateManager.getInstance();
  }

  public void reset(){
    // clear
    sleepTime = 0f;
    curEventIndex = 0;
    curWave = 0;
    waitingForEventToFinish = false;

    if(Core.sm != null)
      Core.sm.reset();

    events.clear();
  }

  public void loadLevelFromFile(final Context context, final int resourceId){
    paused = true;

    waveCount = 0;
    pathCount = 0;

    customMap = false;
    customMapArgs.clear();

    final InputStream inputStream = context.getResources().openRawResource(
        resourceId);
    final InputStreamReader inputStreamReader = new InputStreamReader(
        inputStream);
    final BufferedReader bufferedReader = new BufferedReader(
        inputStreamReader);

    String nextLine;
    //read file

    reset();

    String[] temp;

    spriteCount = 0;
    totalSpriteGold = 0;
    
    Group group = new Group();
    int groupNumber = 0;
    group.groupNumber = groupNumber;
    
    try {
      while ((nextLine = bufferedReader.readLine()) != null)
      {
        if(nextLine.length() == 0 || nextLine.charAt(0) == '/'){
          // it's a comment... skip...
          continue;
        }

        int index = nextLine.indexOf("//");
        if(index != -1) {
          // comment found... remove it!
          nextLine = nextLine.substring(0, index);
        }
        
        char type = nextLine.charAt(0);

        nextLine = nextLine.substring(1);  // remove the first character
        nextLine = nextLine.trim();      // trim spaces

        Event event = new Event();

        switch(type) {
        case TYPE_SPAWN:
        case TYPE_SPAWN_BOSS:
          waveCount++;

          SpawnEvent se = new SpawnEvent();
          lastSpawnEvent = se;
          
          if(group.memberCount == 0) {
            group.groupLeader = se;
          }

          // this is how spawns will be set...
          // first s denotes a spawn command followed by a space

          // all subsequent arguments will be separated by a single space
          temp = nextLine.split("[ \t]+");

          // the first argument is the sprite type 
          // (refer to sprite sheet for more info)
          int unitType = Integer.parseInt(temp[0]);

          // the second argument is the number of sprite to spawn
          int numUnits = Integer.parseInt(temp[1]);

          // the third number is the spawn rate (the higher the number the slower the spawn rate)
          int spawnrate = Integer.parseInt(temp[2]);

          // the fifth value is the HP of the sprite
          int hp = Integer.parseInt(temp[3]);
          
          // gold reward
          int gold = Integer.parseInt(temp[4]);
          
          int pathId = 0;  // default path to the 'a' path...
          if(temp.length > 5) {
            pathId = temp[5].charAt(0) - 'a';
          }
          
          if(type == TYPE_SPAWN_BOSS) {
            unitType += Sprite.TYPE_BOSS;
          }
          
          se.waveNumber = waveCount - 1;
          se.numUnits = numUnits;
          se.spawnRate = spawnrate / 1000f;
          se.index = events.size();
          se.enemyType = unitType;
          se.gold = gold;
          se.hp = hp;
          se.pathIndex = pathId;
          group.memberCount++;
          se.group = group;

          se.approxTime = se.numUnits * se.spawnRate;

          spriteCount += numUnits;
          totalSpriteGold += spriteCount * gold; // update the total gold count...
          
          event.cmd = Command.SPAWN_UNIT;
          event.args = se;

          events.add(event);
          break;
        case TYPE_INIT_LIVES:
          initLives = Integer.parseInt(nextLine);
          break;
        case TYPE_INIT_GOLD:
          initGold = Integer.parseInt(nextLine);
          break;
        case TYPE_SLEEP:
          final float sleepTime = Integer.parseInt(nextLine) / 1000f;
          event.cmd = Command.SLEEP;
          event.args = sleepTime;

          if (lastSpawnEvent != null) {
            lastSpawnEvent.group.groupLeader.approxTime += sleepTime;
          }
          
          group = new Group();
          groupNumber++;
          group.groupNumber = groupNumber;

          events.add(event);
          break;
        case TYPE_MESSAGE:
          event.cmd = Command.MESSAGE;
          event.args = nextLine;

          events.add(event);
          break;
        case TYPE_MAP:
          String[] args = nextLine.trim().split(" ");
          if(args.length == 1)
            mapType = Integer.parseInt(args[0]);
          else {
            mapType = Integer.parseInt(args[0]);
            int w = Integer.parseInt(args[1]);
            int h = Integer.parseInt(args[2]);
            
            customMapW = w;
            customMapH = h;
            
            /*
             * Note that the specification of paths is optional.
             * If no path count is given, then that means we should
             * just use the default path of the map.
             * 
             * Because custom path is optional, we detect if this feature
             * is used by checking the argument for the number of path on
             * the map is specified. If it is then this means that we
             * are indeed using custom paths. Else we assume the default path
             * is used.
             */
            if(args.length > 3)
              pathCount = Integer.parseInt(args[3]);
            else
              pathCount = 0;

            for(int i = 0; i < h; i++) {
              customMapArgs.add(bufferedReader.readLine());
            }

            if(pathCount != 0) {
              // let's analyze the number of arguments after...
              int extraArgs = Integer.parseInt(bufferedReader.readLine());
              for(int i = 0; i < extraArgs; i++) {
                String line = bufferedReader.readLine();
                String[] tokens = line.split(" ");

                ArrayList<Character> chars = new ArrayList<Character>(tokens.length - 1);

                for(int j = 1; j < tokens.length; j++) {
                  chars.add(tokens[j].charAt(0));
                }
                symbolMap.put(tokens[0].charAt(0), chars);
              }
            }

            customMap = true;
          }
          break;
        case TYPE_SPECIAL:
          if(mock) break;
          int arg = Integer.parseInt(nextLine);
          event.cmd = Command.SPECIAL;
          event.args = arg;

          switch(arg) {
          case 0:
            start();
            break;
          case 1:
            Core.game.setOnGameReadyListener(new OnGameReadyListener() {

              @Override
              public void onGameReady() {
                start();
              }
              
            });
            break;
          default:
            break;
          }

          events.add(event);
          break;
        case TYPE_DIFFICULTY:
          difficulty = Integer.parseInt(nextLine);
          break;
        case TYPE_LEVEL_NAME:
          levelName = nextLine.trim();
          break;
        default:
          DebugLog.e(TAG, "Error. Unsupported level command: " + type);
          break;
        }
      }
    } catch (IOException e) {
      DebugLog.e(TAG, e);
    }
  }

  public int getSpriteCount() {
    return spriteCount;
  }

  public int getMapType() {
    return mapType;
  }

  public boolean isCustomMap() {
    return customMap;
  }
  
  public int getCustomMapW() {
    return customMapW;
  }
  
  public int getCustomMapH() {
    return customMapH;
  }

  public List<String> getCustomMapArgs() {
    return customMapArgs;
  }
  
  public HashMap<Character, List<Character>> getCustomMapSymbolMap() {
    return symbolMap;
  }
  
  public int getPathCount() {
    return pathCount;
  }

  public int getInitLives() {
    return initLives;
  }

  public int getInitGold() {
    return initGold;
  }

  public boolean hasNextEvent() {
    return curEventIndex < events.size();
  }

  public void putBackLast() {
    curEventIndex--;
  }

  public Event getNextEvent() {
    if(curEventIndex == events.size())
      return null;
    return events.get(curEventIndex++);
  }

  public List<Event> getRawEvents() {
    return events;
  }

  public Event getEventAt(int index) {
    return events.get(index);
  }

  public int getWaveCount() {
    return waveCount;
  }

  public void setCurrentEventDone() {
    waitingForEventToFinish = false;
  }
  
  public void speedUpSleep() {
    sleepModifier = 5f;
  }
  
  public void resetSleepModifier() {
    sleepModifier = 1f;
  }
  
  public void setOnWaveChangeListener(WaveChangeListener listener) {
    waveChangeListener = listener;
  }

  @Override
  public boolean update(float dt) {
    if(paused)
      return true;
    if(sleepTime > 0){
      dt *= sleepModifier;
      if(lastSpawnEvent != null) {
        lastSpawnEvent.group.groupLeader.elapsed += dt;
      }
      sleepTime -= dt;
      return true;
    }

    if(!waitingForEventToFinish) {
      if(hasNextEvent()) {
        Event event = getNextEvent();
        switch(event.cmd) {
        case SPAWN_UNIT:
          DebugLog.d(TAG, "Spawning more enemies...");

          do {
            curWave++;
            SpawnEvent se = (SpawnEvent) event.args;
            lastSpawnEvent = se;
            Core.sm.queueSpawn(se);
            
            event = getNextEvent();
          } while(event != null && event.cmd == Command.SPAWN_UNIT);
          
          if(event != null)
            putBackLast();
          
          waitingForEventToFinish = true;
          
          Core.hud.showMessage("Wave " + (lastSpawnEvent.group.groupNumber + 1));
          if(waveChangeListener != null) {
            waveChangeListener.onWaveChange(curWave);
          }
          break;
        case SLEEP:
          sleepTime = ((Float) event.args);
          resetSleepModifier();
          DebugLog.d(TAG, "Sleeping for: " + sleepTime);
          break;
        case START:
          DebugLog.d(TAG, "Start event!");
          break;
        case MESSAGE: {
          final MessageDialog d = new MessageDialog();
          d.setMessage((String) event.args);
          d.setOnDismissListener(new OnDismissListener() {

            @Override
            public void onDismiss() {
              setCurrentEventDone();
            }

          });
          Core.glView.queueEvent(new Runnable() {

            @Override
            public void run() {
              d.build();
              d.show();
            }

          });
          waitingForEventToFinish = true;
          break; }
        case SPECIAL:
          DebugLog.d(TAG, "Special event!");
          // special events can do a variety of things...
          int arg = (Integer) event.args;
          switch(arg) {
          case 0:
            Core.glView.queueEvent(new Runnable() {

              @Override
              public void run() {
                boolean skipable = stateMgr.isOpeningSkipable();
                
                // set up the cinematics...
                float w = Core.SDP * 3f;
                float h = w;
                float centerX = (Core.canvasWidth - w) / 2f;
                float centerY = (Core.canvasHeight - h) / 2f;

                Paint p = new Paint();
                p.setTextSize(Core.SDP);
                p.setColor(Color.WHITE);
                p.setAntiAlias(true);
                
                float dim = Core.SDP * 2;
                final Button skip = new Button(Core.canvasWidth - dim, Core.canvasHeight - dim, dim, dim, "Skip", p) {
                  @Override
                  public void draw(float offX, float offY) {
                    super.draw(0, 0);
                  }
                  
                  @Override
                  public boolean onTouchEvent(int action, float _x, float _y) {
                    final float x = Core.originalTouchX;
                    final float y = Core.originalTouchY;
                    DebugLog.d(TAG, "x" + x + "y" + y);
                    return super.onTouchEvent(action, x, y);
                  }
                };
                
                final String[] numerators   = {"2", "7", "9", "8", "4"};
                final String[] denominators = {"2", "3", "5" , "4", "1"};
                final String[] answers     = {"1", "2", "1" , "2", "4"};

                final Button bg =  new Button(0, 0, Core.canvasWidth, Core.canvasHeight, -1) {
                  @Override
                  public boolean onTouchEvent(int action, float x, float y) {
                    return true;
                  }
                };
                final Rectangle rect = new Rectangle(0, 0, Core.canvasWidth, Core.canvasHeight, 0xFF000000);
                final PictureBox divisionMachine = new PictureBox(centerX, centerY, w, h, R.drawable.division_machine);
                final Label arg1 = new Label(-999, -999, p, "2");
                final Label arg2 = new Label(-999, -999, p, "6");
                final Label result = new Label(-999, -999, p, "3");
                final Label enemy = new Label(-999, -999, p, "0");
                final ExplosionGenerator explosion = new ExplosionGenerator(20);
                explosion.setPosition(divisionMachine.x + divisionMachine.w/2f, divisionMachine.y + divisionMachine.h/2f);
                explosion.setParticleTexture(R.drawable.aoe_blast);
                explosion.setParticleSize(Core.SDP * 2.2f);
                explosion.setSizeVariance(0.4f);
                explosion.setDistanceVariance(Core.SDP * 2.5f);
                explosion.setGenerationChance(0.5f);
                explosion.setInitialParticles(10);
                explosion.setVisible(false);
                explosion.build();
                
                final ParticleEngine sparks = new ParticleEngine(10);
                sparks.setParticleTexture(R.drawable.spark);
                sparks.setPosition(explosion.x, explosion.y);
                sparks.setParticleSize(Core.SDP / 8f, Core.SDP);
                sparks.setMaxVelocity(Core.SDP * 0.3f);
                sparks.setColor(1f, 0.7f, 0.5f);
                sparks.setVisible(false);
                sparks.build();
                
                Paint pp = new Paint();
                pp.setTextSize(Core.SDP_H * 0.8f);
                pp.setColor(Color.BLACK);
                pp.setAntiAlias(true);
                final Button bubble = new Button(-999, -999, Core.SDP * 3f, Core.SDP, R.drawable.speech_bubble, "Muahahahaha!", pp);
                
                final DrawableCollection<Drawable> drawables = new DrawableCollection<Drawable>();
                
                if(skipable) {
                  drawables.addDrawable(skip);
                }
                
                drawables.addDrawable(explosion);
                drawables.addDrawable(sparks);
                drawables.addDrawable(divisionMachine);
                drawables.addDrawable(result);
                drawables.addDrawable(enemy);
                drawables.addDrawable(arg1);
                drawables.addDrawable(arg2);
                drawables.addDrawable(bubble);
                drawables.addDrawable(rect);
                
                Core.game.front.addClickable(bg);
                if(skipable) {
                  Core.game.front.addClickable(skip);
                }
                
                Core.game.hud.addDrawableToTop(drawables);

                Core.offX = 0f;
                Core.offY = 0f;

                final UpdatableCollection c = new UpdatableCollection();
                
                final Updatable u = new Updatable() {
                  final float DURATION = 4f;
                  float time = 0f;
                  final float START_X = divisionMachine.x + Core.SDP;
                  final float START_Y = divisionMachine.y + Core.SDP;

                  final float C_X = Core.SDP * 10f;
                  final float C_Y = Core.SDP * 10f;
                  
                  int counter = 0;

                  public void reset() {
                    time = 0f;
                  }

                  @Override
                  public boolean update(float dt) {
                    time += dt;
                    if(time < DURATION) {
                      float t = time / DURATION;
                      result.x = START_X + t * C_X;
                      result.y = START_Y + t * C_Y;
                      return true;
                    } else {
                      reset();
                      result.setText(answers[counter]);
                      counter++;
                      if(counter == numerators.length) {
                        counter = 0;
                      }
                      return false;
                    }
                  }

                };
                
                final Updatable finishUp = new Updatable() {
                  final float DURATION = 3f;
                  float time = 0f;
                  
                  @Override
                  public boolean update(float dt) {
                    time += dt;
                    
                    if(time < DURATION) {
                      divisionMachine.transparency = 1f - time;
                      return true;
                    } else {
                      pause();
                      waitingForEventToFinish = false;
                      Core.game.front.removeClickable(bg);
                      Core.game.front.removeClickable(skip);
                      Core.gu.stopCinematic();
                      Core.game.hud.removeDrawable(drawables);
                      Core.game.enableZoom();
                      stateMgr.setOpeningSkipable(true);
                      return false;
                    }
                  }
                  
                };
                

                skip.setOnClickListener(new OnClickListener() {

                  @Override
                  public void onClick(Button sender) {
                    DebugLog.d(TAG, "Clicked");
                    c.add(finishUp);
                    finishUp.update(3f);
                  }
                  
                });
                
                final Updatable enterMachine = new Updatable() {
                  final float DURATION = 1f;
                  
                  float START_X = enemy.x;
                  
                  final float C_X = Core.SDP * 1.25f;
                  
                  float time = 0f;
                  
                  @Override
                  public boolean update(float dt) {
                    if(time == 0f) {
                      START_X = enemy.x;
                    }
                    
                    time += dt;
                    
                    if(time < DURATION) {
                      float t = time / DURATION;
                      enemy.x = START_X + t * C_X;
                      return true;
                    } else {
                      enemy.transparency = 0f;
                      arg1.transparency = 0f;
                      arg2.transparency = 0f;
                      result.transparency = 0f;
                      
                      c.add(finishUp);
                      c.add(explosion);
                      c.add(sparks);
                      explosion.setVisible(true);
                      sparks.setVisible(true);
                      return false;
                    }
                  }
                  
                };
                
                final Updatable killMachine = new Updatable() {
                  final float DURATION = 1.5f;
                  
                  float START_X = enemy.x;
                  float START_Y = enemy.y;
                  
                  final float C_X = Core.SDP * 1.25f;
                  final float C_Y = Core.SDP * 1.25f;
                  
                  float time = 0f;
                  
                  @Override
                  public boolean update(float dt) {
                    if(time == 0f) {
                      START_X = enemy.x;
                      START_Y = enemy.y;    
                    }
                    
                    time += dt;
                    
                    if(time < DURATION) {
                      float t = time / DURATION;
                      enemy.x = START_X + t * C_X;
                      enemy.y = START_Y + t * C_Y;
                      return true;
                    } else {
                      c.add(enterMachine);
                      return false;
                    }
                  }
                  
                };
                
                final Updatable wait = new Updatable() {
                  final float DURATION = 2f;
                  float time = 0f;
                  
                  @Override
                  public boolean update(float dt) {
                    time += dt;
                    
                    if(time >= DURATION) {
                      // cause the 0 to proceed to kill the machine...
                      // also remove the dialog box...
                      bubble.isVisible = false;
                      c.add(killMachine);
                      return false;
                    }
                    return true;
                  }
                  
                };
                
                final Updatable evilEntrance = new Updatable() {
                  final float START_X = divisionMachine.x - Core.SDP * 2f;
                  final float START_Y = -Core.SDP;
                  
                  final float C_Y = divisionMachine.y - START_Y;
                  
                  final float DURATION = 3f;
                  float time = 0f;
                  @Override
                  public boolean update(float dt) {
                    time += dt;
                    if(time < DURATION) {
                      enemy.x = START_X;
                      enemy.y = START_Y + time / DURATION * C_Y;
                      
                      return true;
                    } else {
                      bubble.x = enemy.x - bubble.w;
                      bubble.y = enemy.y - bubble.h;
                      c.add(wait);
                      return false;
                    }
                  }
                  
                };

                final Updatable inputUpdate = new Updatable() {
                  private static final float DURATION = 4f;

                  private final float START_X = divisionMachine.x - Core.SDP * 9f;
                  private final float START_Y = divisionMachine.y + Core.SDP * 1.25f;

                  private final float START_X2 = divisionMachine.x + Core.SDP * 1.25f;
                  private final float START_Y2 = divisionMachine.y - Core.SDP * 9f;

                  private final float C_X = Core.SDP * 10f;

                  private final float C_Y2 = Core.SDP * 10f;

                  private float time = 0f;

                  int counter = 0;
                  
                  boolean evilEntered = false;
                  
                  @Override
                  public boolean update(float dt) {
                    time += dt;

                    if(time < DURATION) {
                      float t = time / DURATION;
                      arg1.x = C_X * t + START_X;
                      arg1.y = START_Y;

                      arg2.x = START_X2;
                      arg2.y = C_Y2 * t + START_Y2;
                      return true;
                    } else {
                      c.add(u);
                      time = 0;
                      
                      if(counter == 1 && !evilEntered) {
                        evilEntered = true;
                        c.add(evilEntrance);
                      }
                      
                      arg2.setText(numerators[counter]);
                      arg1.setText(denominators[counter]);
                      counter++;
                      if(counter == numerators.length) {
                        counter = 0;
                      }
                      return true;  
                    }
                  }

                };
                
                Core.game.disableZoom();
                Core.gu.startCinematic(c);

                c.add(inputUpdate);
              }

            });
            waitingForEventToFinish = true;
            break;
          case 1:
            final float OFF_X = Core.SDP * -20f;
            
            final int MACHINES = 20;
            
            final PictureBox[] divisionMachines = new PictureBox[MACHINES];
            
            Core.game.map.setEnabled(false);
            
            Core.glView.queueEvent(new Runnable() {

              @Override
              public void run() {
                final float size = Core.SDP * 2f;
                final int COLUMN_SIZE = 5;
                final float x = -OFF_X + Core.offX;// - (Core.canvasWidth - size * COLUMN_SIZE) / 2f;
                for(int i = 0; i < divisionMachines.length; i++) {
                  divisionMachines[i] = new PictureBox(x + (i/COLUMN_SIZE)*size, (i%COLUMN_SIZE)*size, 
                      Core.SDP, Core.SDP, R.drawable.division_machine);
                  Core.game.hud.addDrawable(divisionMachines[i]);
                }
              }
              
            });
            
            final Runnable tutPart6 = new Runnable() {
              @Override
              public void run() {
                MessageDialog d = new MessageDialog();
                d.setMessage("Good luck!");
                d.setShowHint(true);
                d.build();
                d.show();
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.game.map.setEnabled(true);
                  }
                  
                });
              }              
            };
            
            final Runnable tutPart5 = new Runnable() {

              @Override
              public void run() {
                MessageDialog d = new MessageDialog();
                d.setMessage("Once you have finished building up a defensive line. " +
                    "Press play to start the level");
                
                d.setShowHint(true);
                d.build();
                d.setPauseOnShown(false);
                d.show();
                
                RectF r = Core.hud.getRegion(Hud.HUD_WAVE_CONTROL);
                d.x = r.left - d.w;
                d.y = r.bottom - d.h;
                
                r.right = r.left + Core.SDP * 1.5f;
                
                final TargetRectangle rect = new TargetRectangle();
                rect.setBounds(r);
                rect.setColor(0xFFFF0000);
                rect.setStrokeWidth(Core.SDP * 0.2f);
                rect.build();

                Core.game.hud.addDrawableToTop(rect);
                Core.gu.addUiUpdatable(rect);
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.game.hud.removeDrawable(rect);
                    Core.gu.removeUiUpdatable(rect);
                    Core.glView.queueEvent(tutPart6);
                  }
                  
                });
              }
              
            };

            
            final Runnable tutPart4 = new Runnable() {

              @Override
              public void run() {
                int gold = Core.player.getGold();
                Core.hud.setSelection(0);
                Core.game.mapClicked(0, 5);

                Core.game.mapClicked(1, 2);
                Core.game.mapClicked(1, 3);
                Core.game.mapClicked(1, 4);
                Core.hud.setSelection(-1);
                Core.player.setGold(gold);
                
                MessageDialog d = new MessageDialog();
                d.setMessage("An incomplete defensive line has already" +
                    " been set up for you.");
                
                d.setShowHint(true);
                d.build();
                d.show();
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.glView.queueEvent(tutPart5);
                  }
                  
                });
              }
              
            };

            final Runnable tutPart3 = new Runnable() {

              @Override
              public void run() {
                MessageDialog d = new MessageDialog();
                d.setMessage("The arrows on the left and right" +
                    " show where enemies will spawn." +
                    " You can place defensive structures" +
                    " anywhere within the grid. However you" +
                    " may not block.");
                d.setShowHint(true);
                d.build();
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.glView.queueEvent(tutPart4);
                  }
                  
                });

                d.x = (Core.canvasWidth - d.w) / 2f;
                d.y = Core.SDP_H;
                
                d.show();
              }
              
            };
            
            final Runnable tutPart2 = new Runnable() {

              @Override
              public void run() {
                MessageDialog d = new MessageDialog();
                d.setMessage("The amount of resources you have as well" +
                    " as the number of division machines still running in this" +
                    " area is displayed here.");
                d.setShowHint(true);
                d.build();
                d.setPauseOnShown(false);

                final TargetRectangle rect = new TargetRectangle();
                rect.setBounds(Core.hud.getRegion(Hud.HUD_LEFT_PANEL));
                rect.setColor(0xFFFF0000);
                rect.setStrokeWidth(Core.SDP * 0.2f);
                rect.build();

                Core.game.hud.addDrawableToTop(rect);
                Core.gu.addUiUpdatable(rect);
                
                RectF r = Core.hud.getRegion(Hud.HUD_LEFT_PANEL);
                d.x = r.left;
                d.y = r.top - d.h;
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.game.hud.removeDrawable(rect);
                    Core.gu.removeUiUpdatable(rect);
                    Core.glView.queueEvent(tutPart3);
                  }
                  
                });
                
                d.show();
              }
              
            };
            
            final Runnable tutPart1 = new Runnable() {

              @Override
              public void run() {
                MessageDialog d = new MessageDialog();
                d.setMessage("You can purchase defensive structures here." +
                    " To buy a tower tap the desired tower" +
                    " and tap a square on the field to place the tower there.\n\n" +
                    "You can double tap a tower to find out more about it.");
                d.setShowHint(true);
                d.setPauseOnShown(false);
                d.build();
                
                final TargetRectangle rect = new TargetRectangle();
                rect.setBounds(Core.hud.getRegion(Hud.HUD_TOWER_MENU));
                rect.setColor(0xFFFF0000);
                rect.setStrokeWidth(Core.SDP * 0.2f);
                rect.build();

                Core.game.hud.addDrawableToTop(rect);
                Core.gu.addUiUpdatable(rect);
                
                RectF r = Core.hud.getRegion(Hud.HUD_RIGHT_PANEL);
                d.x = r.left;
                d.y = r.top - d.h;
                
                d.setOnDismissListener(new OnDismissListener() {

                  @Override
                  public void onDismiss() {
                    Core.game.hud.removeDrawable(rect);
                    Core.gu.removeUiUpdatable(rect);
                    Core.glView.queueEvent(tutPart2);
                  }
                  
                });
                
                d.show();
              }
              
            };
            
            final Updatable scrollBack = new Updatable() {
              final float DURATION = 2f;
              
              final float START_X = Core.offX;
              
              float time = 0f;
              
              @Override
              public boolean update(float dt) {
                time += dt;
                
                if(time < DURATION) {
                  float t = time / DURATION;
                  Core.game.map.setOffsetX(START_X + t * t * -OFF_X + OFF_X);
                  return true;
                } else {
                  Core.game.map.setOffsetX(START_X);

                  setCurrentEventDone();
                  pause();
                  
                  Core.glView.queueEvent(new Runnable() {

                    @Override
                    public void run() {
                      MessageDialog d = new MessageDialog();
                      d.setMessage("A large number of zeros has been seen around the area. " +
                          "They appear to be targeting the 20 machines here. " +
                          "Fortunately, the zeros will have to pass through this field " +
                          "to get to the machines, so we can set up a defensive " +
                          "parameter here...");
                      d.setShowHint(true);
                      d.setOnDismissListener(new OnDismissListener() {
                      
                        @Override
                        public void onDismiss() {
                          Core.glView.queueEvent(tutPart1);
                        }
                        
                      });
                      d.build();
                      d.show();
                    }
                    
                  });
                  return false;
                }
              }
              
            };
            
            final Updatable theDialogs = new Updatable() {
              final float DURATION = 3f;
              final float ALTERNATE = 0.5f;
              float time = 0f;
              
              @Override
              public boolean update(float dt) {
                time += dt;
                
                if(time < DURATION) {
                  if((int)(time / ALTERNATE) % 2 == 0) {
                  for(int i = 0; i < divisionMachines.length; i++) {
                    divisionMachines[i].transparency = 0.5f;
                  }
                  } else {
                    for(int i = 0; i < divisionMachines.length; i++) {
                      divisionMachines[i].transparency = 1f;
                    }
                  }
                  return true;
                } else {
                  for(int i = 0; i < divisionMachines.length; i++) {
                    divisionMachines[i].transparency = 1f;
                  }
                  
                  Core.glView.queueEvent(new Runnable() {

                    @Override
                    public void run() {
                      MessageDialog d = new MessageDialog();
                      d.setMessage("The zeros appear to be targeting division machines. If any" +
                          " zero enters a division machine, the machine will malfunciton and blow" +
                          " up so we must stop any zeros from coming near them. " +
                          " Your goal is to protect these machines from the zeros...");
                      d.setShowHint(true);
                      d.setOnDismissListener(new OnDismissListener() {

                        @Override
                        public void onDismiss() {
                          Core.gu.addUiUpdatable(scrollBack);
                        }
                        
                      });
                      d.build();
                      d.show();
                    }
                    
                  });
                  return false;
                }
              }
              
            };
            
            final Updatable scrollTo = new Updatable() {
              final float DURATION = 2f;
              
              final float START_X = Core.offX;
              
              float time = 0f;
              
              @Override
              public boolean update(float dt) {
                time += dt;
                
                if(time < DURATION) {
                  float t = time / DURATION;
                  Core.game.map.setOffsetX(START_X + t * t * OFF_X);
                  return true;
                } else {
                  Core.game.map.setOffsetX(OFF_X + START_X);
                  Core.gu.addUiUpdatable(theDialogs);
                  return false;
                }
              }
              
            };
            
            
            final MessageDialog intro = new MessageDialog();
            intro.setMessage("Recent reports show that a high number of zeros has" +
                " been spotted in the mainframe and they have been linked to" +
                " faliures in critical machines...");
            intro.setShowHint(true);
            intro.setOnDismissListener(new OnDismissListener() {

              @Override
              public void onDismiss() {
                Core.gu.addUiUpdatable(scrollTo);
              }

            });
            
            
            final MessageDialog d = new MessageDialog();
            d.setMessage("Welcome to Division By Zero!");
            d.setShowHint(true);
            d.setOnDismissListener(new OnDismissListener() {

              @Override
              public void onDismiss() {
                Core.glView.queueEvent(new Runnable() {

                  @Override
                  public void run() {
                    intro.build();
                    intro.show();
                  }

                });
              }

            });
            Core.glView.queueEvent(new Runnable() {

              @Override
              public void run() {
                d.build();
                d.show();
              }

            });
            waitingForEventToFinish = true;
            break;
          default:
            break;
          }
          break;
        default:
          break;
        }
      }
    }
    return true;
  }

  public void start() {
    paused = false;
  }
  
  public void pause() {
    paused = true;
  }

  public boolean isStarted() {
    return !paused;
  }

  public int getCurrentWave() {
    return curWave;
  }

  public void skipToNextEvent() {
    if(hasNextEvent()) {
      Event e = getNextEvent();
      // skip all sleeps
      while(e.cmd == Command.SLEEP && hasNextEvent()) {
        e = getNextEvent();
      }
      putBackLast();
    } else {
      DebugLog.d(TAG, "No more events to process!");
    }

    sleepTime = 0;
    waitingForEventToFinish = false;
  }

  public void save(DataOutputStream stream) throws IOException {
    stream.writeInt(curEventIndex);
    stream.writeBoolean(waitingForEventToFinish);
    stream.writeFloat(sleepTime);
    stream.writeBoolean(paused);
    stream.writeInt(curWave);
    if(lastSpawnEvent == null) {
      stream.writeInt(-1);
    } else {
      stream.writeInt(lastSpawnEvent.index);
      stream.writeFloat(lastSpawnEvent.elapsed);
    }
  }

  public void load(DataInputStream stream) throws IOException {
    curEventIndex = stream.readInt();
    waitingForEventToFinish = stream.readBoolean();
    sleepTime = stream.readFloat();
    paused = stream.readBoolean();
    curWave = stream.readInt();
    int index = stream.readInt();
    if(index == -1) {
      lastSpawnEvent = null;
    } else {
      lastSpawnEvent = (SpawnEvent) events.get(index).args;
      lastSpawnEvent.elapsed = stream.readFloat();
    }
  }

  public int getLevelDifficulty() {
    return difficulty;
  }

  public String getLevelName() {
    return levelName;
  }

  public void setMockMode(boolean b) {
    mock = b;
  }
  
  public float getTotalSpriteGold() {
    return totalSpriteGold;
  }
}




Java Source Code List

com.ggstudios.divisionbyzero.ActivityAbout.java
com.ggstudios.divisionbyzero.ActivityLevelSelection.java
com.ggstudios.divisionbyzero.ActivityMainMenu.java
com.ggstudios.divisionbyzero.ActivitySettings.java
com.ggstudios.divisionbyzero.ActivitySplashScreen.java
com.ggstudios.divisionbyzero.ApplicationMain.java
com.ggstudios.divisionbyzero.BaseActivity.java
com.ggstudios.divisionbyzero.BaseDialog.java
com.ggstudios.divisionbyzero.BulletManager.java
com.ggstudios.divisionbyzero.Bullet.java
com.ggstudios.divisionbyzero.Button.java
com.ggstudios.divisionbyzero.Circle.java
com.ggstudios.divisionbyzero.ClickableCollection.java
com.ggstudios.divisionbyzero.Clickable.java
com.ggstudios.divisionbyzero.ConfirmDialog.java
com.ggstudios.divisionbyzero.Core.java
com.ggstudios.divisionbyzero.CustomGLSurfaceView.java
com.ggstudios.divisionbyzero.DialogManager.java
com.ggstudios.divisionbyzero.DrawableCollection.java
com.ggstudios.divisionbyzero.DrawableString.java
com.ggstudios.divisionbyzero.Drawable.java
com.ggstudios.divisionbyzero.EndDialog.java
com.ggstudios.divisionbyzero.Event.java
com.ggstudios.divisionbyzero.ExplosionGenerator.java
com.ggstudios.divisionbyzero.ExtrasManager.java
com.ggstudios.divisionbyzero.FontManager.java
com.ggstudios.divisionbyzero.GameRenderer.java
com.ggstudios.divisionbyzero.GameUpdater.java
com.ggstudios.divisionbyzero.Game.java
com.ggstudios.divisionbyzero.Grid.java
com.ggstudios.divisionbyzero.Hud.java
com.ggstudios.divisionbyzero.InGameMenu.java
com.ggstudios.divisionbyzero.InfoDialog.java
com.ggstudios.divisionbyzero.Label.java
com.ggstudios.divisionbyzero.LevelManager.java
com.ggstudios.divisionbyzero.LevelMap.java
com.ggstudios.divisionbyzero.LineGuide.java
com.ggstudios.divisionbyzero.MainActivity.java
com.ggstudios.divisionbyzero.Map.java
com.ggstudios.divisionbyzero.MessageDialog.java
com.ggstudios.divisionbyzero.ParticleEngine.java
com.ggstudios.divisionbyzero.PathFinder.java
com.ggstudios.divisionbyzero.PauseMenu.java
com.ggstudios.divisionbyzero.PictureBox.java
com.ggstudios.divisionbyzero.Player.java
com.ggstudios.divisionbyzero.PopupMenu.java
com.ggstudios.divisionbyzero.Rectangle.java
com.ggstudios.divisionbyzero.Shader.java
com.ggstudios.divisionbyzero.SpawnManager.java
com.ggstudios.divisionbyzero.SpriteAnimation.java
com.ggstudios.divisionbyzero.SpriteManager.java
com.ggstudios.divisionbyzero.Sprite.java
com.ggstudios.divisionbyzero.Statbar.java
com.ggstudios.divisionbyzero.StateManager.java
com.ggstudios.divisionbyzero.TargetRectangle.java
com.ggstudios.divisionbyzero.TextureManager.java
com.ggstudios.divisionbyzero.TowerInfoDialog.java
com.ggstudios.divisionbyzero.TowerLibrary.java
com.ggstudios.divisionbyzero.TowerManager.java
com.ggstudios.divisionbyzero.TowerMenu.java
com.ggstudios.divisionbyzero.Tower.java
com.ggstudios.divisionbyzero.UpdatableCollection.java
com.ggstudios.divisionbyzero.Updatable.java
com.ggstudios.divisionbyzero.UpgradeDialog.java
com.ggstudios.divisionbyzero.Utils.java
com.ggstudios.divisionbyzero.VBO.java
com.ggstudios.divisionbyzero.WaveControlDialog.java
com.ggstudios.divisionbyzero.WaveControlHud.java
com.ggstudios.divisionbyzero.ZoomControl.java
com.ggstudios.utils.BitmapUtils.java
com.ggstudios.utils.BufferUtils.java
com.ggstudios.utils.DebugLog.java
com.ggstudios.utils.ShaderUtils.java
com.ggstudios.widget.LevelMapBackground.java
fix.android.opengl.GLES20.java