Camera utilities and menu implementation

This commit is contained in:
Ash Reynolds 2016-02-10 18:21:32 +00:00
parent 71ffec00ab
commit 61a10aa7e7
12 changed files with 203 additions and 104 deletions

View file

@ -5,15 +5,15 @@
</tileset>
<layer name="PLATFORM" width="50" height="8">
<data encoding="base64" compression="zlib">
eJxjYBgF1ABMSJgYwAjEzGj0QAHGAbZ/qANmPBifHmTAyIA/Hkg1nxBgwoLxAUYsGNld+PQh06S4DZvZ2NxAbYArTCi1j5TygR6AnHSLDgAqVwCE
eJztk8EKACAIQzX//5/rOEKWktGhHgxPy5kl8qmggSLokE31FprsH53xFYyIeRAVvofV+dmdNEcMdYS5mA/rLl6GarJ/OeLP3PVJsH/03bLsHTB3AJM=
</data>
</layer>
<objectgroup name="PLAYER">
<object id="19" gid="3" x="64" y="320" width="64" height="64"/>
</objectgroup>
<objectgroup name="BOUNDARY">
<object id="23" x="-64" y="-128">
<polyline points="0,0 0,768 3392,768 3392,0 0,0"/>
<object id="23" x="0" y="-192">
<polyline points="0,0 0,1024 3328,1024 3328,0 0,0"/>
</object>
</objectgroup>
</map>

View file

