Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Ball/Ball.cpp@10:da5743dfb137, 2019-05-09 (annotated)
- Committer:
- kocemax
- Date:
- Thu May 09 10:53:00 2019 +0000
- Revision:
- 10:da5743dfb137
- Parent:
- 9:f720f5d87420
- Child:
- 12:b3ec47d606a5
Added test files and completed any left-overs. Ready to submit.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kocemax | 2:006a2ddfabb6 | 1 | #include "Ball.h" |
kocemax | 8:9b77eea95088 | 2 | #include "Paddle.h" |
kocemax | 8:9b77eea95088 | 3 | #include <math.h> |
kocemax | 2:006a2ddfabb6 | 4 | |
kocemax | 8:9b77eea95088 | 5 | /** Constructor */ |
kocemax | 2:006a2ddfabb6 | 6 | Ball::Ball() |
kocemax | 2:006a2ddfabb6 | 7 | { |
kocemax | 8:9b77eea95088 | 8 | reset(); /** initial parameters of ball */ |
kocemax | 2:006a2ddfabb6 | 9 | } |
kocemax | 2:006a2ddfabb6 | 10 | |
kocemax | 8:9b77eea95088 | 11 | /** Destructor - nothing happens here */ |
kocemax | 2:006a2ddfabb6 | 12 | Ball::~Ball() |
kocemax | 2:006a2ddfabb6 | 13 | { |
kocemax | 2:006a2ddfabb6 | 14 | } |
kocemax | 2:006a2ddfabb6 | 15 | |
kocemax | 8:9b77eea95088 | 16 | /** Ball screen edge detection and movement */ |
kocemax | 7:cd3cafda3dd4 | 17 | void Ball::move() |
kocemax | 7:cd3cafda3dd4 | 18 | { |
kocemax | 6:39bda45efeed | 19 | GameObject::move(); |
kocemax | 10:da5743dfb137 | 20 | |
kocemax | 10:da5743dfb137 | 21 | /** Right edge */ |
kocemax | 7:cd3cafda3dd4 | 22 | if (pos.x > WIDTH-1) { |
kocemax | 8:9b77eea95088 | 23 | velocity.x = -velocity.x; |
kocemax | 8:9b77eea95088 | 24 | pos.x = WIDTH-1; |
kocemax | 10:da5743dfb137 | 25 | } |
kocemax | 10:da5743dfb137 | 26 | /** Left edge */ |
kocemax | 10:da5743dfb137 | 27 | else if(pos.x < 1) { |
kocemax | 8:9b77eea95088 | 28 | velocity.x = -velocity.x; |
kocemax | 8:9b77eea95088 | 29 | pos.x = 1; |
kocemax | 2:006a2ddfabb6 | 30 | } |
kocemax | 10:da5743dfb137 | 31 | /** Top edge */ |
kocemax | 7:cd3cafda3dd4 | 32 | if (pos.y < 1) { |
kocemax | 8:9b77eea95088 | 33 | velocity.y = -velocity.y; |
kocemax | 8:9b77eea95088 | 34 | pos.y = 1; |
kocemax | 10:da5743dfb137 | 35 | } |
kocemax | 10:da5743dfb137 | 36 | /** Bottom edge */ |
kocemax | 10:da5743dfb137 | 37 | else if (pos.y > HEIGHT-1) { |
kocemax | 8:9b77eea95088 | 38 | velocity.y = -velocity.y; |
kocemax | 8:9b77eea95088 | 39 | pos.y = HEIGHT-1; |
kocemax | 2:006a2ddfabb6 | 40 | } |
kocemax | 3:fe856d0890ee | 41 | } |
kocemax | 3:fe856d0890ee | 42 | |
kocemax | 8:9b77eea95088 | 43 | |
kocemax | 8:9b77eea95088 | 44 | #define PI 3.14159265 |
kocemax | 8:9b77eea95088 | 45 | float Deg2Rad = PI / 180; |
kocemax | 8:9b77eea95088 | 46 | float Rad2Deg = 180 / PI; |
kocemax | 8:9b77eea95088 | 47 | |
kocemax | 8:9b77eea95088 | 48 | /** NOTE: This is how our coordinate system is setup. */ |
kocemax | 8:9b77eea95088 | 49 | /** angles go clock-wise, right is zero, up is -pi/2, down is pi/2 */ |
kocemax | 8:9b77eea95088 | 50 | /** printf("angle of down: %.02f\n", atan2(1.f, 0)); */ |
kocemax | 8:9b77eea95088 | 51 | /** printf("angle of right: %.02f\n", atan2(0.f, 1)); */ |
kocemax | 8:9b77eea95088 | 52 | /** printf("angle of up: %.02f\n", atan2(-1.f, 0)); */ |
kocemax | 8:9b77eea95088 | 53 | |
kocemax | 8:9b77eea95088 | 54 | /** Standard rotation of a vector by given degrees */ |
kocemax | 8:9b77eea95088 | 55 | /** Example of this function to play around with: https://repl.it/repls/HopefulTrimWordprocessing */ |
kocemax | 8:9b77eea95088 | 56 | void Rotate(Vector2D& v, float degrees) |
kocemax | 8:9b77eea95088 | 57 | { |
kocemax | 8:9b77eea95088 | 58 | float s = (float)sin(degrees * Deg2Rad); /** stores sin value betweem -1 and 1 */ |
kocemax | 8:9b77eea95088 | 59 | float c = (float)cos(degrees * Deg2Rad); /** stores cos value betweem -1 and 1 */ |
kocemax | 8:9b77eea95088 | 60 | |
kocemax | 8:9b77eea95088 | 61 | float tx = v.x; /** 2D Vector (tx, ty) for the velocity */ |
kocemax | 8:9b77eea95088 | 62 | float ty = v.y; |
kocemax | 8:9b77eea95088 | 63 | |
kocemax | 8:9b77eea95088 | 64 | /** Rotation: Multiply vector by rotation matrix */ |
kocemax | 8:9b77eea95088 | 65 | v.x = (c * tx) - (s * ty); |
kocemax | 8:9b77eea95088 | 66 | v.y = (s * tx) + (c * ty); |
kocemax | 8:9b77eea95088 | 67 | } |
kocemax | 8:9b77eea95088 | 68 | |
kocemax | 8:9b77eea95088 | 69 | /** Sets upper and lower boundary for angle |
kocemax | 8:9b77eea95088 | 70 | * @return clamped angle between sane boundaries |
kocemax | 8:9b77eea95088 | 71 | */ |
kocemax | 8:9b77eea95088 | 72 | float clamp(float x, float minn, float maxx) |
kocemax | 3:fe856d0890ee | 73 | { |
kocemax | 8:9b77eea95088 | 74 | return min(max(x, minn), maxx); |
kocemax | 8:9b77eea95088 | 75 | } |
kocemax | 8:9b77eea95088 | 76 | |
kocemax | 8:9b77eea95088 | 77 | |
kocemax | 8:9b77eea95088 | 78 | |
kocemax | 8:9b77eea95088 | 79 | /** Collision detection between ball and paddle */ |
kocemax | 8:9b77eea95088 | 80 | void Ball::hitPad(Paddle &paddle) |
kocemax | 8:9b77eea95088 | 81 | { |
kocemax | 8:9b77eea95088 | 82 | const Vector2D& posPad = paddle.getPos(); |
kocemax | 9:f720f5d87420 | 83 | if (pos.y >= posPad.y - 1 && (pos.x >= posPad.x && pos.x <= posPad.x + paddle.getW())) { |
kocemax | 8:9b77eea95088 | 84 | /** We hit the pad */ |
kocemax | 8:9b77eea95088 | 85 | |
kocemax | 8:9b77eea95088 | 86 | /** First: rotate about paddle's surface normal (flip upward) */ |
kocemax | 8:9b77eea95088 | 87 | velocity.y = -velocity.y; |
kocemax | 8:9b77eea95088 | 88 | |
kocemax | 8:9b77eea95088 | 89 | /** Change angle based on distance to center */ |
kocemax | 8:9b77eea95088 | 90 | float distanceSensitivity = 120; /** Add at most this many degrees */ |
kocemax | 8:9b77eea95088 | 91 | float maxDx = paddle.getW()/2; /** Maximum distance from centre */ |
kocemax | 8:9b77eea95088 | 92 | float cx = posPad.x + paddle.getW()/2.0f; /** Maximum distance from current paddle centre */ |
kocemax | 8:9b77eea95088 | 93 | float dx = pos.x - cx; /** Positive dx means right of center, 0 means at center */ |
kocemax | 8:9b77eea95088 | 94 | |
kocemax | 8:9b77eea95088 | 95 | float dangle = dx/maxDx * distanceSensitivity; /** Delta angle, meaning change in angle */ |
kocemax | 8:9b77eea95088 | 96 | float currentAngle = atan2(velocity.y, velocity.x)*Rad2Deg; /** Angle of our original outgoing velocity vector */ |
kocemax | 8:9b77eea95088 | 97 | float newAngle = currentAngle + dangle; /** The current angle + the change in the angle */ |
kocemax | 8:9b77eea95088 | 98 | |
kocemax | 8:9b77eea95088 | 99 | //printf("angle: %.02f %.02f, %.02f\n", dx, currentAngle, newAngle); |
kocemax | 8:9b77eea95088 | 100 | |
kocemax | 8:9b77eea95088 | 101 | |
kocemax | 8:9b77eea95088 | 102 | /** Always clamp angle in sane boundaries */ |
kocemax | 8:9b77eea95088 | 103 | newAngle = clamp(newAngle, -160, -20); /** Clamp to the range of an upward facing cone (NOTE: -90 degrees is up) */ |
kocemax | 8:9b77eea95088 | 104 | |
kocemax | 8:9b77eea95088 | 105 | /** Rotate the outgoing vector by the clamped dangle */ |
kocemax | 8:9b77eea95088 | 106 | dangle = newAngle - currentAngle; |
kocemax | 8:9b77eea95088 | 107 | Rotate(velocity, dangle); |
kocemax | 8:9b77eea95088 | 108 | |
kocemax | 2:006a2ddfabb6 | 109 | } |
kocemax | 2:006a2ddfabb6 | 110 | |
kocemax | 6:39bda45efeed | 111 | } |
kocemax | 6:39bda45efeed | 112 | |
kocemax | 8:9b77eea95088 | 113 | /** Randomizes the initial x-direction of the ball */ |
kocemax | 6:39bda45efeed | 114 | int Ball::randomize() |
kocemax | 4:0e01cbb95434 | 115 | { |
kocemax | 8:9b77eea95088 | 116 | AnalogIn noisy(PTB0); /** Disconnected pin so will have random noise */ |
kocemax | 8:9b77eea95088 | 117 | srand(1000000*noisy.read()); /** Read the random noise and seed */ |
kocemax | 8:9b77eea95088 | 118 | int direction = rand() % 2; /** Randomise initial direction */ |
kocemax | 8:9b77eea95088 | 119 | int movement; /** Int to store the x-direction */ |
kocemax | 7:cd3cafda3dd4 | 120 | if (direction == 0) { |
kocemax | 6:39bda45efeed | 121 | movement = -1; |
kocemax | 7:cd3cafda3dd4 | 122 | } else if (direction == 1) { |
kocemax | 6:39bda45efeed | 123 | movement = 1; |
kocemax | 6:39bda45efeed | 124 | } |
kocemax | 7:cd3cafda3dd4 | 125 | return movement; |
kocemax | 6:39bda45efeed | 126 | } |
kocemax | 6:39bda45efeed | 127 | |
kocemax | 8:9b77eea95088 | 128 | /** Resets ball's initial parameters when game is over / lost */ |
kocemax | 7:cd3cafda3dd4 | 129 | void Ball::reset() |
kocemax | 6:39bda45efeed | 130 | { |
kocemax | 8:9b77eea95088 | 131 | pos.x = WIDTH/2; /** initial position of ball on x-axis */ |
kocemax | 8:9b77eea95088 | 132 | pos.y = HEIGHT - GAP - 2; /** initial position of ball on y-axis */ |
kocemax | 8:9b77eea95088 | 133 | velocity.x = randomize(); /** initial x-velocity of ball */ |
kocemax | 8:9b77eea95088 | 134 | velocity.y = -1; /** initial y-velocity of ball */ |
kocemax | 8:9b77eea95088 | 135 | w = 1; /** width of the ball */ |
kocemax | 8:9b77eea95088 | 136 | h = 1; /** height of the ball */ |
kocemax | 2:006a2ddfabb6 | 137 | } |