A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Body.cc 2.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include "Body.h"
  2. #include <math.h>
  3. #include <array>
  4. #include <algorithm>
  5. #include "WorldPlane.h"
  6. #include "Win.h"
  7. namespace Swan {
  8. static float epsilon = 0.0001;
  9. void Body::friction(Vec2 coef) {
  10. force_ += -vel_ * coef;
  11. }
  12. void Body::gravity(Vec2 g) {
  13. force_ += g * mass_;
  14. }
  15. void Body::collideX(WorldPlane &plane) {
  16. auto bounds = getBounds();
  17. bool collided = false;
  18. for (int y = (int)floor(bounds.top() + epsilon); y <= (int)floor(bounds.bottom() - epsilon); ++y) {
  19. int lx = (int)floor(bounds.left() + epsilon);
  20. Tile &left = plane.getTile({ lx, y });
  21. if (left.is_solid_) {
  22. bounds.pos.x = (float)lx + 1.0;
  23. collided = true;
  24. break;
  25. }
  26. int rx = (int)floor(bounds.right() - epsilon);
  27. Tile &right = plane.getTile({ rx, y });
  28. if (right.is_solid_) {
  29. bounds.pos.x = (float)rx - bounds.size.x;
  30. collided = true;
  31. break;
  32. }
  33. }
  34. if (collided) {
  35. pos_.x = bounds.pos.x;
  36. vel_.x *= -bounciness_;
  37. if (abs(vel_.x) < mushyness_)
  38. vel_.x = 0;
  39. }
  40. }
  41. void Body::collideY(WorldPlane &plane) {
  42. auto bounds = getBounds();
  43. bool collided = false;
  44. on_ground_ = false;
  45. for (int x = (int)floor(bounds.left() + epsilon); x <= (int)floor(bounds.right() - epsilon); ++x) {
  46. int by = (int)floor(bounds.bottom() - epsilon);
  47. Tile &bottom = plane.getTile({ x, by });
  48. if (bottom.is_solid_) {
  49. bounds.pos.y = (float)by - bounds.size.y;
  50. collided = true;
  51. on_ground_ = true;
  52. break;
  53. }
  54. int ty = (int)floor(bounds.top() + epsilon);
  55. Tile &top = plane.getTile({ x, ty });
  56. if (top.is_solid_) {
  57. bounds.pos.y = (float)ty + 1.0;
  58. collided = true;
  59. break;
  60. }
  61. }
  62. if (collided) {
  63. pos_.y = bounds.pos.y;
  64. vel_.y *= -bounciness_;
  65. if (abs(vel_.y) < mushyness_)
  66. vel_.y = 0;
  67. }
  68. }
  69. void Body::outline(Win &win) {
  70. win.drawRect(pos_, size_);
  71. }
  72. void Body::update(WorldPlane &plane, float dt) {
  73. vel_ += (force_ / mass_) * dt;
  74. force_ = { 0, 0 };
  75. pos_.x += vel_.x * dt;
  76. collideX(plane);
  77. pos_.y += vel_.y * dt;
  78. collideY(plane);
  79. }
  80. void Body::updateWithoutCollision(float dt) {
  81. vel_ += (force_ / mass_) * dt;
  82. pos_ += vel_ * dt;
  83. force_ = { 0, 0 };
  84. }
  85. }