@ -1,9 +1,7 @@
package com.game.Actor;
import static com.game.Misc.Vars.PPM;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import com.game.Misc.Vars;
/**
* Created by Ash on 08/02/2016.

View file

@ -3,18 +3,16 @@ package com.game.Actor;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import com.game.Misc.Box2dUtils;
import com.game.Misc.Vars;
import static com.game.Misc.Vars.PPM;
import static com.game.Misc.Vars.TILESIZE;
/**
* Created by Ash on 08/02/2016.
*/
public class Platform extends Base {
public Platform(World world, Vector2 pos, Colours curColour) {
super(world, pos, new Vector2(TILESIZE, TILESIZE), "STATIC", curColour);
public Platform(World world, Vector2 pos, Vector2 size, Colours curColour) {
super(world, pos, size, "STATIC", curColour);
body = Box2dUtils.makeBody(world,
BodyDef.BodyType.StaticBody,
@ -23,8 +21,8 @@ public class Platform extends Base {
Box2dUtils.makePolygon(body, size, "", false);
Box2dUtils.makeChain(body,
new Vector2[]{
new Vector2((-TILESIZE / 2 + 5) / PPM, (TILESIZE / 2 + 5) / PPM),
new Vector2((TILESIZE / 2 - 5) / PPM, (TILESIZE / 2 + 5) / PPM)
new Vector2((-size.x / 2 + 5) / PPM, (size.y / 2 + 5) / PPM),
new Vector2((size.x / 2 - 5) / PPM, (size.y / 2 + 5) / PPM)
},
"PLATFORM",
true

View file

@ -2,38 +2,53 @@ package com.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.game.Misc.Vars;
import com.game.States.StateManager;
import com.game.Managers.StateManager;
public class Game extends ApplicationAdapter {
public class App extends ApplicationAdapter {
private float accum;
// Batches
private SpriteBatch sb;
private ShapeRenderer sr;
// Cameras
private OrthographicCamera cam;
private OrthographicCamera hudCam;
// Managers
private StateManager sm;
@Override
public void create() {
sb = new SpriteBatch();
// Create batches
sb = new SpriteBatch();
sr = new ShapeRenderer();
// Create Main + HUD cameras
cam = new OrthographicCamera();
cam.setToOrtho(false, Vars.SCREEN_WIDTH, Vars.SCREEN_HEIGHT);
hudCam = new OrthographicCamera();
hudCam.setToOrtho(false, Vars.SCREEN_WIDTH, Vars.SCREEN_HEIGHT);
// Create statemanager (Should always happen last)
sm = new StateManager(this);
}
@Override
public void resize (int width, int height) {
}
@Override
public void render () {
super.render();
accum += Gdx.graphics.getDeltaTime();
while (accum >= Vars.STEP) {
accum -= Vars.STEP;
@ -41,22 +56,20 @@ public class Game extends ApplicationAdapter {
sm.update(Vars.STEP);
sm.render();
}
}
@Override
public void pause () {
}
@Override
public void resume () {
if(Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) { Gdx.app.exit(); }
}
@Override
public void dispose () {
sm.dispose();
sb.dispose();
sr.dispose();
}
public SpriteBatch getSpriteBatch() { return sb; }
public ShapeRenderer getSr() { return sr; }
public StateManager getSm() { return sm; }
public OrthographicCamera getCam() { return cam; }
public OrthographicCamera getHudCam() { return hudCam; }
}

View file

@ -0,0 +1,7 @@
package com.game.Managers;
/**
* Created by Ash on 10/02/2016.
*/
public class Assets {
}

View file

@ -1,6 +1,9 @@
package com.game.States;
package com.game.Managers;
import com.game.Game;
import com.game.App;
import com.game.States.Menu;
import com.game.States.Play;
import com.game.States.State;
import java.util.HashMap;
@ -8,7 +11,8 @@ import java.util.HashMap;
* Created by Ash on 08/02/2016.
*/
public class StateManager {
private Game game;
protected final App app;
private HashMap<States, State> states = new HashMap<States, State>();
@ -20,13 +24,13 @@ public class StateManager {
PLAY,
}
public StateManager(Game game)
public StateManager(App app)
{
this.game = game;
this.app = app;
states.put(States.MENU, new Menu(this));
states.put(States.PLAY, new Play(this));
setState(States.PLAY); // TODO, set to MENU
setState(States.MENU); // TODO, set to MENU
}
public void update(float dt)
@ -50,7 +54,7 @@ public class StateManager {
}
// Accessors
public Game game() { return game; }
public App app() { return app; }
// Mutators
public void setState(States state)

View file

@ -0,0 +1,54 @@
package com.game.Misc;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
/**
* Created by Ash on 10/02/2016.
*/
public class CameraUtils {
public static void lockOnTarget(Camera cam, float tarX, float tarY)
{
Vector3 pos = cam.position;
pos.x = tarX;
pos.y = tarY;
cam.position.set(pos);
cam.update();
}
public static void lerpToTarget(Camera cam, float tarX, float tarY)
{
Vector3 pos = cam.position;
pos.x = cam.position.x + (tarX - cam.position.x) * .2f;
pos.y = cam.position.y + (tarY - cam.position.y) * .2f;;
cam.position.set(pos);
cam.update();
}
public static void setBoundary(Camera cam, Vector2 start, Vector2 size)
{
Vector3 pos = cam.position;
if(pos.x < start.x)
{
pos.x = start.x;
}
if(pos.y < start.y)
{
pos.y = start.y;
}
if(pos.x > start.x + size.x)
{
pos.x = start.x + size.x;
}
if(pos.y > start.y + size.y)
{
pos.y = start.y + size.y;
}
cam.position.set(pos);
cam.update();
}
}

View file

@ -2,8 +2,6 @@ package com.game.Misc;
import com.badlogic.gdx.math.Vector2;
import java.io.File;
/**
* Created by Ash on 08/02/2016.
*/
@ -19,7 +17,7 @@ public class Vars {
public static final float STEP = 1 / FRAMERATE;
public static final Vector2 GRAVITY = new Vector2(0, -9.81f);
public static final float PPM = 100f; // Pixels per meter
public static final float TILESIZE = 64f;
//public static final Vector2 TILESIZE = new Vector2(64, 64);
public static final Vector2 SCROLLSPEED = new Vector2(150f, 0);
// Filter bits

View file

@ -1,10 +1,15 @@
package com.game.States;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.game.Managers.StateManager;
/**
* Created by Ash on 08/02/2016.
*/
public class Menu extends State {
public Menu(StateManager sm) {
super(sm);
}
@ -26,7 +31,10 @@ public class Menu extends State {
@Override
public void handleInput() {
if(Gdx.input.isKeyPressed(Input.Keys.ENTER))
{
sm.setState(StateManager.States.PLAY);
}
}
@Override

View file

@ -6,8 +6,8 @@ import com.badlogic.gdx.Input;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.MapProperties;
import com.badlogic.gdx.maps.objects.PolylineMapObject;
import com.badlogic.gdx.maps.objects.TextureMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
@ -21,7 +21,11 @@ import com.badlogic.gdx.physics.box2d.*;
import com.game.Actor.Base;
import com.game.Actor.Platform;
import com.game.Actor.Player;
import com.game.App;
import com.game.Managers.StateManager;
import com.game.Misc.CameraUtils;
import com.game.Misc.Vars;
import javafx.beans.property.MapProperty;
import java.util.ArrayList;
@ -31,28 +35,162 @@ import java.util.ArrayList;
public class Play extends State {
// TODO, remove
public boolean isDebug = true;
public boolean isDebug = false;
// Physics related
private World world;
private Box2DDebugRenderer b2dr; // TODO, remove
private OrthographicCamera b2dCam; // TODO, remove
private OrthographicCamera b2dCam;
private float tileSize;
Player player;
// TileMap and Map Renderer
private TiledMap tileMap;
private OrthogonalTiledMapRenderer tmr;
private float mapWidth, mapHeight;
private Vector2 tileSize;
// All Actors in level
private Player player;
private ArrayList<Platform> platforms = new ArrayList<Platform>();
ArrayList<Platform> platforms = new ArrayList<Platform>();
private Sound jumpSound = Gdx.audio.newSound(Gdx.files.internal("sounds/jumping.mp3"));
public Play(StateManager sm) {
super(sm);
world = new World(new Vector2(0, Vars.GRAVITY.y), true);
world.setContactListener(cl);
b2dr = new Box2DDebugRenderer(); // TODO, remove
b2dCam = new OrthographicCamera();
b2dCam.setToOrtho(false, Vars.SCREEN_WIDTH / PPM, Vars.SCREEN_HEIGHT / PPM);
}
@Override
public void init() {
setupLevel();
}
@Override
public void update(float dt) {
world.step(dt, 6, 2);
CameraUtils.lerpToTarget(cam, player.getPos().scl(PPM).x, 0);
CameraUtils.lockOnTarget(b2dCam, player.getPos().x, player.getPos().y);
Vector2 start = new Vector2(cam.viewportWidth / 2, cam.viewportHeight / 2);
CameraUtils.setBoundary(cam, start, new Vector2(mapWidth * tileSize.x - start.x * 2, mapHeight * tileSize.y - start.y * 2));
player.update(dt);
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.setProjectionMatrix(cam.combined);
if(!isDebug)
{
sb.begin();
player.render(sb);
sb.end();
tmr.setView(cam);
tmr.render();
}
else
{
b2dr.render(world, b2dCam.combined);
}
}
@Override
public void handleInput() {
if(Gdx.input.isKeyPressed(Input.Keys.SPACE))
{
//jumpSound.play(); //TODO, fix sound?
player.jump();
}
if(Gdx.input.isKeyJustPressed(Input.Keys.V)) { isDebug = !isDebug; }
}
@Override
public void dispose() {
world.dispose();
}
private void setupLevel()
{
tileMap = new TmxMapLoader().load("levels/level1.tmx");
tmr = new OrthogonalTiledMapRenderer(tileMap);
MapProperties mapProp = tileMap.getProperties();
mapWidth = mapProp.get("width", Integer.class);
mapHeight = mapProp.get("height", Integer.class);
tileSize = new Vector2(mapProp.get("tilewidth", Integer.class), mapProp.get("tileheight", Integer.class));
TiledMapTileLayer platformLayer = (TiledMapTileLayer)tileMap.getLayers().get("PLATFORM");
MapLayer boundaryLayer = tileMap.getLayers().get("BOUNDARY");
PolylineMapObject polylineObj = (PolylineMapObject)boundaryLayer.getObjects().get(0);
buildBoundary(polylineObj);
MapLayer playerLayer = tileMap.getLayers().get("PLAYER");
TextureMapObject playerObj = (TextureMapObject)playerLayer.getObjects().get(0);
player = new Player(world, new Vector2(playerObj.getX(), playerObj.getY()), new Vector2(60, 60), Base.Colours.NONE);
for(int row = 0; row < platformLayer.getHeight(); row++)
{
for(int col = 0; col < platformLayer.getWidth(); col++)
{
TiledMapTileLayer.Cell cell = platformLayer.getCell(col, row);
if(cell == null) { continue; }
if(cell.getTile() == null) { continue; }
if(cell.getTile().getId() == 1) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize.x, (row + 0.5f) * tileSize.y), new Vector2(tileSize.x, tileSize.y), Base.Colours.RED)); }
else if(cell.getTile().getId() == 2) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize.x, (row + 0.5f) * tileSize.y), new Vector2(tileSize.x, tileSize.y), Base.Colours.GREEN)); }
else if(cell.getTile().getId() == 3) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize.x, (row + 0.5f) * tileSize.y), new Vector2(tileSize.x, tileSize.y), Base.Colours.BLUE)); }
}
}
}
private void buildBoundary(PolylineMapObject polylineObj)
{
Polyline r = polylineObj.getPolyline();
BodyDef bd = new BodyDef();
bd.type = BodyDef.BodyType.StaticBody;
Body body = world.createBody(bd);
FixtureDef fd = new FixtureDef();
ChainShape chain = new ChainShape();
float[] v = r.getTransformedVertices();
Vector2[] finalV = new Vector2[v.length / 2];
for(int i = 0; i < v.length / 2; ++i)
{
finalV[i] = new Vector2();
finalV[i].x = v[i * 2] / PPM;
finalV[i].y = v[i * 2 + 1] / PPM;
}
chain.createChain(finalV);
fd.shape = chain;
body.createFixture(fd).setUserData("boundary");
}
// Accessors
// Mutators
// Contact Listener
ContactListener cl = new ContactListener() {
@Override
public void beginContact(Contact contact) {
@ -86,139 +224,4 @@ public class Play extends State {
}
};
world.setContactListener(cl);
b2dr = new Box2DDebugRenderer(); // TODO, remove
b2dCam = new OrthographicCamera();
b2dCam.setToOrtho(false, Vars.SCREEN_WIDTH / PPM, Vars.SCREEN_HEIGHT / PPM);
}
@Override
public void init() {
setupLevel();
}
@Override
public void update(float dt) {
world.step(dt, 6, 2);
cameraUpdate(dt);
b2dCam.position.x = player.getPos().x;
b2dCam.update();
player.update(dt);
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.setProjectionMatrix(cam.combined);
if(!isDebug)
{
sb.begin();
player.render(sb);
sb.end();
tmr.setView(cam);
tmr.render();
}
else
{
b2dr.render(world, b2dCam.combined);
}
}
@Override
public void handleInput() {
if(Gdx.input.isKeyPressed(Input.Keys.SPACE))
{
//jumpSound.play(); TODO, fix sound?
player.jump();
}
if(Gdx.input.isKeyJustPressed(Input.Keys.V)) { isDebug = !isDebug; }
}
@Override
public void dispose() {
}
private void cameraUpdate(float dt)
{
Vector3 camPos = cam.position;
camPos.x = cam.position.x + ((player.getPos().x * PPM) - cam.position.x) * .2f;
//camPos.y = cam.position.y + ((player.getPos().y * PPM) - cam.position.y) * .2f;
cam.position.set(camPos);
cam.update();
}
private void setupLevel()
{
tileMap = new TmxMapLoader().load("levels/level1.tmx");
tmr = new OrthogonalTiledMapRenderer(tileMap);
TiledMapTileLayer platformLayer = (TiledMapTileLayer)tileMap.getLayers().get("PLATFORM");
tileSize = platformLayer.getTileWidth();
MapLayer boundaryLayer = tileMap.getLayers().get("BOUNDARY");
PolylineMapObject polylineObj = (PolylineMapObject)boundaryLayer.getObjects().get(0);
buildBoundary(polylineObj);
MapLayer playerLayer = tileMap.getLayers().get("PLAYER");
TextureMapObject playerObj = (TextureMapObject)playerLayer.getObjects().get(0);
player = new Player(world, new Vector2(playerObj.getX(), playerObj.getY()), new Vector2(60, 60), Base.Colours.NONE);
for(int row = 0; row < platformLayer.getHeight(); row++)
{
for(int col = 0; col < platformLayer.getWidth(); col++)
{
TiledMapTileLayer.Cell cell = platformLayer.getCell(col, row);
if(cell == null) { continue; }
if(cell.getTile() == null) { continue; }
if(cell.getTile().getId() == 1) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize, (row + 0.5f) * tileSize), Base.Colours.RED)); }
else if(cell.getTile().getId() == 2) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize, (row + 0.5f) * tileSize), Base.Colours.GREEN)); }
else if(cell.getTile().getId() == 3) { platforms.add(new Platform(world, new Vector2((col + 0.5f) * tileSize, (row + 0.5f) * tileSize), Base.Colours.BLUE)); }
}
}
}
public void buildBoundary(PolylineMapObject polylineObj)
{
Polyline r = polylineObj.getPolyline();
BodyDef bd = new BodyDef();
bd.type = BodyDef.BodyType.StaticBody;
Body body = world.createBody(bd);
FixtureDef fd = new FixtureDef();
ChainShape chain = new ChainShape();
float[] v = r.getTransformedVertices();
Vector2[] finalV = new Vector2[v.length / 2];
for(int i = 0; i < v.length / 2; ++i)
{
finalV[i] = new Vector2();
finalV[i].x = v[i * 2] / PPM;
finalV[i].y = v[i * 2 + 1] / PPM;
}
chain.createChain(finalV);
fd.shape = chain;
body.createFixture(fd).setUserData("boundary");
}
// Accessors
// Mutators
}

