package com.ptrprograms.asteroidbelttv.Objects;
import com.ptrprograms.asteroidbelttv.GameView;
import com.ptrprograms.asteroidbelttv.Utils.Constants;
import com.ptrprograms.asteroidbelttv.Utils.GamepadController;
import com.ptrprograms.asteroidbelttv.Utils.ShapeBuffer;
import com.ptrprograms.asteroidbelttv.Utils.Utils;
/**
* Created by PaulTR on 7/20/14.
*/
public class Ship {
private final GamepadController mController = new GamepadController();
private static final float SHIP_SIZE = 5.0f;
private static final float DRAG = 0.05f;
private static final float MINIMUM_VELOCITY = 0.05f;
private static final int FIRE_REFRESH_TIMER = 10;//frames
private float mHeadingX;
private float mHeadingY;
private float mVelocityX;
private float mVelocityY;
private float mVelocityMultiplier = 1.5f;
private float mPositionX;
private float mPositionY;
private float mRespawnTimer = 3.0f;
private int mFireTimer = 0;
private float mAimX, mAimY;
private Utils.Color mColor = Utils.Color.WHITE;
public Ship() {
reset();
}
public void reset() {
setVelocity(0.0f, 0.0f);
setPosition( 0.0f, 0.0f );
setHeadingX( 0.0f );
setHeadingY( 1.0f );
}
public void draw( ShapeBuffer sb) {
if (!isSpawned()) {
return;
}
sb.add2DShape( mPositionX, mPositionY, mColor, getShipVerticies(), SHIP_SIZE, SHIP_SIZE,
mHeadingX, mHeadingY);
}
private float[] getShipVerticies() {
float verticies[] = {
-1.0f, 0.5f,
-1.0f, -0.5f,
1.0f, 0.0f
};
return verticies;
}
public void setVelocity( float velX, float velY ) {
setVelocityX( velX );
setVelocityY( velY );
}
public void setVelocityX( float vel ) {
mVelocityX = vel * mVelocityMultiplier;
}
public void setVelocityY( float vel ) {
mVelocityY = vel * mVelocityMultiplier;
}
public void setPosition( float posX, float posY ) {
setPositionX( posX );
setPositionY( posY );
}
public void setPositionX( float position ) {
if( Utils.isInXPlane( position, SHIP_SIZE ) ) {
mPositionX = position;
} else if( Utils.isOffScreenToRight(position, SHIP_SIZE) ) {
mPositionX = Constants.MAP_LEFT_COORDINATE;
} else if( Utils.isOffScreenToLeft( position, SHIP_SIZE ) ) {
mPositionX = Constants.MAP_RIGHT_COORDINATE;
}
}
public void setPositionY( float position ) {
if( Utils.isInYPlane( position, SHIP_SIZE ) ) {
mPositionY = position;
} else if( Utils.isOffScreenAboveTop( position, SHIP_SIZE ) ) {
mPositionY = Constants.MAP_BOTTOM_COORDINATE;
} else if( Utils.isOffScreenBelowBottom( position, SHIP_SIZE ) ) {
mPositionY = Constants.MAP_TOP_COORDINATE;
}
}
public void update(float delta ) {
if ( !updateStatus( delta ) ) {
return;
}
updateShipPosition( delta );
handleKeyInput( delta );
}
private boolean updateStatus( float delta ) {
updateSpawningStatus( delta );
return isSpawned();
}
public boolean isSpawned() {
return ( mRespawnTimer <= 0.0f );
}
private void updateSpawningStatus( float delta ) {
if (mRespawnTimer > 0.0f) {
mRespawnTimer -= delta;
if (mRespawnTimer <= 0.0f) {
// Time to respawn.
mRespawnTimer = 0.0f;
// Spawn in middle
setPositionX( ( Constants.MAP_LEFT_COORDINATE + Constants.MAP_RIGHT_COORDINATE ) / 2 );
setPositionY( ( Constants.MAP_TOP_COORDINATE + Constants.MAP_BOTTOM_COORDINATE ) / 2 );
}
}
}
//Determines velocity by getting direction and magnitude from the joystick controller
private void updateShipPosition(float frameDelta) {
float newHeadingX = mController.getJoystickPosition(GamepadController.JOYSTICK_1,
GamepadController.AXIS_X);
float newHeadingY = mController.getJoystickPosition(GamepadController.JOYSTICK_1,
GamepadController.AXIS_Y);
float magnitude = Utils.vector2DLength(newHeadingX, newHeadingY);
//Joystick being used at least a little bit
if (magnitude > GamepadController.JOYSTICK_MOVEMENT_THRESHOLD) {
//Get the heading divided by how much the joystick is being used
mHeadingX = newHeadingX / magnitude;
mHeadingY = -newHeadingY / magnitude;
setVelocity( newHeadingX, -newHeadingY );
if (magnitude > 1.0f) {
//Sets a cap velocity
mVelocityX /= magnitude;
mVelocityY /= magnitude;
}
}
setPosition( mPositionX + mVelocityX * frameDelta, mPositionY + mVelocityY * frameDelta );
// Use drag so that the ship will coast to a stop after the movement controller
// is released.
mVelocityX *= 1.0f - frameDelta * DRAG;
mVelocityY *= 1.0f - frameDelta * DRAG;
if (Utils.vector2DLength(mVelocityX, mVelocityY) < MINIMUM_VELOCITY) {
setVelocity( 0.0f, 0.0f );
}
}
private void handleKeyInput( float delta ) {
if( mFireTimer > 0 ) {
mFireTimer--;
return;
}
if ( mController.isButtonDown( GamepadController.BUTTON_X ) && mFireTimer == 0 ) {
mFireTimer = FIRE_REFRESH_TIMER;
calculateAimDirection();
fireGun();
}
}
private void fireGun() {
//Bullets angle is based on angle of the ship + speed of the ship in a given direction
GameView.getInstance().mBullets.add(new Bullet(mColor, mAimX + mVelocityX, mAimY + mVelocityY, mPositionX, mPositionY));
}
protected void calculateAimDirection() {
mAimX = mController.getJoystickPosition(GamepadController.JOYSTICK_2,
GamepadController.AXIS_X);
mAimY = -mController.getJoystickPosition(GamepadController.JOYSTICK_2,
GamepadController.AXIS_Y);
float magnitude = Utils.vector2DLength(mAimX, mAimY);
if (magnitude > 0.1f ) {
// Normalize the direction vector.
mAimX /= magnitude;
mAimY /= magnitude;
} else {
// The firing joystick is not being used, so fire any shots in the direction
// the player is currently traveling.
mAimX = mHeadingX;
mAimY = mHeadingY;
}
}
public void setHeadingX( float heading ) {
mHeadingX = heading;
}
public void setHeadingY( float heading ) {
mHeadingY = heading;
}
public GamepadController getController() {
return mController;
}
}