Guest User

Untitled

a guest
Apr 23rd, 2019
87
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # include <Siv3D.hpp> // OpenSiv3D v0.3.2
  2.  
  3.  
  4. class Bullet : public Circle
  5. {
  6. private:
  7. Vec2 m_vel;
  8. bool m_is_friend;
  9.  
  10. public:
  11. Bullet(Vec2 pos, Vec2 vel, bool is_friend = false)
  12. : Circle(pos, 5)
  13. , m_vel(vel)
  14. , m_is_friend(is_friend)
  15. {}
  16.  
  17. bool isFriend() const { return m_is_friend; }
  18. bool isOut() const { return !intersects(Window::ClientRect().stretched(100)); }
  19. void update() { moveBy(m_vel); }
  20. void draw() const { Circle::draw(ColorF(m_is_friend ? 0.8 : 0.6)); }
  21. };
  22.  
  23.  
  24. class Item : public RectF
  25. {
  26. private:
  27. static Array<String> m_Label;
  28. int m_category;
  29.  
  30. public:
  31. Item(Vec2 pos, int category)
  32. : RectF(pos, 40.0)
  33. , m_category(Min(category, getCategoryNum()))
  34. {}
  35.  
  36. String getLabel() const { return m_Label.at(m_category); }
  37. static int getCategoryNum() { return m_Label.count() - 1; }
  38. bool isOut() const { return !RectF::intersects(Window::ClientRect().stretched(100)); }
  39. void update() { RectF::moveBy(Vec2::Down(100.0 * System::DeltaTime())); }
  40.  
  41. void draw() const
  42. {
  43. rotated(Periodic::Sine0_1(3.0s) * Math::TwoPi)
  44. .draw(HSV(220).lerp(HSV(330), (double)m_category / getCategoryNum()))
  45. .drawFrame(1.0, ColorF(0.0));
  46. FontAsset(U"item")(m_Label.at(m_category)).drawAt(center());
  47. }
  48. };
  49. Array<String> Item::m_Label({ U"HP", U"S", U"R", U"W" });
  50.  
  51.  
  52. class Shooter
  53. {
  54. protected:
  55. double m_Max_health;
  56. double m_health;
  57. Stopwatch m_cooldown;
  58.  
  59. public:
  60. Shooter(double Max_health = 100.0)
  61. : m_Max_health(Max_health)
  62. , m_health(Max_health)
  63. , m_cooldown(true)
  64. {}
  65.  
  66. bool isDead() const { return m_health <= 0.0; }
  67. void damage(double amount) { m_health = Max(0.0, m_health - amount); }
  68. void heal(double amout) { m_health = Min(m_Max_health, m_health + amout); }
  69. };
  70.  
  71.  
  72. class Player : public Triangle, public Shooter
  73. {
  74. private:
  75. double m_speed_factor;
  76. double m_reload_factor;
  77. int m_way;
  78. Font m_font;
  79.  
  80. public:
  81. Player(double health = 1000.0)
  82. : Triangle(Window::Width() / 2, Window::Height() * 4 / 5, 30.0)
  83. , Shooter(health)
  84. , m_speed_factor(1.0)
  85. , m_reload_factor(1.0)
  86. , m_way(1)
  87. , m_font(100)
  88. {}
  89.  
  90. void addSpeed(double amount = 0.3) { m_speed_factor += amount; }
  91. void addReload(double amount = 0.3) { m_reload_factor += amount; }
  92. void addWay(int amount = 1) { m_way += amount; }
  93.  
  94. Array<Bullet> GenerateBullets() const
  95. {
  96. Array<Bullet> generate;
  97. if (m_way == 1)
  98. {
  99. generate << Bullet(centroid(), Vec2::Up(5.0), true);
  100. return generate;
  101. }
  102. const double theta_base = 30_deg / Math::Pow((double)(m_way - 1), 0.8);
  103. for (int i : step(m_way))
  104. {
  105. const double theta = (i - (double)(m_way - 1) / 2) * theta_base;
  106. generate << Bullet(centroid(), Circular(5.0, theta), true);
  107. }
  108. return generate;
  109. }
  110.  
  111. bool update()
  112. {
  113. Vec2 Key_input(KeyD.pressed() - KeyA.pressed(), KeyS.pressed() - KeyW.pressed());
  114. if (Key_input.length() > 1.0) Key_input.normalize();
  115. const double speed = (KeyShift.pressed() ? 0.5 : 1.0) * m_speed_factor * 100.0 * System::DeltaTime();
  116. const Vec2 pos = centroid().movedBy(Key_input * speed);
  117. setCentroid(pos.clamped(Window::ClientRect()));
  118.  
  119. if (KeySpace.pressed() && m_cooldown.msF() > 200.0 / m_reload_factor)
  120. {
  121. m_cooldown.restart();
  122. return true;
  123. }
  124. return false;
  125. }
  126.  
  127. void drawStatus(int score) const
  128. {
  129. const int baseX = Window::Width() / 6, baseY = Window::Height() / 6;
  130. Transformer2D t0(Mat3x2::Translate(baseX, baseY));
  131. m_font(U"Score {:d}"_fmt(score)).draw(0, 0, ColorF(1.0, 0.2));
  132. Transformer2D t1(Mat3x2::Translate(0, baseY));
  133. m_font(U"Speed {:.1f}"_fmt(m_speed_factor)).draw(0, 0, ColorF(1.0, 0.2));
  134. Transformer2D t2(Mat3x2::Translate(0, baseY));
  135. m_font(U"Reload {:.1f}"_fmt(m_reload_factor)).draw(0, 0, ColorF(1.0, 0.2));
  136. Transformer2D t3(Mat3x2::Translate(0, baseY));
  137. m_font(U"Way {:d}"_fmt(m_way)).draw(0, 0, ColorF(1.0, 0.2));
  138. Transformer2D t4(Mat3x2::Translate(0, baseY));
  139. const double e = Max(0.0, m_health) / m_Max_health;
  140. const HSV color = HSV(0, 0.2).lerp(HSV(120, 0.2), e);
  141. m_font(U"HP {:.1f}%"_fmt(100.0 * e)).draw(0, 0, color);
  142. }
  143.  
  144. void draw() const
  145. {
  146. Triangle::draw(ColorF(0.5, 0.5, 1.0));
  147. }
  148. };
  149.  
  150.  
  151. class Enemy : public Circle, public Shooter
  152. {
  153. private:
  154. Vec2 m_start;
  155. Vec2 m_dest;
  156. Transition m_transition;
  157.  
  158. public:
  159. Enemy(double health = 100.0)
  160. : Circle(20)
  161. , Shooter(health)
  162. , m_transition(3.0s)
  163. {
  164. m_dest = RandomVec2(Window::Width(), Window::Height() * 0.3);
  165. m_start = m_dest + Vec2(m_dest - Window::Center());
  166. setPos(m_start);
  167. }
  168.  
  169. bool update()
  170. {
  171. m_transition.update(true);
  172. setPos(m_start.lerp(m_dest, m_transition.easeOut()));
  173.  
  174. if (m_cooldown > 2.0s)
  175. {
  176. m_cooldown.restart();
  177. return true;
  178. }
  179. return false;
  180. }
  181.  
  182. void draw() const
  183. {
  184. const double e = Max(0.0, m_health) / m_Max_health;
  185. Circle::draw(ColorF(1.0, 0.5, 0.5))
  186. .drawFrame(1.0, ColorF(0.0))
  187. .drawPie(-Math::Pi * e, Math::TwoPi * e, HSV(0).lerp(HSV(120), e));
  188. Line({ 0, 0 }, Circular(r, Math::Pi * e)).movedBy(center).draw(ColorF(0.0, EaseOutExpo(1.0 - e)));
  189. Line({ 0, 0 }, Circular(r, -Math::Pi * e)).movedBy(center).draw(ColorF(0.0, EaseOutExpo(1.0 - e)));
  190. Circle::scaled(0.7).draw(ColorF(1.0, 0.5, 0.5))
  191. .drawArc(-Math::Pi * e, Math::TwoPi * e, 1.0, 0.0, ColorF(0.0));
  192. }
  193. };
  194.  
  195.  
  196. void Main()
  197. {
  198. Window::Resize(800, 800);
  199.  
  200. Player player;
  201. int score = 0;
  202. Array<Enemy> enemies(10);
  203. Array<Bullet> bullets;
  204. Array<Item> items;
  205. FontAsset::Register(U"item", 24);
  206.  
  207. System::Sleep(5.0s);
  208.  
  209. while (System::Update())
  210. {
  211. if (player.update())
  212. bullets.append(player.GenerateBullets());
  213. if (RandomBool(2.0 * System::DeltaTime()))
  214. enemies << Enemy();
  215. for (auto it = enemies.begin(); it != enemies.end();)
  216. {
  217. if (it->isDead())
  218. {
  219. score++;
  220. if (RandomBool()) items << Item(it->center, Random(Item::getCategoryNum()));
  221. it = enemies.erase(it);
  222. continue;
  223. }
  224. if (it->update())
  225. bullets << Bullet(it->center, Circular(3.0, Random(160_deg, 200_deg)));
  226. it++;
  227. }
  228. for (auto it = bullets.begin(); it != bullets.end();)
  229. {
  230. it->update();
  231. bool is_hit = false;
  232. if (it->isFriend())
  233. {
  234. Optional<int> enemy_index;
  235. enemies.each_index([&](int i, auto & e) { if (it->intersects(e)) enemy_index = i; });
  236. if (enemy_index)
  237. {
  238. enemies.at(enemy_index.value()).damage(Random(20.0, 60.0));
  239. is_hit = true;
  240. }
  241. }
  242. else {
  243. if (it->intersects(player))
  244. {
  245. player.damage(Random(8.0, 12.0));
  246. is_hit = true;
  247. }
  248. }
  249. if (it->isOut() || is_hit)
  250. it = bullets.erase(it);
  251. else
  252. it++;
  253. }
  254. for (auto it = items.begin(); it != items.end();)
  255. {
  256. it->update();
  257. if (it->intersects(player))
  258. {
  259. if (it->getLabel() == U"HP") player.heal(50.0);
  260. if (it->getLabel() == U"S") player.addSpeed();
  261. if (it->getLabel() == U"R") player.addReload();
  262. if (it->getLabel() == U"W") player.addWay();
  263. it = items.erase(it);
  264. }
  265. else if (it->isOut())
  266. it = items.erase(it);
  267. else
  268. it++;
  269. }
  270.  
  271. player.drawStatus(score);
  272. bullets.each([](const auto & b) { b.draw(); });
  273. items.each([](const auto & i) { i.draw(); });
  274. enemies.each([](const auto & e) { e.draw(); });
  275. player.draw();
  276. }
  277. }
RAW Paste Data