Demo update

-added 'dot' function to vector math
-fixed Circle tool rendering
-fixed some potentiall memory leaks
-added 'collision' module which now separates ShootGrid from SpaceInvaders demo
-separate some systems from demos to 'basic' module to better demos functionality sharing
-slow down snake
-added new graphics
-BrickBreaker demo now works (without blocks breaking and with bugged collision detection)

-some bug fixes
This commit is contained in:
Mergul 2020-07-08 22:09:10 +02:00
parent a0efa4e67d
commit 74179b4fc8
14 changed files with 871 additions and 468 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before After
Before After

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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");
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}*/
}
}

View file

@ -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));
}
}
}

View file

@ -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;

View file

@ -5,7 +5,8 @@ import bubel.ecs.system;
struct SystemGUI
{
const (char)* name;
System* system;
//System* system;
ushort id;
bool enabled = true;
}

View file

@ -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);

View file

@ -95,6 +95,11 @@ struct vec2
}
}
float dot(vec2 a, vec2 b)
{
return a.x*b.x + a.y*b.y;
}
struct vec4
{
union