package com.gebauz.pingk.entities;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.Bauzoid.graphics.sprite.Sprite;
import com.gebauz.Bauzoid.math.MathUtil;
import com.gebauz.Bauzoid.math.Vector2;
import com.gebauz.pingk.game.GameConsts;
import com.gebauz.pingk.game.GameLogic;
public class Ball
extends Entity
{
static public final int DIRECTION_LEFT =
0;
static public final int DIRECTION_RIGHT =
1;
private Sprite mBallSprite =
null;
// movement parameters
private float mRotation = 0.0f
;
private float mSpeed = GameConsts.
BALL_INITIAL_SPEED;
private float mSpeedUpTimer = 0.0f
;
private float mAngularVelocity = 0.0f
;
private Vector2 mLastPosition =
new Vector2
();
private int mLastPaddleTouched = -
1;
public Ball
(GameLogic gameLogic
)
{
super(gameLogic
);
}
@
Override
public void init
()
{
mBallSprite =
new Sprite
(getGameLogic
().
getGraphics(),
new Texture
(Gdx.
files.
internal("data/textures/ball.png")));
mBallSprite.
x = GameConsts.
VIRTUAL_SCREEN_WIDTH/2.0f
;
mBallSprite.
y = getGameLogic
().
getPlayField().
getVirtualHeight()/2.0f
;
mBallSprite.
w = GameConsts.
BALL_SIZE;
mBallSprite.
h = GameConsts.
BALL_SIZE;
mBallSprite.
centerPivot();
reset
(DIRECTION_LEFT
);
}
@
Override
public void exit
()
{
}
/** Reset the ball for a new game round. */
public void reset
(int direction
)
{
mSpeed = GameConsts.
BALL_INITIAL_SPEED;
mSpeedUpTimer = 0.0f
;
mAngularVelocity = 0.0f
;
mLastPaddleTouched = -
1;
if (direction == DIRECTION_LEFT
)
{
mRotation = 270.0f
;
}
else if (direction == DIRECTION_RIGHT
)
{
mRotation = 90.0f
;
}
mBallSprite.
x = GameConsts.
VIRTUAL_SCREEN_WIDTH / 2.0f
;
mBallSprite.
y = getGameLogic
().
getPlayField().
getVirtualHeight() / 2.0f
;
//mGameLogic.getBallTrail().reset();
//mGameLogic.getBallTrail().addTrailPoint(mBallSprite.x, mBallSprite.y, mRotation);
//updateLastPosition();
}
@
Override
public void update
(float deltaTime
)
{
// store last position then move forward
speedUp
(deltaTime
);
updateLastPosition
();
processAngularVelocity
(deltaTime
);
moveForward
(deltaTime
);
// check for collisions
reflectFromEntities
(deltaTime
);
reflectFromBoard
(deltaTime
);
checkPlayerGainsScore
();
// mGameLogic.getBackground().setMonkeyRotationSpeed(mAngularVelocity);
mBallSprite.
update(deltaTime
);
}
public void speedUp
(float deltaTime
)
{
mSpeedUpTimer += deltaTime
;
if (mSpeedUpTimer
>= GameConsts.
BALL_SPEEDUP_TIMER)
{
mSpeedUpTimer = mSpeedUpTimer - GameConsts.
BALL_SPEEDUP_TIMER;
mSpeed += GameConsts.
BALL_SPEEDUP_INCREASE;
}
// decrease angular velocity
if (mAngularVelocity
> 0)
{
mAngularVelocity -=
(GameConsts.
BALL_ANGULAR_SPEED_DECREASE * deltaTime
);
if (mAngularVelocity
< 0.0f
)
{
mAngularVelocity = 0.0f
;
}
}
else if (mAngularVelocity
< 0)
{
mAngularVelocity +=
(GameConsts.
BALL_ANGULAR_SPEED_DECREASE * deltaTime
);
if (mAngularVelocity
> 0.0f
)
{
mAngularVelocity = 0.0f
;
}
}
}
public void processAngularVelocity
(float deltaTime
)
{
mRotation += mAngularVelocity
* deltaTime
;
}
public void moveForward
(float deltaTime
)
{
Vector2 move =
new Vector2
();
move.
x =
(float)Math.
sin(Math.
toRadians(mRotation
));
move.
y =
(float)Math.
cos(Math.
toRadians(mRotation
));
move.
setLength(mSpeed
* deltaTime
);
mBallSprite.
x += move.
x;
mBallSprite.
y += move.
y;
}
public void reflectFromBoard
(float deltaTime
)
{
float virtualPlayFieldHeight = getGameLogic
().
getPlayField().
getVirtualHeight();
float newY = MathUtil.
clamp(mBallSprite.
y, GameConsts.
PLAYFIELD_BORDER_Y,
getGameLogic
().
getPlayField().
getVirtualHeight() - GameConsts.
PLAYFIELD_BORDER_Y);
if ((mBallSprite.
y < GameConsts.
PLAYFIELD_BORDER_Y) && (mLastPosition.
y >= GameConsts.
PLAYFIELD_BORDER_Y))
{
// upper bounce
reflectAlongNormal
(0.0f
);
clampToAngle
(GameConsts.
BALL_STEEPEST_ANGLE_REFLECT_FROM_BOARD); // clamp to steepest angle from board
//mGameLogic.getPlayField().createImpact(mBallSprite.x, GameConsts.PLAYFIELD_BORDER_Y - GameConsts.PLAYFIELD_IMPACT_OFFSET_Y, 180.0f);
//mGameLogic.playSound(R.raw.wallimpact);
//if (mGameLogic.getPowerUpEffect().isCrystalActive())
{
//mGameLogic.getCrystals().spawnCrystal(getX(), newY + GameConsts.POWERUP_CRYSTAL_RADIUS/2.0f, new Vector2(0.0f, 1.0f));
//mGameLogic.getPowerUpEffect().deactivateCrystal();
}
}
else if (mBallSprite.
y > (virtualPlayFieldHeight - GameConsts.
PLAYFIELD_BORDER_Y) &&
(mLastPosition.
y <=
(virtualPlayFieldHeight - GameConsts.
PLAYFIELD_BORDER_Y)))
{
// lower bounce
reflectAlongNormal
(180.0f
);
clampToAngle
(GameConsts.
BALL_STEEPEST_ANGLE_REFLECT_FROM_BOARD); // clamp to steepest angle from board
//mGameLogic.getPlayField().createImpact(mBallSprite.x, (mGameLogic.getVirtualPlayFieldHeight() - GameConsts.PLAYFIELD_BORDER_Y + GameConsts.PLAYFIELD_IMPACT_OFFSET_Y), 0.0f);
//mGameLogic.playSound(R.raw.wallimpact);
//if (mGameLogic.getPowerUpEffect().isCrystalActive())
{
//mGameLogic.getCrystals().spawnCrystal(getX(), newY - GameConsts.POWERUP_CRYSTAL_RADIUS/2.0f, new Vector2(0.0f, -1.0f));
//mGameLogic.getPowerUpEffect().deactivateCrystal();
}
}
mBallSprite.
y = newY
;
}
public void reflectFromEntities
(float deltaTime
)
{
for (int i =
0; i
< getGameLogic
().
getNumReflectables(); i++
)
{
IReflectable reflectable = getGameLogic
().
getReflectable(i
);
reflectable.
reflect(this, deltaTime
);
}
}
public void checkPlayerGainsScore
()
{
if (mBallSprite.
x < GameConsts.
PLAYFIELD_BORDER_X)
{
// reached left -> left player scores
//mGameLogic.playerGainsScore(Paddle.PLAYER_2, mLastPaddleTouched);
//mGameLogic.getBallTrail().addTrailPoint(mBallSprite.x, mBallSprite.y, 270.0f);
//reset(DIRECTION_RIGHT);
return;
}
else if (mBallSprite.
x > (GameConsts.
VIRTUAL_SCREEN_WIDTH - GameConsts.
PLAYFIELD_BORDER_X))
{
// reached right -> right player scores
//mGameLogic.playerGainsScore(Paddle.PLAYER_1, mLastPaddleTouched);
//mGameLogic.getBallTrail().addTrailPoint(mBallSprite.x, mBallSprite.y, 90.0f);
//reset(DIRECTION_LEFT);
return;
}
}
public void updateLastPosition
()
{
mLastPosition.
x = mBallSprite.
x;
mLastPosition.
y = mBallSprite.
y;
}
public void clampToAngle
(float steepestAngle
)
{
mRotation = MathUtil.
stayInDegrees0to360(mRotation
);
if (steepestAngle
<=
0)
return;
if (mRotation
< steepestAngle
)
mRotation = steepestAngle
;
if (mRotation
> (360.0f - steepestAngle
))
mRotation = 360.0f - steepestAngle
;
if ((mRotation
> (180.0f - steepestAngle
)) && (mRotation
<= 180.0f
))
mRotation = 180.0f - steepestAngle
;
if ((mRotation
< 180.0f + steepestAngle
) && (mRotation
>= 180.0f
))
mRotation = 180.0f + steepestAngle
;
}
public void reflectAlongNormal
(float rot
)
{
mRotation += 180.0f
;
mRotation = MathUtil.
stayInDegrees0to360(mRotation
);
float difference = rot - mRotation
;
mRotation = rot + difference
;
mRotation = MathUtil.
stayInDegrees0to360(mRotation
);
if (MathUtil.
turnDegrees(mRotation, rot
) >= 90.0f
)
{
mRotation = 360.0f - mRotation
;
mRotation = MathUtil.
stayInDegrees0to360(mRotation
);
}
//mGameLogic.getBallTrail().addTrailPoint(getX(), getY(), rot);
}
public void setLastPaddleTouched
(int paddle
)
{
mLastPaddleTouched = paddle
;
}
@
Override
public void render
()
{
mBallSprite.
render();
}
public float getX
() { return mBallSprite.
x; }
public float getY
() { return mBallSprite.
y; }
public void setX
(float x
) { mBallSprite.
x = x
; }
public void setY
(float y
) { mBallSprite.
y = y
; }
public float getLastX
() { return mLastPosition.
x; }
public float getLastY
() { return mLastPosition.
y; }
public float getWidth
() { return mBallSprite.
w; }
public float getHeight
() { return mBallSprite.
h; }
public float getAngularVelocity
() { return mAngularVelocity
; }
public void setAngularVelocity
(float angularSpeed
)
{
mAngularVelocity = MathUtil.
clamp(angularSpeed, -GameConsts.
BALL_MAXIMUM_ANGULAR_SPEED, GameConsts.
BALL_MAXIMUM_ANGULAR_SPEED);
}
}