com.mob.client.engine.PhysicsEngine.java Source code

Java tutorial

Introduction

Here is the source code for com.mob.client.engine.PhysicsEngine.java

Source

/*******************************************************************************
 * Copyright (C) 2014  Rodrigo Troncoso
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
/**
 * Contains Box2D methods and main loop of the engine 
 * @author Rodrigo Troncoso
 * @version 0.1
 * @since 2014-04-22
 */
package com.mob.client.engine;

import box2dLight.RayHandler;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.mob.client.Game;
import com.mob.client.data.MapBlockData;
import com.mob.client.data.MapData;
import com.mob.client.elements.Tile;
import com.mob.client.handlers.LightHandler;
import com.mob.client.interfaces.Constants;
import com.mob.client.textures.BundledTexture;

public class PhysicsEngine extends Engine implements Constants {
    // ===========================================================
    // Constants
    // ===========================================================

    // ===========================================================
    // Fields
    // ===========================================================
    private Game mGame;
    private World mWorld;
    private Box2DDebugRenderer mDebugRenderer;
    private RayHandler mRayHandler;
    private LightHandler mLightHandler;

    // ===========================================================
    // Constructors
    // ===========================================================
    public PhysicsEngine(Game pGame) {
        super(pGame);
        this.mGame = pGame;
    }