View file

@ -2,26 +2,42 @@ package com.game.States;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.game.Game;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.game.App;
import com.game.Managers.StateManager;
/**
* Created by Ash on 08/02/2016.
*/
public abstract class State {
protected StateManager sm;
protected Game game;
// App reference
protected final App app;
// Batches
protected SpriteBatch sb;
protected ShapeRenderer sr;
// Cameras
protected OrthographicCamera cam;
protected OrthographicCamera hudCam;
// Stage
protected Stage stage;
// Managers
protected final StateManager sm;
public State (StateManager sm)
{
this.sm = sm;
game = sm.game();
sb = game.getSpriteBatch();
cam = game.getCam();
hudCam = game.getHudCam();
this.app = sm.app();
sb = app.getSpriteBatch();
sr = app.getSr();
cam = app.getCam();
hudCam = app.getHudCam();
stage = new Stage();
}
public abstract void init();

View file

@ -3,19 +3,19 @@ package com.game.desktop;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.PixmapIO;
import com.game.Game;
import com.game.App;
import com.game.Misc.Vars;
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
new LwjglApplication(new Game(), config);
new LwjglApplication(new App(), config);
config.title = Vars.TITLE;
config.width = Vars.SCREEN_WIDTH;
config.height = Vars.SCREEN_HEIGHT;
config.resizable = Vars.RESIZABLE;
config.addIcon("spritesheets/icon.jpg", Files.FileType.Internal);
config.foregroundFPS = (int)Vars.FRAMERATE;
config.backgroundFPS = (int)Vars.FRAMERATE;
}
}