PongDocumentation is on the right hand side of this page. |
DocumentationImportant TipsHow To Skip Levels How To Get Basic Pong
InstructionsObjective Movement Trajectory FeaturesThe basic features are:
Below are extra features that have been implemented in the game. (Extra) (New Obs Func) Starting CounterBefore the game begins, a countdown timer signifies that the game is about to start. It counts
down for 3 seconds before allowing the game to start, after which point the game commences.
Note: It is was made deliberately not possible to skip this even when the player tries to
click to skip a level.
A purely observable related addition, the 'takeWhile' function was added to the Observable class. Unfortunately I later realised this was not necessary, as I was able to achieve the same result using takeUntil to unsubscribe observers once a given Observable fired. However the function can still be tested by commenting out line 1285 in pong.ts, which will unsub the AI paddle when the human player scores 1 point (you can compare to commenting out line 1286, with the same condition on a filter, here the AI paddle resumes when the human player scores another point unlike takeWhile) (Extra) LevelsEvery 5 points you score up to 20, and every 10 points you score thereafter will take you to the
next level, increasing the difficulty of the game. Difficulty is increased by adding more balls,
increasing the speed of the balls, and increasing the speed of the AI's paddle.
After reaching higher levels, more balls will be added to increase the difficulty.
AI has been improved to cater to multiple balls.
NOTE: For clarity, a cyan circle has been added around the ball that the AI is currently moving
to hit. This also shows the target changing as another ball is determined.
1. (AIpaddleX - ballX) / ballXspeed 2. (AIpaddleX - ballX + (rightEdge - ballX)*2) / ballXspeed (Extra) TrajectoryWhen the ball collides with the paddle, the ratio formula 3 below is used to calculate the amount of Y speed and X speed to give the ball based on which part of the paddle it hits. The further top and bottom of the paddle the ball hits, the wider the trajectory (more Y speed, less X speed). Conversely the closer to the middle of the paddle, the flatter the trajectory (more X speed, less or no Y speed). To prevent the balls having 1 Y speed and 0 X speed (only goes straight up and down), trajectory scaler has been capped at 80%, meaning you can have at most 80% Y speed and 20% X speed. As described, formula 4 and 5 are used to calculate Y and X speed respectively. 3. min(abs(ballY - paddleCenterY) / HalfPaddleHeight, 0.8) 4. ballYspeed * trajectory 5. ballXspeed * (1-trajectory) (Extra) Vertical CollisionUsing an 'overlapping intervals' function and treating collision on horizontal axis separate to the collision on
vertical axis, it was possible to enable collision with the top and bottom edges of the paddle, rather than just
the left and right. This was done by segmenting the paddle into smaller collision boxes. Note there are some areas
that are covered by both collision boxes. This was done to minimise the ball getting stuck, and in practice does not
negatively impact collision detection.
3. min(abs(ballY - paddleCenterY) / HalfPaddleHeight, 0.8) 4. ballYspeed * trajectory 5. ballXspeed * (1-trajectory) (Extra) Generic SVG functionsOriginally I wanted to use a circle for a ball, but then moved to a rectangle. I realised that the attributes were different for a circle than for a rectangle, for example: 'width' did not exist on a circle and 'r' did not exist on a rectangle (naturally since it does not have a radius). However this meant all physics functions could not be generalised to work with multiple shapes. There were also no "left", "right" or other derived attributes readily available. So I added a 'getGeneric' attribute getter, and generalised 'getX', 'getY', etc. functions that specified which attributes to use for which SVG element types, with an optional functional applied to the output, as well as converting it to a number. This greatly simplified the physics code. 3. min(abs(ballY - paddleCenterY) / HalfPaddleHeight, 0.8) 4. ballYspeed * trajectory 5. ballXspeed * (1-trajectory) |