package com.gebauz.burutaru.game.entities;
import com.badlogic.gdx.audio.Sound;
import com.gebauz.bauzoid.graphics.sprite.SimpleSprite;
import com.gebauz.bauzoid.graphics.sprite.Sprite;
import com.gebauz.bauzoid.graphics.sprite.SpriteInstance;
import com.gebauz.bauzoid.math.MathUtil;
import com.gebauz.bauzoid.math.Vector2;
import com.gebauz.bauzoid.math.collision.Shape;
import com.gebauz.burutaru.GameConsts;
import com.gebauz.burutaru.game.GameLogic;
import com.gebauz.burutaru.game.entities.CollisionWorld.CollisionInfo;
public class Ship
extends Entity
{
// Constants========================================================================================
public static final int SHIP_WIDTH =
64;
public static final int SHIP_HEIGHT =
64;
// HACK: for powerup pickup
public static final float SHIP_RADIUS_SQR = SHIP_WIDTH
*SHIP_WIDTH
* 0.5f
;
public static final int NUM_UP_FRAMES =
5;
public static final int NUM_DOWN_FRAMES =
5;
public static final int NUM_SHIP_FRAMES =
1 + NUM_UP_FRAMES + NUM_DOWN_FRAMES
;
public static final int SHIP_SPRITE_SIZE =
128;
public static final int NUM_SHIP_FRAMES_X =
4;
public static final int NUM_SHIP_FRAMES_Y =
4;
public static final float UPDOWN_ANIM_SPEED = 4.0f
;
public static final float UPDOWN_THRESHOLD = 20.0f
;
public static final float MUZZLEFLASH_DURATION = 0.15f
;
public static final float MUZZLEFLASH_SIZE = 40.0f
;
public static final float EXHAUST_WIDTH =
28;
public static final float EXHAUST_HEIGHT =
16;
public static final float EXHAUST_BOOST_MAX = 0.3f
;
public static final float EXHAUST_BOOST_MIN = -0.1f
;
public static final float EXHAUST_BOOST_FACTOR = 11.0f
;
public static final float EXHAUST_ANIM_SPEED = 4000.0f
;
public static final float ENGINE_BOOST_DURATION = 0.5f
;
public static final float BEAMSHOT_COOLDOWN_TIME = 0.2f
;
public static final float DAMAGE_COOLDOWN_TIME = 0.2f
;
public static final float START_POSITION_X =
300;
public static final float START_POSITION_Y =
300;
// Embedded Types===================================================================================
public enum MoveDirection
{
NONE,
UP,
DOWN
}
// Fields===========================================================================================
private SpriteInstance mShipInstance =
null;
//private float mPositionX = 100;
//private float mPositionY = 100;
/*private float mLastMoveX = 0.0f;
private float mLastMoveY = 0.0f;*/
private Vector2 mLastMove =
new Vector2
();
private Shape mShipShape =
null;
private int mCurrentShipFrame =
0;
private MoveDirection mMoveDirection = MoveDirection.
NONE;
private Sprite mMuzzleFlash =
null;
private SpriteInstance mMuzzleFlashInstance =
null;
private SpriteInstance mEngineBoostInstance =
null;
private float mMuzzleFlashTimer = -1.0f
;
private float mBeamShotTimer = 0.0f
;
private SimpleSprite mEngineExhaust =
null;
private float mEngineExhaustScale = 1.0f
;
private float mEngineExhaustBoost = 0.0f
;
private float mMoveDirectionCoeff = 0.0f
;
private float mMoveDirectionCoeffTarget = 0.0f
;
private float mEngineBoostTimer = 0.0f
;
private Sound mEngineBoostSfx =
null;
private float mDamageCoolDown = 0.0f
;
private CollisionInfo mCollisionResult =
new CollisionInfo
();
// Methods==========================================================================================
public Ship
(GameLogic gameLogic
)
{
super(gameLogic
);
mShipInstance =
new SpriteInstance
(new Sprite
(getGraphics
(),
"data/textures/shipframes.png",
"data/textures/ship.txt"));
mEngineExhaust =
new SimpleSprite
(getGraphics
(),
"data/textures/engine_exhaust.png");
mMuzzleFlash =
new Sprite
(getGraphics
(),
"data/textures/plasma_muzzleflash.png");
mShipShape =
new Shape(getGame
(),
"data/textures/ship.shape");
}
@
Override
public void initAsync
()
{
mShipInstance.
initAsync();
mEngineExhaust.
initAsync();
mMuzzleFlash.
initAsync();
//getGameLogic().getAssetManager().load("data/textures/ship.shape", Shape.class);
mShipShape.
initAsync();
}
@
Override
public void init
()
{
mShipInstance.
init();
mEngineExhaust.
init();
mMuzzleFlash.
init();
//mShipShape = getGameLogic().getAssetManager().get("data/textures/ship.shape", Shape.class);
mShipShape.
init();
mMuzzleFlashInstance = mMuzzleFlash.
createSpriteInstance(0);
mEngineBoostInstance = mMuzzleFlash.
createSpriteInstance(0);
mShipInstance.
transform.
x = START_POSITION_X
;
mShipInstance.
transform.
y = START_POSITION_Y
;
mShipInstance.
transform.
w = SHIP_WIDTH
;
mShipInstance.
transform.
h = SHIP_HEIGHT
;
mShipInstance.
centerPivot();
}
@
Override
public void exit
()
{
if (mShipInstance
!=
null)
{
mShipInstance.
dispose(true);
mShipInstance =
null;
}
if (mEngineExhaust
!=
null)
{
mEngineExhaust.
dispose();
mEngineExhaust =
null;
mMuzzleFlashInstance =
null;
mEngineBoostInstance =
null;
}
if (mMuzzleFlash
!=
null)
{
mMuzzleFlash.
dispose();
mMuzzleFlash =
null;
}
mShipShape =
null;
}
@
Override
public void update
(float deltaTime
)
{
if (mMoveDirection == MoveDirection.
UP)
{
// move towards -1
mMoveDirectionCoeff -= deltaTime
* UPDOWN_ANIM_SPEED
;
if (mMoveDirectionCoeff
< mMoveDirectionCoeffTarget
)
mMoveDirectionCoeff = mMoveDirectionCoeffTarget
;
}
else if (mMoveDirection == MoveDirection.
DOWN)
{
// move towards +1
mMoveDirectionCoeff += deltaTime
* UPDOWN_ANIM_SPEED
;
if (mMoveDirectionCoeff
> mMoveDirectionCoeffTarget
)
mMoveDirectionCoeff = mMoveDirectionCoeffTarget
;
}
else if (mMoveDirection == MoveDirection.
NONE)
{
// move towards 0
if (mMoveDirectionCoeff
> 0)
mMoveDirectionCoeff = MathUtil.
clamp(mMoveDirectionCoeff - deltaTime
* UPDOWN_ANIM_SPEED,
0,
1);
else if (mMoveDirectionCoeff
< 0)
mMoveDirectionCoeff = MathUtil.
clamp(mMoveDirectionCoeff + deltaTime
* UPDOWN_ANIM_SPEED, -
1,
0);
}
mMoveDirectionCoeff = MathUtil.
clamp(mMoveDirectionCoeff, -
1,
1);
if (mMoveDirectionCoeff
> 0)
{
mCurrentShipFrame =
(int)(1 +
(NUM_DOWN_FRAMES-
1) * (mMoveDirectionCoeff
));
}
else if (mMoveDirectionCoeff
< 0)
{
mCurrentShipFrame =
(int)(1 + NUM_DOWN_FRAMES +
(NUM_UP_FRAMES-
1) * (-mMoveDirectionCoeff
));
}
else
{
mCurrentShipFrame =
0;
}
//Gdx.app.log(GameConsts.LOG_TAG, "coeff = " + mMoveDirectionCoeff + ", frame = " + mCurrentShipFrame + ", dir = " + mMoveDirection);
mCurrentShipFrame = MathUtil.
clamp(mCurrentShipFrame,
0, NUM_SHIP_FRAMES-
1);
mShipInstance.
setCurrentFrame(mCurrentShipFrame
);
if (mLastMove.
x > 0.0f
)
{
// grow
float diff = EXHAUST_BOOST_MAX - mEngineExhaustBoost
;
mEngineExhaustBoost += diff
* deltaTime
* EXHAUST_BOOST_FACTOR
;
}
else if (mLastMove.
x < 0.0f
)
{
float diff = EXHAUST_BOOST_MIN - mEngineExhaustBoost
;
mEngineExhaustBoost += diff
* deltaTime
* EXHAUST_BOOST_FACTOR
;
}
else
{
float diff = 0.0f - mEngineExhaustBoost
;
mEngineExhaustBoost += diff
* deltaTime
* EXHAUST_BOOST_FACTOR
;
}
mEngineExhaustScale = 0.9f + MathUtil.
sin(getGame
().
getTime() * EXHAUST_ANIM_SPEED
) * 0.05f + mEngineExhaustBoost
;
if (mEngineBoostTimer
> 0.0f
)
{
mEngineBoostTimer -= deltaTime
;
if (mEngineBoostTimer
< 0.0f
)
mEngineBoostTimer = 0.0f
;
}
mEngineExhaustScale +=
((mEngineBoostTimer / ENGINE_BOOST_DURATION
) * 1.8f
);
if (mMuzzleFlashTimer
> 0.0f
)
mMuzzleFlashTimer -= deltaTime
;
if (mBeamShotTimer
> 0.0f
)
mBeamShotTimer -= deltaTime
;
if (mDamageCoolDown
> 0.0f
)
mDamageCoolDown -= deltaTime
;
}
Vector2 contactPoint =
null;
@
Override
public void render
()
{
// render engine boost
if (mEngineBoostTimer
> 0.0f
)
{
mEngineBoostInstance.
transform.
x = mShipInstance.
transform.
x;
mEngineBoostInstance.
transform.
y = mShipInstance.
transform.
y -
1;
mEngineBoostInstance.
transform.
w = MUZZLEFLASH_SIZE
* (1 + mEngineBoostTimer / ENGINE_BOOST_DURATION
);
mEngineBoostInstance.
transform.
h = MUZZLEFLASH_SIZE
* (1 + 0.5f
*mEngineBoostTimer / ENGINE_BOOST_DURATION
);
mEngineBoostInstance.
transform.
pivotX = mEngineBoostInstance.
transform.
w;
mEngineBoostInstance.
transform.
pivotY = mEngineBoostInstance.
transform.
h/
2;
mEngineBoostInstance.
transform.
mirrorX =
true;
mEngineBoostInstance.
alpha =
(mEngineBoostTimer / ENGINE_BOOST_DURATION
);
mEngineBoostInstance.
render();
}
// render engine exhaust
mEngineExhaust.
getSpriteTransform().
x = mShipInstance.
transform.
x - EXHAUST_WIDTH/
2;
mEngineExhaust.
getSpriteTransform().
y = mShipInstance.
transform.
y -
2;
mEngineExhaust.
getSpriteTransform().
w = EXHAUST_WIDTH
* mEngineExhaustScale
;
mEngineExhaust.
getSpriteTransform().
h = EXHAUST_HEIGHT
;
mEngineExhaust.
getSpriteTransform().
pivotX = mEngineExhaust.
getSpriteTransform().
w;
mEngineExhaust.
getSpriteTransform().
pivotY = mEngineExhaust.
getSpriteTransform().
h/
2;
mEngineExhaust.
render();
// render ship
mShipInstance.
render();
// render muzzle flash
if (mMuzzleFlashTimer
> 0.0f
)
{
mMuzzleFlashInstance.
transform.
x = mShipInstance.
transform.
x + SHIP_WIDTH/
2;
mMuzzleFlashInstance.
transform.
y = mShipInstance.
transform.
y;
mMuzzleFlashInstance.
transform.
w = MUZZLEFLASH_SIZE
;
mMuzzleFlashInstance.
transform.
h = MUZZLEFLASH_SIZE
;
mMuzzleFlashInstance.
transform.
pivotX = mMuzzleFlashInstance.
transform.
w/
3 + 1.0f
;
mMuzzleFlashInstance.
transform.
pivotY = mMuzzleFlashInstance.
transform.
h/
2;
mMuzzleFlashInstance.
transform.
mirrorX =
false;
mMuzzleFlashInstance.
alpha = mMuzzleFlashTimer/MUZZLEFLASH_DURATION
;
mMuzzleFlashInstance.
render();
}
/*
mShipCollider.renderDebug(getGraphics());
if (contactPoint != null)
RenderUtil.drawEllipse(getGraphics(), contactPoint.x-2, contactPoint.y-2, contactPoint.x+2, contactPoint.y+2, new Vector4(1, 0.5f, 0.5f, 1));*/
}
public void moveBy
(float x,
float y,
float deltaTime
)
{
mLastMove.
x = x
* deltaTime
;
mLastMove.
y = y
* deltaTime
;
mShipShape.
transform.
set(mShipInstance.
transform);
//CollisionInfo result = getGameLogic().getCollisionWorld().collideWithResponsePassiveColliders(CollisionWorld.FILTER_LEVEL_ELEMENTS, mShipShape, new Vector2(mLastMoveX, mLastMoveY));
//if (result.isColliding)
if (getGameLogic
().
getCollisionWorld().
checkCollisionSat(CollisionWorld.
FILTER_LEVEL_ELEMENTS, mShipShape, mLastMove, mCollisionResult
))
{
mLastMove.
x += mCollisionResult.
penetrationVector.
x;
mLastMove.
y += mCollisionResult.
penetrationVector.
y;
contactPoint = mCollisionResult.
contactPoint;
}
else
contactPoint =
null;
//result.reset();
//result = getGameLogic().getCollisionWorld().collideWithResponsePassiveColliders(CollisionWorld.FILTER_ENEMIES, mShipShape, new Vector2(mLastMoveX, mLastMoveY));
//if (result.isColliding)
if (getGameLogic
().
getCollisionWorld().
checkCollisionSat(CollisionWorld.
FILTER_ENEMIES, mShipShape, mLastMove, mCollisionResult
))
{
mLastMove.
x += mCollisionResult.
penetrationVector.
x/
2;
mLastMove.
y += mCollisionResult.
penetrationVector.
y/
2;
mCollisionResult.
collidingEnemyInstance.
addImpulse(-mCollisionResult.
penetrationVector.
x/
2, -mCollisionResult.
penetrationVector.
y/
2);
}
mShipInstance.
transform.
x = MathUtil.
clamp(mShipInstance.
transform.
x + mLastMove.
x, 0.0f, GameConsts.
VIRTUAL_SCREEN_WIDTH);
mShipInstance.
transform.
y = MathUtil.
clamp(mShipInstance.
transform.
y + mLastMove.
y, 0.0f, GameConsts.
VIRTUAL_SCREEN_HEIGHT);
// TODO: scale with amount of y
if (y
< -UPDOWN_THRESHOLD
)
{
mMoveDirection = MoveDirection.
UP;
//mMoveDirectionCoeffTarget = -1.0f;
mMoveDirectionCoeffTarget =
(y + UPDOWN_THRESHOLD
) * 0.01f
;
}
else if (y
> UPDOWN_THRESHOLD
)
{
mMoveDirection = MoveDirection.
DOWN;
mMoveDirectionCoeffTarget =
(y - UPDOWN_THRESHOLD
) * 0.01f
;
}
else
{
mMoveDirection = MoveDirection.
NONE;
mMoveDirectionCoeffTarget = 0.0f
;
}
}
public void resetNoUpDownMovement
()
{
mMoveDirection = MoveDirection.
NONE;
mMoveDirectionCoeffTarget = 0.0f
;
}
public void shoot
()
{
switch (getGameLogic
().
getShipParameters().
getWeaponType())
{
case PLASMA_SHOT:
shootPlasma
();
break;
case BEAM_SHOT:
shootBeamShot
();
break;
case SPREAD_SHOT:
break;
case NAPALM_SHOT:
break;
}
shootMissile
();
shootBomb
();
}
public void shootPlasma
()
{
getGameLogic
().
getPlasmaShots().
spawnShot(mShipInstance.
transform.
x + SHIP_WIDTH/
4, mShipInstance.
transform.
y);
mMuzzleFlashTimer = MUZZLEFLASH_DURATION
;
}
public void shootMissile
()
{
if (getGameLogic
().
getShipParameters().
areMissilesEnabled())
getGameLogic
().
getMissiles().
launch(mShipInstance.
transform.
x + SHIP_WIDTH/
3, mShipInstance.
transform.
y);
}
public void shootBomb
()
{
if (getGameLogic
().
getShipParameters().
areBombsEnabled())
getGameLogic
().
getBombs().
launch(mShipInstance.
transform.
x + SHIP_WIDTH/
3, mShipInstance.
transform.
y);
}
public void shootBeamShot
()
{
if (mBeamShotTimer
<= 0.0f
)
{
getGameLogic
().
getBeamShots().
spawnShot(mShipInstance.
transform.
x + SHIP_WIDTH/
2, mShipInstance.
transform.
y);
mBeamShotTimer = BEAMSHOT_COOLDOWN_TIME
;
}
}
public void boostEngine
()
{
// boost for speed up powerup
mEngineBoostTimer = ENGINE_BOOST_DURATION
;
//mEngineBoostSfx.play();
}
// Getters/Setters==================================================================================
public float getPositionX
() { return mShipInstance.
transform.
x; }
public float getPositionY
() { return mShipInstance.
transform.
y; }
}