Add mult-shape sprites and actors

This commit is contained in:
n00b87
2026-02-16 03:07:18 -06:00
parent 72ecdc046e
commit 5779e59cdd
10 changed files with 723 additions and 14 deletions

View File

@@ -360,6 +360,8 @@ int rc_createSprite(int img_id, double w, double h)
else
rc_sprite[spr_id].image_id = -1;
rc_sprite[spr_id].parent_sprite = -1;
b2BodyDef sprBodyDef;
sprBodyDef.type = b2_dynamicBody;
sprBodyDef.position.Set(w/2, h/2);
@@ -377,6 +379,7 @@ int rc_createSprite(int img_id, double w, double h)
sprFixtureDef.shape = rc_sprite[spr_id].physics.shape;
sprFixtureDef.isSensor = true;
sprFixtureDef.density = 1;
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
rc_sprite[spr_id].physics.fixture = rc_sprite[spr_id].physics.body->CreateFixture(&sprFixtureDef);
rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(w/2, h/2), 0);
@@ -429,10 +432,18 @@ void rc_deleteSprite(int spr_id)
if(rc_sprite[spr_id].physics.body)
{
if(rc_sprite[spr_id].parent_canvas >= 0 && rc_sprite[spr_id].parent_canvas < rc_canvas.size())
for(int i = 0; i < rc_sprite[spr_id].child_sprites.size(); i++)
{
rc_deleteSprite(rc_sprite[spr_id].child_sprites[i]);
}
if(rc_sprite[spr_id].parent_sprite < 0)
{
if(rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world)
rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world->DestroyBody(rc_sprite[spr_id].physics.body);
if(rc_sprite[spr_id].parent_canvas >= 0 && rc_sprite[spr_id].parent_canvas < rc_canvas.size())
{
if(rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world)
rc_canvas[rc_sprite[spr_id].parent_canvas].physics2D.world->DestroyBody(rc_sprite[spr_id].physics.body);
}
}
rc_sprite[spr_id].physics.body = NULL;
}
@@ -442,6 +453,8 @@ void rc_deleteSprite(int spr_id)
rc_sprite[spr_id].active = false;
rc_sprite[spr_id].parent_canvas = -1;
rc_sprite[spr_id].animation.clear();
rc_sprite[spr_id].child_sprites.clear();
rc_sprite[spr_id].parent_sprite = -1;
//std::cout << "DEBUG: Clear " << spr_id << " From " << parent_canvas << std::endl;
@@ -461,6 +474,210 @@ void rc_deleteSprite(int spr_id)
}
}
int rc_addSpriteChild(int spr_id, int child_sprite_id, double x, double y)
{
if(spr_id < 0 || spr_id >= rc_sprite.size())
return -1;
if(!rc_sprite[spr_id].active)
return -1;
if(child_sprite_id < 0 || child_sprite_id >= rc_sprite.size())
return -1;
if(!rc_sprite[child_sprite_id].active)
return -1;
b2FixtureDef childFixtureDef = rc_sprite[child_sprite_id].physics.fixture_def;
switch(childFixtureDef.shape->GetType())
{
case b2Shape::e_polygon:
{
b2PolygonShape* shape = new b2PolygonShape();
childFixtureDef.shape = shape;
b2Transform t(b2Vec2((float)x, (float)y), b2Rot(0));
int v_count = rc_sprite[child_sprite_id].physics.vertices.size();
b2Vec2 vert[v_count];
for(int i = 0; i < v_count; i++)
{
vert[i] = b2Mul(t, rc_sprite[child_sprite_id].physics.vertices[i]);
}
}
break;
case b2Shape::e_chain:
{
b2ChainShape* shape = new b2ChainShape();
childFixtureDef.shape = shape;
b2Transform t(b2Vec2((float)x, (float)y), b2Rot(0));
int v_count = rc_sprite[child_sprite_id].physics.vertices.size();
b2Vec2 vert[v_count];
for(int i = 0; i < v_count; i++)
{
vert[i] = b2Mul(t, rc_sprite[child_sprite_id].physics.vertices[i]);
}
b2Vec2 prev_vert = b2Mul(t, rc_sprite[child_sprite_id].physics.prev_vertex);
b2Vec2 next_vert = b2Mul(t, rc_sprite[child_sprite_id].physics.next_vertex);
shape->CreateChain(vert, v_count, prev_vert, next_vert);
}
break;
case b2Shape::e_circle:
{
b2CircleShape* shape = new b2CircleShape();
childFixtureDef.shape = shape;
shape->m_p.Set((float)x, (float)y);
shape->m_radius = rc_sprite[child_sprite_id].physics.radius;
}
break;
}
rc_sprite[child_sprite_id].physics.fixture = rc_sprite[spr_id].physics.body->CreateFixture(&childFixtureDef);
rc_sprite[child_sprite_id].physics.fixture_def = childFixtureDef;
if(rc_sprite[child_sprite_id].physics.body)
{
if(rc_sprite[child_sprite_id].parent_canvas >= 0 && rc_sprite[child_sprite_id].parent_canvas < rc_canvas.size())
{
if(rc_canvas[rc_sprite[child_sprite_id].parent_canvas].physics2D.world)
rc_canvas[rc_sprite[child_sprite_id].parent_canvas].physics2D.world->DestroyBody(rc_sprite[child_sprite_id].physics.body);
}
}
rc_sprite[child_sprite_id].physics.body = rc_sprite[spr_id].physics.body;
rc_sprite[child_sprite_id].isSolid = rc_sprite[spr_id].isSolid;
int index = rc_sprite[spr_id].child_sprites.size();
rc_sprite[spr_id].child_sprites.push_back(child_sprite_id);
rc_sprite[child_sprite_id].parent_sprite = spr_id;
return spr_id;
}
void rc_removeSpriteChild(int spr_id, int child_index)
{
if(spr_id < 0 || spr_id >= rc_sprite.size())
return;
if(!rc_sprite[spr_id].active)
return;
if(child_index < 0 || child_index >= rc_sprite[spr_id].child_sprites.size())
return;
int child_sprite_id = rc_sprite[spr_id].child_sprites[child_index];
if(child_sprite_id < 0 || child_sprite_id >= rc_sprite.size())
return;
if(!rc_sprite[child_sprite_id].active)
return;
b2FixtureDef childFixtureDef = rc_sprite[child_sprite_id].physics.fixture_def;
int shape_type = childFixtureDef.shape->GetType();
int off_x = rc_sprite[child_sprite_id].physics.fixture_offset_x;
int off_y = rc_sprite[child_sprite_id].physics.fixture_offset_y;
float angle = rc_sprite[child_sprite_id].physics.body->GetAngle();
switch(shape_type)
{
case b2Shape::e_polygon:
{
b2PolygonShape* shape = new b2PolygonShape();
int v_count = rc_sprite[child_sprite_id].physics.vertices.size();
b2Vec2 vert[v_count];
for(int i = 0; i < v_count; i++)
{
vert[i] = rc_sprite[child_sprite_id].physics.vertices[i];
}
shape->Set(vert, v_count);
childFixtureDef.shape = shape;
}
break;
case b2Shape::e_chain:
{
b2ChainShape* shape = new b2ChainShape();
int v_count = rc_sprite[child_sprite_id].physics.vertices.size();
b2Vec2 vert[v_count];
b2Vec2 prev_vert = rc_sprite[child_sprite_id].physics.prev_vertex;
b2Vec2 next_vert = rc_sprite[child_sprite_id].physics.next_vertex;
for(int i = 0; i < v_count; i++)
{
vert[i] = rc_sprite[child_sprite_id].physics.vertices[i];
}
shape->CreateChain(vert, v_count, prev_vert, next_vert);
childFixtureDef.shape = shape;
}
break;
case b2Shape::e_circle:
{
b2CircleShape* shape = new b2CircleShape();
shape->m_radius = rc_sprite[child_sprite_id].physics.radius;
childFixtureDef.shape = shape;
}
break;
}
b2BodyDef sprBodyDef;
int frame_w = rc_sprite[child_sprite_id].frame_size.Width;
int frame_h = rc_sprite[child_sprite_id].frame_size.Height;
float body_x = rc_sprite[child_sprite_id].physics.body->GetPosition().x;
float body_y = rc_sprite[child_sprite_id].physics.body->GetPosition().y;
int x = body_x + rc_sprite[child_sprite_id].physics.fixture_offset_x;
int y = body_y + rc_sprite[child_sprite_id].physics.fixture_offset_y;
rc_sprite[spr_id].physics.body->DestroyFixture(rc_sprite[child_sprite_id].physics.fixture);
sprBodyDef.type = b2_dynamicBody;
sprBodyDef.position.Set(x, y);
sprBodyDef.angle = angle;
sprBodyDef.userData.pointer = child_sprite_id;
rc_sprite[child_sprite_id].physics.body = rc_canvas[rc_active_canvas].physics2D.world->CreateBody(&sprBodyDef);
rc_sprite[child_sprite_id].isSolid = rc_sprite[spr_id].isSolid;
childFixtureDef.isSensor = !rc_sprite[child_sprite_id].isSolid;
rc_sprite[child_sprite_id].physics.shape = (b2Shape*)childFixtureDef.shape;
rc_sprite[child_sprite_id].physics.fixture_def = childFixtureDef;
rc_sprite[child_sprite_id].physics.fixture = rc_sprite[child_sprite_id].physics.body->CreateFixture(&childFixtureDef);
rc_sprite[child_sprite_id].parent_sprite = -1;
rc_sprite[spr_id].child_sprites.erase(child_index);
}
void rc_setSpriteSource(int spr_id, int img_id)
{
if(spr_id < 0 || spr_id >= rc_sprite.size())
@@ -635,6 +852,8 @@ void rc_setSpriteCollisionShape(int spr_id, int sprite_shape)
}
break;
}
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
}
int rc_getSpriteCollisionShape(int spr_id)
@@ -678,6 +897,8 @@ void rc_setSpriteRadius(int spr_id, double radius)
sprFixtureDef.density = density;
rc_sprite[spr_id].physics.fixture = rc_sprite[spr_id].physics.body->CreateFixture(&sprFixtureDef);
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
//NOTE: Changing the radius doesn't move its position so a new transform is not necessary
}
}
@@ -755,6 +976,8 @@ void rc_setSpriteBox(int spr_id, int w, int h)
//rc_setSpritePosition(spr_id, bx, by);
//std::cout << "Box At: " << bx << ", " << by << std::endl;
rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(bx + off_x, by + off_y), rc_sprite[spr_id].physics.body->GetAngle());
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
}
}
@@ -856,6 +1079,8 @@ void rc_setSpriteChain(int spr_id, double* vx, double* vy, int v_count, double p
//rc_setSpritePosition(spr_id, bx, by);
//std::cout << "Box At: " << bx << ", " << by << std::endl;
rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(bx + off_x, by + off_y), rc_sprite[spr_id].physics.body->GetAngle());
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
}
}
@@ -932,6 +1157,8 @@ void rc_setSpriteChainLoop(int spr_id, double* vx, double* vy, int v_count)
//rc_setSpritePosition(spr_id, bx, by);
//std::cout << "Box At: " << bx << ", " << by << std::endl;
rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(bx + off_x, by + off_y), rc_sprite[spr_id].physics.body->GetAngle());
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
}
}
@@ -1010,6 +1237,8 @@ void rc_setSpritePolygon(int spr_id, double* vx, double* vy, int v_count)
//rc_setSpritePosition(spr_id, bx, by);
//std::cout << "Box At: " << bx << ", " << by << std::endl;
rc_sprite[spr_id].physics.body->SetTransform(b2Vec2(bx + off_x, by + off_y), rc_sprite[spr_id].physics.body->GetAngle());
rc_sprite[spr_id].physics.fixture_def = sprFixtureDef;
}
}
@@ -1943,6 +2172,12 @@ void drawSprites(int canvas_id)
y = (int)(sprite->physics.body->GetWorldCenter().y - sprite->physics.offset_y - offset_y);
}
if(rc_sprite[spr_id].parent_sprite >= 0 && rc_sprite[spr_id].parent_sprite < rc_sprite.size())
{
x += rc_sprite[spr_id].physics.fixture_offset_x;
y += rc_sprite[spr_id].physics.fixture_offset_y;
}
int frame_offset_x = sprite->physics.user_offset_x;
int frame_offset_y = sprite->physics.user_offset_y;
@@ -2057,7 +2292,15 @@ void drawSprites(int canvas_id)
scale.set(sprite->scale.X, sprite->scale.Y);
rotationPoint.set(x + (src_size.Width/2)*scale.X - sprite->physics.user_offset_x, y + (src_size.Height/2)*scale.Y - sprite->physics.user_offset_y); //TODO: need to account for offset once that is implemented
if(rc_sprite[spr_id].parent_sprite >= 0 && rc_sprite[spr_id].parent_sprite < rc_sprite.size())
{
rotationPoint.set(x + (src_size.Width/2)*scale.X - sprite->physics.fixture_offset_x, y + (src_size.Height/2)*scale.Y - sprite->physics.fixture_offset_y);
}
else
{
rotationPoint.set(x + (src_size.Width/2)*scale.X - sprite->physics.user_offset_x, y + (src_size.Height/2)*scale.Y - sprite->physics.user_offset_y); //TODO: need to account for offset once that is implemented
}
rotation = -1 * (sprite->physics.body->GetAngle() * RAD_TO_DEG); //convert Box2D radians to degrees
color.set(sprite->alpha,