package com.igorcrevar.goingunder.objects; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.igorcrevar.goingunder.GameData; import com.igorcrevar.goingunder.utils.Mathf; public class Player implements IGameObject { public final float InitialAngle = 90.0f; private Sprite gameObject; private float velocityX; private GameData gameData; private float rotationAngle; private boolean dieAnimationStarted; private float diePositionX; private float diePositionY; private TextureRegion[] liveTextureRegions; private TextureRegion[] dieTextureRegions; private float animationTimer; private int currentFrame; public Player(TextureRegion[] liveTextureRegions, TextureRegion[] dieTextureRegions) { gameObject = new Sprite(); this.liveTextureRegions = liveTextureRegions; this.dieTextureRegions = dieTextureRegions; } public void addVelocity(float inc) { velocityX += inc; if (velocityX > gameData.MaxVelocityX) { velocityX = gameData.MaxVelocityX; } else if (velocityX < -gameData.MaxVelocityX) { velocityX = -gameData.MaxVelocityX; } } @Override public void init(Object data) { this.gameData = (GameData)data; this.rotationAngle = InitialAngle; this.velocityX = 0.0f; gameObject.setSize(gameData.PlayerSizeX, gameData.PlayerSizeY); gameObject.setOrigin(gameData.PlayerSizeX / 2.0f, gameData.PlayerSizeY / 2.0f); gameObject.setScale(1.0f, 1.0f); gameObject.setRotation(0.0f); gameObject.setPosition(-gameData.PlayerSizeX / 2, -gameData.PlayerSizeY / 2 + gameData.CameraDist); gameObject.setRegion(liveTextureRegions[0]); this.dieAnimationStarted = false; this.animationTimer = 0.0f; this.currentFrame = 0; } @Override public void update(float deltaTime) { // rotation float minAngle = InitialAngle - gameData.RotationMaxAngle; float maxAngle = InitialAngle + gameData.RotationMaxAngle; if (velocityX > 0.0f) { rotationAngle -= gameData.RotationSpeed * deltaTime; rotationAngle = Math.max(rotationAngle, minAngle); } else if (velocityX < 0.0f) { rotationAngle += gameData.RotationSpeed * deltaTime; rotationAngle = Math.min(rotationAngle, maxAngle); } else if (rotationAngle > InitialAngle) { rotationAngle -= gameData.RotationSpeed * deltaTime; rotationAngle = Math.max(rotationAngle, InitialAngle); } else if (rotationAngle < InitialAngle) { rotationAngle += gameData.RotationSpeed * deltaTime; rotationAngle = Math.min(rotationAngle, InitialAngle); } // set rotation this.gameObject.setRotation(getAngle()); // calculate new position float newX = gameObject.getX() + velocityX * deltaTime; float newY = gameObject.getY() + gameData.VelocityY * deltaTime; // bouncing on left/right boundaries this.gameObject.setPosition(newX, newY); if (velocityX > 0.0f && newX + gameData.PlayerSizeX >= gameData.CameraHalfWidth || velocityX < 0.0f && newX <= -gameData.CameraHalfWidth) { velocityX = Math.abs(velocityX * gameData.BoundariesBouncingFactor); if (newX > 0.0f) { velocityX = -velocityX; newX = gameData.CameraHalfWidth - gameData.PlayerSizeX; } else { newX = -gameData.CameraHalfWidth; } } // update position and rotation this.gameObject.setPosition(newX, newY); // update X velocity (with friction) if (velocityX > 0.0f) { velocityX -= gameData.Friction * deltaTime; if (velocityX < 0.0f) { velocityX = 0.0f; } } else if (velocityX < 0.0f) { velocityX += gameData.Friction * deltaTime; if (velocityX > 0.0f) { velocityX = 0.0f; } } // update animation updateAnimation(liveTextureRegions, deltaTime); } @Override public void draw(SpriteBatch spriteBatch) { gameObject.draw(spriteBatch); } @Override public boolean isEnabled() { return true; } @Override public void setIsEnabled(boolean value) { } public void updateDie(float additionalTimer, float deltaTime) { if (!dieAnimationStarted) { dieAnimationStarted = true; animationTimer = 0.0f; currentFrame = 0; gameObject.setRegion(dieTextureRegions[0]); diePositionX = this.gameObject.getX(); diePositionY = this.gameObject.getY(); } float playerDiedAnimTime1 = 1.0f; if (additionalTimer <= playerDiedAnimTime1) { float realTime = additionalTimer / playerDiedAnimTime1; float scale = Mathf.lerp(1.0f, 4.0f, realTime); float nx = Mathf.lerp(diePositionX, -gameObject.getWidth() / 2, realTime); float ny = Mathf.lerp(diePositionY, gameData.CameraYPosition, realTime); gameObject.setScale(scale, scale); gameObject.setPosition(nx, ny); } else if (gameObject.getScaleY() > 0.0f) { float realTimer = (additionalTimer - playerDiedAnimTime1) / 1.5f; float scale = Mathf.lerp(4.0f, 0.0f, realTimer); gameObject.setScale(scale); gameObject.rotate(2.0f * 360.0f * deltaTime); } // animation updateAnimation(dieTextureRegions, deltaTime); } public Rectangle getBoundingRectangle() { return gameObject.getBoundingRectangle(); } public float getAngle() { float finalAngle = rotationAngle > InitialAngle ? rotationAngle - InitialAngle : rotationAngle + (360.0f - InitialAngle); return finalAngle; } public float getX() { return gameObject.getX() + gameData.PlayerSizeX / 2.0f; } public float getY() { return gameObject.getY() + gameData.PlayerSizeY / 2.0f; } private void updateAnimation(TextureRegion[] textures, float deltaTime) { // [0 - 0.99] float tmp = animationTimer - (int)animationTimer + 0.0001f; // calculate current fame int desiredFrame = (int)Math.ceil(tmp * textures.length) - 1; if (desiredFrame < 0) desiredFrame = 0; else if (desiredFrame >= textures.length) desiredFrame = textures.length - 1; // only swap textures if needed if (desiredFrame != currentFrame) { currentFrame = desiredFrame; gameObject.setRegion(textures[currentFrame]); } animationTimer += deltaTime; } private Vector2[] points = null; private Color tmpColor2 = new Color(1f, 1f, 1f, 0.2f); private Color tmpColor1 = new Color(1f, 1f, 1f, 0.0f); public void drawLights(ShapeRenderer shapeRenderer, GameData gameData) { if (dieAnimationStarted) return; if (points == null) { points = new Vector2[6]; for (int i = 0; i < points.length; ++i) { points[i] = new Vector2(); } } // draw lights float inX = gameObject.getX() + gameData.PlayerSizeX / 2.0f; float inY = gameObject.getY() + gameData.PlayerSizeY / 2.0f - gameData.CameraYPosition; float angle = getAngle(); float maxY = -2.2f; points[2].set(- 0.15f, - 0.4f); points[1].set(+ 0.15f, - 0.4f); points[0].set(- 0.9f, maxY); points[5].set(+ 0.15f, - 0.4f); points[4].set(+ 0.9f, maxY); points[3].set(- 0.9f, maxY); for (int i = 0; i < points.length; ++i) { points[i].rotate(angle); points[i].add(inX, inY); } Gdx.gl.glEnable(GL20.GL_BLEND); shapeRenderer.begin(ShapeType.Filled); for (int i = 0; i < points.length / 3; ++i) { Vector2 p1 = points[i * 3]; Vector2 p2 = points[i * 3 + 1]; Vector2 p3 = points[i * 3 + 2]; Color cl = i == 0 ? tmpColor2 : tmpColor1; shapeRenderer.triangle(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, tmpColor1, cl, tmpColor2); } shapeRenderer.end(); } }