    // ===========================================================
    // Methods
    // ===========================================================
    public void initEngine() {

        // Init box2d world
        this.mWorld = new World(new Vector2(), true);
        this.mDebugRenderer = new Box2DDebugRenderer();
        this.mDebugRenderer.setDrawBodies(false);

        // RayHandler setup
        RayHandler.setGammaCorrection(true);
        RayHandler.useDiffuseLight(true);
        this.mRayHandler = new RayHandler(this.mWorld);
        this.mRayHandler.setCulling(true);
        this.mRayHandler.setBlurNum(5);

        // LightHandler setup
        this.setLightHandler(new LightHandler(this.mGame));
    }

    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================
    @Override
    public void update(float dt) {

        // Vars
        int screenMinX, screenMaxX, screenMinY, screenMaxY, minAreaX, minAreaY, maxAreaX, maxAreaY;
        MapData mapData = this.mGame.getMapHandler().get(this.getMapNumber());

        // Calculate visible part of the map
        int cameraPosX = (int) (this.mGame.getCamera().position.x / TILE_PIXEL_WIDTH);
        int cameraPosY = (int) (this.mGame.getCamera().position.y / TILE_PIXEL_HEIGHT);
        int halfWindowTileWidth = (int) ((this.mGame.getCamera().viewportWidth / TILE_PIXEL_WIDTH) / 2f);
        int halfWindowTileHeight = (int) ((this.mGame.getCamera().viewportHeight / TILE_PIXEL_HEIGHT) / 2f);

        screenMinX = cameraPosX - halfWindowTileWidth - 1;
        screenMaxX = cameraPosX + halfWindowTileWidth + 1;
        screenMinY = cameraPosY - halfWindowTileHeight - 1;
        screenMaxY = cameraPosY + halfWindowTileHeight + 1;

        minAreaX = screenMinX - TILE_BUFFER_SIZE;
        maxAreaX = screenMaxX + TILE_BUFFER_SIZE;
        minAreaY = screenMinY - TILE_BUFFER_SIZE;
        maxAreaY = screenMaxY + TILE_BUFFER_SIZE;

        // Make sure it is between map bounds
        if (minAreaX < MIN_MAP_SIZE_WIDTH)
            minAreaX = MIN_MAP_SIZE_WIDTH;
        if (maxAreaX > MAX_MAP_SIZE_WIDTH)
            maxAreaX = MAX_MAP_SIZE_WIDTH;
        if (minAreaY < MIN_MAP_SIZE_HEIGHT)
            minAreaY = MIN_MAP_SIZE_HEIGHT;
        if (maxAreaY > MAX_MAP_SIZE_HEIGHT)
            maxAreaY = MAX_MAP_SIZE_HEIGHT;

        if (screenMinX < MIN_MAP_SIZE_WIDTH)
            screenMinX = MIN_MAP_SIZE_WIDTH;
        if (screenMaxX > MAX_MAP_SIZE_WIDTH)
            screenMaxX = MAX_MAP_SIZE_WIDTH;
        if (screenMinY < MIN_MAP_SIZE_HEIGHT)
            screenMinY = MIN_MAP_SIZE_HEIGHT;
        if (screenMaxY > MAX_MAP_SIZE_HEIGHT)
            screenMaxY = MAX_MAP_SIZE_HEIGHT;

        // Start map render
        /******************************************
         * Layer 1
         ******************************************/
        for (int y = screenMinY; y <= screenMaxY; y++) {
            for (int x = screenMinX; x <= screenMaxX; x++) {

                Tile tile = this.getTile(x, y);
                BundledTexture layer = tile.getGraphic(0);

                layer.setAnimationTime(layer.getAnimationTime() + dt);

                if (mapData.getTile(x, y).getGraphic()[0] != 0) {
                    this.mGame.getSpriteBatch().draw(layer.getGraphic(true), layer.getX(), layer.getY());
                }
            }
        }

        /******************************************
         * Layer 2
         ******************************************/
        for (int y = minAreaY; y <= maxAreaY; y++) {
            for (int x = minAreaX; x <= maxAreaX; x++) {

                Tile tile = this.getTile(x, y);
                BundledTexture layer = tile.getGraphic(1);

                if (mapData.getTile(x, y).getGraphic()[1] != 0) {
                    layer.setAnimationTime(layer.getAnimationTime() + dt);
                    this.mGame.getSpriteBatch().draw(layer.getGraphic(true), layer.getX(), layer.getY());
                }
            }
        }

        /******************************************
         * Layer 3
         ******************************************/
        for (int y = minAreaY; y <= maxAreaY; y++) {
            for (int x = minAreaX; x <= maxAreaX; x++) {

                Tile tile = this.getTile(x, y);
                BundledTexture layer = tile.getGraphic(2);

                // Layer 3
                if (mapData.getTile(x, y).getGraphic()[2] != 0) {

                    layer.setAnimationTime(layer.getAnimationTime() + dt);

                    // If user is behind a tree draw it with alpha blend
                    if (tile.hasTree()) {
                        if (Math.abs(this.mGame.getCharacterHandler().getPlayer().getUserPosX() - x) < 4
                                && Math.abs(this.mGame.getCharacterHandler().getPlayer().getUserPosY() - y) < 4) {
                            Color oldColor = this.mGame.getSpriteBatch().getColor();
                            this.mGame.getSpriteBatch()
                                    .setColor(new Color(oldColor.r, oldColor.g, oldColor.b, ALPHA_TREES));
                            this.mGame.getSpriteBatch().draw(layer.getGraphic(), layer.getX(), layer.getY());
                            this.mGame.getSpriteBatch().setColor(oldColor);
                        } else {
                            this.mGame.getSpriteBatch().draw(layer.getGraphic(true), layer.getX(), layer.getY());
                        }
                    } else {
                        this.mGame.getSpriteBatch().draw(layer.getGraphic(true), layer.getX(), layer.getY());
                    }
                }

                // Character layer
                if (tile.getCharIndex() > 0) {
                    tile.getCharacter().update(dt);
                }
            }
        }

        /******************************************
         * Layer 4
         ******************************************/
        // If user is under a roof we hide it
        if (this.mGame.getCharacterHandler().getPlayer().isUnderRoof()) {
            if (this.mTechoAB > 0) {
                this.mTechoAB -= dt;
            }
            if (this.mTechoAB < 0.05f)
                this.mTechoAB = 0.0f;
        } else {
            if (this.mTechoAB < 1) {
                this.mTechoAB += dt;
            }
            if (this.mTechoAB > .95f)
                this.mTechoAB = 1.0f;
        }

        for (int y = minAreaY; y <= maxAreaY; y++) {
            for (int x = minAreaX; x <= maxAreaX; x++) {

                Tile tile = this.getTile(x, y);
                BundledTexture layer = tile.getGraphic(3);

                if (mapData.getTile(x, y).getGraphic()[3] != 0) {
                    layer.setAnimationTime(layer.getAnimationTime() + dt);

                    // Don't draw the shader above roofs
                    Color oldColor = this.mGame.getSpriteBatch().getColor();
                    this.mGame.getSpriteBatch()
                            .setColor(new Color(oldColor.r, oldColor.g, oldColor.b, this.mTechoAB));
                    this.mGame.getSpriteBatch().draw(layer.getGraphic(true), layer.getX(), layer.getY());
                    this.mGame.getSpriteBatch().setColor(oldColor);
                }
            }
        }
    }

