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 }