Subversion Repositories AndroidProjects

Rev

Rev 6 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 chris 1
package com.gebauz.pingK.entities;
2
 
7 chris 3
import java.util.Vector;
4 chris 4
 
2 chris 5
import com.gebauz.pingK.GameMain;
4 chris 6
import com.gebauz.pingK.R;
7
import com.gebauz.pingK.util.Vector2D;
8
import com.gebauz.pingK.util.MathUtil;
2 chris 9
 
4 chris 10
import android.graphics.Bitmap;
11
import android.graphics.BitmapFactory;
2 chris 12
import android.graphics.Canvas;
7 chris 13
import android.graphics.Color;
4 chris 14
import android.graphics.Matrix;
15
import android.graphics.Paint;
2 chris 16
 
17
public class Ball extends BaseEntity {
18
 
4 chris 19
        public static final int DIRECTION_RANDOM = 0;
20
        public static final int DIRECTION_UP = 1;
21
        public static final int DIRECTION_DOWN = 2;
22
 
23
        public static final float BALL_INITIAL_SPEED = 300.0f;
24
        public static final float HIT_ZONE_DEVIATION = 0.40f;
25
        public static final float BALL_STEEPEST_ANGLE_REFLECT_FROM_BOARD = 1.0f;
6 chris 26
        public static final float BALL_STEEPEST_ANGLE_HIT_PADDLE = 1.0f;
4 chris 27
        public static final float TOP_SPIN_INTENSITY = 0.18f;
28
        public static final float BALL_MAXIMUM_ANGULAR_SPEED = 500.0f;
29
 
30
        public static final float PLAYFIELD_BORDER = 8.0f;
7 chris 31
        public static final float PADDLE_HIT_OFFSET = 0.0f;
4 chris 32
 
33
        Bitmap mBall;
34
 
35
        Vector2D position = new Vector2D();
36
        Vector2D lastPosition = new Vector2D();
6 chris 37
        int lastPaddleTouched = -1;
4 chris 38
        float size;    
39
 
40
        float speed;
41
        float rotation;
42
        float angularVelocity;
43
 
7 chris 44
        public static final int TRAIL_LENGTH = 15;
45
        Vector<Vector2D> mTrail = new Vector<Vector2D>();
46
 
2 chris 47
        public Ball(GameMain gameMain) {
48
                super(gameMain);
7 chris 49
        }      
2 chris 50
 
51
        @Override
52
        public void init() {
4 chris 53
                mBall = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
2 chris 54
 
4 chris 55
                size = mBall.getWidth();
56
 
57
                reset(DIRECTION_RANDOM);
2 chris 58
        }
59
 
4 chris 60
        public void reset(int direction) {
7 chris 61
                resetTrail();
62
 
4 chris 63
                position.x = mGameMain.getWidth() / 2.0f;
64
                position.y = mGameMain.getHeight() / 2.0f;
65
 
66
                speed = BALL_INITIAL_SPEED;
67
                if (direction == DIRECTION_UP) {
68
                        rotation = 0.0f;
69
 
70
                } else if (direction == DIRECTION_DOWN) {
71
                        rotation = 180.0f;
72
                } else {
73
                        if (Math.random() > 0.5)
74
                                rotation = 0.0f;
75
                        else
76
                                rotation = 180.0f;
77
                }
78
 
79
                angularVelocity = 0.0f;
6 chris 80
                lastPaddleTouched = -1;
4 chris 81
        }
82
 
2 chris 83
        @Override
84
        public void destroy() {
85
 
86
        }
87
 
88
        @Override
89
        public void update(float deltaTime) {
4 chris 90
                // move forward, calculating collisions with other entities
2 chris 91
 
4 chris 92
                lastPosition.x = position.x;
93
                lastPosition.y = position.y;
94
 
95
            processAngularVelocity(deltaTime);
96
            moveForward(deltaTime);
97
            //collectPowerUps;
98
            //reflectFromCrystals;
99
            reflectFromBoard(deltaTime);
100
            reflectFromEntities(deltaTime);
101
            //updateBallSparks;
102
 
103
            //updateTrail
104
            checkPlayerGainsScore();
2 chris 105
        }
106
 
4 chris 107
        public void checkPlayerGainsScore() {
108
                if (position.y < PLAYFIELD_BORDER) {
6 chris 109
                        // reached top -> bottom player scores                  
110
                        mGameMain.playerGainsScore(Paddle.PADDLE_BOTTOM, lastPaddleTouched);
4 chris 111
                        return;
112
                }
113
                if (position.y > (mGameMain.getHeight() - PLAYFIELD_BORDER)) {
6 chris 114
                        // reached bottom -> top player scores
115
                        mGameMain.playerGainsScore(Paddle.PADDLE_TOP, lastPaddleTouched);
4 chris 116
                        return;
117
                }                      
118
        }
119
 
120
        public void processAngularVelocity(float deltaTime) {
121
                rotation += angularVelocity * deltaTime;
122
        }
123
 
124
        public void moveForward(float deltaTime) {
125
                Vector2D move = new Vector2D();
126
                move.x = (float)Math.sin(Math.toRadians(rotation));
127
                move.y = (float)Math.cos(Math.toRadians(rotation));
128
 
129
                move.setLength(speed * deltaTime);
130
 
131
                position.addVector(move);
7 chris 132
 
133
                Vector2D newPos = new Vector2D(position.x, position.y);
134
                mTrail.add(newPos);
135
                while (mTrail.size() > TRAIL_LENGTH)
136
                        mTrail.remove(0);                      
4 chris 137
        }
138
 
139
        public void reflectFromBoard(float deltaTime) {
140
                float impactDirection = -1;
141
 
142
                // left bounce
143
                if (position.x < PLAYFIELD_BORDER) {
144
                        reflectAlongNormal(90.0f);
145
                        impactDirection = 0.0f;
146
                        clampToAngle(BALL_STEEPEST_ANGLE_REFLECT_FROM_BOARD);   // clamp to steepest angle from board
6 chris 147
                        mGameMain.playSound(R.raw.wallimpact);
7 chris 148
                        mGameMain.getWallImpactEffect().spawnInstance(PLAYFIELD_BORDER, position.y, 90.0f);
4 chris 149
                }
150
 
151
                // right bounce
152
                if (position.x > (mGameMain.getWidth() - PLAYFIELD_BORDER)) {
153
                        reflectAlongNormal(270.0f);
154
                        impactDirection = 180.0f;
155
                        clampToAngle(BALL_STEEPEST_ANGLE_REFLECT_FROM_BOARD);   // clamp to steepest angle from board
6 chris 156
                        mGameMain.playSound(R.raw.wallimpact);
7 chris 157
                        mGameMain.getWallImpactEffect().spawnInstance(mGameMain.getWidth() - PLAYFIELD_BORDER, position.y, 270.0f);
4 chris 158
                }
159
 
160
                position.x = MathUtil.clampToRange(position.x, 0, mGameMain.getWidth());
5 chris 161
 
162
                // if (impactdirection >- 1) then generateImpact(settings.pos,impactdirection,SX_EIMPACT_MODE_WALL);
4 chris 163
        }
164
 
165
        public void reflectFromEntities(float deltaTime) {
166
                // entities in this case are the paddles
167
                Paddle[] paddles = mGameMain.getPaddles();
168
                reflectFromPaddle(paddles[Paddle.PADDLE_TOP]);
169
                reflectFromPaddle(paddles[Paddle.PADDLE_BOTTOM]);
170
        }
171
 
172
        public void reflectFromPaddle(Paddle paddle) {
173
                // if hit
174
                if (Math.abs(position.x - paddle.position.x) < (paddle.getWidth()/2.0f)) {
175
                        float paddleY = paddle.position.y;
176
                        if (paddleY < (mGameMain.getHeight() / 2.0f)) {
177
                                paddleY -= PADDLE_HIT_OFFSET;
178
                                if ((position.y <= paddleY) && (lastPosition.y > paddleY)) {
179
                                        ballHitsPaddle(paddle);
6 chris 180
                                        lastPaddleTouched = paddle.getMode();
181
                                        mGameMain.playSound(R.raw.paddleimpact);
4 chris 182
                                }
183
                        } else {
184
                                paddleY += PADDLE_HIT_OFFSET;
185
                                if ((position.y >= paddleY) && (lastPosition.y < paddleY)) {
186
                                        ballHitsPaddle(paddle);
6 chris 187
                                        lastPaddleTouched = paddle.getMode();
188
                                        mGameMain.playSound(R.raw.paddleimpact);
4 chris 189
                                }
190
                        }
191
                }
192
        }
193
 
194
        public void ballHitsPaddle(Paddle paddle) {
7 chris 195
 
196
                paddle.startImpactEffect();
197
 
4 chris 198
                float newY = position.y;
199
                float xDifference = (position.x - paddle.position.x) * HIT_ZONE_DEVIATION;
200
 
201
                // TODO: concave handling
202
                float direction = 0.0f;
203
                float paddleDirection = 0.0f;
204
                int invertPlayer2Paddle = 0;
205
 
206
                if (paddle.getMode() == Paddle.PADDLE_TOP) {
207
                        paddleDirection = 0.0f;
208
                        //direction = 90.0f - xDifference;
209
                        direction = xDifference;
210
                        newY += 6;
211
                        invertPlayer2Paddle = 1;
212
                } else {
213
                        paddleDirection = 180.0f;
214
                        //direction = 270.0f + xDifference;
215
                        direction = 180.0f + xDifference;
216
                        newY -= 6;
217
                        invertPlayer2Paddle = -1;
218
                }
219
 
220
                // todo: belong to player
221
                position.y = newY;
222
                reflectAlongNormal(direction);
5 chris 223
 
224
                // todo: generate impact                
225
                // generateImpact(paddle.settings.pos,paddledirection, SX_EIMPACT_MODE_PADDLE);
226
 
4 chris 227
                float angularSpeed = paddle.getMovementSpeed() * TOP_SPIN_INTENSITY * invertPlayer2Paddle;
228
                setAngularVelocity(angularVelocity + angularSpeed);
229
                clampToAngle(BALL_STEEPEST_ANGLE_HIT_PADDLE);
230
        }
231
 
232
        public void reflectAlongNormal(float rot) {
233
                rotation += 180.0f;
234
                rotation = MathUtil.stayInDegrees0to360(rotation);
235
 
236
                float difference = rot - rotation;
237
 
238
                rotation = rot + difference;
239
                rotation = MathUtil.stayInDegrees0to360(rotation);
240
 
241
                if (MathUtil.turnDegrees(rotation, rot) >= 90.0f) {
242
                        rotation = (float)(2*Math.PI) - rotation;
243
                        rotation = MathUtil.stayInDegrees0to360(rotation);
244
                }              
245
        }
246
 
247
        public void clampToAngle(float steepestAngle) {
248
                rotation = MathUtil.stayInDegrees0to360(rotation);
249
                if (steepestAngle <= 0)
250
                        return;
251
 
252
                if (rotation < steepestAngle)
253
                        rotation = steepestAngle;
254
                if (rotation > (360.0f - steepestAngle))
255
                        rotation = 360.0f - steepestAngle;
256
                if ((rotation > (180.0f - steepestAngle)) && (rotation <= 180.0f))
257
                        rotation = 180.0f - steepestAngle;
258
                if ((rotation < 180.0f + steepestAngle) && (rotation >= 180.0f))
259
                        rotation = 180.0f + steepestAngle;
260
        }
261
 
2 chris 262
        @Override
263
        public void render(Canvas canvas) {
4 chris 264
                Paint paint = new Paint();
2 chris 265
 
4 chris 266
                Matrix matrix = new Matrix();
267
                matrix.setTranslate(position.x - mBall.getWidth()/2, position.y - mBall.getHeight()/2);
268
 
269
                canvas.drawBitmap(mBall, matrix, paint);
7 chris 270
 
271
                renderTrail(canvas);
2 chris 272
        }
4 chris 273
 
7 chris 274
        public void renderTrail(Canvas canvas) {
275
                Paint paint = new Paint();
276
                paint.setStrokeWidth(10.0f);
277
 
278
                for (int i = 0; i < mTrail.size()-1; i++) {
279
                        int alpha = (int)(((float)i / (float)mTrail.size()) * 128.0f);
280
                        paint.setColor(Color.argb(alpha, 255, 0, 153));
281
                        Vector2D pt1 = mTrail.get(i);
282
                        Vector2D pt2 = mTrail.get(i+1);
283
                        canvas.drawLine(pt1.x, pt1.y, pt2.x, pt2.y, paint);
284
                }
285
        }
286
 
4 chris 287
        public void setAngularVelocity(float angularSpeed) {
288
                angularVelocity = MathUtil.clampToRange(angularSpeed, -BALL_MAXIMUM_ANGULAR_SPEED, BALL_MAXIMUM_ANGULAR_SPEED);        
289
        }
7 chris 290
 
291
        public void resetTrail() {
292
                mTrail.removeAllElements();
293
        }
294
 
295
        public Vector2D getPosition() {
296
                return position;
297
        }
2 chris 298
 
299
}