1 module player; 2 3 import std.math; 4 import std.datetime; 5 import std.datetime.stopwatch : StopWatch; 6 7 import helpers : asSeconds; 8 import resourcemanager; 9 import dsfml.graphics; 10 import collidable; 11 import collider; 12 13 static this() { 14 assert(resource_manager.register!Texture("assets/dino_crouch1.png", "crouch1", make_collider)); 15 assert(resource_manager.register!Texture("assets/dino_crouch2.png", "crouch2", make_collider)); 16 assert(resource_manager.register!Texture("assets/dino_jump.png", "jump", make_collider)); 17 assert(resource_manager.register!Texture("assets/dino1.png", "step1", make_collider)); 18 assert(resource_manager.register!Texture("assets/dino2.png", "step2", make_collider)); 19 assert(resource_manager.register!Texture("assets/dead.png", "dead", make_collider)); 20 } 21 22 /// Class representing the dinosaur 23 class Player : Drawable, Collidable { 24 private StopWatch delta_time_clock; 25 private StopWatch leg_swap_clock; 26 private float total_displacement = 0; 27 private float delta_seconds = 0; 28 private bool crouch; 29 private bool leg; 30 31 /// Dead Player has a different texture 32 bool dead; 33 34 /// Distance from the left side of the window at which a player stays 35 static immutable float horizontal_offset = 60; 36 37 /// Size of the standing player 38 static immutable Vector2f size_normal = Vector2f(40, 43); 39 /// Size of the crouching player 40 static immutable Vector2f size_crouching = Vector2f(55, 26); 41 42 /// Initial vertical speed immediately after jumping 43 static immutable float initial_jump_speed = 750; 44 /// Gravitational acceleration 45 static immutable float gravity_acc = 3000; 46 47 /// Height of the window in which player resides 48 float window_height; 49 50 /// Actual downards acceleration 51 float gravity() const { return gravity_acc * (Keyboard.isKeyPressed(Keyboard.Key.Down) ? 3 : 1); } 52 53 /// Distance that the player has covered in the LAST FRAME 54 float displacement() const { return dead ? 0 : delta_seconds * speed; } 55 56 /// Returns the total displacement 57 float displacement_tot() const { return total_displacement; } 58 59 /// Speed at which the player moves to the right 60 float speed = 450; 61 /// Distance from the ground 62 float height = 0; 63 /// Vertical velocity, positive means up 64 float vert_velocity = 0; 65 66 private string texture_name() const { 67 if(dead) { 68 return "dead"; 69 } 70 if(height > 0) { 71 return "jump"; 72 } 73 if(crouch) { 74 return leg ? "crouch1" : "crouch2"; 75 } 76 77 return leg ? "step1" : "step2"; 78 } 79 80 /// Default constructor 81 this() { 82 delta_time_clock.start(); 83 leg_swap_clock.start(); 84 } 85 86 /// Effective size 87 Vector2f size() const { 88 return (crouch && !dead) ? size_crouching : size_normal; 89 } 90 91 /// Current texture 92 const(Texture) texture() const { 93 return resource_manager.get!Texture(texture_name); 94 } 95 96 /// Position of the player 97 Vector2f position() const { 98 return Vector2f(horizontal_offset, window_height - size.y - height); 99 } 100 101 /// Attempts to jump 102 bool jump() { 103 if(height == 0) { 104 vert_velocity = initial_jump_speed; 105 crouch = false; 106 return true; 107 } 108 return false; 109 } 110 111 /// Applies gravitational acceleration, moves the player etc. 112 void update() { 113 crouch = Keyboard.isKeyPressed(Keyboard.Key.Down) && height == 0; 114 115 delta_seconds = delta_time_clock.peek.asSeconds; 116 delta_time_clock.reset(); 117 118 if(!dead) { 119 vert_velocity -= delta_seconds * gravity; 120 height += delta_seconds * vert_velocity; 121 speed += delta_seconds / 100 * (1500 - speed); 122 123 if(height < 0) { 124 height = 0; 125 vert_velocity = 0; 126 } 127 if(leg_swap_clock.peek.asSeconds * sqrt(speed / 450) > 0.1f) { 128 leg = !leg; 129 leg_swap_clock.reset(); 130 } 131 } 132 133 total_displacement += displacement; 134 } 135 136 /* Override methods from Drawable and Collidable */ 137 override void draw(RenderTarget target, RenderStates states) const { 138 auto rt = new RectangleShape; 139 rt.position(position); 140 rt.size(size); 141 rt.fillColor(Color.White); 142 rt.setTexture(texture); 143 144 target.draw(rt, states); 145 146 target.draw(collider); 147 } 148 149 override Collider collider() const { 150 return resource_manager.get!Collider(texture_name).translate(position); 151 } 152 }