package com.gebauz.pingK.game;
import android.util.Log;
import com.gebauz.framework.util.MathUtil;
import com.gebauz.framework.util.Sprite2D;
import com.gebauz.framework.util.Vector2;
import com.gebauz.pingK.R;
public class Ball
{
static public final int DIRECTION_LEFT =
0;
static public final int DIRECTION_RIGHT =
1;
private GameLogic mGameLogic =
null;
private Sprite2D mBallSprite
;
//private BallTrail mBallTrail;
// 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
)
{
mGameLogic = gameLogic
;
}
public void init
()
{
mBallSprite =
new Sprite2D
();
mBallSprite.
init(R.
drawable.
ball, GameConsts.
VIRTUAL_SCREEN_WIDTH/2.0f, mGameLogic.
getVirtualPlayFieldHeight()/2.0f, GameConsts.
BALL_SIZE, GameConsts.
BALL_SIZE);
reset
(DIRECTION_LEFT
);
}
public void exit
()
{
}
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 = mGameLogic.
getVirtualPlayFieldHeight() / 2.0f
;
//mBallSprite.y = mGameLogic.getVirtualPlayFieldHeight() - 10.0f;
mGameLogic.
getBallTrail().
reset();
mGameLogic.
getBallTrail().
addTrailPoint(mBallSprite.
x, mBallSprite.
y, mRotation
);
/* mRotation = 0.0f;
mBallSprite.x = GameConsts.PADDLE_DISTANCE_FROM_EDGE_X;
mBallSprite.y = 30.0f;*/
/*mBallTrail.addTrailPoint(200.0f, 200.0f, -1);
mBallTrail.addTrailPoint(250.0f, 200.0f, -1);
mBallTrail.addTrailPoint(300.0f, 200.0f, -1);
mBallTrail.addTrailPoint(250.0f, 300.0f, 0);
mBallTrail.addTrailPoint(300.0f, 300.0f, -1);*/
updateLastPosition
();
}
public void update
(float deltaTime
)
{
// store last position then move forward
speedUp
(deltaTime
);
updateLastPosition
();
processAngularVelocity
(deltaTime
);
moveForward
(deltaTime
);
// check for collisions
//collectPowerUps;
//reflectFromCrystals;
reflectFromEntities
(deltaTime
);
reflectFromBoard
(deltaTime
);
//updateBallSparks;
//updateTrail
checkPlayerGainsScore
();
mGameLogic.
getBackground().
setMonkeyRotationSpeed(mAngularVelocity
);
mBallSprite.
update(deltaTime
);
}
public void render
()
{
mBallSprite.
render();
}
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 newY = MathUtil.
clampToRange(mBallSprite.
y, GameConsts.
PLAYFIELD_BORDER_Y, mGameLogic.
getVirtualPlayFieldHeight() - 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 > (mGameLogic.
getVirtualPlayFieldHeight() - GameConsts.
PLAYFIELD_BORDER_Y) &&
(mLastPosition.
y <=
(mGameLogic.
getVirtualPlayFieldHeight() - 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
)
{
mGameLogic.
reflect(this, deltaTime
);
}
public void checkPlayerGainsScore
()
{
if (mBallSprite.
x < GameConsts.
PLAYFIELD_BORDER_X)
{
// reached top -> bottom player scores
//mGameMain.playerGainsScore(Paddle.PADDLE_BOTTOM, lastPaddleTouched);
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 bottom -> top player scores
//mGameMain.playerGainsScore(Paddle.PADDLE_TOP, lastPaddleTouched);
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 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.
clampToRange(angularSpeed, -GameConsts.
BALL_MAXIMUM_ANGULAR_SPEED, GameConsts.
BALL_MAXIMUM_ANGULAR_SPEED);
}
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
;
}
}