We are writing a game for Android using AndEngine. Part 4

    Hello everybody!

    The fourth part promises to be very interesting. In it, I am going to consider the creation of laser guns, mirrors and reflections. Please read the previous parts before reading.

    Part 1.
    Part 2.
    Part 3.

    Interesting?

    Step 1. Limitations.
    Let's start a little from far. As everyone knows, an ideal laser moves at the speed of light, and if there are no obstacles in its path, it is unlikely that it will ever stop. Our LaserLine will not be ideal and the first thing to do is not to give it the opportunity to "fly" out of the playing field. To do this, add a method to the GameObjectsMap class:
    public static boolean outOfArea(Point pos) {
      return pos.x < 0 || pos.y < 0 || pos.x > WIDTH - 1
          || pos.y > HEIGHT - 1;
    }

    * This source code was highlighted with Source Code Highlighter.

    We will check the position of the laser by this method during its construction.
    Step 2. LaserGun.
    I hope everyone remembers the second part of the article, where in addition to the laser class, we had a laser gun class that could rotate and obstruct the laser’s movement. Add the field to it:

    private LaserLine mLaserLine;

    Add to the constructor:

    mLaserLine = new LaserLine(new Point(posX, posY), angle);

    Add the method to attachTo:

    scene.getChild(GameObjectsMap.LASER_LAYER).attachChild(mLaserLine);

    Well, now our gun has a laser, but it is not visible. To see him, you need to ask him a sequence of points through which he will pass. To do this, write a method in the LaserGun class:
    public void buildLaser(GameObject[][] map) {
      mLaserLine.setAngle(getAngle());
      mLaserLine.build(map);
    }

    * This source code was highlighted with Source Code Highlighter.


    Everything is clear here at first glance, the laser path depends on the initial direction and on the objects in its path, just for this we needed a map. But the LaserLine.build () method does not exist yet. Take care of them.
    public void build(GameObject[][] map) {
      sBuilder.buildPath(this, map);
      buildLines();
    }

    * This source code was highlighted with Source Code Highlighter.

    The method is short, but I have not yet talked about sBuilder. There is hidden magic. Do not forget to add to the LaserLine class:

    private static LaserLineBuilder sBuilder = new LaserLineBuilder();

    Having made it static, we will be sure that we will not have a separate copy for each laser, which will save us some memory and positively affect the speed.

    Step 3. LaserBuilder
    It's time to show what the laser build looks like:
    public class LaserLineBuilder {

      private static final int MAX_STEPS = 200;

      public void buildPath(LaserLine laserLine, GameObject[][] map) {
        laserLine.clearPoints();
        int step = 0;
        int angle = laserLine.getAngle();
        Point position = new Point(laserLine.getStartPosition());
        GameObject gameObject;
        while (step < MAX_STEPS) {
          nextPosition(position, angle);
          if (GameObjectsMap.outOfArea(position)) {
            laserLine.addPoint(position);
            return;
          }
          gameObject = map[position.x][position.y];
          if (gameObject == null) {
            continue;
          } else {
            laserLine.addPoint(position);
            int reflection = gameObject.onLaser(angle);
            if (reflection < 0) {
              return;
            } else {
              angle = reflection;
            }
          }
        }
        laserLine.addPoint(position);
      }

      private void nextPosition(Point position, final int angle) {
        switch (angle) {
        case DynamicGameObject.DEG_0:
          position.x++;
          break;
        case DynamicGameObject.DEG_90:
          position.y++;
          break;
        case DynamicGameObject.DEG_180:
          position.x--;
          break;
        case DynamicGameObject.DEG_270:
          position.y--;
          break;
        case DynamicGameObject.DEG_45:
          position.x++;
          position.y++;
          break;
        case DynamicGameObject.DEG_135:
          position.x--;
          position.y++;
          break;
        case DynamicGameObject.DEG_225:
          position.x--;
          position.y--;
          break;
        case DynamicGameObject.DEG_315:
          position.x++;
          position.y--;
          break;
        default:
          break;
        }
      }
    }

    * This source code was highlighted with Source Code Highlighter.

    Let's go in order. The limit on 200 laser steps, I think it’s clear why. Further, the first laser point is added during creation and coincides with the coordinates of LaserGun, while the remaining points are added when leaving the game area, when stopping, and when reflected. I note that initially points were added along the passage of each cell, in Mirrors Maze it is still like this. But AndEngine was not used there.
    nextPosition hopefully needs no explanation.

    Step 4. The mirror.
    So far, we have not had objects that allow us to reflect lasers. Now we need to make one such, and check whether everything works as intended. Do not forget to add the desired texture.
    public class Mirror extends DynamicGameObject {

      public Mirror(final int posX, final int posY, final int angle,
          final TextureRegion region) {
        super(posX, posY, angle, region);
      }

      @Override
      void attachTo(Scene scene) {
        scene.getChild(GameObjectsMap.GAME_OBJECTS_LAYER).attachChild(
            getSprite());
      }

      @Override
      int onLaser(int angle) {
        int a = getAngle() % 4;
        if (angle == (a + 1) % 8) return (a + 7) % 8;
        if (angle == (a + 7) % 8) return (a + 1) % 8;
        if (angle == (a + 3) % 8) return (a + 5) % 8;
        if (angle == (a + 5) % 8) return (a + 3) % 8;
        return -1;
      }

    }

    * This source code was highlighted with Source Code Highlighter.

    Creating a new game object is very simple. We can do without spoilers and I will leave it to the interested reader to figure out how the onLaser method works. Two-way mirror is ready. It remains to add its initialization in GameObjectsMap.
    Step 4: initialize the laser.
    After all the manipulations, the add method now looks like this:
    public void add(Type type, final int posH, final int posW, final int angle) {
        GameObject object = null;
        switch (type) {
        case lasergun:
          LaserGun l = new LaserGun(posH, posW, angle, mTextures
              .getLaserGun());
          mLaserGuns.add(l);
          object = l;
          break;
        case mirror:
          object = new Mirror(posH, posW, angle, mTextures.getMirror());
          break;
        case target:

          break;
        default:
          break;
        }
        mMap[posH][posW] = object;
      }

    * This source code was highlighted with Source Code Highlighter.

    But we were not limited to adding a mirror, for even more convenient work and guns we need: and

    private LinkedList mLaserGuns;

    public void buildLasers() {
      for (LaserGun gun : mLaserGuns) {
        gun.buildLaser(mMap);
      }
    }

    * This source code was highlighted with Source Code Highlighter.

    Well, now let's see what happened. Add the code with StageActivity:
    private void initMap() {
      mGameObjectsMap = new GameObjectsMap(mTextures);
      mGameObjectsMap.add(Type.lasergun, 0, 0, 3);
      mGameObjectsMap.add(Type.lasergun, 3, 2, 7);
      mGameObjectsMap.add(Type.lasergun, 3, 4, 4);
      mGameObjectsMap.add(Type.mirror, 3, 3, 3);
      mGameObjectsMap.addToScene(mEngine.getScene());
      mGameObjectsController = new GameObjectsController(mGameObjectsMap, this);
      final Scene scene = getEngine().getScene();
      mGameObjectsMap.buildLasers();
    }

    * This source code was highlighted with Source Code Highlighter.

    In the end, we will see something for fun:
    image

    Today is enough. Thanks for attention. I will be glad to questions, advice and suggestions.
    Source.

    Also popular now: