In this chapter, we will create the enemy missile which will be fired from the enemy plane in LibGdx with the help of Box2D!

We will use the enemy missile factory class to create a missile for the enemy plane, the missile factory will become an item in the array list of the enemy missile manager class.

This is the enemy missile class.

package com.gamingdirectional.lonemoon;

import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;

import java.util.Random;

public class EnemyMissile {

    private Body body;
    final static int BOX2D_TOGAME_SCALE = 1;
    private Random rn = new Random();

    public void createBodyFixture(float position_offset, TextureRegion missileRegion, World world, Vector2 position) {

        // First we create a body definition
        BodyDef bodyDef = new BodyDef();
        // We set our body to dynamic, for something like ground which doesn't move we would set it to StaticBody
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        // Set our body's starting position in the world
        bodyDef.position.set(position_offset + position.x - missileRegion.getRegionWidth(), position.y- missileRegion.getRegionHeight()*2 + 2);

        // Create our body in the world using our body definition
        body = world.createBody(bodyDef);

        // Create a box shape and set its radius
        PolygonShape box = new PolygonShape();
        box.setAsBox(missileRegion.getRegionWidth()/2*BOX2D_TOGAME_SCALE, missileRegion.getRegionHeight()/2*BOX2D_TOGAME_SCALE);

        // Create a fixture definition to apply our shape to
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = box;
        fixtureDef.density = 0.5f;
        fixtureDef.friction = 0.3f;
        fixtureDef.restitution = 0.6f; // Make it bounce a little bit

        // Create our fixture and attach it to the body
        Fixture fixture = body.createFixture(fixtureDef);

        // Remember to dispose of any shapes after you're done with them!
        // BodyDef and FixtureDef don't need disposing, but shapes do.
        box.dispose();

        // link body to player missile
        body.setUserData(missileRegion);

        // set up the speed
        body.applyForceToCenter(0, -rn.nextInt(50),  false);
        body.setLinearVelocity(0, -100);

    }

    public Body getEnemyMissileBody() {
        return body;
    }
}

Here is the enemy missile factory class.

package com.gamingdirectional.lonemoon;

import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.World;

import java.util.ArrayList;

public class EnemyMissileFactory {

    private World world;
    private TextureRegion enemyMissileRegion;
    private EnemyMissile enemyMissile;
    private ArrayList<EnemyMissile> enemy_missile_list = new ArrayList<EnemyMissile>();

    EnemyMissileFactory(World world, TextureRegion enemyMissileRegion) {
        this.world = world;
        this.enemyMissileRegion = enemyMissileRegion;
    }

    public void createMissle(float position_offset, Vector2 position) {
        enemyMissile = new EnemyMissile();
        enemyMissile.createBodyFixture(position_offset, enemyMissileRegion, world, position);
        enemy_missile_list.add(enemyMissile);
    }

    public ArrayList<EnemyMissile> getEnemy_missile_list() {
        return enemy_missile_list;
    }

}

Here is the enemy missile manager class.

package com.gamingdirectional.lonemoon;

import java.util.ArrayList;

public class EnemyMissileManager {

    ArrayList<EnemyMissileFactory> emfl = new ArrayList<EnemyMissileFactory>();

    public EnemyMissileManager() {
        emfl = new ArrayList<EnemyMissileFactory>();
    }

    public void addEnemyMissileFactory(EnemyMissileFactory emf) {
        emfl.add(emf);
    }

    public ArrayList<EnemyMissileFactory> getEnemyMissileFactoryList() {
        return emfl;
    }
}

Besides the above classes we will also need to revise our Enemy class and the MainActivity class.

package com.gamingdirectional.lonemoon;

import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;

import java.util.Random;

public class Enemy {

    private Body body;
    final static int BOX2D_TOGAME_SCALE = 1;
    private Random rn = new Random();
    private EnemyMissileFactory emf;
    private World world;
    private TextureRegion enemyRegion;
    private int count = 0;

    public Enemy(World world, TextureRegion enemyRegion, TextureRegion enemyMissileRegion, EnemyMissileManager em) {
        this.world = world;
        this.enemyRegion = enemyRegion;
        emf = new EnemyMissileFactory(world, enemyMissileRegion);
        em.addEnemyMissileFactory(emf);
    }