    public void updatePhysics(float dt) {
        // Render box2d world
        this.mWorld.step(1 / 45f, 6, 2);
        this.mDebugRenderer.render(this.mWorld, this.mGame.getCamera().combined);

        // Render lights
        this.mRayHandler.setAmbientLight(this.mGame.getEngine().getTint().r, this.mGame.getEngine().getTint().g,
                this.mGame.getEngine().getTint().b, this.mGame.getEngine().getTint().a);
        this.mRayHandler.setCombinedMatrix(this.mGame.getCamera().combined, this.mGame.getCamera().position.x,
                this.mGame.getCamera().position.y, this.mGame.getCamera().viewportWidth,
                this.mGame.getCamera().viewportHeight);
        this.mRayHandler.updateAndRender();
    }

    @Override
    public void reset() {
        Array<Body> tmpBodies = new Array<Body>();
        this.mWorld.getBodies(tmpBodies);
        for (int i = 0; i < tmpBodies.size; i++) {
            tmpBodies.get(i).setActive(false);
            this.mWorld.destroyBody(tmpBodies.get(i));
        }
    }

    @Override
    public void show() {
    }

    @Override
    public void draw() {
    }

    @Override
    public void load() {

        // Get mapData
        MapData mapData = this.mGame.getMapHandler().get(this.mMapNumber);

        // Clear box2d world
        this.reset();

        // Move MapData tiles into our array
        this.mTiles = new Tile[MAX_MAP_SIZE_WIDTH + 1][MAX_MAP_SIZE_HEIGHT + 1];
        for (int y = MIN_MAP_SIZE_HEIGHT; y <= MAX_MAP_SIZE_HEIGHT; y++) {
            for (int x = MIN_MAP_SIZE_WIDTH; x <= MAX_MAP_SIZE_WIDTH; x++) {

                MapBlockData tile = mapData.getTile(x, y);
                this.mTiles[x][y] = new Tile(this.mGame, x, y, tile.getGraphic());
                this.mTiles[x][y].setBlocked(tile.isBlocked());
                this.mTiles[x][y].setTrigger(tile.getTrigger());
            }
        }
    }

    @Override
    public void dispose() {
        this.mRayHandler.dispose();
    }

    // ===========================================================
    // Getter & Setter
    // ===========================================================
    /**
     * @return the mWorld
     */
    public World getWorld() {
        return mWorld;
    }

    /**
     * @param mWorld the mWorld to set
     */
    public void setWorld(World mWorld) {
        this.mWorld = mWorld;
    }

    /**
     * @return the mLightHandler
     */
    public LightHandler getLightHandler() {
        return mLightHandler;
    }

    /**
     * @param mLightHandler the mLightHandler to set
     */
    public void setLightHandler(LightHandler mLightHandler) {
        this.mLightHandler = mLightHandler;
    }

    /**
     * @return the mRayHandler
     */
    public RayHandler getRayHandler() {
        return mRayHandler;
    }

    /**
     * @param mRayHandler the mRayHandler to set
     */
    public void setRayHandler(RayHandler mRayHandler) {
        this.mRayHandler = mRayHandler;
    }

    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================
}