1 module game; 2 3 import std.stdio; 4 import std.format; 5 6 import dlib.core.memory; 7 import dlib.container.array; 8 import dlib.math.vector; 9 import dlib.math.matrix; 10 import dlib.math.affine; 11 import dlib.image.color; 12 13 import derelict.opengl.gl; 14 import derelict.opengl.glu; 15 import derelict.sdl.sdl; 16 import dgl.core.application; 17 import dgl.core.interfaces; 18 import dgl.core.event; 19 import dgl.graphics.shapes; 20 import dgl.graphics.material; 21 import dgl.ui.font; 22 import dgl.ui.ftfont; 23 import dgl.ui.textline; 24 25 import dmech.world; 26 import dmech.geometry; 27 import dmech.rigidbody; 28 import dmech.shape; 29 30 import testbed.grid; 31 import testbed.physicsentity; 32 import testbed.fpcamera; 33 import testbed.character; 34 35 class TestApp: Application 36 { 37 FirstPersonCamera camera; 38 CharacterController charController; 39 40 DynamicArray!Drawable drawables; 41 Vector4f lightPosition; 42 43 Grid grid; 44 ShapeBox sBox; 45 46 Material boxMaterial; 47 48 PhysicsWorld world; 49 GeomBox gFloor; 50 GeomBox gBox; 51 GeomSphere gSphere; 52 53 RigidBody bFloor; 54 55 enum fixedTimeStep = 1.0 / 60.0; 56 57 Font font; 58 TextLine fpsText; 59 TextLine ctrlText; 60 61 bool mouseControl = true; 62 63 this() 64 { 65 super(800, 600, "dmech game demo"); 66 67 clearColor = Color4f(0.5f, 0.5f, 0.5f); 68 lightPosition = Vector4f(5, 10, 2, 1); 69 70 grid = New!Grid(); 71 72 world = New!PhysicsWorld(1000); 73 74 gFloor = New!GeomBox(Vector3f(40, 1, 40)); 75 bFloor = world.addStaticBody(Vector3f(0, -1, 0)); 76 world.addShapeComponent(bFloor, gFloor, Vector3f(0, 0, 0), 1.0f); 77 78 Vector3f boxHalfSize = Vector3f(0.75f, 0.75f, 0.75f); 79 gBox = New!GeomBox(boxHalfSize); // Physical shape 80 sBox = New!ShapeBox(boxHalfSize); // Graphical shape 81 82 Vector3f characterPos = Vector3f(0, 5, 5); 83 camera = New!FirstPersonCamera(characterPos); 84 camera.turn = -90.0f; 85 86 gSphere = New!GeomSphere(1.0f); 87 charController = New!CharacterController(world, characterPos, 1.0f, gSphere); 88 89 boxMaterial = New!Material(); 90 boxMaterial.ambientColor = Color4f(0.75f, 0.3f, 0); 91 boxMaterial.diffuseColor = Color4f(1, 0.5f, 0); 92 93 foreach(i; 0..10) 94 addBoxEntity(Vector3f(-10 + i, 2 + i * 2.1, 0), boxMaterial); 95 96 font = New!FreeTypeFont("data/fonts/droid/DroidSans.ttf", 12); 97 98 fpsText = New!TextLine(font, "FPS: 0", Vector2f(8, 8)); 99 fpsText.color = Color4f(1, 1, 1); 100 101 ctrlText = New!TextLine(font, 102 "Mouse/WASD - move; Space - jump; Enter - release mouse pointer; Esc - exit", 103 Vector2f(8, eventManager.windowHeight - font.height - 8)); 104 ctrlText.color = Color4f(1, 1, 1); 105 106 eventManager.showCursor(false); 107 } 108 109 ~this() 110 { 111 camera.free(); 112 charController.free(); 113 foreach(d; drawables.data) 114 d.free(); 115 drawables.free(); 116 grid.free(); 117 world.free(); 118 sBox.free(); 119 gFloor.free(); 120 gBox.free(); 121 gSphere.free(); 122 font.free(); 123 fpsText.free(); 124 ctrlText.free(); 125 boxMaterial.free(); 126 } 127 128 PhysicsEntity addBoxEntity(Vector3f pos, Material m) 129 { 130 auto bBox = world.addDynamicBody(pos, 0.0f); 131 auto scBox = world.addShapeComponent(bBox, gBox, Vector3f(0, 0, 0), 10.0f); 132 PhysicsEntity peBox = New!PhysicsEntity(sBox, bBox); 133 peBox.material = m; 134 addDrawable(peBox); 135 return peBox; 136 } 137 138 void addDrawable(Drawable d) 139 { 140 drawables.append(d); 141 } 142 143 void updateCamera() 144 { 145 int hWidth = eventManager.windowWidth / 2; 146 int hHeight = eventManager.windowHeight / 2; 147 float turn_m = -(hWidth - eventManager.mouseX) * 0.1f; 148 float pitch_m = (hHeight - eventManager.mouseY) * 0.1f; 149 camera.pitch += pitch_m; 150 camera.turn += turn_m; 151 float pitchLimitMax = 60.0f; 152 float pitchLimitMin = -60.0f; 153 if (camera.pitch > pitchLimitMax) 154 camera.pitch = pitchLimitMax; 155 else if (camera.pitch < pitchLimitMin) 156 camera.pitch = pitchLimitMin; 157 158 eventManager.setMouseToCenter(); 159 } 160 161 void updateCharacter() 162 { 163 Vector3f forward = camera.characterMatrix.forward; 164 Vector3f right = camera.characterMatrix.right; 165 166 if (eventManager.keyPressed['w']) charController.move(forward, -12.0f); 167 if (eventManager.keyPressed['s']) charController.move(forward, 12.0f); 168 if (eventManager.keyPressed['a']) charController.move(right, -12.0f); 169 if (eventManager.keyPressed['d']) charController.move(right, 12.0f); 170 if (eventManager.keyPressed[SDLK_SPACE]) charController.jump(1.0f); 171 172 charController.update(); 173 } 174 175 override void onKeyDown(int key) 176 { 177 super.onKeyDown(key); 178 179 if (key == SDLK_RETURN) 180 { 181 mouseControl = !mouseControl; 182 eventManager.showCursor(!mouseControl); 183 eventManager.setMouseToCenter(); 184 } 185 } 186 187 override void onMouseButtonDown(int button) 188 { 189 } 190 191 override void free() 192 { 193 Delete(this); 194 } 195 196 double time = 0.0; 197 198 override void onUpdate() 199 { 200 double dt = eventManager.deltaTime; 201 202 if (mouseControl) 203 { 204 updateCamera(); 205 } 206 207 time += dt; 208 if (time >= fixedTimeStep) 209 { 210 time -= fixedTimeStep; 211 updateCharacter(); 212 world.update(fixedTimeStep); 213 } 214 215 camera.position = charController.rbody.position; 216 217 fpsText.setText(format("FPS: %s", eventManager.fps)); 218 } 219 220 override void onRedraw() 221 { 222 double dt = eventManager.deltaTime; 223 224 float aspectRatio = cast(float)eventManager.windowWidth / cast(float)eventManager.windowHeight; 225 226 glMatrixMode(GL_PROJECTION); 227 glLoadIdentity(); 228 gluPerspective(60.0f, aspectRatio, 0.1, 1000.0); 229 glMatrixMode(GL_MODELVIEW); 230 231 glLoadIdentity(); 232 glPushMatrix(); 233 camera.bind(dt); 234 235 grid.draw(dt); 236 237 glEnable(GL_LIGHTING); 238 glEnable(GL_LIGHT0); 239 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.arrayof.ptr); 240 241 foreach(d; drawables.data) 242 d.draw(dt); 243 244 glDisable(GL_LIGHTING); 245 246 camera.unbind(); 247 glPopMatrix(); 248 249 glMatrixMode(GL_PROJECTION); 250 glLoadIdentity(); 251 glOrtho(0, eventManager.windowWidth, 0, eventManager.windowHeight, 0, 1); 252 glMatrixMode(GL_MODELVIEW); 253 254 fpsText.draw(dt); 255 ctrlText.draw(dt); 256 } 257 258 override void onResize(int width, int height) 259 { 260 super.onResize(width, height); 261 ctrlText.setPosition(8, height - font.height - 8); 262 } 263 } 264 265 void main(string[] args) 266 { 267 loadLibraries(); 268 writefln("Allocated memory at start: %s", allocatedMemory); 269 auto app = New!TestApp(); 270 app.run(); 271 Delete(app); 272 writefln("Allocated memory at end: %s", allocatedMemory); 273 }