1 module birdo;
2 
3 import collider;
4 import collidable;
5 import dsfml.graphics;
6 import resourcemanager;
7 import std.math : fmod;
8 import helpers : asSeconds;
9 
10 import std.datetime;
11 import std.datetime.stopwatch : StopWatch;
12 
13 static this() {
14   assert(resource_manager.register!Texture("assets/birdo1.png", "birdo1", make_collider));
15   assert(resource_manager.register!Texture("assets/birdo2.png", "birdo2", make_collider));
16 }
17 
18 private float toFloat(const Birdo.Level level) {
19   final switch(level) {
20     case Birdo.Level.Low:  return 40;
21     case Birdo.Level.Mid:  return 68;
22     case Birdo.Level.High: return 130;
23   }
24 }
25 
26 /// Holds the state of that prehitoric birdo
27 class Birdo : Drawable, Collidable {
28   /// Represents birdo's altitude
29   enum Level {
30     Low, Mid, High
31   }
32 
33   private immutable wing_flaprate = .5;
34   private StopWatch sw;
35   private float horizontal_offset;
36   private Level level;
37 
38   /// Height of the window
39   float window_height;
40 
41   private string texname() const {
42     immutable tex_choice = sw.peek.asSeconds.fmod(wing_flaprate) > wing_flaprate / 2;
43     return tex_choice ? "birdo1" : "birdo2";
44   }
45 
46   /// Returns the texture of the birdo
47   const(Texture) texture() const {
48     return resource_manager.get!Texture(texname);
49   }
50 
51   /// Returns position of the birdo
52   Vector2f position() const {
53     return Vector2f(horizontal_offset, window_height - level.toFloat);
54   }
55 
56   /// Constructs a birdo from horizontal offset and level
57   this(const float _horizontal_offset, const Level _level) {
58     horizontal_offset = _horizontal_offset;
59     level = _level;
60     sw.start();
61   }
62 
63   /// Moves the birdo to the left by f px
64   void move(const float f) {
65     horizontal_offset -= f;
66   }
67 
68   /// Randomizes Birdo.Level
69   static Birdo.Level random_level() {
70     import std.random : uniform;
71     final switch(uniform!uint % 3) {
72       case 0: return Birdo.Level.Low;
73       case 1: return Birdo.Level.Mid;
74       case 2: return Birdo.Level.High;
75     }
76   }
77 
78   override void draw(RenderTarget window, RenderStates states) const {
79     auto sprite = new Sprite(texture);
80     sprite.position(position);
81     window.draw(sprite, states);
82     window.draw(collider);
83   }
84 
85   override Collider collider() const {
86     return resource_manager.get!Collider(texname).translate(position);
87   }
88 }