1 module main; 2 3 import std.stdio; 4 import std.conv; 5 import std.random; 6 import Engine.Material; 7 import Engine.UI.all; 8 import std.math; 9 import std.variant; 10 import Engine.math; 11 import Engine.all; 12 import Engine.CStorage; 13 import dbox; 14 15 Shader shader; 16 Camera camera; 17 Texture ballTexture; 18 19 import std.parallelism; 20 import std.datetime; 21 import Engine.util; 22 23 class Physics : System { 24 25 public static b2World* world; 26 27 override void start() { 28 // Define the gravity vector. 29 b2Vec2 gravity = b2Vec2(0.0f, -20.0f); 30 31 // Construct a world object, which will hold and simulate the rigid bodies. 32 Physics.world = new b2World(gravity); 33 34 35 b2BodyDef groundBodyDef; 36 groundBodyDef.position.Set(0.0f, -10.0f); 37 38 // Call the body factory which allocates memory for the ground body 39 // from a pool and creates the ground box shape (also from a pool). 40 // The body is also added to the world. 41 b2Body* groundBody = world.CreateBody(&groundBodyDef); 42 43 // Define the ground box shape. 44 b2PolygonShape groundBox = new b2PolygonShape; 45 46 // The extents are the half-widths of the box. 47 groundBox.SetAsBox(10000.0f, 10.0f); 48 49 // Add the ground fixture to the ground body. 50 groundBody.CreateFixture(groundBox, 0.0f); 51 } 52 53 @property override Timing timing() { 54 return cast(Timing)(Timing.Update+1); 55 } 56 57 override void process() { 58 auto bounds = camera.bounds(); 59 auto mpos = vec3(camera.MouseWorldPosition(),0); 60 auto delta = Core.DeltaTime; 61 auto components = ComponentStorage.components!(Rigidbody)(); 62 63 StopWatch timer; 64 timer.start(); 65 66 float32 timeStep = 1.0f / 60.0f; 67 int32 velocityIterations = 6; 68 int32 positionIterations = 2; 69 70 world.Step(timeStep, velocityIterations, positionIterations); 71 72 foreach (c; components) { 73 auto pos = c.Body.GetPosition(); 74 c.transform.position = vec3(pos.x, pos.y, 0); 75 } 76 timer.stop(); 77 if (timer.peek.msecs > 10) { 78 //writeln("slowdown ", timer.peek.msecs); 79 } 80 } 81 82 override void onEntityEnter(Entity e) { 83 84 } 85 override void onEntityLeave(Entity e) { 86 87 } 88 } 89 90 class Rigidbody { 91 mixin ComponentBase; 92 93 b2BodyDef bodyDef; 94 b2Body* Body; 95 96 void Awake() { 97 // Define the ground body. 98 bodyDef.type = b2_dynamicBody; 99 bodyDef.position.Set(this.transform.position.x, this.transform.position.y); 100 101 // Call the body factory which allocates memory for the ground body 102 // from a pool and creates the ground box shape (also from a pool). 103 // The body is also added to the world. 104 Body = Physics.world.CreateBody(&bodyDef); 105 106 b2CircleShape shape = new b2CircleShape(); 107 shape.m_radius = (this.transform.scale.x + this.transform.scale.y) / 4f; 108 109 // Define the dynamic body fixture. 110 b2FixtureDef fixtureDef; 111 fixtureDef.shape = shape; 112 113 // Set the box density to be non-zero, so it will be dynamic. 114 fixtureDef.density = 1.0f; 115 116 // Override the default friction. 117 fixtureDef.friction = 0.3f; 118 119 fixtureDef.restitution = 0.5f; 120 121 // Add the shape to the body. 122 Body.CreateFixture(&fixtureDef); 123 124 } 125 } 126 127 struct InputHandle { 128 mixin ComponentBase; 129 130 131 void Start() { 132 writeln("InputHandler started"); 133 } 134 135 void Update() { 136 if (Input.MouseScroll().y > 0) { 137 Core.camera.size += 3*Core.DeltaTime; 138 Core.camera.UpdateResolution(); 139 } 140 if (Input.MouseScroll().y < 0) { 141 Core.camera.size -= 3*Core.DeltaTime; 142 Core.camera.UpdateResolution(); 143 } 144 if (Input.KeyDown(Key.A)) { 145 Core.camera.transform.rotation.y = Core.camera.transform.rotation.y - Core.DeltaTime; 146 } 147 if (Input.KeyDown(Key.S)) { 148 Core.camera.transform.rotation.y = Core.camera.transform.rotation.y - Core.DeltaTime; 149 } 150 if (Input.KeyDown(Key.MOUSE_BUTTON_1)) { 151 { 152 auto mpos = vec3(Core.camera.MouseWorldPosition(),0); 153 for (int i=0;i<5;i++) { 154 auto ship = new Entity(); 155 ship.AddComponent!(Sprite)(ballTexture); 156 ship.AddComponent(new Rigidbody()); 157 ship.transform.rotation = vec3(0,0,0); 158 ship.transform.position = mpos + vec3(-5+i/2,-5+i/2,0) ; 159 ship.transform.scale = vec3(10, 10, 1); 160 Core.AddEntity(ship); 161 } 162 } 163 } 164 } 165 } 166 167 168 class HTest { 169 int b; 170 } 171 172 class Test : HTest { 173 mixin ComponentBase; 174 175 public void Hello() { 176 writeln("Hello"); 177 } 178 179 public int Hello(int b) { 180 writeln("Hello int ",b); 181 this.b = b; 182 return 0; 183 } 184 } 185 186 struct TestA { 187 int a; 188 189 public void Foo() { 190 writeln("Foo"); 191 } 192 } 193 194 195 bool tests() { 196 197 void testComponent(Tp, Args...)(Args args) { 198 alias T = baseType!Tp; 199 Entity e = new Entity(false); 200 auto hTest = e.AddComponent!T(args); 201 assert(e.GetComponent!T() == hTest); 202 assert(e.RemoveComponents!T()); 203 assert(e.GetComponent!T() is null); 204 e.AddComponent(new Component(hTest)); 205 assert(e.GetComponent!T() == hTest); 206 assert(e.RemoveComponents!T()); 207 assert(e.GetComponent!T() is null); 208 e.Destory(); 209 } 210 211 testComponent!HTest(); 212 testComponent!TestA(); 213 testComponent!Test(); 214 testComponent!(HTest*)(); 215 testComponent!(TestA*)(); 216 testComponent!(Test*)(); 217 218 return true; 219 } 220 221 void main(string[] args) { 222 try { 223 assert(tests()); 224 run(); 225 } 226 catch (Exception e) { 227 writeln(e.msg); 228 scanf("\n"); 229 } 230 } 231 232 void run() { 233 Core.Start(); 234 235 Font t = new Font("./public/arial.ttf\0", 32, Font.ASCII); 236 ballTexture = new Texture("./public/sprite.png\0"); 237 //ballTexture.SetFiltering(GL_LINEAR,GL_LINEAR); 238 239 Core.AddSystem(new Physics()); 240 241 auto mmouse = new Entity(); 242 //mmouse.AddComponent!(Sprite)(ballTexture); 243 mmouse.transform.scale = vec3(100, 100, 1); 244 245 auto gravityBall = new Entity(); 246 gravityBall.AddComponent!(Sprite)(ballTexture); 247 gravityBall.AddComponent!(Rigidbody)(); 248 gravityBall.transform.scale = vec3(15, 15, 1); 249 250 251 float entities = 1000; 252 float m = sqrt(entities/(Core.width*Core.height)); 253 for (int x=0;x<Core.width*m;x++) { 254 for (int y=0;y<Core.height*m;y++) { 255 auto gball = gravityBall.Clone(); 256 gball.name = to!string(x); 257 gball.transform.position = vec3(x/m + cast(float)(y&20),y/m,0); 258 Core.AddEntity(gball); 259 } 260 } 261 262 263 264 for (int i=0;i<10;i++) { 265 auto e2 = new Entity(); 266 e2.transform.scale.x = 32; 267 e2.transform.scale.y = 32; 268 e2.AddComponent!Rigidbody(); 269 e2.transform.position = vec3(((i%100)*10)%Core.width,(i*25)%Core.height,0); 270 e2.AddComponent!Label(t,to!string(i)); 271 Core.AddEntity(e2); 272 } 273 274 auto cam = new Entity(); 275 camera = cam.AddComponent!Camera(); 276 cam.AddComponent!InputHandle(); 277 Core.AddEntity(cam); 278 Core.camera = cam.GetComponent!Camera(); 279 280 cam.transform.position = vec3(Core.width/2,+Core.height/2,0); 281 282 auto e3 = new Entity(); 283 e3.transform.scale.x = 32; 284 e3.transform.scale.y = 32; 285 e3.transform.position = vec3(100,Core.height-50,0); 286 auto fps = e3.AddComponent!Label(t,"FPS"); 287 Core.AddEntity(e3); 288 289 290 291 StartCoroutine( { 292 float time = 0; 293 int frames = 0; 294 while (true) { 295 time += Core.DeltaTime; 296 frames++; 297 if (time >= 1) { 298 fps.SetText("FPS: " ~ to!string(frames) ~ " Entities:" ~ to!string(Core.EntitiesCount) ); 299 writeln(to!string(frames)); 300 time -= 1; 301 frames = 0; 302 } 303 auto camRect = Core.camera.bounds(); 304 fps.entity.transform.position = vec3((camRect.max.x+camRect.min.x) / 2, camRect.max.y - 50*Core.camera.size,0); 305 fps.entity.transform.scale = vec3(1,1,1) * Core.camera.size * 34; 306 mmouse.transform.position = vec3(Core.camera.MouseWorldPosition(),0); 307 308 Coroutine.yield(); 309 } 310 }); 311 /* 312 StartCoroutine( { 313 auto sprite = mmouse.GetComponent!Sprite(); 314 auto dTexture = new DynamicTexture(sprite.material.texture); 315 float t = 0; 316 while (true) { 317 if (sprite.color.r > 1) 318 sprite.color.r = 0; 319 320 alias Vector!(ubyte,4) color; 321 322 dTexture.Update!(color)((pixels){ 323 for (int i=0;i<pixels.length;i++) { 324 pixels[i].r = cast(ubyte)(i + t); 325 pixels[i].g = cast(ubyte)(i + t); 326 pixels[i].b = 0xff; 327 pixels[i].a = 0xff; 328 } 329 }); 330 t += Core.DeltaTime*1000; 331 //sprite.color.r += 0.1; 332 Coroutine.yield(); 333 } 334 }); 335 */ 336 337 Core.Run(); 338 }