diff --git a/demos/source/app.d b/demos/source/app.d index 1dbf9f4..5879daf 100644 --- a/demos/source/app.d +++ b/demos/source/app.d @@ -117,12 +117,12 @@ struct Launcher gui_manager.clear(); //launcher.ent - if(this.demo.deinitialize)this.demo.deinitialize(); - manager.begin(); manager.update("clean"); manager.end(); + if(this.demo.deinitialize)this.demo.deinitialize(); + foreach(ref system; manager.systems) { if(system.id != CountSystem.system_id && system.id != CleanSystem.system_id)system.disable(); @@ -946,12 +946,19 @@ void mainLoop(void* arg) void quit() { + import game_core.rendering : TexCoordsManager; launcher.gui_manager.clear(); Mallocator.dispose(launcher.gui_manager); + if(launcher.demo.deinitialize)launcher.demo.deinitialize(); + launcher.manager.destroy(); launcher.manager = null; + TexCoordsManager.destroy(); + + SDL_Quit(); + version(WebAssembly)emscripten_cancel_main_loop(); } @@ -1060,10 +1067,11 @@ int app_main(int argc, char** argv) } } - ImFontConfig* config = ImFontConfig_ImFontConfig(); + //ImFontConfig* config = ImFontConfig_ImFontConfig(); ImGuiIO* io = igGetIO(); const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts); - ImFontAtlas_AddFontFromFileTTF(io.Fonts,"assets/fonts/Ruda-Bold.ttf", 15.0f, config, font_ranges); + ImFontAtlas_AddFontFromFileTTF(io.Fonts,"assets/fonts/Ruda-Bold.ttf", 15.0f, null, font_ranges); + //ImFontConfig_destroy(config); setStyle(3); @@ -1139,9 +1147,6 @@ int app_main(int argc, char** argv) } } - TexCoordsManager.destroy(); - EntityManager.destroy(); - return 0; } diff --git a/demos/source/demos/brick_breaker.d b/demos/source/demos/brick_breaker.d index ec4571f..c15c503 100644 --- a/demos/source/demos/brick_breaker.d +++ b/demos/source/demos/brick_breaker.d @@ -54,6 +54,15 @@ struct CBall ubyte radius; } +struct CHitPoints +{ + mixin ECS.Component; + + alias value this; + + short value; +} + // struct CVelocityFactor // { // mixin ECS.Component; @@ -72,6 +81,13 @@ struct CBall // vec2 value = vec2(0); // } +struct EDamage +{ + mixin ECS.Event; + + ubyte damage = 1; +} + /*####################################################################################################################### ------------------------------------------------ Systems ------------------------------------------------------------------ #######################################################################################################################*/ @@ -152,7 +168,7 @@ struct BallCollisionSystem { mixin ECS.System!64; - mixin ECS.ReadOnlyDependencies!(ShootGridDependency); + mixin ECS.ReadOnlyDependencies!(ShootGridDependency, BVHDependency); struct EntitiesData { @@ -165,72 +181,136 @@ struct BallCollisionSystem @readonly CBall[] ball_flag; } + struct State + { + bool test(EntityID id) + { + Entity* entity = launcher.manager.getEntity(id); + if(entity) + { + CLocation* location = entity.getComponent!CLocation; + CScale* scale = entity.getComponent!CScale; + if(location && scale) + { + float radius = data.scale[i].x; + 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; + launcher.manager.sendEvent(id,EDamage(1)); + return false; + } + } + 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; + launcher.manager.sendEvent(id,EDamage(1)); + return false; + } + } + 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,EDamage(1)); + return false; + } + } + } + } + } + return true; + } + + EntitiesData data; + uint i; + } + ShootGrid* grid; + BVHTree* tree; + BVHTree* static_tree; bool onBegin() { - grid = launcher.manager.getSystem!ShootGridManager().grid; - if(grid is null)return false; + //grid = launcher.manager.getSystem!ShootGridManager().grid; + tree = launcher.manager.getSystem!BVHBuilder().tree; + static_tree = launcher.manager.getSystem!StaticBVHBuilder().tree; + //if(grid is null)return false; + if(tree is null || static_tree is null)return false; else return true; } void onUpdate(EntitiesData data) { - EntityID id; + // State state; + // state.data = data; + // EntityID id; + // foreach(i; 0..data.length) + // { + // state.i = i; + // float radius = data.scale[i].x; + // if(grid.test(id, data.location[i] - radius, data.location[i] + radius, ubyte.max)) + // { + // state.test(id); + // } + // } + State state; + state.data = data; 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); - } + state.i = i; + //float radius = data.scale[i].x; + AABB bounding = AABB(data.location[i]-data.scale[i], data.location[i]+data.scale[i]); + tree.test(bounding, cast(bool delegate(EntityID id))&state.test); + static_tree.test(bounding, cast(bool delegate(EntityID id))&state.test); } } } +struct DamageSystem +{ + mixin ECS.System!64; + + mixin ECS.ReadOnlyDependencies!(ShootGridDependency); + + struct EntitiesData + { + ///variable named "length" contain entites count + uint length; + const (Entity)[] entity; + CHitPoints[] hit_points; + } + + void handleEvent(Entity* entity, EDamage event) + { + EntityMeta meta = entity.getMeta(); + CHitPoints* hp = meta.getComponent!CHitPoints; + hp.value -= event.damage; + if(hp.value < 0)launcher.manager.removeEntity(entity.id); + } + +} + /*####################################################################################################################### ------------------------------------------------ Functions ------------------------------------------------------------------ #######################################################################################################################*/ @@ -239,7 +319,7 @@ struct BrickBreakerDemo { __gshared const (char)* tips = "Brick breaker demo. It's a game about destroying evil bricks."; - EntityTemplate* tmpl; + //EntityTemplate* tmpl; Texture texture; } @@ -268,12 +348,16 @@ void brickBreakerRegister() launcher.manager.registerComponent!CDamping; launcher.manager.registerComponent!CVelocityFactor; launcher.manager.registerComponent!CBall; + launcher.manager.registerComponent!CHitPoints; + + launcher.manager.registerEvent!EDamage; launcher.manager.registerSystem!MoveSystem(-100); launcher.manager.registerSystem!EdgeCollisionSystem(-99); launcher.manager.registerSystem!BallCollisionSystem(-79); launcher.manager.registerSystem!InputMovementSystem(-120); launcher.manager.registerSystem!DampingSystem(-120); + launcher.manager.registerSystem!DamageSystem(-120); launcher.manager.endRegister(); } @@ -289,11 +373,14 @@ void brickBreakerStart() EntityTemplate* brick_tmpl = launcher.manager.allocateTemplate( [CLocation.component_id, CScale.component_id, CColor.component_id, - CTexCoordsIndex.component_id, CShootGrid.component_id].staticArray + CTexCoordsIndex.component_id, CBVH.component_id, CHitPoints.component_id, + CAABB.component_id, CStatic.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); + brick_tmpl.getComponent!CHitPoints().value = 2; + //brick_tmpl.getComponent!CAABB().bounding = AABB(vec2(),vec2()); EntityTemplate* big_brick_tmpl = launcher.manager.allocateTemplate(brick_tmpl); big_brick_tmpl.getComponent!CTexCoordsIndex().value = TexCoordsManager.instance.getCoordIndex(vec4(320,32,16,16)*px); @@ -302,7 +389,8 @@ void brickBreakerStart() 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 + CDamping.component_id, CVelocityFactor.component_id, CBVH.component_id, + CAABB.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); @@ -330,7 +418,11 @@ void brickBreakerStart() launcher.gui_manager.addComponent(CBall(), "Ball"); launcher.gui_manager.addSystem(MoveSystem.system_id, "Move System"); + launcher.gui_manager.addSystem(EdgeCollisionSystem.system_id, "Edge Collision System"); launcher.gui_manager.addSystem(BallCollisionSystem.system_id, "Ball Collision System"); + launcher.gui_manager.addSystem(InputMovementSystem.system_id, "Input Movement System"); + launcher.gui_manager.addSystem(DampingSystem.system_id, "Damping System"); + launcher.gui_manager.addSystem(DamageSystem.system_id, "Damage System"); launcher.gui_manager.addTemplate(brick_tmpl, "Brick"); launcher.gui_manager.addTemplate(big_brick_tmpl, "Big Brick"); diff --git a/demos/source/demos/snake.d b/demos/source/demos/snake.d index 525b4ab..865ab75 100644 --- a/demos/source/demos/snake.d +++ b/demos/source/demos/snake.d @@ -72,7 +72,7 @@ struct Snake bool move_system = true; bool draw_system = true; - const int map_size = 18; + enum int map_size = 18; MapElement[map_size * map_size] map; @@ -83,7 +83,7 @@ struct Snake if(apple_tmpl)launcher.manager.freeTemplate(apple_tmpl); if(snake_tmpl)launcher.manager.freeTemplate(snake_tmpl); if(snake_destroy_particle)launcher.manager.freeTemplate(snake_destroy_particle); - texture.destory(); + texture.destroy(); } MapElement element(ivec2 pos) diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index 66be099..ece3c2b 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -64,7 +64,7 @@ struct SpaceInvaders { if(tmpl)launcher.manager.freeTemplate(tmpl); } - texture.destory(); + texture.destroy(); } } @@ -90,7 +90,7 @@ struct SceneGrid cells = Mallocator.makeArray!Cell(cells_count.x * cells_count.y); } - void destory() + void destroy() { if(cells) { @@ -707,6 +707,7 @@ struct ShipWeaponSystem void onDestroy() { + __xdtor(); /*launcher.manager.freeTemplate(laser1_tmpl); launcher.manager.freeTemplate(laser2_tmpl); launcher.manager.freeTemplate(main_weapon_tmpl);*/ diff --git a/demos/source/game_core/collision.d b/demos/source/game_core/collision.d index 75c46f8..794f8d8 100644 --- a/demos/source/game_core/collision.d +++ b/demos/source/game_core/collision.d @@ -1,10 +1,13 @@ module game_core.collision; import bubel.ecs.attributes; +import bubel.ecs.block_allocator; import bubel.ecs.core; import bubel.ecs.std; +import bubel.ecs.vector; import ecs_utils.math.vector; +import ecs_utils.utils; import game_core.basic; @@ -12,22 +15,54 @@ import game_core.basic; void registerCollisionModule(EntityManager* manager) { manager.registerDependency(ShootGridDependency); + manager.registerDependency(BVHDependency); + manager.registerDependency(StaticBVHDependency); manager.registerComponent!CShootGrid; manager.registerComponent!CShootGridMask; manager.registerComponent!CColliderScale; + manager.registerComponent!CBVH; + manager.registerComponent!CAABB; + manager.registerComponent!CStatic; manager.registerSystem!ShootGridManager(-80); manager.registerSystem!ShootGridCleaner(-101); + manager.registerSystem!BVHBuilder(-80); + manager.registerSystem!StaticBVHBuilder(-80); + //manager.registerSystem!BVHBuilder2(-79); + manager.registerSystem!AABBUpdater(-81); } enum ShootGridDependency = "ShootGridDependency"; +enum BVHDependency = "BVHDependency"; +enum StaticBVHDependency = "StaticBVHDependency"; struct CShootGrid { mixin ECS.Component; } +struct CBVH +{ + mixin ECS.Component; + + uint index; +} + +struct CStatic +{ + mixin ECS.Component; +} + +struct CAABB +{ + mixin ECS.Component; + + alias bounding this; + + AABB bounding; +} + struct CShootGridMask { mixin ECS.Component; @@ -46,6 +81,7 @@ struct CColliderScale vec2 value = vec2(16,16); } + struct ShootGrid { @@ -84,7 +120,7 @@ struct ShootGrid foreach(j; ibeg.x .. iend.x) { nodes[i * size.x + j] = id; - masks[i * size.x +j] = mask; + masks[i * size.x + j] = mask; } } } @@ -229,4 +265,759 @@ struct ShootGridManager } } +} + +struct AABB +{ + vec2 size() + { + return max-min; + } + + vec2 center() + { + return (max+min) * 0.5; + } + + float area() + { + return size.x * size.y; + } + + void set(ref AABB base, vec2 position, float angle, vec2 scale) + { + import std.algorithm.comparison : max; + + float sr = sinf(angle); + float cr = cosf(angle); + /*mat2 m = mat2(cr,-sr, + sr,cr);*/ + + + //vec2 pos = ;//m * ((base.max + base.min)*0.5*scale); + vec2 size = (base.max - base.min)*scale; + vec2[2] axis = [vec2(cr*size.x,sr*size.y),vec2(-sr*size.x,cr*size.y)]; + + this.max.x = max(fabs(axis[0].x),fabs(axis[1].x)); + this.max.y = max(fabs(axis[0].y),fabs(axis[1].y)); + + this.min = -this.max; + + this.min += center + position; + this.max += center + position; + } + + void set(ref AABB base, vec2 position, vec2 scale) + { + vec2 size = (base.max - base.min)*scale; + + this.min = -size; + this.max = size; + + this.min += center + position; + this.max += center + position; + } + + void set(ref AABB base, vec2 position, float angle) + { + import std.algorithm.comparison : max; + + float sr = sinf(angle); + float cr = cosf(angle); + /*mat2 m = mat2(cr,-sr, + sr,cr);*/ + + + //vec2 pos = ;//m * ((base.max + base.min)*0.5*scale); + vec2 size = (base.max - base.min);//*scale; + vec2[2] axis = [vec2(cr*size.x,sr*size.y),vec2(-sr*size.x,cr*size.y)]; + + this.max.x = max(fabs(axis[0].x),fabs(axis[1].x)); + this.max.y = max(fabs(axis[0].y),fabs(axis[1].y)); + + this.min = -this.max; + + this.min += center + position; + this.max += center + position; + } + + void set(ref AABB base, vec2 position) + { + min = base.min + position; + max = base.max + position; + } + + vec2 min; + vec2 max; +} + +bool test(AABB a, AABB b) +{ + if((a.max.x>b.min.x && a.max.y>b.min.y) && + (a.min.x b.max.x && a.max.y > b.max.y)return 2; + else if((a.max.x>b.min.x && a.max.y>b.min.y) && + (a.min.xb.min.x && point.y>b.min.y) && + (point.x