1 /// contains the simple box object class 2 module ysge.objects.simpleBox; 3 4 import ysge.project; 5 6 /// contains physics info 7 struct Physics { 8 Vec2!int velocity; 9 bool drag; 10 bool gravityOn; 11 Vec2!int gravity; 12 } 13 14 /// box object with AABB collision 15 class SimpleBox : GameObject { 16 SDL_Rect box; 17 bool physicsOn; 18 Physics physics; 19 RenderInfo render; 20 21 /// initialises with a box and a colour image 22 this(SDL_Rect pbox, SDL_Color colour) { 23 box = pbox; 24 render.type = RenderType.Colour; 25 render.value = RenderValue(colour); 26 } 27 28 /// initialises with a box and a texture 29 this(SDL_Rect pbox, Texture texture) { 30 box = pbox; 31 render.type = RenderType.Texture; 32 render.value = RenderValue(texture); 33 } 34 35 /// makes the object render as a coloured box 36 void SetRenderColour(SDL_Color colour) { 37 render.type = RenderType.Colour; 38 render.value = RenderValue(colour); 39 } 40 41 /// makes the object render as a texture 42 void SetRenderTexture(Texture texture) { 43 render.type = RenderType.Texture; 44 render.value = RenderValue(texture); 45 } 46 47 /// updates the object (physics etc) 48 override void Update(Project parent) { 49 if (physicsOn) { 50 int old; 51 52 old = box.x; 53 box.x += physics.velocity.x; 54 foreach (ref object ; parent.currentScene.objects) { 55 if (object is this) { 56 continue; 57 } 58 59 if (object.CollidesWith(this)) { 60 box.x = old; 61 physics.velocity.x = 0; 62 break; 63 } 64 } 65 66 old = box.y; 67 box.y += physics.velocity.y; 68 foreach (ref object ; parent.currentScene.objects) { 69 if (object is this) { 70 continue; 71 } 72 73 if (object.CollidesWith(this)) { 74 box.y = old; 75 physics.velocity.y = 0; 76 break; 77 } 78 } 79 80 if (physics.drag) { 81 if (physics.velocity.x > 0) { 82 -- physics.velocity.x; 83 } 84 if (physics.velocity.y > 0) { 85 -- physics.velocity.y; 86 } 87 if (physics.velocity.x < 0) { 88 ++ physics.velocity.x; 89 } 90 if (physics.velocity.y < 0) { 91 ++ physics.velocity.y; 92 } 93 } 94 95 if (physics.gravityOn) { 96 physics.velocity.x += physics.gravity.x; 97 physics.velocity.y += physics.gravity.y; 98 } 99 } 100 return; 101 } 102 103 /** 104 * move the box right while checking collision 105 * returns whether it did move 106 */ 107 bool MoveRight(Scene scene, int pixels) { 108 for (int i = 0; i < pixels; ++ i) { 109 int old = box.x; 110 ++ box.x; 111 112 foreach (ref object ; scene.objects) { 113 if (object is this) { 114 continue; 115 } 116 117 if (object.CollidesWith(this)) { 118 box.x = old; 119 return false; 120 } 121 } 122 } 123 124 return true; 125 } 126 127 /** 128 * move the box left while checking collision 129 * returns whether it did move 130 */ 131 bool MoveLeft(Scene scene, int pixels) { 132 for (int i = 0; i < pixels; ++ i) { 133 int old = box.x; 134 +--box.x; 135 136 foreach (ref object ; scene.objects) { 137 if (object is this) { 138 continue; 139 } 140 141 if (object.CollidesWith(this)) { 142 box.x = old; 143 return false; 144 } 145 } 146 } 147 148 return true; 149 } 150 151 /** 152 * move the box up while checking collision 153 * returns whether it did move 154 */ 155 bool MoveUp(Scene scene, int pixels) { 156 for (int i = 0; i < pixels; ++ i) { 157 int old = box.y; 158 -- box.y; 159 160 foreach (ref object ; scene.objects) { 161 if (object is this) { 162 continue; 163 } 164 165 if (object.CollidesWith(this)) { 166 box.y = old; 167 return false; 168 } 169 } 170 } 171 172 return true; 173 } 174 175 /** 176 * move the box down while checking collision 177 * returns whether it did move 178 */ 179 bool MoveDown(Scene scene, int pixels) { 180 for (int i = 0; i < pixels; ++ i) { 181 int old = box.y; 182 ++ box.y; 183 184 foreach (ref object ; scene.objects) { 185 if (object is this) { 186 continue; 187 } 188 189 if (object.CollidesWith(this)) { 190 box.y = old; 191 return false; 192 } 193 } 194 } 195 196 return true; 197 } 198 199 /// uses AABB to check if it collides with another box 200 override bool CollidesWith(SimpleBox other) { 201 return ( 202 (box.x < other.box.x + other.box.w) && 203 (box.x + box.w > other.box.x) && 204 (box.y < other.box.y + other.box.h) && 205 (box.y + box.h > other.box.y) 206 ); 207 } 208 209 /** 210 * renders the object 211 * should not be called by user 212 */ 213 override void Render(Project parent) { 214 SDL_Rect screenBox = box; 215 screenBox.x -= parent.currentScene.camera.x; 216 screenBox.y -= parent.currentScene.camera.y; 217 218 switch (render.type) { 219 case RenderType.Colour: { 220 SDL_SetRenderDrawColor( 221 parent.renderer, 222 render.value.colour.r, 223 render.value.colour.g, 224 render.value.colour.b, 225 render.value.colour.a 226 ); 227 SDL_RenderFillRect(parent.renderer, &screenBox); 228 break; 229 } 230 case RenderType.Texture: { 231 SDL_Rect* src; 232 233 if (render.props.doCrop) { 234 src = new SDL_Rect(); 235 *src = render.props.crop; 236 } 237 238 SDL_RenderCopy( 239 parent.renderer, render.value.texture.texture, src, 240 &screenBox 241 ); 242 break; 243 } 244 default: assert(0); 245 } 246 } 247 }