    public void createBodyFixture(Vector2 position) {

        // First we create a body definition
        BodyDef bodyDef = new BodyDef();
        // We set our body to dynamic, for something like ground which doesn't move we would set it to StaticBody
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        // Set our body's starting position in the world
        bodyDef.position.set(position.x, position.y);

        // Create our body in the world using our body definition
        body = world.createBody(bodyDef);

        // Create a box shape and set its radius
        PolygonShape box = new PolygonShape();
        box.setAsBox(enemyRegion.getRegionWidth()/2*BOX2D_TOGAME_SCALE, enemyRegion.getRegionHeight()/2*BOX2D_TOGAME_SCALE);

        // Create a fixture definition to apply our shape to
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = box;
        fixtureDef.density = 0.5f;
        fixtureDef.friction = 0.3f;
        fixtureDef.restitution = 0.6f; // Make it bounce a little bit

        // Create our fixture and attach it to the body
        Fixture fixture = body.createFixture(fixtureDef);

        // Remember to dispose of any shapes after you're done with them!
        // BodyDef and FixtureDef don't need disposing, but shapes do.
        box.dispose();

        // link body to player missile
        body.setUserData(enemyRegion);

        // set up the velocity and force of the enemy plane
        body.applyForceToCenter(0, -rn.nextInt(50),  false);
        body.setLinearVelocity(0, -100);

    }

    public void createMissile() {
        emf.createMissle(5, getEnemyBody().getPosition());
        emf.createMissle(((TextureRegion) getEnemyBody().getUserData()).getRegionWidth(), getEnemyBody().getPosition());
    }

    public Body getEnemyBody() {
        return body;
    }

    public void updateMissile() {
        if(count >  100) {
            createMissile();
            count = 0;
        }
        count++;
    }
}
package com.gamingdirectional.lonemoon;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.FitViewport;

import java.util.Random;

public class MainActivity extends ApplicationAdapter  {

	SpriteBatch batch;
	OrthographicCamera camera;
	float viewportWidth;
	float viewportHeight;
	TextureRegion bgRegion;
	TextureRegion planeRegion;
	Vector2 planePosition;
	BitmapFont font;
	StringBuilder score = new StringBuilder();
	Integer point;
	TextureAtlas atlas;
	Vector2 touchPosition;
	Vector3 cameraposition = new Vector3();
	DetectTouch touchadaptor;
	Player player;
	World world;
	static final float STEP_TIME = 1f/60f;
	float accumulator = 0;
	Box2DDebugRenderer debugRenderer;
	final static int BOX2D_TOGAME_SCALE = 1;
	private FitViewport viewport;
	private Stage bj;
    private TextureRegion controllerRegion;
    private TextureRegion controller_knobRegion;
    private PlaneMissileFactory plane_missile_factory;
	private EnemyFactory enemy_factory;
	private Random rnd;
	private Vector2 enemyPosition = new Vector2();
	private int enemy_creation_count = 0;
	private EnemyMissileManager em;

	public MainActivity(int width, int height) {
		viewportWidth = width;
		viewportHeight = height;
	}
	
	@Override
	public void create () {
		resetGame();
	}

