diff --git a/demos/assets/textures/atlas.png b/demos/assets/textures/atlas.png index 1e269e5..a799eb7 100644 Binary files a/demos/assets/textures/atlas.png and b/demos/assets/textures/atlas.png differ diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index 56d891d..f61df5c 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -16,12 +16,15 @@ import ecs_utils.gfx.texture; import ecs_utils.math.vector; import ecs_utils.utils; -import std.math : PI; +//import std.math : PI; + +enum PI = 3.141592653589793238462643383279502884197169399375105820; //import std.array : staticArray; enum float px = 1.0/512.0; + extern(C): enum ShootGridDependency = "ShootGridDependency"; @@ -47,6 +50,8 @@ struct SpaceInvaders const vec2 map_size = vec2(400,300); const float cell_size = 60; + EntityID player_ship; + ~this() @nogc nothrow { if(shoot_grid)Mallocator.dispose(shoot_grid); @@ -123,6 +128,15 @@ struct CScale vec2 value = vec2(16,16); } +struct CColliderScale +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(16,16); +} + struct CRotation { mixin ECS.Component; @@ -137,7 +151,8 @@ struct CTexture { mixin ECS.Component; - Texture tex; + //Texture tex; + uint id; vec4 coords = vec4(0,0,0,1); } @@ -203,6 +218,13 @@ struct CLaserWeapon float shoot_time = 0; } +struct CWeaponLocation +{ + mixin ECS.Component; + + vec2 rel_pos = vec2(0,0); +} + struct CShootDirection { mixin ECS.Component; @@ -239,6 +261,7 @@ struct CTargetPartent vec2 rel_pos; } + struct CHitPoints { mixin ECS.Component; @@ -312,6 +335,68 @@ struct CParticle float life = 0; } +struct CTarget +{ + mixin ECS.Component; + + EntityID target; +} + +struct CTargetPlayerShip +{ + mixin ECS.Component; +} + +struct CChildren +{ + mixin ECS.Component; + + EntityID[] childern; +} + +struct CBoss +{ + mixin ECS.Component; +} + +struct CParts +{ + mixin ECS.Component; + + ubyte count; +} + +struct CInit +{ + mixin ECS.Component; + + enum Type + { + space_ship, + tower, + boss + } + + Type type; +} + +struct CParticleEmitter +{ + mixin ECS.Component; + + vec2 range; + vec2 time_range; +} + +///Due to perfarmance reason emitter time and attributes are divided into seprate components. +///Beyon that both components are considerd to be used together. +struct CParticleEmitterTime +{ + mixin ECS.Component; + + float time; +} + /*####################################################################################################################### ------------------------------------------------ Events ------------------------------------------------------------------ #######################################################################################################################*/ @@ -350,6 +435,18 @@ struct EDamage uint damage = 0; } +struct EDestroyedChild +{ + mixin ECS.Event; + + this(EntityID id) + { + this.id = id; + } + + EntityID id; +} + /*####################################################################################################################### ------------------------------------------------ Systems ------------------------------------------------------------------ #######################################################################################################################*/ @@ -477,9 +574,10 @@ struct ShootGridManager uint thread_id; const (Entity)[] entity; @readonly CLocation[] locations; - @readonly CScale[] scale; @readonly CShootGrid[] grid_flag; @readonly CGuild[] guild; + @optional @readonly CScale[] scale; + @optional @readonly CColliderScale[] collider_scale; } ShootGrid* grid; @@ -498,14 +596,310 @@ struct ShootGridManager 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 = data.scale[i] * 0.5; + 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; + + struct EntitiesData + { + CChildren[] children; + } + + void onRemoveEntity(EntitiesData data) + { + //currently EntitiesData always has only one element + foreach(child; data.children[0].childern) + { + launcher.manager.removeEntity(child); + } + if(data.children[0].childern.length)Mallocator.dispose(data.children[0].childern); + } +} + +struct ShipWeaponSystem +{ + mixin ECS.System; + + struct EntitiesData + { + int length; + Entity[] entity; + CInit[] init; + //CShip[] ship; + //CChildren[] children; + } + + struct Ship + { + EntityTemplate* laser1_tmpl; + EntityTemplate* laser2_tmpl; + EntityTemplate* main_weapon_tmpl; + + void add(Entity* entity) + { + CChildren* children = entity.getComponent!CChildren; + if(children is null || children.childern.length != 0)return; + EntityID[3] weapons; + laser1_tmpl.getComponent!CTargetPartent().parent = entity.id; + laser2_tmpl.getComponent!CTargetPartent().parent = entity.id; + main_weapon_tmpl.getComponent!CTargetPartent().parent = entity.id; + weapons[0] = launcher.manager.addEntity(laser1_tmpl).id; + weapons[1] = launcher.manager.addEntity(laser2_tmpl).id; + weapons[2] = launcher.manager.addEntity(main_weapon_tmpl).id; + children.childern = Mallocator.makeArray(weapons); + } + + void create() + { + laser1_tmpl = launcher.manager.allocateTemplate([CLaserWeapon.component_id, CLocation.component_id, CShootDirection.component_id, CTargetPartent.component_id, CGuild.component_id, CVelocity.component_id].staticArray); + main_weapon_tmpl = launcher.manager.allocateTemplate([CLocation.component_id, CShootDirection.component_id, CTargetPartent.component_id, CGuild.component_id, CVelocity.component_id].staticArray); + *laser1_tmpl.getComponent!CLaserWeapon = CLaserWeapon(3,0.0); + laser1_tmpl.getComponent!CTargetPartent().rel_pos = vec2(10,13); + main_weapon_tmpl.getComponent!CTargetPartent().rel_pos = vec2(0,4); + laser2_tmpl = launcher.manager.allocateTemplate(laser1_tmpl); + laser2_tmpl.getComponent!CTargetPartent().rel_pos = vec2(-10,13); + } + + ~this() + { + launcher.manager.freeTemplate(laser1_tmpl); + launcher.manager.freeTemplate(laser2_tmpl); + launcher.manager.freeTemplate(main_weapon_tmpl); + } + } + + struct Tower + { + EntityTemplate* weapon_tmpl; + EntityTemplate* top_tmpl; + + void add(Entity* entity) + { + CChildren* children = entity.getComponent!CChildren; + if(children is null || children.childern.length != 0)return; + CDepth* depth = entity.getComponent!CDepth; + EntityID[2] weapons; + weapon_tmpl.getComponent!CTargetPartent().parent = entity.id; + if(depth)weapon_tmpl.getComponent!CDepth().depth = cast(short)(depth.depth - 1); + else weapon_tmpl.getComponent!CDepth().depth = -1; + top_tmpl.getComponent!CTargetPartent().parent = entity.id; + if(depth)top_tmpl.getComponent!CDepth().depth = cast(short)(depth.depth - 2); + else top_tmpl.getComponent!CDepth().depth = -2; + + weapons[0] = launcher.manager.addEntity(weapon_tmpl).id; + weapons[1] = launcher.manager.addEntity(top_tmpl).id; + children.childern = Mallocator.makeArray(weapons); + } + + void create() + { + weapon_tmpl = launcher.manager.allocateTemplate( + [CLaserWeapon.component_id, CLocation.component_id, CShootDirection.component_id, + CTargetPartent.component_id, CGuild.component_id, CVelocity.component_id, + CAutoShoot.component_id, CTarget.component_id, CTargetPlayerShip.component_id, + CRotation.component_id, CScale.component_id, CTexture.component_id, + CDepth.component_id, CWeaponLocation.component_id].staticArray); + *weapon_tmpl.getComponent!CLaserWeapon = CLaserWeapon(3,0.0); + weapon_tmpl.getComponent!CTargetPartent().rel_pos = vec2(0,0); + weapon_tmpl.getComponent!CGuild().guild = 1; + weapon_tmpl.getComponent!CScale().value = vec2(4,16); + weapon_tmpl.getComponent!CLaserWeapon().level = 1; + weapon_tmpl.getComponent!CDepth().depth = -1; + weapon_tmpl.getComponent!CTexture().coords = vec4(136,96,4,16)*px; + weapon_tmpl.getComponent!CWeaponLocation().rel_pos = vec2(0,12); + + top_tmpl = launcher.manager.allocateTemplate( + [CLocation.component_id, CTargetPartent.component_id, CScale.component_id, + CTexture.component_id, CDepth.component_id].staticArray); + top_tmpl.getComponent!CTargetPartent().rel_pos = vec2(0,1); + top_tmpl.getComponent!CScale().value = vec2(10,11); + top_tmpl.getComponent!CDepth().depth = -2; + top_tmpl.getComponent!CTexture().coords = vec4(112,96,10,11)*px; + + } + + ~this() + { + launcher.manager.freeTemplate(weapon_tmpl); + launcher.manager.freeTemplate(top_tmpl); + } + } + + struct Boss + { + EntityTemplate* tower1_tmpl; + EntityTemplate* tower2_tmpl; + EntityTemplate* tower3_tmpl; + EntityTemplate* tower4_tmpl; + + void add(Entity* entity) + { + CChildren* children = entity.getComponent!CChildren; + if(children is null || children.childern.length != 0)return; + CParts* parts = entity.getComponent!CParts; + if(parts)parts.count = 4; + EntityID[4] towers; + tower1_tmpl.getComponent!CTargetPartent().parent = entity.id; + tower2_tmpl.getComponent!CTargetPartent().parent = entity.id; + tower3_tmpl.getComponent!CTargetPartent().parent = entity.id; + tower4_tmpl.getComponent!CTargetPartent().parent = entity.id; + towers[0] = launcher.manager.addEntity(tower1_tmpl).id; + towers[1] = launcher.manager.addEntity(tower2_tmpl).id; + towers[2] = launcher.manager.addEntity(tower3_tmpl).id; + towers[3] = launcher.manager.addEntity(tower4_tmpl).id; + children.childern = Mallocator.makeArray(towers); + } + + void create() + { + tower1_tmpl = launcher.manager.allocateTemplate( + [CHitMark.component_id, CHitPoints.component_id, CLocation.component_id, + CTexture.component_id, CScale.component_id, CEnemy.component_id, + CShootGrid.component_id, CGuild.component_id, CInit.component_id, + CChildren.component_id, CDepth.component_id, CTargetPartent.component_id].staticArray + ); + + CTexture* tex_comp = tower1_tmpl.getComponent!CTexture; + //tex_comp.tex = space_invaders.texture;//ship_tex; + tex_comp.coords = vec4(96*px,96*px,16*px,16*px); + CLocation* loc_comp = tower1_tmpl.getComponent!CLocation; + loc_comp.value = vec2(64,space_invaders.map_size.y - 16); + tower1_tmpl.getComponent!CGuild().guild = 1; + tower1_tmpl.getComponent!CInit().type = CInit.Type.tower; + tower1_tmpl.getComponent!CHitPoints().value = 10; + tower1_tmpl.getComponent!CDepth().depth = -5; + tower1_tmpl.getComponent!CTargetPartent().rel_pos = vec2(-33,2); + + tower2_tmpl = launcher.manager.allocateTemplate(tower1_tmpl); + tower2_tmpl.getComponent!CTargetPartent().rel_pos = vec2(33,2); + + tower3_tmpl = launcher.manager.allocateTemplate(tower1_tmpl); + tower3_tmpl.getComponent!CTargetPartent().rel_pos = vec2(-39,-15); + + tower4_tmpl = launcher.manager.allocateTemplate(tower1_tmpl); + tower4_tmpl.getComponent!CTargetPartent().rel_pos = vec2(39,-15); + } + + ~this() + { + launcher.manager.freeTemplate(tower1_tmpl); + launcher.manager.freeTemplate(tower2_tmpl); + launcher.manager.freeTemplate(tower3_tmpl); + launcher.manager.freeTemplate(tower4_tmpl); + } + } + + Ship ship; + Tower tower; + Boss boss; + + void onCreate() + { + ship.create(); + tower.create(); + boss.create(); + /*ship.laser1_tmpl = launcher.manager.allocateTemplate([CLaserWeapon.component_id, CLocation.component_id, CShootDirection.component_id, CTargetPartent.component_id, CGuild.component_id, CVelocity.component_id].staticArray); + ship.main_weapon_tmpl = launcher.manager.allocateTemplate([CLocation.component_id, CShootDirection.component_id, CTargetPartent.component_id, CGuild.component_id, CVelocity.component_id].staticArray); + *ship.laser1_tmpl.getComponent!CLaserWeapon = CLaserWeapon(3,0.0); + ship.laser1_tmpl.getComponent!CTargetPartent().rel_pos = vec2(10,13); + ship.main_weapon_tmpl.getComponent!CTargetPartent().rel_pos = vec2(0,4); + ship.laser2_tmpl = launcher.manager.allocateTemplate(ship.laser1_tmpl); + ship.laser2_tmpl.getComponent!CTargetPartent().rel_pos = vec2(-10,13);*/ + } + + void onDestroy() + { + /*launcher.manager.freeTemplate(laser1_tmpl); + launcher.manager.freeTemplate(laser2_tmpl); + launcher.manager.freeTemplate(main_weapon_tmpl);*/ + } + + void onAddEntity(EntitiesData data) + { + foreach(i; 0..data.length) + { + /*if(data.children[i].childern.length != 0)continue; + EntityID[3] weapons; + laser1_tmpl.getComponent!CTargetPartent().parent = data.entity[i].id; + laser2_tmpl.getComponent!CTargetPartent().parent = data.entity[i].id; + main_weapon_tmpl.getComponent!CTargetPartent().parent = data.entity[i].id; + weapons[0] = launcher.manager.addEntity(laser1_tmpl).id; + weapons[1] = launcher.manager.addEntity(laser2_tmpl).id; + weapons[2] = launcher.manager.addEntity(main_weapon_tmpl).id; + data.children[i].childern = Mallocator.makeArray(weapons);*/ + final switch(data.init[i].type) + { + case CInit.Type.space_ship:ship.add(&data.entity[i]);break; + case CInit.Type.tower:tower.add(&data.entity[i]);break; + case CInit.Type.boss:boss.add(&data.entity[i]);break; + } + + } + } +} + +struct MoveToParentTargetSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + int length; + CLocation[] location; + @optional CVelocity[] velocity; + @readonly CTargetPartent[] target; + } + + void onUpdate(EntitiesData data) + { + if(data.velocity) + { + foreach(i;0..data.length) + { + Entity* target = launcher.manager.getEntity(data.target[i].parent); + if(target) + { + CLocation* target_loc = target.getComponent!CLocation; + if(target_loc != null) + { + data.location[i] = *target_loc + data.target[i].rel_pos; + } + CVelocity* target_vel = target.getComponent!CVelocity; + if(target_vel != null) + { + data.velocity[i] = *target_vel; + } + } + } + } + else + foreach(i;0..data.length) + { + Entity* target = launcher.manager.getEntity(data.target[i].parent); + if(target) + { + CLocation* target_loc = target.getComponent!CLocation; + if(target_loc != null) + { + data.location[i] = *target_loc + data.target[i].rel_pos; + } + } + } + } +} + struct DrawSystem { mixin ECS.System!32; @@ -531,21 +925,24 @@ struct DrawSystem foreach(i; 0..data.length) { uint color = 0x80808080 + 0x01010101 * data.hit_mark[i]; - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)data.locations[i].y, color, 0, 0, 0, data.thread_id); + short depth = cast(short)(data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, color, 0, 0, 0, data.thread_id); } } else if(data.rotation) { foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)data.locations[i].y, 0x80808080, data.rotation[i], 0, 0, data.thread_id); + short depth = cast(short)(data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, 0x80808080, data.rotation[i], 0, 0, data.thread_id); } } else { foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)data.locations[i].y, 0x80808080, 0, 0, 0, data.thread_id); + short depth = cast(short)(data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, 0x80808080, 0, 0, 0, data.thread_id); } } } @@ -558,7 +955,8 @@ struct DrawSystem foreach(i; 0..data.length) { uint color = 0x80808080 + 0x01010101 * data.hit_mark[i]; - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)(data.depth[i] * 4 + data.locations[i].y), color, data.rotation[i], 0, 0, data.thread_id); + short depth = cast(short)(data.depth[i] * 16 + data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, color, data.rotation[i], 0, 0, data.thread_id); } } else @@ -566,7 +964,8 @@ struct DrawSystem foreach(i; 0..data.length) { uint color = 0x80808080 + 0x01010101 * data.hit_mark[i]; - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)(data.depth[i] * 4 + data.locations[i].y), color, 0, 0, 0, data.thread_id); + short depth = cast(short)(data.depth[i] * 16 + data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, color, 0, 0, 0, data.thread_id); } } } @@ -574,14 +973,16 @@ struct DrawSystem { foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)(data.depth[i] * 4 + data.locations[i].y), 0x80808080, data.rotation[i], 0, 0, data.thread_id); + short depth = cast(short)(data.depth[i] * 16 + data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, 0x80808080, data.rotation[i], 0, 0, data.thread_id); } } else { foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].value, data.scale[i], data.textures[i].coords, cast(short)(data.depth[i] * 4 + data.locations[i].y), 0x80808080, 0, 0, 0, data.thread_id); + short depth = cast(short)(data.depth[i] * 16 + data.locations[i].y*8 + data.locations[i].x); + launcher.renderer.draw(space_invaders.texture, data.locations[i].value, data.scale[i], data.textures[i].coords, depth, 0x80808080, 0, 0, 0, data.thread_id); } } } @@ -628,12 +1029,15 @@ struct LaserShootingSystem uint length; ///variable named "length" contain thread identifier uint thread_id; - @readonly CShootDirection[] shoot_direction; - @readonly @optional CAutoShoot[] auto_shoot; + CLaserWeapon[] laser; @readonly CLocation[] location; @readonly CGuild[] guild; + + @optional @readonly CShootDirection[] shoot_direction; + @optional @readonly CWeaponLocation[] weapon_location; + @optional @readonly CAutoShoot[] auto_shoot; @optional @readonly CVelocity[] velocity; - CLaserWeapon[] laser; + @optional @readonly CRotation[] rotation; } struct ThreadData @@ -661,7 +1065,7 @@ struct LaserShootingSystem ); CTexture* tex_comp = threads[0].laser_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//laser_tex; + //tex_comp.tex = space_invaders.texture;//laser_tex; tex_comp.coords = vec4(0*px,24*px,2*px,8*px); CScale* scale_comp = threads[0].laser_tmpl.getComponent!CScale; scale_comp.value = vec2(2,8); @@ -676,7 +1080,7 @@ struct LaserShootingSystem ); tex_comp = threads[0].fire_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//laser_tex; + //tex_comp.tex = space_invaders.texture;//laser_tex; tex_comp.coords = vec4(96*px,64*px,8*px,16*px); scale_comp = threads[0].fire_tmpl.getComponent!CScale; scale_comp.value = vec2(8,16); @@ -736,8 +1140,13 @@ struct LaserShootingSystem { laser.shoot_time -= CLaserWeapon.levels[laser.level - 1].reload_time; thread.laser_location.value = data.location[i]; - thread.laser_velocity.value = vec2((randomf()*2-1) * CLaserWeapon.levels[laser.level - 1].dispersion,data.shoot_direction[i].direction == Direction.up ? 1.0 : -1.0); + + thread.laser_velocity.value = vec2((randomf()*2-1) * CLaserWeapon.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)thread.laser_velocity.y = -1; + thread.laser_guild.guild = data.guild[i].guild; + + if(laser.level < 3)thread.laser_velocity.value = thread.laser_velocity.value * 0.4f; if(data.velocity) { @@ -746,19 +1155,40 @@ struct LaserShootingSystem } else thread.fire_velocity.value = vec2(0,0); - launcher.manager.addEntity(thread.laser_tmpl); - thread.fire_location.value = data.location[i]; if(data.shoot_direction[i].direction == Direction.down) { thread.fire_rotation.value = PI; - thread.fire_location.value.y -= 16; + //thread.fire_location.value.y -= 16; } else { thread.fire_rotation.value = 0; - thread.fire_location.value.y += 24; + //thread.fire_location.value.y += 24; } + + if(data.rotation) + { + float sinn = sinf(data.rotation[i]); + float coss = cosf(data.rotation[i]); + float x = thread.laser_velocity.y*sinn + thread.laser_velocity.x*coss; + float y = thread.laser_velocity.y*coss + thread.laser_velocity.x*sinn; + thread.laser_velocity.value = vec2(x,y); + thread.fire_rotation.value = data.rotation[i]; + if(data.weapon_location) + { + vec2 rel_pos = vec2(data.weapon_location[i].rel_pos.y*sinn+data.weapon_location[i].rel_pos.x*coss, data.weapon_location[i].rel_pos.y*coss+data.weapon_location[i].rel_pos.x*sinn); + thread.laser_location.value += rel_pos; + thread.fire_location.value += rel_pos; + } + } + else if(data.weapon_location) + { + thread.laser_location.value += data.weapon_location[i].rel_pos; + thread.fire_location.value += data.weapon_location[i].rel_pos; + } + + launcher.manager.addEntity(thread.laser_tmpl); launcher.manager.addEntity(thread.fire_tmpl); } } @@ -792,7 +1222,6 @@ struct DampingSystem bool onBegin() { - import core.stdc.math : powf; foreach(i;0..10) { damp[i] = powf((0.98 - cast(float)i * 0.02),launcher.delta_time*0.1); @@ -880,7 +1309,7 @@ struct UpgradeSystem struct EntitiesData { const (Entity)[] entity; - @readonly CShip[] ship; + //@readonly CShip[] ship; } void handleEvent(Entity* entity, EUpgrade event) @@ -890,6 +1319,15 @@ struct UpgradeSystem { if(laser.level < CLaserWeapon.levels.length)laser.level++; } + CShip* ship = entity.getComponent!CShip; + if(ship) + { + CChildren* children = entity.getComponent!CChildren; + foreach(child;children.childern) + { + launcher.manager.sendEvent(child,EUpgrade()); + } + } } } @@ -908,6 +1346,7 @@ struct ChangeDirectionSystem CVelocity[] velocity; const(CSideMove)[] side_move; + @optional const(CScale)[] scale; } void onCreate() @@ -918,20 +1357,6 @@ struct ChangeDirectionSystem } } - /*bool onBegin() - { - foreach(direction; groups_directions) - { - if(direction != cast(Direction)-1)//return true; - { - has_changes = true; -INFO: Uniform block alig - break; - } - } - return true; - }*/ - void onEnd() { if(has_changes) @@ -947,13 +1372,8 @@ INFO: Uniform block alig if(direction != cast(Direction)-1) { has_changes = true; - //direction = cast(Direction)-1; } } - /*foreach(ref direction; groups_directions) - { - direction = cast(Direction)-1; - }*/ } void onUpdate(EntitiesData data) @@ -998,6 +1418,34 @@ INFO: Uniform block alig } } } + else if(data.scale) + { + foreach(i;0..data.length) + { + if(data.locations[i].x - data.scale[i].x * 0.5 < 0) + { + if(data.side_move[i].group == -1) + { + if(data.velocity[i].x < 0)data.velocity[i].x = -data.velocity[i].x; + } + else + { + groups_directions[data.side_move[i].group] = Direction.right; + } + } + else if(data.locations[i].x + data.scale[i].x * 0.5 > space_invaders.map_size.x) + { + if(data.side_move[i].group == -1) + { + if(data.velocity[i].x > 0)data.velocity[i].x = -data.velocity[i].x; + } + else + { + groups_directions[data.side_move[i].group] = Direction.left; + } + } + } + } else { foreach(i;0..data.length) @@ -1024,38 +1472,9 @@ INFO: Uniform block alig groups_directions[data.side_move[i].group] = Direction.left; } } - //if(data.locations[i].y < 0) data.locations[i].y = 0; - //else if(data.locations[i].y > space_invaders.map_size.y)data.locations[i].y = space_invaders.map_size.y; } } } - - /*void handleEvent(Entity* entity, EChangeDirection event) - { - CSideMove* side_move = entity.getComponent!CSideMove; - if(side_move && side_move.group != -1) - { - groups_directions[side_move.group] = event.direction; - return; - } - //Entity* entity = launcher.manager.getEntity(event.entity_id); - CVelocity* velocity = entity.getComponent!CVelocity; - final switch(event.direction) - { - case Direction.up: - if(velocity.value.y > 0)velocity.value.y = -velocity.value.y; - break; - case Direction.down: - if(velocity.value.y < 0)velocity.value.y = -velocity.value.y; - break; - case Direction.left: - if(velocity.value.x > 0)velocity.value.x = -velocity.value.x; - break; - case Direction.right: - if(velocity.value.x < 0)velocity.value.x = -velocity.value.x; - break; - } - }*/ } struct HitMarkingSystem @@ -1101,7 +1520,7 @@ struct HitPointsSystem { upgrade_tmpl = launcher.manager.allocateTemplate([CVelocity.component_id, CLocation.component_id, CTexture.component_id, CScale.component_id, CUpgrade.component_id, CAnimation.component_id, CAnimationLooped.component_id].staticArray); CTexture* tex_comp = upgrade_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//ship_tex; + //tex_comp.tex = space_invaders.texture;//ship_tex; tex_comp.coords = vec4(0*px,32*px,16*px,16*px); *upgrade_tmpl.getComponent!CAnimation = CAnimation(upgrade_laser_frames, 0, 1); CVelocity* vel_comp = upgrade_tmpl.getComponent!CVelocity; @@ -1109,7 +1528,7 @@ struct HitPointsSystem upgrade_location = upgrade_tmpl.getComponent!CLocation; explosion_tmpl = launcher.manager.allocateTemplate([CDepth.component_id, CParticle.component_id, CLocation.component_id, CTexture.component_id, CScale.component_id, CAnimation.component_id].staticArray); - explosion_tmpl.getComponent!(CTexture).tex = space_invaders.texture; + //explosion_tmpl.getComponent!(CTexture).tex = space_invaders.texture; *explosion_tmpl.getComponent!CAnimation = CAnimation(explosion_laser_frames, 0, 1.333); explosion_tmpl.getComponent!(CParticle).life = 600; *explosion_tmpl.getComponent!CDepth = -1; @@ -1156,6 +1575,47 @@ struct HitPointsSystem } } +struct ChildDestroySystem +{ + mixin ECS.System; + + struct EntitiesData + { + CTargetPartent[] parent; + } + + void handleEvent(Entity* entity, EDeath event) + { + CTargetPartent* parent = entity.getComponent!CTargetPartent; + if(parent) + { + launcher.manager.sendEvent(parent.parent, EDestroyedChild(entity.id)); + } + } +} + +struct PartsDestroySystem +{ + mixin ECS.System; + + struct EntitiesData + { + CInit[] init; + CChildren[] children; + CParts[] parts; + } + + void handleEvent(Entity* entity, EDestroyedChild event) + { + CParts* parts = entity.getComponent!CParts; + parts.count--; + if(parts.count == 0) + { + launcher.manager.addComponents(entity.id, CHitPoints(100), CShootGrid()); + } + } +} + struct ClampPositionSystem { mixin ECS.System!32; @@ -1168,7 +1628,10 @@ struct ClampPositionSystem //components are treated as required by default CLocation[] locations; + @optional @readonly CColliderScale[] collider_scale; + @optional @readonly CScale[] scale; @optional const (CLaser)[] laser; + @optional const (CUpgrade)[] upgrade; //@optional CVelocity[] velocity; //@optional const (CSideMove)[] side_move; } @@ -1177,7 +1640,7 @@ struct ClampPositionSystem void onUpdate(EntitiesData data) { - if(data.laser) + if(data.laser || data.upgrade) { foreach(i;0..data.length) { @@ -1219,6 +1682,28 @@ struct ClampPositionSystem else if(data.locations[i].y > space_invaders.map_size.y)data.locations[i].y = space_invaders.map_size.y; } }*/ + else if(data.collider_scale) + { + foreach(i;0..data.length) + { + vec2 hscale = data.collider_scale[i] * 0.5; + if(data.locations[i].x - hscale.x < 0)data.locations[i].x = hscale.x; + else if(data.locations[i].x + hscale.x > space_invaders.map_size.x)data.locations[i].x = space_invaders.map_size.x - hscale.x; + if(data.locations[i].y - hscale.y < 0)data.locations[i].y = hscale.y; + else if(data.locations[i].y + hscale.y > space_invaders.map_size.y)data.locations[i].y = space_invaders.map_size.y - hscale.y; + } + } + else if(data.scale) + { + foreach(i;0..data.length) + { + vec2 hscale = data.scale[i] * 0.5; + if(data.locations[i].x - hscale.x < 0)data.locations[i].x = hscale.x; + else if(data.locations[i].x + hscale.x > space_invaders.map_size.x)data.locations[i].x = space_invaders.map_size.x - hscale.x; + if(data.locations[i].y - hscale.y < 0)data.locations[i].y = hscale.y; + else if(data.locations[i].y + hscale.y > space_invaders.map_size.y)data.locations[i].y = space_invaders.map_size.y - hscale.y; + } + } else { foreach(i;0..data.length) @@ -1317,7 +1802,116 @@ struct ParticleSystem } } +struct RotateToTargetSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + int length; + @readonly CTarget[] target; + @readonly CLocation[] location; + CRotation[] rotation; + } + + void onUpdate(EntitiesData data) + { + foreach(i;0..data.length) + { + Entity* target = launcher.manager.getEntity(data.target[i].target); + if(target) + { + CLocation* target_loc = target.getComponent!CLocation; + if(target_loc) + { + vec2 rel_pos = target_loc.value - data.location[i]; + float length = sqrtf(rel_pos.x*rel_pos.x + rel_pos.y*rel_pos.y); + if(rel_pos.x > 0)data.rotation[i] = acosf(rel_pos.y/length); + else data.rotation[i] = 2 * PI - acosf(rel_pos.y/length); + + } + } + //CLocation* target_loc = + //vec2 rel_pos = d + //data.rotation = 0; + } + } +} + +struct ShipTargetSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + int length; + @readonly CTargetPlayerShip[] target_player; + CTarget[] target; + } + + EntityID player_ship; + + void iterateShips(CShipIterator.EntitiesData data) + { + player_ship = data.entity[0].id; + } + + void onAddEntity(EntitiesData data) + { + foreach(i;0..data.length) + { + data.target[i].target = player_ship; + } + } + + bool onBegin() + { + Entity* ship = launcher.manager.getEntity(player_ship); + if(ship is null) + { + launcher.manager.callEntitiesFunction!CShipIterator(&iterateShips); + ship = launcher.manager.getEntity(player_ship); + if(ship is null)return false; + return true; + } + return false; + } + + void onUpdate(EntitiesData data) + { + foreach(i;0..data.length) + { + data.target[i].target = player_ship; + } + } +} + +struct CShipIterator +{ + mixin ECS.System!1; + + struct EntitiesData + { + @readonly Entity[] entity; + @readonly CShip[] ship; + } + + bool onBegin() + { + return false; + } + + void onUpdate(EntitiesData data) + { + + } +} + extern(C) float sqrtf(float x) @nogc nothrow @system; +extern(C) float acosf(float x) @nogc nothrow @system; +extern(C) float sinf(float x) @nogc nothrow @system; +extern(C) float cosf(float x) @nogc nothrow @system; +extern(C) float powf(float x, float y) @nogc nothrow @system; /** *System is responsible for movement of objects with CInput component. @@ -1455,11 +2049,23 @@ void spaceInvadersStart() launcher.manager.registerComponent!CRotation; launcher.manager.registerComponent!CAnimationLooped; launcher.manager.registerComponent!CDamping; + launcher.manager.registerComponent!CTargetPartent; + launcher.manager.registerComponent!CTarget; + launcher.manager.registerComponent!CTargetPlayerShip; + launcher.manager.registerComponent!CChildren; + launcher.manager.registerComponent!CWeaponLocation; + launcher.manager.registerComponent!CInit; + launcher.manager.registerComponent!CBoss; + launcher.manager.registerComponent!CParts; + launcher.manager.registerComponent!CColliderScale; + launcher.manager.registerComponent!CParticleEmitter; + launcher.manager.registerComponent!CParticleEmitterTime; launcher.manager.registerEvent!EChangeDirection; launcher.manager.registerEvent!EDamage; launcher.manager.registerEvent!EUpgrade; launcher.manager.registerEvent!EDeath; + launcher.manager.registerEvent!EDestroyedChild; //launcher.manager.registerSystem!MoveSystem(0); launcher.manager.registerSystem!DrawSystem(100); @@ -1478,7 +2084,16 @@ void spaceInvadersStart() launcher.manager.registerSystem!ParticleSystem(-100); launcher.manager.registerSystem!AnimationSystem(-100); launcher.manager.registerSystem!DampingSystem(-101); - + launcher.manager.registerSystem!MoveToParentTargetSystem(99); + launcher.manager.registerSystem!ParentOwnerSystem(-101); + launcher.manager.registerSystem!ShipWeaponSystem(-100); + + launcher.manager.registerSystem!RotateToTargetSystem(-100); + launcher.manager.registerSystem!ShipTargetSystem(-110); + launcher.manager.registerSystem!CShipIterator(-100); + launcher.manager.registerSystem!PartsDestroySystem(-80); + launcher.manager.registerSystem!ChildDestroySystem(-110); + launcher.manager.endRegister(); launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System"); @@ -1487,28 +2102,38 @@ void spaceInvadersStart() launcher.gui_manager.addSystem(MovementSystem.system_id,"Movement 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(LaserCollisionSystem.system_id,"Draw System"); + launcher.gui_manager.addSystem(ShootGridManager.system_id,"Shoot Grid Manager"); + launcher.gui_manager.addSystem(ShootGridCleaner.system_id,"Shoot Grid Cleaner"); + launcher.gui_manager.addSystem(HitPointsSystem.system_id,"Hit Points System"); + launcher.gui_manager.addSystem(HitMarkingSystem.system_id,"Hit Matking System"); + launcher.gui_manager.addSystem(UpgradeCollisionSystem.system_id,"Upgrade Collision System"); + launcher.gui_manager.addSystem(UpgradeSystem.system_id,"Upgrade System"); + launcher.gui_manager.addSystem(ParticleSystem.system_id,"Particle System"); + launcher.gui_manager.addSystem(AnimationSystem.system_id,"Animation System"); + launcher.gui_manager.addSystem(DampingSystem.system_id,"Damping System"); + launcher.gui_manager.addSystem(MoveToParentTargetSystem.system_id,"Move To Target System"); + launcher.gui_manager.addSystem(ParentOwnerSystem.system_id,"Parent Owner System System"); + launcher.gui_manager.addSystem(ShipWeaponSystem.system_id,"Ship Weapon System"); //launcher.manager.getSystem(CleanSystem.system_id).disable(); { space_invaders.ship_tmpl = launcher.manager.allocateTemplate( [CVelocity.component_id, CHitMark.component_id, CHitPoints.component_id, CLocation.component_id, CTexture.component_id, CInput.component_id, - CShip.component_id, CScale.component_id, CLaserWeapon.component_id, + CShip.component_id, CScale.component_id, CColliderScale.component_id, CShootDirection.component_id, CShootGrid.component_id, CGuild.component_id, - CDamping.component_id].staticArray + CDamping.component_id, CChildren.component_id, CInit.component_id].staticArray ); - - CScale* scale_comp = space_invaders.ship_tmpl.getComponent!CScale; - scale_comp.value = vec2(48,32); - CTexture* tex_comp = space_invaders.ship_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//ship_tex; - tex_comp.coords = vec4(0*px,80*px,48*px,32*px); - CLocation* loc_comp = space_invaders.ship_tmpl.getComponent!CLocation; - loc_comp.value = vec2(64,64); - CLaserWeapon* weapon = space_invaders.ship_tmpl.getComponent!CLaserWeapon; - weapon.level = 3; + //CLaserWeapon* weapon = space_invaders.ship_tmpl.getComponent!CLaserWeapon; + //weapon.level = 3; + space_invaders.ship_tmpl.getComponent!CTexture().coords = vec4(0*px,80*px,48*px,32*px); + space_invaders.ship_tmpl.getComponent!CScale().value = vec2(48,32); + space_invaders.ship_tmpl.getComponent!CLocation().value = vec2(64,64); space_invaders.ship_tmpl.getComponent!CHitPoints().value = 1000; space_invaders.ship_tmpl.getComponent!CDamping().value = 7; + space_invaders.ship_tmpl.getComponent!CInit().type = CInit.Type.space_ship; + space_invaders.ship_tmpl.getComponent!CColliderScale().value = vec2(26,24); launcher.manager.addEntity(space_invaders.ship_tmpl); } @@ -1518,7 +2143,7 @@ void spaceInvadersStart() space_invaders.laser_tmpl = launcher.manager.allocateTemplate(components); CTexture* tex_comp = space_invaders.laser_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//laser_tex; + //tex_comp.tex = 0;//space_invaders.texture;//laser_tex; tex_comp.coords = vec4(0*px,24*px,2*px,8*px); CScale* scale_comp = space_invaders.laser_tmpl.getComponent!CScale; scale_comp.value = vec2(2,8); @@ -1528,15 +2153,63 @@ void spaceInvadersStart() EntityTemplate* enemy_tmpl; EntityTemplate* grouped_tmpl; + EntityTemplate* tower_tmpl; + EntityTemplate* boss_tmpl; + //EntityTemplate* tower_weapon_tmpl; EntityID enemy_id; EntityID grouped_id; { - ushort[12] components = [CHitMark.component_id, CHitPoints.component_id, CVelocity.component_id, CAutoShoot.component_id, CLocation.component_id, CTexture.component_id, CScale.component_id, CLaserWeapon.component_id, CEnemy.component_id, CShootDirection.component_id, CShootGrid.component_id, CGuild.component_id]; - space_invaders.enemy_tmpl = launcher.manager.allocateTemplate(components); + boss_tmpl = launcher.manager.allocateTemplate( + [CHitMark.component_id, CParts.component_id, CLocation.component_id, + CTexture.component_id, CScale.component_id, CEnemy.component_id, + CBoss.component_id, CGuild.component_id, CInit.component_id, + CChildren.component_id, CSideMove.component_id, CVelocity.component_id, + CDepth.component_id].staticArray + ); + + CTexture* tex_comp = boss_tmpl.getComponent!CTexture; + //tex_comp.tex = space_invaders.texture;//ship_tex; + tex_comp.coords = vec4(128*px,0*px,96*px,48*px); + CLocation* loc_comp = boss_tmpl.getComponent!CLocation; + loc_comp.value = vec2(64,space_invaders.map_size.y - 16); + boss_tmpl.getComponent!CGuild().guild = 1; + boss_tmpl.getComponent!CInit().type = CInit.Type.boss; + boss_tmpl.getComponent!CScale().value = vec2(96,48); + boss_tmpl.getComponent!CDepth().depth = -1; + boss_tmpl.getComponent!CParts().count = 4; + boss_tmpl.getComponent!CVelocity().value = vec2(0.05,0); + } + + { + tower_tmpl = launcher.manager.allocateTemplate( + [CHitMark.component_id, CHitPoints.component_id, CLocation.component_id, + CTexture.component_id, CScale.component_id, CEnemy.component_id, + CShootGrid.component_id, CGuild.component_id, CInit.component_id, + CChildren.component_id].staticArray + ); + + CTexture* tex_comp = tower_tmpl.getComponent!CTexture; + //tex_comp.tex = space_invaders.texture;//ship_tex; + tex_comp.coords = vec4(96*px,96*px,16*px,16*px); + CLocation* loc_comp = tower_tmpl.getComponent!CLocation; + loc_comp.value = vec2(64,space_invaders.map_size.y - 16); + tower_tmpl.getComponent!CGuild().guild = 1; + tower_tmpl.getComponent!CInit().type = CInit.Type.tower; + tower_tmpl.getComponent!CHitPoints().value = 10; + } + + { + space_invaders.enemy_tmpl = launcher.manager.allocateTemplate( + [CWeaponLocation.component_id, CHitMark.component_id, CHitPoints.component_id, + CVelocity.component_id, CAutoShoot.component_id, CLocation.component_id, + CTexture.component_id, CScale.component_id, CLaserWeapon.component_id, + CEnemy.component_id, CShootDirection.component_id, CShootGrid.component_id, + CGuild.component_id].staticArray + ); CTexture* tex_comp = space_invaders.enemy_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//ship_tex; + //tex_comp.tex = space_invaders.texture;//ship_tex; tex_comp.coords = vec4(32*px,32*px,16*px,16*px); CLocation* loc_comp = space_invaders.enemy_tmpl.getComponent!CLocation; loc_comp.value = vec2(64,space_invaders.map_size.y - 16); @@ -1545,6 +2218,7 @@ void spaceInvadersStart() CVelocity* vel_comp = space_invaders.enemy_tmpl.getComponent!CVelocity; vel_comp.value = vec2(0.1,0); space_invaders.enemy_tmpl.getComponent!CGuild().guild = 1; + space_invaders.enemy_tmpl.getComponent!CWeaponLocation().rel_pos = vec2(0,-15); Entity* current_entity; @@ -1568,13 +2242,13 @@ void spaceInvadersStart() grouped_id = current_entity.id; //grouped_tmpl = launcher.manager.allocateTemplate(current_entity.id); } - + EntityTemplate* upgrade_tmpl; { upgrade_tmpl = launcher.manager.allocateTemplate([CVelocity.component_id, CLocation.component_id, CTexture.component_id, CScale.component_id, CUpgrade.component_id, CAnimationLooped.component_id, CAnimation.component_id].staticArray); CTexture* tex_comp = upgrade_tmpl.getComponent!CTexture; - tex_comp.tex = space_invaders.texture;//ship_tex; + //tex_comp.tex = space_invaders.texture;//ship_tex; tex_comp.coords = vec4(0*px,32*px,16*px,16*px); CVelocity* vel_comp = upgrade_tmpl.getComponent!CVelocity; vel_comp.value = vec2(0,-0.1); @@ -1586,22 +2260,23 @@ void spaceInvadersStart() enemy_tmpl = launcher.manager.allocateTemplate(enemy_id); grouped_tmpl = launcher.manager.allocateTemplate(grouped_id); - launcher.gui_manager.addTemplate(launcher.manager.allocateTemplate(space_invaders.ship_tmpl),"Ship"); launcher.gui_manager.addTemplate(enemy_tmpl,"Enemy"); launcher.gui_manager.addTemplate(grouped_tmpl,"Grouped enemy"); + launcher.gui_manager.addTemplate(launcher.manager.allocateTemplate(space_invaders.ship_tmpl),"Ship"); launcher.gui_manager.addTemplate(launcher.manager.allocateTemplate(space_invaders.laser_tmpl),"Laser"); launcher.gui_manager.addTemplate(upgrade_tmpl,"Upgrade"); - + launcher.gui_manager.addTemplate(tower_tmpl,"Tower"); + launcher.gui_manager.addTemplate(boss_tmpl,"Boss"); } void spaceInvadersEnd() { - launcher.manager.getSystem(DrawSystem.system_id).disable(); + /*launcher.manager.getSystem(DrawSystem.system_id).disable(); launcher.manager.getSystem(InputMovementSystem.system_id).disable(); launcher.manager.getSystem(LaserShootingSystem.system_id).disable(); launcher.manager.getSystem(MovementSystem.system_id).disable(); launcher.manager.getSystem(ClampPositionSystem.system_id).disable(); - launcher.manager.getSystem(ShootGridCleaner.system_id).disable(); + launcher.manager.getSystem(ShootGridCleaner.system_id).disable();*/ //launcher.manager.freeTemplate(space_invaders.enemy_tmpl); Mallocator.dispose(space_invaders);