objects.h 6.9 KB

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