	@Override
	public void render () {
		Gdx.gl.glClearColor(1, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		updateGame();
		drawGame();
	}

	private void drawGame() {

		updateCamera();
		batch.setProjectionMatrix(camera.combined);
		batch.begin();
		batch.draw(bgRegion, 0, 0);
        batch.draw(controllerRegion, viewportWidth/2 - controllerRegion.getRegionWidth()/2, controller_knobRegion.getRegionHeight()/5);
        batch.draw(controller_knobRegion, viewportWidth/2 - controller_knobRegion.getRegionWidth()/2, 0);
		batch.draw((TextureRegion) player.getPlayerBody().getUserData(), player.getPlayerBody().getPosition().x-planeRegion.getRegionWidth()/2, player.getPlayerBody().getPosition().y-planeRegion.getRegionHeight()/2);
		font.draw(batch, score, viewportWidth/6-font.getScaleX()/2, viewportHeight - font.getScaleY()/4);
		drawPlaneMissile();
		drawEnemyPlane();
		drawEnemyMissile();
		batch.end();
		debugRenderer.render(world, camera.combined);
	}

	private void drawEnemyMissile() {
		for(EnemyMissileFactory emf : em.getEnemyMissileFactoryList()) {
			if(emf != null){
				for(EnemyMissile em : emf.getEnemy_missile_list()) {
					batch.draw((TextureRegion) em.getEnemyMissileBody().getUserData(), em.getEnemyMissileBody().getPosition().x-((TextureRegion) em.getEnemyMissileBody().getUserData()).getRegionWidth()/2, em.getEnemyMissileBody().getPosition().y-((TextureRegion) em.getEnemyMissileBody().getUserData()).getRegionHeight()/2);
				}
			}

		}
	}

	private void drawEnemyPlane() {
		for(Enemy enemy : enemy_factory.getEnemy_list()) {
			if(enemy != null)
				batch.draw((TextureRegion) enemy.getEnemyBody().getUserData(), enemy.getEnemyBody().getPosition().x-((TextureRegion) enemy.getEnemyBody().getUserData()).getRegionWidth()/2, enemy.getEnemyBody().getPosition().y-((TextureRegion) enemy.getEnemyBody().getUserData()).getRegionHeight()/2);
		}
	}

	private void drawPlaneMissile() {
    	for(PlaneMissile planemissile : plane_missile_factory.getPlane_missile_list()) {
    		if(planemissile != null)
				batch.draw((TextureRegion) planemissile.getPlaneMissileBody().getUserData(), planemissile.getPlaneMissileBody().getPosition().x-((TextureRegion) planemissile.getPlaneMissileBody().getUserData()).getRegionWidth()/2, planemissile.getPlaneMissileBody().getPosition().y-((TextureRegion) planemissile.getPlaneMissileBody().getUserData()).getRegionHeight()/2);
		}
	}

	private void updateCamera() {
		cameraposition.set(player.getPlayerBody().getPosition().x, player.getPlayerBody().getPosition().y,0);
		//camera.unproject(cameraposition);
		camera.update();
	}

	private void updateGame() {
		updateEnemy();
		updateEnemyFactory();
		updatePosition();
		updateScore();
	}

	private void updateEnemyFactory() {
		enemy_factory.updateMissile();
	}

	// create latest enemy
	private void updateEnemy() {
		if(enemy_creation_count > 300) {
			enemy_factory.createEnemy(enemyPosition.set(rnd.nextFloat()*viewportWidth, viewportHeight));
			enemy_creation_count = 0;
		}
		enemy_creation_count++;
	}

	// step time control
	private void updatePosition() {

		float delta = Gdx.graphics.getDeltaTime();

		accumulator += Math.min(delta, 0.25f);

		if (accumulator >= STEP_TIME) {
			accumulator -= STEP_TIME;
			world.step(STEP_TIME, 6, 2);
		}
	}

	private void updateScore() {
		//Float f = player.getPlayerBody().getPosition().x;
		//score.replace(0, 1, f.toString());
	}
	
	/* resetting game objects, background, font, camera, and create sprite batch object */

	private void resetGame() {
		batch = new SpriteBatch();
		atlas = new TextureAtlas(Gdx.files.internal("lonemoon.txt"));
		debugRenderer = new Box2DDebugRenderer();
		resetScore();
		resetFont();
		resetPysWorld();
		resetGameController();
		resetPlaneMissileFactory();
		resetEnemyMissileManager();
		resetEnemyFactory();
		resetPlane();
		resetCamera();
		resetBackground();
        Gdx.input.setInputProcessor(touchadaptor);
        resetRandomFenerator();
	}

	private void resetEnemyMissileManager() {
		em = new EnemyMissileManager();
	}

	private void resetRandomFenerator() {
		rnd = new Random();
	}

	private void resetEnemyFactory() {
		enemy_factory = new EnemyFactory(world, atlas, em);
	}

	private void resetPlaneMissileFactory() {
        plane_missile_factory = new PlaneMissileFactory(world, atlas);
    }

    private void resetPysWorld() {
		world = new World(new Vector2(0, 0), false);
	}

	private void resetScore() {
		point = 0;
	}

	private void resetFont() {

		font = new BitmapFont(Gdx.files.internal("freefont.fnt"),
				Gdx.files.internal("freefont.png"), false);
	}

	private void resetCamera() {
		camera = new OrthographicCamera();
		camera.setToOrtho(false, viewportWidth, viewportHeight);
		viewport = new FitViewport(viewportWidth, viewportHeight, camera);
	}

	private void resetPlane() {
		planeRegion = atlas.findRegion("plane");//new TextureRegion(plane, plane.getWidth(), plane.getHeight());
		planePosition= new Vector2();
		touchPosition=new Vector2();
		planePosition.set((viewportWidth/2-planeRegion.getRegionWidth()/2)/BOX2D_TOGAME_SCALE, (viewportHeight/2 - planeRegion.getRegionHeight()/2)/BOX2D_TOGAME_SCALE);
		player = new Player(planePosition, world, planeRegion);
		touchadaptor = new DetectTouch(player, viewportHeight, viewportWidth, controller_knobRegion, this, plane_missile_factory);
	}

	private void resetBackground() {
		bgRegion = atlas.findRegion("background0");//new TextureRegion(background, background.getWidth(), background.getHeight());
	}

	private void resetGameController() {
	    controllerRegion = atlas.findRegion("controller");
        controller_knobRegion = atlas.findRegion("controller_knob");
    }

	@Override
	public void dispose () {
		batch.dispose();
		font.dispose();
		atlas.dispose();
		world.dispose();
	}

}

As you can see from the above program, every time an enemy factory class has been created, the enemy manager class will keep the enemy factory class inside an enemy factory’s array list. The enemy class will then call the enemy missile factory to create missiles after a certain count down. Those missiles will then be kept inside the enemy missile’s array list which stays in each of the enemy missile factory classes. The enemy missile manager class will then call each enemy missile factory to retrieve their enemy missiles from the enemy missile list of each enemy plane and then draw them on the game screen.

The enemy plane fires missiles

In the next chapter we will make the player and enemy plane stays within the game scene boundary. Do help me to share this post if you like it!

Click to rate this post!
[Total: 0 Average: 0]
Please follow and like us:

Leave a Reply

Your email address will not be published. Required fields are marked *