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.pingk.game.GameConsts;
import com.gebauz.pingk.game.GameLogic;
public class Paddle
extends Entity implements IReflectable
{
public static final int PLAYER_1 =
0;
public static final int PLAYER_2 =
1;
private int mPlayerIndex = -
1;
private Sprite mPaddleSprite
;
private boolean mIsAI =
true;
private float mAITimeOut = 0.0f
;
private float mAIRandom = 0.0f
;
private float mAIRandomTimer = 0.0f
;
private float mTargetPositionY = GameConsts.
VIRTUAL_SCREEN_HEIGHT / 2.0f
;
private float mLastDeltaTime = 0.0f
;
private float mLastPositionY = mTargetPositionY
;
public Paddle
(GameLogic gameLogic,
int playerIndex
)
{
super(gameLogic
);
mPlayerIndex = playerIndex
;
gameLogic.
addReflectable(this);
}
@
Override
public void init
()
{
float x =
0;
float y =
0;
float angle =
0;
if (mPlayerIndex == PLAYER_1
)
{
x = GameConsts.
PADDLE_DISTANCE_FROM_EDGE_X;
angle = 180.0f
;
}
else
{
x = GameConsts.
VIRTUAL_SCREEN_WIDTH - GameConsts.
PADDLE_DISTANCE_FROM_EDGE_X;
}
y = getGameLogic
().
getPlayField().
getVirtualHeight() / 2.0f
;
mTargetPositionY = y
;
mLastPositionY = mTargetPositionY
;
mAITimeOut = 0.0f
;
// init sprite
mPaddleSprite =
new Sprite
(getGameLogic
().
getGraphics(),
new Texture
(Gdx.
files.
internal("data/textures/paddle.png")));
mPaddleSprite.
x = x
;
mPaddleSprite.
y = y
;
mPaddleSprite.
angle = angle
;
mPaddleSprite.
centerPivot();
}
@
Override
public void exit
()
{
if (mPaddleSprite
!=
null)
{
mPaddleSprite.
dispose();
mPaddleSprite =
null;
}
}
@
Override
public void update
(float deltaTime
)
{
mLastPositionY = mPaddleSprite.
y;
mLastDeltaTime = deltaTime
;
mAITimeOut += deltaTime
;
mAIRandomTimer += deltaTime
;
float virtualPlayfieldHeight = getGameLogic
().
getPlayField().
getVirtualHeight();
// update positions
/* if (mPlayerIndex == PLAYER_1)
{
Finger finger = MultitouchInput.getInstance().getTouchPointInside(0, 0, GameConsts.VIRTUAL_SCREEN_WIDTH / 2.0f, mGameLogic.getVirtualPlayFieldHeight());
if (finger != null)
{
mTargetPositionY = finger.y;
mIsAI = false;
mAITimeOut = 0.0f;
}
}
else
{
Finger finger = MultitouchInput.getInstance().getTouchPointInside(GameConsts.VIRTUAL_SCREEN_WIDTH / 2.0f, 0, GameConsts.VIRTUAL_SCREEN_WIDTH, mGameLogic.getVirtualPlayFieldHeight());
if (finger != null)
{
mTargetPositionY = finger.y;
mIsAI = false;
mAITimeOut = 0.0f;
}
}*/
if ((!mIsAI
) && (mAITimeOut
> GameConsts.
PADDLE_AI_TIMEOUT))
{
mIsAI =
true;
}
if (mIsAI
)
{
if (mAIRandomTimer
> GameConsts.
PADDLE_AI_RANDOM_TIMER)
{
mAIRandomTimer = 0.0f
;
mAIRandom = getGameLogic
().
getGame().
getRandomizer().
nextFloat();
}
// try to reach ball, but only react when ball is inside own territory
float ballX = getGameLogic
().
getBall().
getX();
if ( ((mPlayerIndex == PLAYER_1
) && (ballX
< (GameConsts.
VIRTUAL_SCREEN_WIDTH/1.5f
))) ||
((mPlayerIndex == PLAYER_2
) && (ballX
> (GameConsts.
VIRTUAL_SCREEN_WIDTH -
(GameConsts.
VIRTUAL_SCREEN_WIDTH/1.5f
)))) )
{
float aiTargetY = getGameLogic
().
getBall().
getY() +
(-GameConsts.
PADDLE_AI_VARIANCE +
2 * mAIRandom
* GameConsts.
PADDLE_AI_VARIANCE);
float diff = aiTargetY - mTargetPositionY
;
mTargetPositionY +=
(diff
* deltaTime
* GameConsts.
PADDLE_AI_ACCEL);
}
else
{
// slowly go to center
float centerTarget = virtualPlayfieldHeight / 2.0f +
(-GameConsts.
PADDLE_AI_VARIANCE2 +
2*mAIRandom
* GameConsts.
PADDLE_AI_VARIANCE2);
float diff = centerTarget - mTargetPositionY
;
mTargetPositionY +=
(diff
* deltaTime
* GameConsts.
PADDLE_AI_ACCEL_SLOW);
}
}
float distanceFromEdgeY = mPaddleSprite.
h / 2.0f + GameConsts.
PADDLE_DISTANCE_FROM_EDGE_Y;
if (mTargetPositionY
< distanceFromEdgeY
)
mTargetPositionY = distanceFromEdgeY
;
else if (mTargetPositionY
> (virtualPlayfieldHeight - distanceFromEdgeY
))
mTargetPositionY =
(virtualPlayfieldHeight - distanceFromEdgeY
);
if (mTargetPositionY
> mPaddleSprite.
y)
{
float diff = mTargetPositionY - mPaddleSprite.
y;
mPaddleSprite.
y +=
(diff
* deltaTime
* GameConsts.
PADDLE_INPUT_ACCEL);
if (mPaddleSprite.
y > mTargetPositionY
)
mPaddleSprite.
y = mTargetPositionY
;
}
else if (mTargetPositionY
< mPaddleSprite.
y)
{
float diff = mPaddleSprite.
y - mTargetPositionY
;
mPaddleSprite.
y -=
(diff
* deltaTime
* GameConsts.
PADDLE_INPUT_ACCEL);
if (mPaddleSprite.
y < mTargetPositionY
)
mPaddleSprite.
y = mTargetPositionY
;
}
mPaddleSprite.
update(deltaTime
);
}
@
Override
public void render
()
{
mPaddleSprite.
render();
}
@
Override
public void reflect
(Ball ball,
float deltaTime
)
{
// check collision from the front
if (Math.
abs(ball.
getY() - mPaddleSprite.
y) < ((mPaddleSprite.
h+ ball.
getHeight())/2.0f
))
{
float offset =
((mPaddleSprite.
w/2.0f
)) - GameConsts.
PADDLE_HIT_OFFSET;
float paddleX = mPaddleSprite.
x;
// if ball is within Y coordinate space of paddle, check the two positions
if (mPlayerIndex == PLAYER_1
)
{
paddleX += offset
;
if ((ball.
getX() <= paddleX
) && (ball.
getLastX() > paddleX
))
{
// paddle touched, reflect the ball
ballHitsPaddleFront
(ball, deltaTime
);
ball.
setLastPaddleTouched(mPlayerIndex
);
/* if (mGameLogic.getPowerUpEffect().isConcaveActive())
mGameLogic.getPaddleImpact().addImpact(mPaddleSprite.x + GameConsts.PADDLE_IMPACT_CONCAVE_OFFSET, mPaddleSprite.y, 0.0f);
else
mGameLogic.getPaddleImpact().addImpact(mPaddleSprite.x, mPaddleSprite.y, 180.0f);
mGameLogic.playSound(R.raw.paddleimpact);
mGameLogic.getCrystalHitCounter().resetHits();*/
return;
}
}
else if (mPlayerIndex == PLAYER_2
)
{
paddleX -= offset
;
if ((ball.
getX() >= paddleX
) && (ball.
getLastX() < paddleX
))
{
// paddle touched, reflect the ball
ballHitsPaddleFront
(ball, deltaTime
);
ball.
setLastPaddleTouched(mPlayerIndex
);
/* if (mGameLogic.getPowerUpEffect().isConcaveActive())
mGameLogic.getPaddleImpact().addImpact(mPaddleSprite.x - GameConsts.PADDLE_IMPACT_CONCAVE_OFFSET, mPaddleSprite.y, 180.0f);
else
mGameLogic.getPaddleImpact().addImpact(mPaddleSprite.x, mPaddleSprite.y, 0.0f);
mGameLogic.playSound(R.raw.paddleimpact);
mGameLogic.getCrystalHitCounter().resetHits();*/
return;
}
}
}
// check collision from below & above
if (Math.
abs(ball.
getX() - mPaddleSprite.
x) < (mPaddleSprite.
w/2.0f
))
{
float halfHeight = mPaddleSprite.
h/2.0f
;
// for sides, use simple reflection
if ((ball.
getY() >=
(mPaddleSprite.
y - halfHeight
)) && (ball.
getLastY() < (mPaddleSprite.
y - halfHeight
)))
{
// above
ball.
reflectAlongNormal(180.0f
);
ball.
clampToAngle(GameConsts.
BALL_STEEPEST_ANGLE_HIT_PADDLE_SIDE);
ball.
setLastPaddleTouched(mPlayerIndex
);
/* mGameLogic.playSound(R.raw.paddleimpact);
mGameLogic.getCrystalHitCounter().resetHits();*/
}
else if ((ball.
getY() <=
(mPaddleSprite.
y + halfHeight
)) && (ball.
getLastY() > (mPaddleSprite.
y + halfHeight
)))
{
// below
ball.
reflectAlongNormal(0.0f
);
ball.
clampToAngle(GameConsts.
BALL_STEEPEST_ANGLE_HIT_PADDLE_SIDE);
ball.
setLastPaddleTouched(mPlayerIndex
);
/* mGameLogic.playSound(R.raw.paddleimpact);
mGameLogic.getCrystalHitCounter().resetHits();*/
}
}
}
public void ballHitsPaddleFront
(Ball ball,
float deltaTime
)
{
float newX = mPaddleSprite.
x;
float yDifference =
(ball.
getY() - mPaddleSprite.
y) * GameConsts.
PADDLE_HIT_ZONE_DEVIATION;
/* if (mGameLogic.getPowerUpEffect().isConcaveActive())
yDifference = -yDifference;*/
float direction = 0.0f
;
float paddleDirection = 0.0f
;
float invertPlayer2Paddle =
0;
if (mPlayerIndex == PLAYER_1
)
{
// left
paddleDirection = 270.0f
;
direction = 90.0f - yDifference
;
newX += mPaddleSprite.
w/3.0f
;
invertPlayer2Paddle = -
1;
}
else if (mPlayerIndex == PLAYER_2
)
{
// right
paddleDirection = 90.0f
;
direction = 270.0f + yDifference
;
newX -= mPaddleSprite.
w/3.0f
;
invertPlayer2Paddle =
1;
}
ball.
setX(newX
);
ball.
reflectAlongNormal(direction
);
float angularSpeed = getMovementSpeed
() * GameConsts.
BALL_TOP_SPIN_INTENSITY * invertPlayer2Paddle
;
ball.
setAngularVelocity(ball.
getAngularVelocity() + angularSpeed
);
ball.
clampToAngle(GameConsts.
BALL_STEEPEST_ANGLE_HIT_PADDLE_FRONT);
}
public float getMovementSpeed
()
{
return (mPaddleSprite.
y - mLastPositionY
) / mLastDeltaTime
;
}
}