In this article we will create the missile for the player object, if you have missed the previous article about how to create the controller of the missile then you can read this post.

The first step to create the player missile system is to create the missile class which will handle the missile body creation as well as assigns the velocity and force to the player missile.

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;

public class PlaneMissile {

    private Body body;
    final static int BOX2D_TOGAME_SCALE = 1;

    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, 3.0f,  false);
        body.setLinearVelocity(0, 50);

    }
    // this one is used to draw the missile object and many more
    public Body getPlaneMissileBody() {
        return body;
    }
}

Next, we will create the missile factory class which will be called by the DetectTouch class to create two missiles every time the user touches on the missile controller.

package com.gamingdirectional.lonemoon;

import com.badlogic.gdx.InputAdapter;
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 DetectTouch extends InputAdapter{

    private final float viewportwidth;
    private final MainActivity activity;
    Vector2 touchPosition;
    float viewportHeight;
    Player player;
    ArrayList<Boolean> direction;
    final static int BOX2D_TOGAME_SCALE = 1;
    TextureRegion controller_knobRegion;
    PlaneMissileFactory plane_missile_factory;

    public DetectTouch(Player player, float viewportHeight, float viewportwidth, TextureRegion controller_knobRegion, MainActivity activity, PlaneMissileFactory plane_missile_factory) {

        touchPosition = new Vector2();
        this.viewportHeight = viewportHeight;
        this.viewportwidth = viewportwidth;
        direction = new ArrayList<Boolean>();
        direction.add(0, true);
        direction.add(1, true);
        this.player  = player;
        this.controller_knobRegion = controller_knobRegion;
        this.activity = activity;
        this.plane_missile_factory = plane_missile_factory;
    }


    private void applyForce() {
        player.applyForceOnBody(direction);
    }

    public boolean touchUp (int x, int y, int pointer, int button) {
        touchPosition.set((float)x/BOX2D_TOGAME_SCALE, (viewportHeight-(float)y)/BOX2D_TOGAME_SCALE);
        calculateposition();
        applyForce();

        /* check to see whether the user has touched the controller knob */
        if(touchPosition.x > viewportwidth/2 - controller_knobRegion.getRegionWidth()/2 &&  touchPosition.x < viewportwidth/2 + controller_knobRegion.getRegionWidth()/2 && touchPosition.y < controller_knobRegion.getRegionHeight()) {
            plane_missile_factory.createMissle(0, player.getPlayerBody().getPosition());
            plane_missile_factory.createMissle(((TextureRegion) player.getPlayerBody().getUserData()).getRegionWidth(), player.getPlayerBody().getPosition());
        }

        return true; // return true to indicate the event was handled
    }

    public boolean touchDown (int x, int y, int pointer, int button) {

        return true;
    }

    public void calculateposition() {
        if(touchPosition.x > player.getPlayerBody().getPosition().x && touchPosition.y > player.getPlayerBody().getPosition().y) {
            direction.set(0, true);
            direction.set(1, true);
        } else if(touchPosition.x < player.getPlayerBody().getPosition().x && touchPosition.y > player.getPlayerBody().getPosition().y) {
            direction.set(0, false);
            direction.set(1, true);
        } else if(touchPosition.x < player.getPlayerBody().getPosition().x && touchPosition.y < player.getPlayerBody().getPosition().y) {
            direction.set(0, false);
            direction.set(1, false);
        } else if(touchPosition.x > player.getPlayerBody().getPosition().x && touchPosition.y < player.getPlayerBody().getPosition().y) {
            direction.set(0, true);
            direction.set(1, false);
        }
    }

}

Next, we need to edit the MainActivity class a little bit to draw the missiles on the game screen on each game loop.

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;

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;

    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();
		batch.end();
		debugRenderer.render(world, camera.combined);
	}

	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() {
		updatePosition();
		updateScore();
	}

	// 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();
		resetPlane();
		resetCamera();
		resetBackground();
        Gdx.input.setInputProcessor(touchadaptor);
	}

    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();
	}

}

Each time the user touches the game controller the plane will fire two missiles.

The LibGdx project with Box2D

Posted by On Mouse Enter on Monday, June 29, 2020

If you like this tutorial, then do share it on Twitter, thank you.

Please follow and like us:

Leave a Reply

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