Subversion Repositories AndroidProjects

Rev

Rev 87 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.gebauz.pingK.game;

import java.util.Random;

import android.util.Log;

import com.gebauz.framework.util.GLUtil;
import com.gebauz.framework.util.Sprite2D;
import com.gebauz.pingK.MultitouchInput;
import com.gebauz.pingK.R;
import com.gebauz.pingK.MultitouchInput.Finger;

public class Paddle implements IReflectable
{      
        public static final int PLAYER_1 = 0;
        public static final int PLAYER_2 = 1;
       
        private GameLogic mGameLogic = null;
        private int mPlayerIndex = -1;
        private boolean mIsAI = true;
        private float mAITimeOut = 0.0f;
        private float mAIRandom = 0.0f;
        private float mAIRandomTimer = 0.0f;
       
        private Sprite2D mPaddleSprite;
       
        private float mTargetPositionY = GameConsts.VIRTUAL_SCREEN_HEIGHT / 2.0f;
        private float mLastDeltaTime = 0.0f;
        private float mLastPositionY = mTargetPositionY;
       
        public Paddle(GameLogic gameLogic, int playerIndex)
        {
                mGameLogic = gameLogic;        
                mPlayerIndex = playerIndex;
               
                mGameLogic.addReflectable(this);
        }
       
        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 = mGameLogic.getVirtualPlayFieldHeight() / 2.0f;
               
                //y = mGameLogic.getVirtualPlayFieldHeight() - 15.0f;
               
                mTargetPositionY = y;
                mLastPositionY = mTargetPositionY;
               
                mPaddleSprite = new Sprite2D();
                mPaddleSprite.init(R.drawable.paddle, x, y, GameConsts.PADDLE_WIDTH, GameConsts.PADDLE_HEIGHT);
                mPaddleSprite.angle = angle;
               
                mAITimeOut = 0.0f;
        }
       
        public void exit()
        {
                mPaddleSprite = null;
        }
       
        public void update(float deltaTime)
        {
                mLastPositionY = mPaddleSprite.y;
                mLastDeltaTime = deltaTime;
                mAITimeOut += deltaTime;
                mAIRandomTimer += deltaTime;
               
                // 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 = mGameLogic.getRandomizer().nextFloat();
                        }
                       
                        // try to reach ball, but only react when ball is inside own territory
                        float ballX = mGameLogic.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 = mGameLogic.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 = mGameLogic.getVirtualPlayFieldHeight() / 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 > (mGameLogic.getVirtualPlayFieldHeight() - distanceFromEdgeY))
                        mTargetPositionY = (mGameLogic.getVirtualPlayFieldHeight() - 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);
        }
       
        public void render()
        {
                mPaddleSprite.mirrorX = mGameLogic.getPowerUpEffect().isConcaveActive();
                mPaddleSprite.render();
        }
       
        public float getMovementSpeed()
        {
                return (mPaddleSprite.y - mLastPositionY) / mLastDeltaTime;
        }
       
        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();
                               
                                // TODO: impact
                        }
                        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();

                                // TODO: impact
                        }
                }
               
               
                // TODO: clamp ball's coordinates to play field
        }
       
        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;
               
                // TODO: concave handling
                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);            
               
                /*

  if (paddle.paddle.belongtoplayer = 1) then
  begin
    paddledirection := 0;
    direction:= 90 - ydifference;
    newx := newx + 6;
    invertplayer2paddle := 1;
  end else
  begin
    paddledirection := 180;
    direction:= 270 + ydifference;
    newx := newx - 6;
    invertplayer2paddle := -1;
  end;

  ball.lasthitplayer:=paddle.paddle.belongtoplayer;
  settings.pos.x := newx;
  reflectAlongNormal(direction);

  generateImpact(paddle.settings.pos,paddledirection, SX_EIMPACT_MODE_PADDLE);

  angularspeed := paddle.getMovementSpeed * getTopSpinIntensity * invertplayer2paddle;
  setAngularVelocity(ball.angularspeed + angularspeed);
  clampToAngle(getBallSteepestAngleHitPaddle);
                 */

               
                //Log.v(GameConsts.LOG_TAG, "AngularVelocity = " + ball.getAngularVelocity() + angularSpeed);
        }

}