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.transformation; 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(null, 1000); 73 74 gFloor = New!GeomBox(world, 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(world, 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(world, 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 Delete(world); 118 sBox.free(); 119 font.free(); 120 fpsText.free(); 121 ctrlText.free(); 122 boxMaterial.free(); 123 } 124 125 PhysicsEntity addBoxEntity(Vector3f pos, Material m) 126 { 127 auto bBox = world.addDynamicBody(pos, 0.0f); 128 auto scBox = world.addShapeComponent(bBox, gBox, Vector3f(0, 0, 0), 10.0f); 129 PhysicsEntity peBox = New!PhysicsEntity(sBox, bBox); 130 peBox.material = m; 131 addDrawable(peBox); 132 return peBox; 133 } 134 135 void addDrawable(Drawable d) 136 { 137 drawables.append(d); 138 } 139 140 void updateCamera() 141 { 142 int hWidth = eventManager.windowWidth / 2; 143 int hHeight = eventManager.windowHeight / 2; 144 float turn_m = -(hWidth - eventManager.mouseX) * 0.1f; 145 float pitch_m = (hHeight - eventManager.mouseY) * 0.1f; 146 camera.pitch += pitch_m; 147 camera.turn += turn_m; 148 float pitchLimitMax = 60.0f; 149 float pitchLimitMin = -60.0f; 150 if (camera.pitch > pitchLimitMax) 151 camera.pitch = pitchLimitMax; 152 else if (camera.pitch < pitchLimitMin) 153 camera.pitch = pitchLimitMin; 154 155 eventManager.setMouseToCenter(); 156 } 157 158 void updateCharacter() 159 { 160 Vector3f forward = camera.characterMatrix.forward; 161 Vector3f right = camera.characterMatrix.right; 162 163 if (eventManager.keyPressed['w']) charController.move(forward, -12.0f); 164 if (eventManager.keyPressed['s']) charController.move(forward, 12.0f); 165 if (eventManager.keyPressed['a']) charController.move(right, -12.0f); 166 if (eventManager.keyPressed['d']) charController.move(right, 12.0f); 167 if (eventManager.keyPressed[SDLK_SPACE]) charController.jump(1.0f); 168 169 charController.update(); 170 } 171 172 override void onKeyDown(int key) 173 { 174 super.onKeyDown(key); 175 176 if (key == SDLK_RETURN) 177 { 178 mouseControl = !mouseControl; 179 eventManager.showCursor(!mouseControl); 180 eventManager.setMouseToCenter(); 181 } 182 } 183 184 override void onMouseButtonDown(int button) 185 { 186 } 187 188 override void free() 189 { 190 Delete(this); 191 } 192 193 double time = 0.0; 194 195 override void onUpdate() 196 { 197 double dt = eventManager.deltaTime; 198 199 if (mouseControl) 200 { 201 updateCamera(); 202 } 203 204 time += dt; 205 if (time >= fixedTimeStep) 206 { 207 time -= fixedTimeStep; 208 updateCharacter(); 209 world.update(fixedTimeStep); 210 } 211 212 camera.position = charController.rbody.position; 213 214 fpsText.setText(format("FPS: %s", eventManager.fps)); 215 } 216 217 override void onRedraw() 218 { 219 double dt = eventManager.deltaTime; 220 221 float aspectRatio = cast(float)eventManager.windowWidth / cast(float)eventManager.windowHeight; 222 223 glMatrixMode(GL_PROJECTION); 224 glLoadIdentity(); 225 gluPerspective(60.0f, aspectRatio, 0.1, 1000.0); 226 glMatrixMode(GL_MODELVIEW); 227 228 glLoadIdentity(); 229 glPushMatrix(); 230 camera.bind(dt); 231 232 grid.draw(dt); 233 234 glEnable(GL_LIGHTING); 235 glEnable(GL_LIGHT0); 236 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.arrayof.ptr); 237 238 foreach(d; drawables.data) 239 d.draw(dt); 240 241 glDisable(GL_LIGHTING); 242 243 camera.unbind(); 244 glPopMatrix(); 245 246 glMatrixMode(GL_PROJECTION); 247 glLoadIdentity(); 248 glOrtho(0, eventManager.windowWidth, 0, eventManager.windowHeight, 0, 1); 249 glMatrixMode(GL_MODELVIEW); 250 251 fpsText.draw(dt); 252 ctrlText.draw(dt); 253 } 254 255 override void onResize(int width, int height) 256 { 257 super.onResize(width, height); 258 ctrlText.setPosition(8, height - font.height - 8); 259 } 260 } 261 262 void main(string[] args) 263 { 264 loadLibraries(); 265 writefln("Allocated memory at start: %s", allocatedMemory); 266 auto app = New!TestApp(); 267 app.run(); 268 Delete(app); 269 writefln("Allocated memory at end: %s", allocatedMemory); 270 }