objects.h 6.3 KB

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