diff --git a/demos/assets/textures/atlas.png b/demos/assets/textures/atlas.png index eea925e..b84c3fa 100644 Binary files a/demos/assets/textures/atlas.png and b/demos/assets/textures/atlas.png differ diff --git a/demos/source/app.d b/demos/source/app.d index 2310413..1dbf9f4 100644 --- a/demos/source/app.d +++ b/demos/source/app.d @@ -43,6 +43,7 @@ struct Mouse struct DemoCallbacks { + void function() register; void function() initialize; void function() deinitialize; bool function() loop; @@ -130,6 +131,7 @@ struct Launcher /*launcher.manager.getSystem(CountSystem.system_id).enable(); launcher.manager.getSystem(CleanSystem.system_id).enable();//*/ + if(callbacks.register)callbacks.register(); if(callbacks.initialize)callbacks.initialize(); demo = callbacks; /*this.loop = loop; @@ -240,8 +242,8 @@ struct Launcher if(location) { position += randomCircularSample() * half_size; - if(position.y < 16)position.y = 16; - else if(position.y > 299)position.y = 299; + //if(position.y < 16)position.y = 16; + //else if(position.y > 299)position.y = 299; *location = position; } manager.addEntity(tmpl); @@ -875,8 +877,6 @@ void mainLoop(void* arg) launcher.renderer.present(); draw_time = launcher.getTime() - draw_time; - //import std.stdio; - //printf("Scalling: %f",launcher.scalling); if(launcher.tool_show)launcher.tool_circle.draw(&launcher.renderer, (launcher.mouse.position*launcher.scalling)-launcher.render_position, cast(float)launcher.tool_size, launcher.renderer.view_size.y*6*launcher.scalling); __gshared float plot_time = 0; @@ -1105,11 +1105,13 @@ int app_main(int argc, char** argv) import demos.simple; import demos.space_invaders; import demos.particles; + import demos.brick_breaker; // launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,SpaceInvaders.tips); // launcher.switchDemo(&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips); // launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,Simple.tips); // launcher.switchDemo(getParticlesDemo()); - launcher.switchDemo(getSimpleDemo()); + // launcher.switchDemo(getSimpleDemo()); + launcher.switchDemo(getBrickBreakerDemo()); } int key_num; diff --git a/demos/source/demos/brick_breaker.d b/demos/source/demos/brick_breaker.d index 1af22b9..ec4571f 100644 --- a/demos/source/demos/brick_breaker.d +++ b/demos/source/demos/brick_breaker.d @@ -18,9 +18,12 @@ import ecs_utils.utils; import game_core.basic; import game_core.rendering; +import game_core.collision; extern(C): +private enum float px = 1.0/512.0; + /*####################################################################################################################### ------------------------------------------------ Components ------------------------------------------------------------------ #######################################################################################################################*/ @@ -51,40 +54,60 @@ struct CBall ubyte radius; } -struct CVelocity -{ - mixin ECS.Component; +// struct CVelocityFactor +// { +// mixin ECS.Component; - alias value this; +// alias value this; - vec2 value; -} +// vec2 value = vec2(1); +// } + +// struct CVelocity +// { +// mixin ECS.Component; + +// alias value this; + +// vec2 value = vec2(0); +// } /*####################################################################################################################### ------------------------------------------------ Systems ------------------------------------------------------------------ #######################################################################################################################*/ -struct MoveSystem -{ - mixin ECS.System!64; +// struct MoveSystem +// { +// mixin ECS.System!64; - struct EntitiesData - { - uint length; - CLocation[] location; - @readonly CVelocity[] velocity; - } +// struct EntitiesData +// { +// uint length; +// CLocation[] location; +// @readonly CVelocity[] velocity; +// @optional @readonly CVelocityFactor[] vel_factor; +// } - void onUpdate(EntitiesData data) - { - foreach(i; 0..data.length) - { - data.location[i] += data.velocity[i] * launcher.delta_time; - } - } -} +// void onUpdate(EntitiesData data) +// { +// if(data.vel_factor) +// { +// foreach(i; 0..data.length) +// { +// data.location[i] += data.velocity[i] * data.vel_factor[i] * launcher.delta_time; +// } +// } +// else +// { +// foreach(i; 0..data.length) +// { +// data.location[i] += data.velocity[i] * launcher.delta_time; +// } +// } +// } +// } -struct BallCollisionSystem +struct EdgeCollisionSystem { mixin ECS.System!64; @@ -93,13 +116,117 @@ struct BallCollisionSystem uint length; CLocation[] location; CVelocity[] velocity; + //CBall[] ball_flag; } void onUpdate(EntitiesData data) { foreach(i; 0..data.length) { - + if(data.location[i].x < 0) + { + if(data.velocity[i].x < 0)data.velocity[i].x = -data.velocity[i].x; + data.location[i].x = 0; + } + else if(data.location[i].x > 400) + { + if(data.velocity[i].x > 0)data.velocity[i].x = -data.velocity[i].x; + data.location[i].x = 400; + } + + if(data.location[i].y < 0) + { + if(data.velocity[i].y < 0)data.velocity[i].y = -data.velocity[i].y; + data.location[i].y = 0; + } + else if(data.location[i].y > 300) + { + if(data.velocity[i].y > 0)data.velocity[i].y = -data.velocity[i].y; + data.location[i].y = 300; + } + } + } +} + +struct BallCollisionSystem +{ + mixin ECS.System!64; + + mixin ECS.ReadOnlyDependencies!(ShootGridDependency); + + struct EntitiesData + { + ///variable named "length" contain entites count + uint length; + const (Entity)[] entity; + CVelocity[] velocity; + @readonly CLocation[] location; + @readonly CScale[] scale; + @readonly CBall[] ball_flag; + } + + ShootGrid* grid; + + bool onBegin() + { + grid = launcher.manager.getSystem!ShootGridManager().grid; + if(grid is null)return false; + else return true; + } + + void onUpdate(EntitiesData data) + { + EntityID id; + foreach(i; 0..data.length) + { + float radius = data.scale[i].x; + //if(grid.test(id, data.location[i], ubyte.max)) + if(grid.test(id, data.location[i] - radius, data.location[i] + radius, ubyte.max)) + { + Entity* entity = launcher.manager.getEntity(id); + if(entity) + { + CLocation* location = entity.getComponent!CLocation; + CScale* scale = entity.getComponent!CScale; + if(location && scale) + { + vec2 rel_pos = *location - data.location[i]; + vec2 abs_rel_pos = rel_pos; + if(abs_rel_pos.x < 0)abs_rel_pos.x = -abs_rel_pos.x; + if(abs_rel_pos.y < 0)abs_rel_pos.y = -abs_rel_pos.y; + + vec2 half_scale = *scale * 0.25f; + + if(abs_rel_pos.x < half_scale.x + radius && + abs_rel_pos.y < half_scale.y + radius) + { + if(abs_rel_pos.x < half_scale.x) + { + if(rel_pos.y * data.velocity[i].y > 0)data.velocity[i].y = -data.velocity[i].y; + } + else if(abs_rel_pos.y < half_scale.y) + { + if(rel_pos.x * data.velocity[i].x > 0)data.velocity[i].x = -data.velocity[i].x; + } + else + { + vec2 vector = abs_rel_pos - half_scale; + if(rel_pos.x > 0)vector.x = -vector.x; + if(rel_pos.y > 0)vector.y = -vector.y; + + float pow_dist = vector.length2(); + if(pow_dist < radius*radius) + { + vector = vector / sqrtf(pow_dist); + data.velocity[i] = data.velocity[i] - vector * (2 * dot(vector, data.velocity[i])); + } + } + } + } + } + //launcher.manager.sendEvent(id, EBulletHit(data.entity[i].id,data.bullet[i].damage)); + //launcher.manager.removeEntity(data.entity[i].id); + } } } } @@ -118,13 +245,17 @@ struct BrickBreakerDemo __gshared BrickBreakerDemo* demo; -void brickBreakerStart() +void brickBreakerRegister() { demo = Mallocator.make!BrickBreakerDemo; + demo.texture.create(); + demo.texture.load("assets/textures/atlas.png"); + launcher.manager.beginRegister(); registerRenderingModule(launcher.manager); + registerCollisionModule(launcher.manager); launcher.manager.registerComponent!CLocation; launcher.manager.registerComponent!CRotation; @@ -132,27 +263,109 @@ void brickBreakerStart() launcher.manager.registerComponent!CTexCoords; launcher.manager.registerComponent!CTexCoordsIndex; launcher.manager.registerComponent!CVelocity; + launcher.manager.registerComponent!CInput; + launcher.manager.registerComponent!CPaddle; + launcher.manager.registerComponent!CDamping; + launcher.manager.registerComponent!CVelocityFactor; + launcher.manager.registerComponent!CBall; launcher.manager.registerSystem!MoveSystem(-100); - launcher.manager.registerSystem!BallCollisionSystem(-99); + launcher.manager.registerSystem!EdgeCollisionSystem(-99); + launcher.manager.registerSystem!BallCollisionSystem(-79); + launcher.manager.registerSystem!InputMovementSystem(-120); + launcher.manager.registerSystem!DampingSystem(-120); launcher.manager.endRegister(); +} - demo.texture.create(); - demo.texture.load("assets/textures/atlas.png"); +void brickBreakerStart() +{ + DrawSystem* draw_system = launcher.manager.getSystem!DrawSystem; + draw_system.default_data.color = 0x80808080; + draw_system.default_data.texture = demo.texture; + draw_system.default_data.size = vec2(16,16); + draw_system.default_data.coords = vec4(246,64,2,2)*px; + draw_system.default_data.material_id = 0; - launcher.manager.beginRegister(); + EntityTemplate* brick_tmpl = launcher.manager.allocateTemplate( + [CLocation.component_id, CScale.component_id, CColor.component_id, + CTexCoordsIndex.component_id, CShootGrid.component_id].staticArray + ); + brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(304,40,16,8)*px); + brick_tmpl.getComponent!CColor().value = 0x80206020; + brick_tmpl.getComponent!CScale().value = vec2(16,8); - launcher.manager.registerComponent!CLocation; + EntityTemplate* big_brick_tmpl = launcher.manager.allocateTemplate(brick_tmpl); + big_brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(320,32,16,16)*px); + big_brick_tmpl.getComponent!CScale().value = vec2(16,16); + + EntityTemplate* paddle_tmpl = launcher.manager.allocateTemplate( + [CLocation.component_id, CScale.component_id, CInput.component_id, + CTexCoordsIndex.component_id, CPaddle.component_id, CVelocity.component_id, + CDamping.component_id, CVelocityFactor.component_id, CShootGrid.component_id].staticArray + ); + paddle_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(272,48,64,10)*px); + paddle_tmpl.getComponent!CScale().value = vec2(64,10); + paddle_tmpl.getComponent!CDamping().value = 14; + paddle_tmpl.getComponent!CVelocityFactor().value = vec2(1,0); + + EntityTemplate* ball_tmpl = launcher.manager.allocateTemplate( + [CLocation.component_id, CScale.component_id, //CDamping.component_id, + CTexCoordsIndex.component_id, CBall.component_id, CVelocity.component_id].staticArray + ); + ball_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(304,32,8,8)*px); + ball_tmpl.getComponent!CScale().value = vec2(8,8); + ball_tmpl.getComponent!CVelocity().value = vec2(0.1,0.1); + // paddle_tmpl.getComponent!CDamping().value = 14; + + launcher.gui_manager.addComponent(CLocation(), "Location"); + launcher.gui_manager.addComponent(CRotation(), "Rotation"); + launcher.gui_manager.addComponent(CScale(), "Scale"); + launcher.gui_manager.addComponent(CColor(), "Color"); + launcher.gui_manager.addComponent(CTexCoords(), "Tex Coords"); + launcher.gui_manager.addComponent(CTexCoordsIndex(), "Tex Coords Index"); + launcher.gui_manager.addComponent(CVelocity(), "Velocity"); + launcher.gui_manager.addComponent(CInput(), "Velocity"); + launcher.gui_manager.addComponent(CDamping(), "Damping"); + launcher.gui_manager.addComponent(CBall(), "Ball"); + + launcher.gui_manager.addSystem(MoveSystem.system_id, "Move System"); + launcher.gui_manager.addSystem(BallCollisionSystem.system_id, "Ball Collision System"); + + launcher.gui_manager.addTemplate(brick_tmpl, "Brick"); + launcher.gui_manager.addTemplate(big_brick_tmpl, "Big Brick"); + launcher.gui_manager.addTemplate(paddle_tmpl, "Paddle"); + launcher.gui_manager.addTemplate(ball_tmpl, "Ball"); + + foreach(i;0..10) + { + CColor color; + final switch(i) + { + case 0:color = 0x80206020;break; + case 1:color = 0x80602020;break; + case 2:color = 0x80202060;break; + case 3:color = 0x80206060;break; + case 4:color = 0x80606020;break; + case 5:color = 0x80602060;break; + case 6:color = 0x80606060;break; + case 7:color = 0x80202020;break; + case 8:color = 0x80008030;break; + case 9:color = 0x80206080;break; + } + foreach (j; 0..20) + { + launcher.manager.addEntity(brick_tmpl,[CLocation(vec2(j*18,300-i*10)).ref_, color.ref_].staticArray); + } + } + + launcher.manager.addEntity(paddle_tmpl,[CLocation(vec2(190,20)).ref_].staticArray); + launcher.manager.addEntity(ball_tmpl,[CLocation(vec2(190,40)).ref_].staticArray); - launcher.manager.endRegister(); } void brickBreakerEnd() { - launcher.manager.getSystem(MoveSystem.system_id).disable(); - launcher.manager.getSystem(DrawSystem.system_id).disable(); - demo.texture.destroy(); Mallocator.dispose(demo); @@ -185,6 +398,7 @@ bool brickBreakerLoop() DemoCallbacks getBrickBreakerDemo() { DemoCallbacks demo; + demo.register = &brickBreakerRegister; demo.initialize = &brickBreakerStart; demo.deinitialize = &brickBreakerEnd; demo.loop = &brickBreakerLoop; diff --git a/demos/source/demos/particles.d b/demos/source/demos/particles.d index 8dac7ff..ec64774 100644 --- a/demos/source/demos/particles.d +++ b/demos/source/demos/particles.d @@ -54,14 +54,14 @@ struct CTexCoords vec4 value; }*/ -struct CVelocity -{ - mixin ECS.Component; +// struct CVelocity +// { +// mixin ECS.Component; - alias value this; +// alias value this; - vec2 value = vec2(0); -} +// vec2 value = vec2(0); +// } struct CForceRange { @@ -85,14 +85,14 @@ struct CVortex float strength = 0.6; } -struct CDamping -{ - mixin ECS.Component; +// struct CDamping +// { +// mixin ECS.Component; - alias power this; +// alias power this; - @GUIRange(0,9) ubyte power = 0; -} +// @GUIRange(0,9) ubyte power = 0; +// } struct CGravity { @@ -165,25 +165,25 @@ struct DrawSystem } }*/ -struct MoveSystem -{ - mixin ECS.System!64; +// struct MoveSystem +// { +// mixin ECS.System!64; - struct EntitiesData - { - uint length; - CLocation[] locations; - @readonly CVelocity[] velocity; - } +// struct EntitiesData +// { +// uint length; +// CLocation[] locations; +// @readonly CVelocity[] velocity; +// } - void onUpdate(EntitiesData data) - { - foreach(i; 0..data.length) - { - data.locations[i] += data.velocity[i] * launcher.delta_time; - } - } -} +// void onUpdate(EntitiesData data) +// { +// foreach(i; 0..data.length) +// { +// data.locations[i] += data.velocity[i] * launcher.delta_time; +// } +// } +// } struct MouseAttractSystem { @@ -347,38 +347,38 @@ struct PlayAreaSystem } } -struct DampingSystem -{ - mixin ECS.System!32; +// struct DampingSystem +// { +// mixin ECS.System!32; - struct EntitiesData - { - uint length; - const (Entity)[] entity; - @readonly CDamping[] damping; - CVelocity[] velocity; - } +// struct EntitiesData +// { +// uint length; +// const (Entity)[] entity; +// @readonly CDamping[] damping; +// CVelocity[] velocity; +// } - float[10] damp = 0; +// float[10] damp = 0; - bool onBegin() - { - foreach(i;0..10) - { - damp[i] = powf((0.99 - cast(float)i * 0.01),launcher.delta_time*0.1); - } +// bool onBegin() +// { +// foreach(i;0..10) +// { +// damp[i] = powf((0.99 - cast(float)i * 0.01),launcher.delta_time*0.1); +// } - return true; - } +// return true; +// } - void onUpdate(EntitiesData data) - { - foreach(i; 0..data.length) - { - data.velocity[i] = data.velocity[i] * damp[data.damping[i]]; - } - } -} +// void onUpdate(EntitiesData data) +// { +// foreach(i; 0..data.length) +// { +// data.velocity[i] = data.velocity[i] * damp[data.damping[i]]; +// } +// } +// } struct ParticleLifeSystem { @@ -444,7 +444,7 @@ struct ParticlesDemo __gshared ParticlesDemo* particles_demo; -void particlesStart() +void particlesRegister() { particles_demo = Mallocator.make!ParticlesDemo; @@ -484,7 +484,10 @@ void particlesStart() launcher.manager.registerSystem!AttractorIterator(-1); launcher.manager.endRegister(); +} +void particlesStart() +{ DrawSystem* draw_system = launcher.manager.getSystem!DrawSystem; draw_system.default_data.size = vec2(2,2); draw_system.default_data.coords = vec4(246,64,2,2)*px; @@ -579,6 +582,7 @@ bool particlesLoop() DemoCallbacks getParticlesDemo() { DemoCallbacks demo; + demo.register = &particlesRegister; demo.initialize = &particlesStart; demo.deinitialize = &particlesEnd; demo.loop = &particlesLoop; diff --git a/demos/source/demos/sandbox.d b/demos/source/demos/sandbox.d index 69a2ef2..925ebb2 100644 --- a/demos/source/demos/sandbox.d +++ b/demos/source/demos/sandbox.d @@ -6,6 +6,7 @@ import demos.simple; import demos.snake; import demos.space_invaders; import demos.particles; +import demos.brick_breaker; import game_core.rendering; @@ -17,10 +18,17 @@ extern(C): void sandboxStart() { + simpleRegister(); + snakeRegister(); + spaceInvadersRegister(); + particlesRegister(); + brickBreakerRegister(); + simpleStart(); snakeStart(); spaceInvadersStart(); particlesStart(); + brickBreakerStart(); DrawSystem* draw_system = launcher.manager.getSystem!DrawSystem; draw_system.default_data.size = vec2(16,16); @@ -28,6 +36,10 @@ void sandboxStart() draw_system.default_data.material_id = 0; draw_system.default_data.texture = particles_demo.texture; draw_system.default_data.color = 0x80808080; + + launcher.manager.getSystem(MouseAttractSystem.system_id).disable(); + launcher.manager.getSystem(demos.simple.MoveSystem.system_id).disable(); + } void sandboxEnd() @@ -56,9 +68,9 @@ bool sandboxLoop() else */ time += delta_time; - while(time > 100) + while(time > 200) { - time -= 100; + time -= 200; launcher.manager.update("fixed"); } diff --git a/demos/source/demos/simple.d b/demos/source/demos/simple.d index 1aafcb2..ecccc12 100644 --- a/demos/source/demos/simple.d +++ b/demos/source/demos/simple.d @@ -107,7 +107,7 @@ struct Simple __gshared Simple* simple; -void simpleStart() +void simpleRegister() { simple = Mallocator.make!Simple; @@ -124,7 +124,10 @@ void simpleStart() // launcher.manager.registerSystem!DrawSystem(1); launcher.manager.endRegister(); - +} + +void simpleStart() +{ DrawSystem* draw_system = launcher.manager.getSystem!DrawSystem; draw_system.default_data.color = 0x80808080; draw_system.default_data.texture = simple.texture; @@ -198,6 +201,7 @@ bool simpleLoop() DemoCallbacks getSimpleDemo() { DemoCallbacks demo; + demo.register = &simpleRegister; demo.initialize = &simpleStart; demo.deinitialize = &simpleEnd; demo.loop = &simpleLoop; diff --git a/demos/source/demos/snake.d b/demos/source/demos/snake.d index 8ff0be6..525b4ab 100644 --- a/demos/source/demos/snake.d +++ b/demos/source/demos/snake.d @@ -235,10 +235,10 @@ struct CMovement Direction direction; } -struct CInput -{ - mixin ECS.Component; -} +// struct CInput +// { +// mixin ECS.Component; +// } struct AppleSystem { @@ -849,7 +849,7 @@ struct CopyLocationSystem __gshared Snake* snake; -void snakeStart() +void snakeRegister() { import game_core.rendering; @@ -890,7 +890,10 @@ void snakeStart() launcher.manager.registerSystem!SnakeSystem(101); launcher.manager.endRegister(); +} +void snakeStart() +{ launcher.gui_manager.addComponent(CApple(),"Apple"); launcher.gui_manager.addComponent(CSnake(),"Snake"); launcher.gui_manager.addComponent(CParticle(1000),"Particle"); @@ -975,9 +978,9 @@ bool snakeLoop() if(launcher.getKeyState(SDL_SCANCODE_SPACE))time += delta_time * 3; else time += delta_time; - while(time > 100) + while(time > 200) { - time -= 100; + time -= 200; launcher.manager.update("fixed"); } @@ -992,6 +995,7 @@ bool snakeLoop() DemoCallbacks getSnakeDemo() { DemoCallbacks demo; + demo.register = &snakeRegister; demo.initialize = &snakeStart; demo.deinitialize = &snakeEnd; demo.loop = &snakeLoop; diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index b249fc1..66be099 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -18,6 +18,7 @@ import ecs_utils.utils; import game_core.basic; import game_core.rendering; +import game_core.collision; //import std.math : PI; @@ -29,8 +30,6 @@ private enum float px = 1.0/512.0; extern(C): -enum ShootGridDependency = "ShootGridDependency"; - /*####################################################################################################################### ------------------------------------------------ Types ------------------------------------------------------------------ #######################################################################################################################*/ @@ -57,7 +56,7 @@ struct SpaceInvaders ~this() @nogc nothrow { - if(shoot_grid)Mallocator.dispose(shoot_grid); + // if(shoot_grid)Mallocator.dispose(shoot_grid); if(enemy_tmpl)launcher.manager.freeTemplate(enemy_tmpl); if(ship_tmpl)launcher.manager.freeTemplate(ship_tmpl); if(laser_tmpl)launcher.manager.freeTemplate(laser_tmpl); @@ -163,28 +162,14 @@ struct CTexture vec4 coords = vec4(0,0,0,1); }*/ -struct CColliderScale -{ - mixin ECS.Component; +// struct CVelocity +// { +// mixin ECS.Component; - alias value this; +// alias value this; - vec2 value = vec2(16,16); -} - -struct CVelocity -{ - mixin ECS.Component; - - alias value this; - - vec2 value = vec2(0,0); -} - -struct CInput -{ - mixin ECS.Component; -} +// vec2 value = vec2(0,0); +// } struct CEnemy { @@ -265,11 +250,6 @@ struct CSideMove byte group = -1; } -struct CShootGrid -{ - mixin ECS.Component; -} - struct CTargetParent { mixin ECS.Component; @@ -336,14 +316,7 @@ struct CAnimationLooped mixin ECS.Component; } -struct CDamping -{ - mixin ECS.Component; - alias value this; - - byte value = 0; -} struct CParticle { @@ -514,163 +487,6 @@ struct EDestroyedChild ------------------------------------------------ Systems ------------------------------------------------------------------ #######################################################################################################################*/ -struct ShootGrid -{ - - ~this() @nogc nothrow - { - if(nodes)Mallocator.dispose(nodes); - if(masks)Mallocator.dispose(masks); - } - - struct Node - { - alias entity this; - - EntityID entity; - } - - void create(ivec2 nodes_count, vec2 node_size) - { - this.size = nodes_count; - this.node_size = node_size; - inv_node_size = vec2(1.0/node_size.x, 1.0/node_size.y); - nodes = Mallocator.makeArray!Node(nodes_count.x * nodes_count.y); - masks = Mallocator.makeArray!ubyte(nodes.length); - } - - void mark(EntityID id, vec2 beg, vec2 end, byte mask) - { - ivec2 ibeg = cast(ivec2)(beg * inv_node_size); - ivec2 iend = cast(ivec2)((end * inv_node_size) + 0.5); - if(ibeg.x < 0)ibeg.x = 0; - if(ibeg.y < 0)ibeg.y = 0; - if(iend.x > size.x)iend.x = size.x; - if(iend.y > size.y)iend.y = size.y; - foreach(i; ibeg.y .. iend.y) - { - foreach(j; ibeg.x .. iend.x) - { - nodes[i * size.x + j] = id; - masks[i * size.x +j] = mask; - } - } - } - - void clear() - { - size_t size = nodes.length * EntityID.sizeof; - memset(nodes.ptr, 0, size); - memset(masks.ptr, 0, masks.length); - } - - bool test(out EntityID id, vec2 beg, vec2 end) - { - ivec2 ibeg = cast(ivec2)(beg * inv_node_size); - ivec2 iend = cast(ivec2)((end * inv_node_size) + 0.5); - if(ibeg.x < 0)ibeg.x = 0; - if(ibeg.y < 0)ibeg.y = 0; - if(iend.x > size.x)iend.x = size.x; - if(iend.y > size.y)iend.y = size.y; - foreach(i; ibeg.y .. iend.y) - { - foreach(j; ibeg.x .. iend.x) - { - if(nodes[i * size.x + j].id != 0) - { - id = nodes[i * size.x + j]; - return true; - } - } - } - return false; - } - - bool test(out EntityID id, vec2 pos, ubyte mask) - { - ivec2 ipos = cast(ivec2)(pos * inv_node_size - 0.5); - if(ipos.x < 0)ipos.x = 0; - if(ipos.y < 0)ipos.y = 0; - if(ipos.x >= size.x)ipos.x = size.x - 1; - if(ipos.y >= size.y)ipos.y = size.y - 1; - size_t index = ipos.y * size.x + ipos.x; - if((masks[index] & mask) == 0)return false; - if(nodes[index].id != 0) - { - id = nodes[index]; - return true; - } - return false; - } - - vec2 inv_node_size; - ivec2 size; - vec2 node_size; - Node[] nodes; - ubyte[] masks; -} - -struct ShootGridCleaner -{ - mixin ECS.System!1; - - struct EntitiesData - { - - } - - void onUpdate(EntitiesData data) - { - if(space_invaders.shoot_grid)space_invaders.shoot_grid.clear(); - } -} - -struct ShootGridManager -{ - mixin ECS.System!128; - - mixin ECS.WritableDependencies!(ShootGridDependency); - - struct EntitiesData - { - uint length; - //uint thread_id; - const (Entity)[] entity; - @readonly CLocation[] locations; - @readonly CShootGrid[] grid_flag; - @readonly CGuild[] guild; - @optional @readonly CScale[] scale; - @optional @readonly CColliderScale[] collider_scale; - } - - ShootGrid* grid; - - void onCreate() - { - grid = space_invaders.shoot_grid; - } - - bool onBegin() - { - if(!grid)return false; - //grid.clear(); - return true; - } - - void onUpdate(EntitiesData data) - { - vec2[] scale; - if(data.collider_scale)scale = cast(vec2[])data.collider_scale; - else if(data.scale)scale = cast(vec2[])data.scale; - else return; - foreach(i; 0..data.length) - { - vec2 half_scale = scale[i] * 0.5; - grid.mark(data.entity[i].id, data.locations[i] - half_scale, data.locations[i] + half_scale, cast(ubyte)(1 << data.guild[i].guild)); - } - } -} - struct ParentOwnerSystem { mixin ECS.System; @@ -833,7 +649,7 @@ struct ShipWeaponSystem CTexCoords.component_id, CScale.component_id, CEnemy.component_id, CShootGrid.component_id, CGuild.component_id, CInit.component_id, CChildren.component_id, CDepth.component_id, CTargetParent.component_id, - CSpawnUponDeath.component_id, CShootWaveUponDeath.component_id].staticArray + CSpawnUponDeath.component_id, CShootWaveUponDeath.component_id, CShootGridMask.component_id].staticArray ); /*CTexCoords* tex_comp = tower1_tmpl.getComponent!CTexCoords; @@ -1215,8 +1031,8 @@ struct ShootingSystem laser.shoot_time -= CWeapon.levels[laser.level - 1].reload_time; laser_location.value = data.location[i]; - laser_velocity.value = vec2((randomf()*2-1) * CWeapon.levels[laser.level - 1].dispersion,1);//data.shoot_direction[i].direction == Direction.up ? 1.0 : -1.0); - if(data.shoot_direction && data.shoot_direction[i].direction == Direction.down)laser_velocity.y = -1; + laser_velocity.value = vec2((randomf()*2-1) * CWeapon.levels[laser.level - 1].dispersion,0.5);//data.shoot_direction[i].direction == Direction.up ? 1.0 : -1.0); + if(data.shoot_direction && data.shoot_direction[i].direction == Direction.down)laser_velocity.y = -0.5; laser_guild.guild = data.guild[i].guild; @@ -1280,39 +1096,6 @@ struct ShootingSystem } } -struct DampingSystem -{ - mixin ECS.System!32; - - struct EntitiesData - { - uint length; - const (Entity)[] entity; - @readonly CDamping[] damping; - CVelocity[] velocity; - } - - float[10] damp = 0; - - bool onBegin() - { - foreach(i;0..10) - { - damp[i] = powf((0.98 - cast(float)i * 0.02),launcher.delta_time*0.1); - } - - return true; - } - - void onUpdate(EntitiesData data) - { - foreach(i; 0..data.length) - { - data.velocity[i] = data.velocity[i] * damp[data.damping[i]]; - } - } -} - struct BulletsCollisionSystem { mixin ECS.System!32; @@ -1343,6 +1126,29 @@ struct BulletsCollisionSystem } } +struct CollisionMaskSystem +{ + mixin ECS.System; + + mixin ECS.ReadOnlyDependencies!(ShootGridDependency); + + struct EntitiesData + { + ///variable named "length" contain entites count + uint length; + CShootGridMask[] mask; + @readonly CGuild[] guild; + } + + void onAddEntity(EntitiesData data) + { + foreach(i;0..data.length) + { + data.mask[i] = cast(ubyte)(1 << data.guild[i].guild); + } + } +} + struct ParticleEmittingSystem { mixin ECS.System!32; @@ -1670,7 +1476,7 @@ struct HitPointsSystem //tex_comp.tex = space_invaders.texture;//ship_tex; upgrade_tmpl.getComponent!CTexCoords().value = vec4(0*px,32*px,16*px,16*px); *upgrade_tmpl.getComponent!CAnimation = CAnimation(upgrade_laser_frames, 0, 1); - upgrade_tmpl.getComponent!CVelocity().value = vec2(0,-0.1); + upgrade_tmpl.getComponent!CVelocity().value = vec2(0,-0.05); explosion_tmpl = launcher.manager.allocateTemplate( [CDepth.component_id, CParticle.component_id, CLocation.component_id, @@ -1975,32 +1781,32 @@ struct ClampPositionSystem } } -struct MovementSystem -{ - mixin ECS.System!32; +// struct MovementSystem +// { +// mixin ECS.System!32; - struct EntitiesData - { - uint length; - //read only components can be marked with @readonly attribute or with const expression instead - const (CVelocity)[] velocity; - //components are treated as required by default - CLocation[] locations; - //@optional const (CBullet)[] laser; - const (Entity)[] entities; +// struct EntitiesData +// { +// uint length; +// //read only components can be marked with @readonly attribute or with const expression instead +// const (CVelocity)[] velocity; +// //components are treated as required by default +// CLocation[] locations; +// //@optional const (CBullet)[] laser; +// const (Entity)[] entities; - //@optional CSideMove[] side_move; - } +// //@optional CSideMove[] side_move; +// } - void onUpdate(EntitiesData data) - { - foreach(i;0..data.length) - { - data.locations[i].x += data.velocity[i].x * launcher.delta_time * 0.5; - data.locations[i].y += data.velocity[i].y * launcher.delta_time * 0.5; - } - } -} +// void onUpdate(EntitiesData data) +// { +// foreach(i;0..data.length) +// { +// data.locations[i].x += data.velocity[i].x * launcher.delta_time * 0.5; +// data.locations[i].y += data.velocity[i].y * launcher.delta_time * 0.5; +// } +// } +// } struct AnimationSystem { @@ -2229,114 +2035,20 @@ struct CShipIterator //void handleEvent(Entity* entity, ) }//*/ -/** -*System is responsible for movement of objects with CInput component. -*In this example every entity has same speed when using movement system. -*/ -struct InputMovementSystem -{ - mixin ECS.System!32; - - vec2 move_vector; - - struct EntitiesData - { - uint length; - //read only components can be marked with @readonly attribute or with const expression instead - const (CInput)[] input; - //components are treated as required by default - //CLocation[] locations; - CVelocity[] velocity; - //CTexture[] textures; - } - - /** - *onBegin gives opportunity to check keys once and call update on entities only when - *one key is pressed. - */ - bool onBegin() - { - move_vector = vec2(0,0); - if(launcher.getKeyState(SDL_SCANCODE_W)) - { - move_vector += vec2(0,1); - } - else if(launcher.getKeyState(SDL_SCANCODE_S)) - { - move_vector += vec2(0,-1); - } - if(launcher.getKeyState(SDL_SCANCODE_A)) - { - move_vector += vec2(-1,0); - } - else if(launcher.getKeyState(SDL_SCANCODE_D)) - { - move_vector += vec2(1,0); - } - - if(move_vector.x != 0 ||move_vector.y != 0) - { - move_vector = move_vector / sqrtf(move_vector.x * move_vector.x + move_vector.y * move_vector.y); - return true; - } - //don't call system update because no key pressed - return false; - } - - /** - *Update is called multiple times in one "manager.update()" call. - *Number of "onUpdate" calls is count of buffers which must be updated during pass. - *When multithreading is used, number of "onUpdate" calls can be greater due to fact that - *JobSystem can split buffers for better data packing. - */ - void onUpdate(EntitiesData data) - { - /*if(move_vector.x == 0) - { - foreach(i; 0..data.length) - { - data.textures[i].coords = vec4(0*px,80*px,48*px,32*px); - } - //return; - }*/ - //move every entity using movement vector - //if(move_vector.x != 0 || move_vector.y != 0) - foreach(i; 0..data.length) - { - data.velocity[i] += move_vector * launcher.delta_time * 0.005; - if(data.velocity[i].x > 0.5)data.velocity[i].x = 0.5; - else if(data.velocity[i].x < -0.5)data.velocity[i].x = -0.5; - if(data.velocity[i].y > 0.5)data.velocity[i].y = 0.5; - else if(data.velocity[i].y < -0.5)data.velocity[i].y = -0.5; - //data.locations[i].x += move_vector.x * launcher.delta_time * 0.25; - //data.locations[i].y += move_vector.y * launcher.delta_time * 0.25; - //if(move_vector.x > 0)data.textures[i].coords = vec4(48*px,80*px,48*px,32*px); - //else data.textures[i].coords = vec4(0*px,80*px,48*px,32*px); - } - /*else - foreach(i; 0..data.length) - { - data.velocity[i] = vec2(0,0); - }*/ - } -} - /*####################################################################################################################### ------------------------------------------------ Functions ------------------------------------------------------------------ #######################################################################################################################*/ __gshared SpaceInvaders* space_invaders; -void spaceInvadersStart() +void spaceInvadersRegister() { + space_invaders = Mallocator.make!SpaceInvaders; space_invaders.texture.create(); space_invaders.texture.load("assets/textures/atlas.png"); - space_invaders.shoot_grid = Mallocator.make!ShootGrid; - space_invaders.shoot_grid.create(ivec2(80,60), vec2(5,5)); - launcher.manager.beginRegister(); launcher.manager.registerDependency(ShootGridDependency); @@ -2381,6 +2093,7 @@ void spaceInvadersStart() launcher.manager.registerComponent!CParticleEmitterTime; launcher.manager.registerComponent!CSpawnUponDeath; launcher.manager.registerComponent!CShootWaveUponDeath; + launcher.manager.registerComponent!CShootGridMask; launcher.manager.registerEvent!EChangeDirection; launcher.manager.registerEvent!EDamage; @@ -2392,7 +2105,8 @@ void spaceInvadersStart() //launcher.manager.registerSystem!MoveSystem(0); launcher.manager.registerSystem!DrawSystem(100); launcher.manager.registerSystem!InputMovementSystem(-100); - launcher.manager.registerSystem!MovementSystem(-99); + //launcher.manager.registerSystem!MovementSystem(-99); + launcher.manager.registerSystem!MoveSystem(-99); launcher.manager.registerSystem!ClampPositionSystem(-90); launcher.manager.registerSystem!ShootingSystem(0); launcher.manager.registerSystem!ChangeDirectionSystem(0); @@ -2417,8 +2131,18 @@ void spaceInvadersStart() launcher.manager.registerSystem!ChildDestroySystem(-110); launcher.manager.registerSystem!ShootWaveSystem(-100); //launcher.manager.registerSystem!SpawnUponDeathSystem(-110); + launcher.manager.registerSystem!CollisionMaskSystem(-100); launcher.manager.endRegister(); +} + +void spaceInvadersStart() +{ + + // space_invaders.shoot_grid = Mallocator.make!ShootGrid; + // space_invaders.shoot_grid.create(ivec2(80,60), vec2(5,5)); + + space_invaders.shoot_grid = launcher.manager.getSystem!ShootGridManager().grid; DrawSystem* draw_system = launcher.manager.getSystem!DrawSystem; draw_system.default_data.color = 0x80808080; @@ -2463,7 +2187,8 @@ void spaceInvadersStart() launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System"); launcher.gui_manager.addSystem(InputMovementSystem.system_id,"Input Movement"); launcher.gui_manager.addSystem(ShootingSystem.system_id,"Shooting System"); - launcher.gui_manager.addSystem(MovementSystem.system_id,"Movement System"); + //launcher.gui_manager.addSystem(MovementSystem.system_id,"Movement System"); + launcher.gui_manager.addSystem(MoveSystem.system_id,"Move System"); launcher.gui_manager.addSystem(ClampPositionSystem.system_id,"Clamp Position System"); launcher.gui_manager.addSystem(ChangeDirectionSystem.system_id,"Change Direction System"); launcher.gui_manager.addSystem(BulletsCollisionSystem.system_id,"Bullets Collision System"); @@ -2494,14 +2219,16 @@ void spaceInvadersStart() CLocation.component_id, CTexCoords.component_id, CInput.component_id, CShip.component_id, CScale.component_id, CColliderScale.component_id, CShootDirection.component_id, CShootGrid.component_id, CGuild.component_id, - CDamping.component_id, CChildren.component_id, CInit.component_id].staticArray + CDamping.component_id, CChildren.component_id, CInit.component_id, + CShootGridMask.component_id, CVelocityFactor.component_id].staticArray ); space_invaders.ship_tmpl.getComponent!CTexCoords().value = vec4(0,80,48,32)*px; space_invaders.ship_tmpl.getComponent!CScale().value = vec2(48,32); space_invaders.ship_tmpl.getComponent!CHitPoints().value = 1000; - space_invaders.ship_tmpl.getComponent!CDamping().value = 7; + space_invaders.ship_tmpl.getComponent!CDamping().value = 14; space_invaders.ship_tmpl.getComponent!CInit().type = CInit.Type.space_ship; space_invaders.ship_tmpl.getComponent!CColliderScale().value = vec2(26,24); + space_invaders.ship_tmpl.getComponent!CVelocityFactor().value = vec2(0.5,0.5); launcher.manager.addEntity(space_invaders.ship_tmpl,[CLocation(vec2(64,64)).ref_].staticArray); } @@ -2512,7 +2239,7 @@ void spaceInvadersStart() space_invaders.laser_tmpl.getComponent!CTexCoords().value = vec4(0,24,2,8)*px; space_invaders.laser_tmpl.getComponent!CScale().value = vec2(2,8); - space_invaders.laser_tmpl.getComponent!CVelocity().value = vec2(0,1); + space_invaders.laser_tmpl.getComponent!CVelocity().value = vec2(0,0.5); } EntityTemplate* enemy_tmpl; @@ -2543,7 +2270,7 @@ void spaceInvadersStart() boss_tmpl.getComponent!CScale().value = vec2(96,48); boss_tmpl.getComponent!CDepth().value = -1; boss_tmpl.getComponent!CParts().count = 4; - boss_tmpl.getComponent!CVelocity().value = vec2(0.05,0); + boss_tmpl.getComponent!CVelocity().value = vec2(0.025,0); } { @@ -2551,7 +2278,7 @@ void spaceInvadersStart() [CColor.component_id, CHitMark.component_id, CHitPoints.component_id, CLocation.component_id, CTexCoords.component_id, CScale.component_id, CEnemy.component_id, CShootGrid.component_id, CGuild.component_id, CInit.component_id, - CChildren.component_id].staticArray + CChildren.component_id, CShootGridMask.component_id].staticArray ); tower_tmpl.getComponent!CTexCoords().value = vec4(96,96,16,16)*px; @@ -2566,12 +2293,12 @@ void spaceInvadersStart() CVelocity.component_id, CAutoShoot.component_id, CLocation.component_id, CTexCoords.component_id, CScale.component_id, CWeapon.component_id, CEnemy.component_id, CShootDirection.component_id, CShootGrid.component_id, - CGuild.component_id].staticArray + CGuild.component_id, CShootGridMask.component_id].staticArray ); space_invaders.enemy_tmpl.getComponent!CTexCoords().value = vec4(32,32,16,16)*px; space_invaders.enemy_tmpl.getComponent!CShootDirection().direction = Direction.down; - space_invaders.enemy_tmpl.getComponent!CVelocity().value = vec2(0.1,0); + space_invaders.enemy_tmpl.getComponent!CVelocity().value = vec2(0.05,0); space_invaders.enemy_tmpl.getComponent!CGuild().guild = 1; space_invaders.enemy_tmpl.getComponent!CWeaponLocation().rel_pos = vec2(0,-15); @@ -2603,7 +2330,7 @@ void spaceInvadersStart() { upgrade_tmpl = launcher.manager.allocateTemplate([CVelocity.component_id, CLocation.component_id, CTexCoords.component_id, CScale.component_id, CUpgrade.component_id, CAnimationLooped.component_id, CAnimation.component_id].staticArray); upgrade_tmpl.getComponent!CTexCoords().value = vec4(0,32,16,16)*px; - upgrade_tmpl.getComponent!CVelocity().value = vec2(0,-0.1); + upgrade_tmpl.getComponent!CVelocity().value = vec2(0,-0.05); *upgrade_tmpl.getComponent!CAnimation = CAnimation(HitPointsSystem.upgrade_laser_frames, 0, 0.75); } @@ -2746,6 +2473,7 @@ bool spaceInvadersLoop() DemoCallbacks getSpaceInvadersDemo() { DemoCallbacks demo; + demo.register = &spaceInvadersRegister; demo.initialize = &spaceInvadersStart; demo.deinitialize = &spaceInvadersEnd; demo.loop = &spaceInvadersLoop; diff --git a/demos/source/game_core/basic.d b/demos/source/game_core/basic.d index 156680b..b47ba52 100644 --- a/demos/source/game_core/basic.d +++ b/demos/source/game_core/basic.d @@ -1,11 +1,18 @@ module game_core.basic; import bubel.ecs.core; +import bubel.ecs.attributes; import ecs_utils.math.vector; import gui.attributes; +import ecs_utils.utils; + +import app : launcher; + +import bindbc.sdl; + struct CLocation { mixin ECS.Component; @@ -56,4 +63,193 @@ struct CSelected mixin ECS.Component; bool value = false; +} + +struct CInput +{ + mixin ECS.Component; +} + +struct CDamping +{ + mixin ECS.Component; + + alias value this; + + @GUIRange(0,9) byte value = 1; +} + +struct CVelocity +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(0,0); +} + +struct CVelocityFactor +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(1); +} + + +struct DampingSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + @readonly CDamping[] damping; + CVelocity[] velocity; + } + + float[20] damp = 0; + + bool onBegin() + { + foreach(i;0..20) + { + damp[i] = powf((0.99 - cast(float)i * 0.01),launcher.delta_time*0.1); + } + + return true; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + data.velocity[i] = data.velocity[i] * damp[data.damping[i]]; + } + } +} + +struct MoveSystem +{ + mixin ECS.System!64; + + struct EntitiesData + { + uint length; + CLocation[] location; + @readonly CVelocity[] velocity; + @optional @readonly CVelocityFactor[] vel_factor; + } + + void onUpdate(EntitiesData data) + { + if(data.vel_factor) + { + foreach(i; 0..data.length) + { + data.location[i] += data.velocity[i] * data.vel_factor[i] * launcher.delta_time; + } + } + else + { + foreach(i; 0..data.length) + { + data.location[i] += data.velocity[i] * launcher.delta_time; + } + } + } +} + +/** +*System is responsible for movement of objects with CInput component. +*In this example every entity has same speed when using movement system. +*/ +struct InputMovementSystem +{ + mixin ECS.System!32; + + vec2 move_vector; + + struct EntitiesData + { + uint length; + //read only components can be marked with @readonly attribute or with const expression instead + const (CInput)[] input; + //components are treated as required by default + //CLocation[] locations; + CVelocity[] velocity; + //CTexture[] textures; + } + + /** + *onBegin gives opportunity to check keys once and call update on entities only when + *one key is pressed. + */ + bool onBegin() + { + move_vector = vec2(0,0); + if(launcher.getKeyState(SDL_SCANCODE_W)) + { + move_vector += vec2(0,1); + } + else if(launcher.getKeyState(SDL_SCANCODE_S)) + { + move_vector += vec2(0,-1); + } + if(launcher.getKeyState(SDL_SCANCODE_A)) + { + move_vector += vec2(-1,0); + } + else if(launcher.getKeyState(SDL_SCANCODE_D)) + { + move_vector += vec2(1,0); + } + + if(move_vector.x != 0 ||move_vector.y != 0) + { + move_vector = move_vector / sqrtf(move_vector.x * move_vector.x + move_vector.y * move_vector.y); + return true; + } + //don't call system update because no key pressed + return false; + } + + /** + *Update is called multiple times in one "manager.update()" call. + *Number of "onUpdate" calls is count of buffers which must be updated during pass. + *When multithreading is used, number of "onUpdate" calls can be greater due to fact that + *JobSystem can split buffers for better data packing. + */ + void onUpdate(EntitiesData data) + { + /*if(move_vector.x == 0) + { + foreach(i; 0..data.length) + { + data.textures[i].coords = vec4(0*px,80*px,48*px,32*px); + } + //return; + }*/ + //move every entity using movement vector + //if(move_vector.x != 0 || move_vector.y != 0) + foreach(i; 0..data.length) + { + data.velocity[i] += move_vector * launcher.delta_time * 0.005; + if(data.velocity[i].x > 0.5)data.velocity[i].x = 0.5; + else if(data.velocity[i].x < -0.5)data.velocity[i].x = -0.5; + if(data.velocity[i].y > 0.5)data.velocity[i].y = 0.5; + else if(data.velocity[i].y < -0.5)data.velocity[i].y = -0.5; + //data.locations[i].x += move_vector.x * launcher.delta_time * 0.25; + //data.locations[i].y += move_vector.y * launcher.delta_time * 0.25; + //if(move_vector.x > 0)data.textures[i].coords = vec4(48*px,80*px,48*px,32*px); + //else data.textures[i].coords = vec4(0*px,80*px,48*px,32*px); + } + /*else + foreach(i; 0..data.length) + { + data.velocity[i] = vec2(0,0); + }*/ + } } \ No newline at end of file diff --git a/demos/source/game_core/collision.d b/demos/source/game_core/collision.d new file mode 100644 index 0000000..75c46f8 --- /dev/null +++ b/demos/source/game_core/collision.d @@ -0,0 +1,232 @@ +module game_core.collision; + +import bubel.ecs.attributes; +import bubel.ecs.core; +import bubel.ecs.std; + +import ecs_utils.math.vector; + +import game_core.basic; + + +void registerCollisionModule(EntityManager* manager) +{ + manager.registerDependency(ShootGridDependency); + + manager.registerComponent!CShootGrid; + manager.registerComponent!CShootGridMask; + manager.registerComponent!CColliderScale; + + manager.registerSystem!ShootGridManager(-80); + manager.registerSystem!ShootGridCleaner(-101); +} + +enum ShootGridDependency = "ShootGridDependency"; + +struct CShootGrid +{ + mixin ECS.Component; +} + +struct CShootGridMask +{ + mixin ECS.Component; + + alias value this; + + ubyte value; +} + +struct CColliderScale +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(16,16); +} + +struct ShootGrid +{ + + ~this() @nogc nothrow + { + if(nodes)Mallocator.dispose(nodes); + if(masks)Mallocator.dispose(masks); + } + + struct Node + { + alias entity this; + + EntityID entity; + } + + void create(ivec2 nodes_count, vec2 node_size) + { + this.size = nodes_count; + this.node_size = node_size; + inv_node_size = vec2(1.0/node_size.x, 1.0/node_size.y); + nodes = Mallocator.makeArray!Node(nodes_count.x * nodes_count.y); + masks = Mallocator.makeArray!ubyte(nodes.length); + } + + void mark(EntityID id, vec2 beg, vec2 end, ubyte mask) + { + ivec2 ibeg = cast(ivec2)(beg * inv_node_size); + ivec2 iend = cast(ivec2)(end * inv_node_size + 0.5); + if(ibeg.x < 0)ibeg.x = 0; + if(ibeg.y < 0)ibeg.y = 0; + if(iend.x > size.x)iend.x = size.x; + if(iend.y > size.y)iend.y = size.y; + foreach(i; ibeg.y .. iend.y) + { + foreach(j; ibeg.x .. iend.x) + { + nodes[i * size.x + j] = id; + masks[i * size.x +j] = mask; + } + } + } + + void clear() + { + size_t size = nodes.length * EntityID.sizeof; + memset(nodes.ptr, 0, size); + memset(masks.ptr, 0, masks.length); + } + + bool test(out EntityID id, vec2 beg, vec2 end, ubyte mask) + { + ivec2 ibeg = cast(ivec2)(beg * inv_node_size); + ivec2 iend = cast(ivec2)(end * inv_node_size + 0.5); + if(ibeg.x < 0)ibeg.x = 0; + if(ibeg.y < 0)ibeg.y = 0; + if(iend.x > size.x)iend.x = size.x; + if(iend.y > size.y)iend.y = size.y; + foreach(i; ibeg.y .. iend.y) + { + foreach(j; ibeg.x .. iend.x) + { + uint index = i * size.x + j; + if(nodes[index].id != 0) + { + if((masks[index] & mask) == 0)continue; + id = nodes[index]; + return true; + } + } + } + return false; + } + + bool test(out EntityID id, vec2 pos, ubyte mask) + { + ivec2 ipos = cast(ivec2)(pos * inv_node_size - 0.5); + if(ipos.x < 0)ipos.x = 0; + if(ipos.y < 0)ipos.y = 0; + if(ipos.x >= size.x)ipos.x = size.x - 1; + if(ipos.y >= size.y)ipos.y = size.y - 1; + size_t index = ipos.y * size.x + ipos.x; + if((masks[index] & mask) == 0)return false; + if(nodes[index].id != 0) + { + id = nodes[index]; + return true; + } + return false; + } + + vec2 inv_node_size; + ivec2 size; + vec2 node_size; + Node[] nodes; + ubyte[] masks; +} + +struct ShootGridCleaner +{ + mixin ECS.System!1; + + struct EntitiesData + { + + } + + ShootGrid* grid; + + bool onBegin() + { + grid = gEM.getSystem!ShootGridManager().grid; + if(grid != null)return true; + else return false; + } + + void onUpdate(EntitiesData data) + { + if(grid)grid.clear(); + } +} + +struct ShootGridManager +{ + mixin ECS.System!128; + + mixin ECS.WritableDependencies!(ShootGridDependency); + + struct EntitiesData + { + uint length; + //uint thread_id; + const (Entity)[] entity; + @readonly CLocation[] locations; + @readonly CShootGrid[] grid_flag; + //@readonly CGuild[] guild; + @optional @readonly CShootGridMask[] mask; + @optional @readonly CScale[] scale; + @optional @readonly CColliderScale[] collider_scale; + } + + ShootGrid* grid; + + void onCreate() + { + //grid = space_invaders.shoot_grid; + grid = Mallocator.make!ShootGrid; + grid.create(ivec2(80,60), vec2(5,5)); + } + + void onDestroy() + { + Mallocator.dispose(grid); + } + + // bool onBegin() + // { + // //if(!grid)return false; + // //grid.clear(); + // return true; + // } + + void onUpdate(EntitiesData data) + { + vec2[] scale; + if(data.collider_scale)scale = cast(vec2[])data.collider_scale; + else if(data.scale)scale = cast(vec2[])data.scale; + else return; + if(data.mask is null) + { + foreach(i; 0..data.length) + { + vec2 half_scale = scale[i] * 0.5; + grid.mark(data.entity[i].id, data.locations[i] - half_scale, data.locations[i] + half_scale, ubyte.max);//cast(ubyte)(1 << data.guild[i].guild)); + } + } + else foreach(i; 0..data.length) + { + vec2 half_scale = scale[i] * 0.5; + grid.mark(data.entity[i].id, data.locations[i] - half_scale, data.locations[i] + half_scale, data.mask[i]);//cast(ubyte)(1 << data.guild[i].guild)); + } + + } +} \ No newline at end of file diff --git a/demos/source/gui/manager.d b/demos/source/gui/manager.d index 3745d9d..b3381ef 100644 --- a/demos/source/gui/manager.d +++ b/demos/source/gui/manager.d @@ -213,7 +213,7 @@ struct GUIManager static if(hasUDA!(member,GUIRange)) { comp_edit.variables[comp_edit.used-1].int_.min = getUDAs!(member,GUIRange)[0].min; - comp_edit.variables[comp_edit.used-1].int_.max = getUDAs!(member,GUIRange)[1].max; + comp_edit.variables[comp_edit.used-1].int_.max = getUDAs!(member,GUIRange)[0].max; } /*{ comp_edit.variables[comp_edit.used-1].int_.min = int.min; diff --git a/demos/source/gui/system.d b/demos/source/gui/system.d index 112bed3..b4899fb 100644 --- a/demos/source/gui/system.d +++ b/demos/source/gui/system.d @@ -5,7 +5,8 @@ import bubel.ecs.system; struct SystemGUI { const (char)* name; - System* system; + //System* system; + ushort id; bool enabled = true; } \ No newline at end of file diff --git a/demos/source/gui/tool_circle.d b/demos/source/gui/tool_circle.d index c43ade3..c8968d4 100644 --- a/demos/source/gui/tool_circle.d +++ b/demos/source/gui/tool_circle.d @@ -26,6 +26,7 @@ struct ToolCircle void draw(Renderer* renderer, vec2 position, float size, float edge = 1) { + glDisable(GL_DEPTH_TEST); position = position * renderer.view_size + renderer.view_pos; vec2 sizes = renderer.view_size * size; vec2 sizes2 = vec2(edge,0); diff --git a/demos/utils/source/ecs_utils/math/vector.d b/demos/utils/source/ecs_utils/math/vector.d index adb3a36..c835d05 100644 --- a/demos/utils/source/ecs_utils/math/vector.d +++ b/demos/utils/source/ecs_utils/math/vector.d @@ -95,6 +95,11 @@ struct vec2 } } +float dot(vec2 a, vec2 b) +{ + return a.x*b.x + a.y*b.y; +} + struct vec4 { union