objects.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #pragma once
  2. #include <vector>
  3. #include "vec2.h"
  4. #include <gui/canvas.h> // for Canvas*
  5. #define DEF_BALL_RADIUS 20
  6. #define DEF_BUMPER_RADIUS 40
  7. #define DEF_BUMPER_BOUNCE 1.0f
  8. #define DEF_FLIPPER_SIZE 120
  9. #define DEF_RAIL_BOUNCE 0.9f
  10. #define DEF_TURBO_RADIUS 20
  11. #define DEF_TURBO_BOOST 5
  12. #define ARC_TANGENT_RESTITUTION 1.0f
  13. #define ARC_NORMAL_RESTITUTION 0.8f
  14. // A dynamic, moveable object with acceleration
  15. class Object {
  16. public:
  17. Object(const Vec2& p_, float r_);
  18. virtual ~Object() = default;
  19. // Verlet data
  20. Vec2 p; // position
  21. Vec2 prev_p; // previous position
  22. Vec2 a;
  23. float r;
  24. bool physical; // is this a real object that can be hit?
  25. float bounce; // < 1 dampens, > 1 adds power
  26. bool fixed; // should this move?
  27. int score; // incremental score for hitting this
  28. void update(float dt); // updates position
  29. inline void accelerate(const Vec2& da) {
  30. a += da;
  31. }
  32. inline void add_velocity(const Vec2& v, float dt) {
  33. prev_p -= v * dt;
  34. }
  35. virtual void draw(Canvas* canvas) = 0;
  36. };
  37. class Ball : public Object {
  38. public:
  39. Ball(const Vec2& p_ = Vec2(), float r_ = DEF_BALL_RADIUS)
  40. : Object(p_, r_) {
  41. }
  42. void draw(Canvas* canvas);
  43. };
  44. class Flipper {
  45. public:
  46. enum Side {
  47. LEFT,
  48. RIGHT
  49. };
  50. Flipper(const Vec2& p_, Side side, size_t size_ = DEF_FLIPPER_SIZE);
  51. void draw(Canvas* canvas);
  52. void update(float dt); // updates position to new position
  53. bool collide(Ball& ball);
  54. Vec2 get_tip() const;
  55. Vec2 p;
  56. Side side;
  57. size_t size;
  58. float r;
  59. float rest_angle;
  60. float max_rotation;
  61. float sign;
  62. float omega; // angular velocity
  63. float rotation;
  64. float current_omega;
  65. bool powered; // is this flipper being activated? i.e. is keypad pressed?
  66. int score;
  67. void (*notification)(void* app);
  68. };
  69. // A static object that never moves and can be any shape
  70. class FixedObject {
  71. public:
  72. FixedObject()
  73. : bounce(1.0f)
  74. , physical(true)
  75. , hidden(false)
  76. , score(0)
  77. , notification(nullptr) {
  78. }
  79. virtual ~FixedObject() = default;
  80. float bounce;
  81. bool physical; // can be hit
  82. bool hidden; // do not draw
  83. int score;
  84. void (*notification)(void* app);
  85. virtual void draw(Canvas* canvas) = 0;
  86. virtual bool collide(Ball& ball) = 0;
  87. virtual void reset_animation() {};
  88. virtual void step_animation() {};
  89. };
  90. class Polygon : public FixedObject {
  91. public:
  92. Polygon()
  93. : FixedObject() {};
  94. std::vector<Vec2> points;
  95. std::vector<Vec2> normals;
  96. void draw(Canvas* canvas);
  97. bool collide(Ball& ball);
  98. void add_point(const Vec2& np) {
  99. points.push_back(np);
  100. }
  101. void finalize();
  102. };
  103. class Portal : public FixedObject {
  104. public:
  105. Portal(const Vec2& a1_, const Vec2& a2_, const Vec2& b1_, const Vec2& b2_)
  106. : FixedObject()
  107. , a1(a1_)
  108. , a2(a2_)
  109. , b1(b1_)
  110. , b2(b2_) {
  111. score = 200;
  112. }
  113. Vec2 a1, a2; // portal 'a'
  114. Vec2 b1, b2; // portal 'b'
  115. Vec2 na, nb; // normals
  116. Vec2 au, bu; // unit vectors
  117. float amag, bmag; // length of portals
  118. bool bidirectional{true}; // TODO: ehhh?
  119. Vec2 enter_p; // where we entered portal
  120. size_t decay{0}; // used for animation
  121. void draw(Canvas* canvas);
  122. bool collide(Ball& ball);
  123. void reset_animation();
  124. void step_animation();
  125. void finalize();
  126. };
  127. class Arc : public FixedObject {
  128. public:
  129. enum Surface {
  130. OUTSIDE,
  131. INSIDE,
  132. BOTH
  133. };
  134. Arc(const Vec2& p_,
  135. float r_,
  136. float s_ = 0,
  137. float e_ = (float)M_PI * 2,
  138. Surface surf_ = OUTSIDE);
  139. Vec2 p;
  140. float r;
  141. float start;
  142. float end;
  143. Surface surface;
  144. void draw(Canvas* canvas);
  145. bool collide(Ball& ball);
  146. };
  147. class Bumper : public Arc {
  148. public:
  149. Bumper(const Vec2& p_, float r_);
  150. size_t decay;
  151. void draw(Canvas* canvas);
  152. void reset_animation();
  153. void step_animation();
  154. };
  155. class Plunger : public Object {
  156. public:
  157. Plunger(const Vec2& p_);
  158. void draw(Canvas* canvas);
  159. int size; // how tall is it
  160. int compression; // how much is it pulled back?
  161. };
  162. // Simply displays a letter after a rollover
  163. class Rollover : public FixedObject {
  164. public:
  165. Rollover(const Vec2& p_, char c_)
  166. : FixedObject()
  167. , p(p_) {
  168. c[0] = c_;
  169. c[1] = '\0';
  170. score = 400;
  171. }
  172. Vec2 p;
  173. char c[2];
  174. bool activated{false};
  175. void draw(Canvas* canvas);
  176. bool collide(Ball& ball);
  177. };
  178. class Turbo : public FixedObject {
  179. public:
  180. Turbo(const Vec2& p_, float angle_, float boost_, float radius_)
  181. : FixedObject()
  182. , p(p_)
  183. , angle(angle_)
  184. , boost(boost_)
  185. , r(radius_) {
  186. // Our boost direction
  187. dir = Vec2(cosf(angle), -sinf(angle));
  188. // define the points of the chevrons at the 0 angle
  189. chevron_1[0] = Vec2(p.x, p.y - r);
  190. chevron_1[1] = Vec2(p.x + r, p.y);
  191. chevron_1[2] = Vec2(p.x, p.y + r);
  192. chevron_2[0] = Vec2(p.x - r, p.y - r);
  193. chevron_2[1] = Vec2(p.x, p.y);
  194. chevron_2[2] = Vec2(p.x - r, p.y + r);
  195. // rotate the chevrons to the correct angle
  196. for(size_t i = 0; i < 3; i++) {
  197. Vec2& v = chevron_1[i];
  198. Vec2 d = v - p;
  199. v.x = p.x + d.x * cosf(angle) - d.y * sinf(angle);
  200. v.y = p.y + d.x * -sinf(angle) + d.y * -cosf(angle);
  201. }
  202. for(size_t i = 0; i < 3; i++) {
  203. Vec2& v = chevron_2[i];
  204. Vec2 d = v - p;
  205. v.x = p.x + d.x * cosf(angle) - d.y * sinf(angle);
  206. v.y = p.y + d.x * -sinf(angle) + d.y * -cosf(angle);
  207. }
  208. }
  209. Vec2 p;
  210. float angle;
  211. float boost;
  212. float r;
  213. Vec2 dir; // unit normal of turbo direction
  214. Vec2 chevron_1[3];
  215. Vec2 chevron_2[3];
  216. void draw(Canvas* canvas);
  217. bool collide(Ball& ball);
  218. };
  219. // Visual item only - chase of dots in one direction
  220. // AXIS-ALIGNED!
  221. class Chaser : public Polygon {
  222. public:
  223. enum Style {
  224. SIMPLE,
  225. SLASH
  226. };
  227. Chaser(const Vec2& p1, const Vec2& p2, size_t gap_ = 8, size_t speed_ = 3, Style style_ = SIMPLE)
  228. : Polygon()
  229. , tick(0)
  230. , offset(0)
  231. , gap(gap_)
  232. , speed(speed_)
  233. , style(style_) {
  234. physical = false;
  235. points.push_back(p1);
  236. points.push_back(p2);
  237. }
  238. size_t tick;
  239. size_t offset;
  240. size_t gap;
  241. size_t speed;
  242. Style style;
  243. void draw(Canvas* canvas);
  244. void step_animation();
  245. };
  246. // class IconImage : public Object {
  247. // Vec2 v;
  248. // };