feat(physics): reworked physics to use colliders, allowing for bodies with multiple colliders
This commit is contained in:
parent
84a940d046
commit
240186c8de
|
@ -1,6 +1,7 @@
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
#include "rigidbody.h"
|
#include "rigidbody.h"
|
||||||
|
#include "collider.h"
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// Shape overlap test using the separating axis theorem
|
// Shape overlap test using the separating axis theorem
|
||||||
|
@ -49,18 +50,18 @@ Vector _internal_collision_overlap_on_axis(PhysicsQuery self, PhysicsQuery other
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int _internal_collision_get_collisions(PhysicsEntity self, PhysicsEntity other, Collision* out) {
|
int _internal_collision_get_collisions(Collider* self, Collider* other, Collision* out) {
|
||||||
// get components used
|
// get components used
|
||||||
Shape* self_shape = self.tc->get_shape(self.data);
|
Shape* self_shape = collider_get_shape(self);
|
||||||
Transform* self_transform = self.transformable->get_transform(self.data);
|
Transform* self_transform = rigidbody_get_transform(collider_get_rigidbody(self));
|
||||||
PhysicsQuery self_query = {
|
PhysicsQuery self_query = {
|
||||||
.shape = self_shape,
|
.shape = self_shape,
|
||||||
.transform = self_transform,
|
.transform = self_transform,
|
||||||
.mask = 0x0 // not used
|
.mask = 0x0 // not used
|
||||||
};
|
};
|
||||||
PhysicsQuery other_query = {
|
PhysicsQuery other_query = {
|
||||||
.shape = other.tc->get_shape(other.data),
|
.shape = collider_get_shape(other),
|
||||||
.transform = other.transformable->get_transform(other.data),
|
.transform = rigidbody_get_transform(collider_get_rigidbody(other)),
|
||||||
.mask = 0x0 // not used
|
.mask = 0x0 // not used
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,8 +78,8 @@ int _internal_collision_get_collisions(PhysicsEntity self, PhysicsEntity other,
|
||||||
// the next point on the line
|
// the next point on the line
|
||||||
size_t next_index = (point_index + 1) % self_point_count;
|
size_t next_index = (point_index + 1) % self_point_count;
|
||||||
// get the two points defining the collision edge
|
// get the two points defining the collision edge
|
||||||
Vector edge_lhs = shape_get_point_transformed(self.tc->get_shape(self.data), point_index, *self_transform);
|
Vector edge_lhs = shape_get_point_transformed(self_shape, point_index, *self_transform);
|
||||||
Vector edge_rhs = shape_get_point_transformed(self.tc->get_shape(self.data), next_index, *self_transform);
|
Vector edge_rhs = shape_get_point_transformed(self_shape, next_index, *self_transform);
|
||||||
// the direction of the line
|
// the direction of the line
|
||||||
Vector normal = vnormalizedf(vperpendicularf(vsubf(edge_rhs, edge_lhs)));
|
Vector normal = vnormalizedf(vperpendicularf(vsubf(edge_rhs, edge_lhs)));
|
||||||
|
|
||||||
|
@ -96,8 +97,8 @@ int _internal_collision_get_collisions(PhysicsEntity self, PhysicsEntity other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidBody* rba = self.tc->get_rigidbody(self.data);
|
RigidBody* rba = collider_get_rigidbody(self);
|
||||||
RigidBody* rbb = other.tc->get_rigidbody(other.data);
|
RigidBody* rbb = collider_get_rigidbody(other);
|
||||||
const Vector velocity = vsubf(rigidbody_get_velocity(rba), rigidbody_get_velocity(rbb));
|
const Vector velocity = vsubf(rigidbody_get_velocity(rba), rigidbody_get_velocity(rbb));
|
||||||
const Vector normal = vnormalizedf(shortest_escape);
|
const Vector normal = vnormalizedf(shortest_escape);
|
||||||
Vector world_point = _internal_collision_get_range_on_axis(self_query, normal).minpoint;
|
Vector world_point = _internal_collision_get_range_on_axis(self_query, normal).minpoint;
|
||||||
|
@ -118,9 +119,9 @@ int _internal_collision_get_collisions(PhysicsEntity self, PhysicsEntity other,
|
||||||
return !veqf(shortest_escape, ZeroVector);
|
return !veqf(shortest_escape, ZeroVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collision collision_invert(Collision collision_a, PhysicsEntity a) {
|
Collision collision_invert(Collision collision_a, Collider* a) {
|
||||||
RigidBody* body = collision_a.other.tc->get_rigidbody(collision_a.other.data);
|
RigidBody* body = collider_get_rigidbody(a);
|
||||||
Shape* shape = collision_a.other.tc->get_shape(collision_a.other.data);
|
Shape* shape = collider_get_shape(a);
|
||||||
Transform* transform = rigidbody_get_transform(body);
|
Transform* transform = rigidbody_get_transform(body);
|
||||||
|
|
||||||
Vector world_point = _internal_collision_get_range_on_axis((PhysicsQuery){.shape = shape, .transform = transform }, collision_a.normal).maxpoint;
|
Vector world_point = _internal_collision_get_range_on_axis((PhysicsQuery){.shape = shape, .transform = transform }, collision_a.normal).maxpoint;
|
||||||
|
@ -136,7 +137,7 @@ Collision collision_invert(Collision collision_a, PhysicsEntity a) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int collision_check(PhysicsEntity a, PhysicsEntity b, Collision* out_a, Collision* out_b) {
|
int collision_check(Collider* a, Collider* b, Collision* out_a, Collision* out_b) {
|
||||||
Collision collision_a, collision_b;
|
Collision collision_a, collision_b;
|
||||||
int collision_a_overlaps = _internal_collision_get_collisions(a, b, &collision_a);
|
int collision_a_overlaps = _internal_collision_get_collisions(a, b, &collision_a);
|
||||||
int collision_b_overlaps = _internal_collision_get_collisions(b, a, &collision_b);
|
int collision_b_overlaps = _internal_collision_get_collisions(b, a, &collision_b);
|
||||||
|
@ -180,11 +181,7 @@ int _internal_overlap_check(PhysicsQuery a, PhysicsQuery b) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int overlap_check(PhysicsQuery query, PhysicsEntity entity) {
|
int overlap_check(PhysicsQuery query, Collider* collider) {
|
||||||
PhysicsQuery entity_q = {
|
PhysicsQuery collider_query = collider_to_query(collider);
|
||||||
.shape = entity.tc->get_shape(entity.data),
|
return (query.mask & collider_query.mask) != 0 && _internal_overlap_check(query, collider_query) || _internal_overlap_check(collider_query, query);
|
||||||
.transform = entity.transformable->get_transform(entity.data),
|
|
||||||
.mask = rigidbody_get_layers(entity.tc->get_rigidbody(entity.data)),
|
|
||||||
};
|
|
||||||
return (query.mask & entity_q.mask) != 0 && _internal_overlap_check(query, entity_q) || _internal_overlap_check(entity_q, query);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,31 +3,13 @@
|
||||||
|
|
||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#include "physics_entity.h"
|
#include "physics_entity.h"
|
||||||
#include <stddef.h>
|
#include "rigidbody.h"
|
||||||
|
#include "physics.h"
|
||||||
|
|
||||||
typedef uint32_t PhysicsMask;
|
typedef struct Collider Collider;
|
||||||
|
|
||||||
typedef struct Collision {
|
extern Collision collision_invert(Collision src, Collider* new_other);
|
||||||
PhysicsEntity other;
|
extern int collision_check(Collider* a, Collider* b, Collision* out_a, Collision* out_b);
|
||||||
|
extern int overlap_check(PhysicsQuery query, Collider* collider);
|
||||||
Vector point;
|
|
||||||
Vector normal;
|
|
||||||
|
|
||||||
Vector velocity;
|
|
||||||
Vector penetration_vector;
|
|
||||||
|
|
||||||
Vector edge_left;
|
|
||||||
Vector edge_right;
|
|
||||||
} Collision;
|
|
||||||
|
|
||||||
typedef struct PhysicsQuery {
|
|
||||||
Shape* shape;
|
|
||||||
Transform* transform;
|
|
||||||
PhysicsMask mask;
|
|
||||||
} PhysicsQuery;
|
|
||||||
|
|
||||||
extern Collision collision_invert(Collision src, PhysicsEntity new_other);
|
|
||||||
extern int collision_check(PhysicsEntity a, PhysicsEntity b, Collision* out_a, Collision* out_b);
|
|
||||||
extern int overlap_check(PhysicsQuery query, PhysicsEntity entity);
|
|
||||||
|
|
||||||
#endif // !_fencer_collision_h
|
#endif // !_fencer_collision_h
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "collider.h"
|
||||||
|
|
||||||
void physics_entity_debug_draw(PhysicsEntity self) {
|
void physics_entity_debug_draw(PhysicsEntity self) {
|
||||||
RigidBody* body = self.tc->get_rigidbody(self.data);
|
RigidBody* body = self.tc->get_rigidbody(self.data);
|
||||||
Shape* shape = self.tc->get_shape(self.data);
|
Transform* transform = rigidbody_get_transform(body);
|
||||||
Transform* transform = self.transformable->get_transform(self.data);
|
|
||||||
|
|
||||||
shape_draw(shape, *transform);
|
list_foreach(Collider**, collider, rigidbody_get_colliders(body)) {
|
||||||
|
shape_draw(collider_get_shape(*collider), *transform);
|
||||||
|
}
|
||||||
rigidbody_debug_draw_contacts(body);
|
rigidbody_debug_draw_contacts(body);
|
||||||
|
|
||||||
Vector lhs = transform->position;
|
Vector lhs = transform->position;
|
||||||
|
@ -81,16 +83,12 @@ void physics_entity_update(PhysicsEntity self) {
|
||||||
|
|
||||||
List* contacts = rigidbody_get_contacts(body);
|
List* contacts = rigidbody_get_contacts(body);
|
||||||
if(contacts->len > 0) {
|
if(contacts->len > 0) {
|
||||||
if(rigidbody_get_overlap(body) == 1) {
|
if (rigidbody_is_static(body) == 0) {
|
||||||
list_foreach(Contact*, contact, contacts)
|
physics_entity_solve_contacts(self, contacts);
|
||||||
self.tc->on_overlap(self.data, contact->hit.other);
|
}
|
||||||
} else {
|
|
||||||
if(rigidbody_is_static(body) == 0) {
|
list_foreach(Contact *, contact, contacts) {
|
||||||
physics_entity_solve_contacts(self, contacts);
|
self.tc->on_collision(self.data, contact->hit);
|
||||||
}
|
|
||||||
list_foreach(Contact*, contact, contacts) {
|
|
||||||
self.tc->on_collision(self.data, contact->hit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rigidbody_collect_contacts(body);
|
rigidbody_collect_contacts(body);
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
#ifndef _fencer_collidable_h
|
#ifndef _fencer_collidable_h
|
||||||
#define _fencer_collidable_h
|
#define _fencer_collidable_h
|
||||||
|
|
||||||
#include "vmath.h"
|
|
||||||
#include "typeclass_helpers.h"
|
#include "typeclass_helpers.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "shape.h"
|
#include "transformable.h"
|
||||||
|
|
||||||
|
typedef struct Collider Collider;
|
||||||
typedef struct Collision Collision;
|
typedef struct Collision Collision;
|
||||||
typedef struct RigidBody RigidBody;
|
typedef struct RigidBody RigidBody;
|
||||||
|
|
||||||
typedef struct PhysicsEntity PhysicsEntity;
|
typedef struct PhysicsEntity PhysicsEntity;
|
||||||
|
|
||||||
typedef struct IPhysicsEntity {
|
typedef struct IPhysicsEntity {
|
||||||
RigidBody* (*const get_rigidbody)(void* self);
|
RigidBody* (*const get_rigidbody)(void* self);
|
||||||
Shape* (*const get_shape)(void* self);
|
|
||||||
void(*const on_collision)(void* self, Collision collision);
|
void(*const on_collision)(void* self, Collision collision);
|
||||||
void(*const on_overlap)(void* self, PhysicsEntity other);
|
void(*const on_overlap)(void* self, Collider* other);
|
||||||
} IPhysicsEntity;
|
} IPhysicsEntity;
|
||||||
|
|
||||||
typedef struct PhysicsEntity {
|
typedef struct PhysicsEntity {
|
||||||
|
@ -28,18 +28,15 @@ extern void physics_entity_solve_contacts(PhysicsEntity self, List* contacts);
|
||||||
extern void physics_entity_update(PhysicsEntity self);
|
extern void physics_entity_update(PhysicsEntity self);
|
||||||
|
|
||||||
|
|
||||||
#define impl_PhysicsEntity_for(T, get_rigidbody_f, get_shape_f, on_collision_f, on_overlap_f)\
|
#define impl_PhysicsEntity_for(T, get_rigidbody_f, on_collision_f, on_overlap_f)\
|
||||||
static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\
|
static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\
|
||||||
TC_FN_TYPECHECK(Transformable, T##_as_Transformable, T*);\
|
|
||||||
TC_FN_TYPECHECK(RigidBody*, get_rigidbody_f, T*);\
|
TC_FN_TYPECHECK(RigidBody*, get_rigidbody_f, T*);\
|
||||||
TC_FN_TYPECHECK(Shape*, get_shape_f, T*);\
|
|
||||||
TC_FN_TYPECHECK(void, on_collision_f, T*, Collision);\
|
TC_FN_TYPECHECK(void, on_collision_f, T*, Collision);\
|
||||||
TC_FN_TYPECHECK(void, on_overlap_f, T*, PhysicsEntity);\
|
TC_FN_TYPECHECK(void, on_overlap_f, T*, Collider*);\
|
||||||
static IPhysicsEntity const tc = {\
|
static IPhysicsEntity const tc = {\
|
||||||
.get_rigidbody = (RigidBody*(*const)(void*)) get_rigidbody_f,\
|
.get_rigidbody = (RigidBody*(*const)(void*)) get_rigidbody_f,\
|
||||||
.get_shape = (Shape*(*const)(void*)) get_shape_f,\
|
|
||||||
.on_collision = (void(*const)(void*,Collision)) on_collision_f,\
|
.on_collision = (void(*const)(void*,Collision)) on_collision_f,\
|
||||||
.on_overlap = (void(*const)(void*,PhysicsEntity)) on_overlap_f,\
|
.on_overlap = (void(*const)(void*,Collider*)) on_overlap_f,\
|
||||||
};\
|
};\
|
||||||
Transformable transformable = T##_as_Transformable(x);\
|
Transformable transformable = T##_as_Transformable(x);\
|
||||||
return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc};\
|
return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc};\
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "physics_world.h"
|
#include "physics_world.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
|
#include "collider.h"
|
||||||
#include "rigidbody.h"
|
#include "rigidbody.h"
|
||||||
|
|
||||||
static List _world_bodies;
|
static List _world_bodies;
|
||||||
|
@ -29,30 +30,53 @@ void physics_world_remove_entity(PhysicsEntity entity) {
|
||||||
ASSERT_RETURN(0,, "Physics entity with data at %p is not registered in physics world", entity.data);
|
ASSERT_RETURN(0,, "Physics entity with data at %p is not registered in physics world", entity.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsEntity physics_world_query(PhysicsQuery query) {
|
Collider* physics_world_query(PhysicsQuery query) {
|
||||||
list_foreach(PhysicsEntity*, entity, &_world_bodies) {
|
list_foreach(RigidBody**, body, &_world_bodies) {
|
||||||
if(overlap_check(query, *entity))
|
list_foreach(Collider**, collider, rigidbody_get_colliders(*body)) {
|
||||||
return *entity;
|
if(overlap_check(query, *collider))
|
||||||
|
return *collider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _internal_physics_check_entities(PhysicsEntity left, PhysicsEntity right) {
|
||||||
|
RigidBody* rbleft = left.tc->get_rigidbody(left.data);
|
||||||
|
RigidBody* rbright = right.tc->get_rigidbody(right.data);
|
||||||
|
|
||||||
|
Collision collision_left, collision_right;
|
||||||
|
int is_overlap = 0;
|
||||||
|
|
||||||
|
list_foreach(Collider**, left_col, rigidbody_get_colliders(rbleft)) {
|
||||||
|
list_foreach(Collider**, right_col, rigidbody_get_colliders(rbright)) {
|
||||||
|
is_overlap = collider_is_overlap(*left_col) || collider_is_overlap(*right_col);
|
||||||
|
|
||||||
|
if(collision_check(*left_col, *right_col, &collision_left, &collision_right)) {
|
||||||
|
if(is_overlap) {
|
||||||
|
left.tc->on_overlap(left.data, *right_col);
|
||||||
|
right.tc->on_overlap(right.data, *left_col);
|
||||||
|
} else {
|
||||||
|
rigidbody_add_contact(rbleft, collision_left);
|
||||||
|
rigidbody_add_contact(rbright, collision_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void _internal_physics_narrow_collision() {
|
void _internal_physics_narrow_collision() {
|
||||||
size_t half_end = _world_bodies.len/2;
|
size_t half_end = _world_bodies.len/2;
|
||||||
Collision collision_left, collision_right;
|
|
||||||
|
|
||||||
PhysicsEntity* right = NULL;
|
PhysicsEntity* right = NULL;
|
||||||
list_foreach(PhysicsEntity*, left, &_world_bodies) {
|
list_foreach(PhysicsEntity*, left, &_world_bodies) {
|
||||||
for(size_t right_index = 0; right_index < half_end; ++right_index) {
|
for(size_t right_index = 0; right_index < half_end; ++right_index) {
|
||||||
right = list_at_as(PhysicsEntity, &_world_bodies, right_index);
|
right = list_at_as(PhysicsEntity, &_world_bodies, right_index);
|
||||||
if(left->data == right->data) continue;
|
|
||||||
|
|
||||||
if(collision_check(*left, *right, &collision_left, &collision_right)) {
|
if(left->data == right->data) continue;
|
||||||
left->tc->on_collision(left->data, collision_left);
|
_internal_physics_check_entities(*left, *right);
|
||||||
right->tc->on_collision(right->data, collision_right);
|
|
||||||
rigidbody_add_contact(left->tc->get_rigidbody(left->data), collision_left);
|
|
||||||
rigidbody_add_contact(right->tc->get_rigidbody(right->data), collision_right);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ extern void physics_world_clean();
|
||||||
extern void physics_world_add_entity(PhysicsEntity entity);
|
extern void physics_world_add_entity(PhysicsEntity entity);
|
||||||
extern void physics_world_remove_entity(PhysicsEntity entity);
|
extern void physics_world_remove_entity(PhysicsEntity entity);
|
||||||
|
|
||||||
extern PhysicsEntity physics_world_query(PhysicsQuery query);
|
extern Collider* physics_world_query(PhysicsQuery query);
|
||||||
|
|
||||||
extern void physics_world_tick();
|
extern void physics_world_tick();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ struct RigidBody {
|
||||||
PhysicsMask layers;
|
PhysicsMask layers;
|
||||||
PhysicsMask collision_mask;
|
PhysicsMask collision_mask;
|
||||||
|
|
||||||
int overlap;
|
List colliders;
|
||||||
|
|
||||||
int is_static;
|
int is_static;
|
||||||
|
|
||||||
List contacts;
|
List contacts;
|
||||||
|
@ -42,7 +43,7 @@ RigidBody* rigidbody_make(Transformable transform) {
|
||||||
.layers = 0x1,
|
.layers = 0x1,
|
||||||
.collision_mask = 0x1,
|
.collision_mask = 0x1,
|
||||||
|
|
||||||
.overlap = 0,
|
.colliders = list_from_type(Collider*),
|
||||||
|
|
||||||
.is_static = 0,
|
.is_static = 0,
|
||||||
|
|
||||||
|
@ -158,14 +159,6 @@ void rigidbody_set_collision_mask(RigidBody* self, PhysicsMask mask) {
|
||||||
self->collision_mask = mask;
|
self->collision_mask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rigidbody_get_overlap(RigidBody* self) {
|
|
||||||
return self->overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rigidbody_set_overlap(RigidBody* self, int value) {
|
|
||||||
self->overlap = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rigidbody_is_static(RigidBody* self) {
|
int rigidbody_is_static(RigidBody* self) {
|
||||||
return self->is_static;
|
return self->is_static;
|
||||||
}
|
}
|
||||||
|
@ -187,6 +180,23 @@ Vector rigidbody_get_force(RigidBody* self) {
|
||||||
return self->next_linear_force;
|
return self->next_linear_force;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rigidbody_add_collider(RigidBody *self, Collider* collider) {
|
||||||
|
list_add(&self->colliders, &collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rigidbody_remove_collider(RigidBody *self, Collider* collider) {
|
||||||
|
for(size_t i = 0; i < self->colliders.len; ++i) {
|
||||||
|
if(collider == *list_at_as(Collider*, &self->colliders, i)) {
|
||||||
|
list_erase(&self->colliders, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List* rigidbody_get_colliders(RigidBody* self) {
|
||||||
|
return &self->colliders;
|
||||||
|
}
|
||||||
|
|
||||||
void rigidbody_debug_draw_contacts(RigidBody* self) {
|
void rigidbody_debug_draw_contacts(RigidBody* self) {
|
||||||
list_foreach(Contact*, contact, &self->contacts) {
|
list_foreach(Contact*, contact, &self->contacts) {
|
||||||
_internal_debug_draw_collision_edge(self, contact);
|
_internal_debug_draw_collision_edge(self, contact);
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#include "transformable.h"
|
#include "transformable.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "collision.h"
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
#include "physics.h"
|
||||||
|
|
||||||
struct Collision;
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct Collision hit;
|
Collision hit;
|
||||||
float duration;
|
float duration;
|
||||||
} Contact;
|
} Contact;
|
||||||
|
|
||||||
|
@ -54,7 +53,12 @@ extern void rigidbody_set_velocity(RigidBody* self, Vector velocity);
|
||||||
|
|
||||||
extern Vector rigidbody_get_force(RigidBody* self);
|
extern Vector rigidbody_get_force(RigidBody* self);
|
||||||
|
|
||||||
|
extern void rigidbody_add_collider(RigidBody* self, Collider* collider);
|
||||||
|
extern void rigidbody_remove_collider(RigidBody* self, Collider* collider);
|
||||||
|
extern List* rigidbody_get_colliders(RigidBody* self);
|
||||||
|
|
||||||
extern void rigidbody_debug_draw_contacts(RigidBody* self);
|
extern void rigidbody_debug_draw_contacts(RigidBody* self);
|
||||||
|
|
||||||
extern Transform* rigidbody_get_transform(RigidBody* self);
|
extern Transform* rigidbody_get_transform(RigidBody* self);
|
||||||
|
|
||||||
impl_Transformable_for(RigidBody,
|
impl_Transformable_for(RigidBody,
|
||||||
|
|
|
@ -27,12 +27,7 @@ Player* MakePlayer() {
|
||||||
*self = (Player) {
|
*self = (Player) {
|
||||||
.transform = IdentityTransform,
|
.transform = IdentityTransform,
|
||||||
.rigidbody = NULL,
|
.rigidbody = NULL,
|
||||||
.collisionShape = shape_new((Vector[]){
|
.physicsCollider = NULL,
|
||||||
MakeVector(-0.15, -0.15),
|
|
||||||
MakeVector( 0.15, -0.15),
|
|
||||||
MakeVector( 0.15, 0.0),
|
|
||||||
MakeVector(-0.15, 0.0)
|
|
||||||
}, 4),
|
|
||||||
.playerInput = playerinput_new(self, -1),
|
.playerInput = playerinput_new(self, -1),
|
||||||
.moveInput = ZeroVector,
|
.moveInput = ZeroVector,
|
||||||
.attackInput = 0,
|
.attackInput = 0,
|
||||||
|
@ -45,8 +40,14 @@ Player* MakePlayer() {
|
||||||
};
|
};
|
||||||
|
|
||||||
self->rigidbody = rigidbody_make(Player_as_Transformable(self));
|
self->rigidbody = rigidbody_make(Player_as_Transformable(self));
|
||||||
|
self->physicsCollider = collider_new(self->rigidbody, shape_new((Vector[]){
|
||||||
|
MakeVector(-0.15, -0.065),
|
||||||
|
MakeVector( 0.15, -0.065),
|
||||||
|
MakeVector( 0.15, 0.065),
|
||||||
|
MakeVector(-0.15, 0.065)
|
||||||
|
}, 4), 0, 0x1);
|
||||||
|
|
||||||
sprite_set_origin(self->sprite, MakeVector(0.45f, 1.f));
|
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
||||||
|
|
||||||
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
|
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
|
||||||
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop);
|
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop);
|
||||||
|
@ -70,8 +71,8 @@ Player* SpawnPlayer(Vector location) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyPlayer(Player* self) {
|
void DestroyPlayer(Player* self) {
|
||||||
|
collider_destroy(self->physicsCollider);
|
||||||
rigidbody_destroy(self->rigidbody);
|
rigidbody_destroy(self->rigidbody);
|
||||||
shape_destroy(self->collisionShape);
|
|
||||||
|
|
||||||
playerinput_drop(self->playerInput);
|
playerinput_drop(self->playerInput);
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ void PlayerUpdate(Player* self, float deltaTime) {
|
||||||
|
|
||||||
void PlayerDraw(Player* self) {
|
void PlayerDraw(Player* self) {
|
||||||
animation_sprite_draw(self->currentAnimation, &self->transform);
|
animation_sprite_draw(self->currentAnimation, &self->transform);
|
||||||
shape_draw(self->collisionShape, self->transform);
|
shape_draw(collider_get_shape(self->physicsCollider), self->transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform* PlayerGetTransform(Player* self) {
|
Transform* PlayerGetTransform(Player* self) {
|
||||||
|
@ -116,9 +117,5 @@ RigidBody* PlayerGetRigidBody(Player* self) {
|
||||||
return self->rigidbody;
|
return self->rigidbody;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape* PlayerGetCollisionShape(Player* self) {
|
|
||||||
return self->collisionShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerOnCollision(Player* self, Collision collision) {}
|
void PlayerOnCollision(Player* self, Collision collision) {}
|
||||||
void PlayerOnOverlap(Player* self, PhysicsEntity other) {}
|
void PlayerOnOverlap(Player* self, Collider* other) {}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "player_input.h"
|
#include "player_input.h"
|
||||||
#include "rigidbody.h"
|
#include "rigidbody.h"
|
||||||
#include "shape.h"
|
#include "collider.h"
|
||||||
|
|
||||||
extern const Vector PLAYER_SPEED;
|
extern const Vector PLAYER_SPEED;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ typedef struct Player {
|
||||||
Transform transform;
|
Transform transform;
|
||||||
|
|
||||||
RigidBody* rigidbody;
|
RigidBody* rigidbody;
|
||||||
Shape* collisionShape;
|
Collider* physicsCollider;
|
||||||
|
|
||||||
PlayerInput* playerInput;
|
PlayerInput* playerInput;
|
||||||
|
|
||||||
|
@ -52,9 +52,8 @@ void PlayerDraw(Player* self);
|
||||||
Transform* PlayerGetTransform(Player* self);
|
Transform* PlayerGetTransform(Player* self);
|
||||||
|
|
||||||
RigidBody* PlayerGetRigidBody(Player* self);
|
RigidBody* PlayerGetRigidBody(Player* self);
|
||||||
Shape* PlayerGetCollisionShape(Player* self);
|
|
||||||
void PlayerOnCollision(Player* self, Collision collision);
|
void PlayerOnCollision(Player* self, Collision collision);
|
||||||
void PlayerOnOverlap(Player* self, PhysicsEntity other);
|
void PlayerOnOverlap(Player* self, Collider* other);
|
||||||
|
|
||||||
static long PlayerGetDepth(Player* self) { return -(int)(self->transform.position.y * 1000); }
|
static long PlayerGetDepth(Player* self) { return -(int)(self->transform.position.y * 1000); }
|
||||||
|
|
||||||
|
@ -75,7 +74,6 @@ impl_Transformable_for(Player,
|
||||||
|
|
||||||
impl_PhysicsEntity_for(Player,
|
impl_PhysicsEntity_for(Player,
|
||||||
PlayerGetRigidBody,
|
PlayerGetRigidBody,
|
||||||
PlayerGetCollisionShape,
|
|
||||||
PlayerOnCollision,
|
PlayerOnCollision,
|
||||||
PlayerOnOverlap
|
PlayerOnOverlap
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,15 +10,16 @@ Prop* MakeProp(Sprite* sprite, Shape* shape) {
|
||||||
.transform = IdentityTransform,
|
.transform = IdentityTransform,
|
||||||
.sprite = sprite,
|
.sprite = sprite,
|
||||||
.rigidbody = NULL,
|
.rigidbody = NULL,
|
||||||
.collisionShape = shape
|
.collisionShape = NULL
|
||||||
};
|
};
|
||||||
self->rigidbody = rigidbody_make(Prop_as_Transformable(self));
|
self->rigidbody = rigidbody_make(Prop_as_Transformable(self));
|
||||||
|
self->collisionShape = collider_new(self->rigidbody, shape, 0, 0x1);
|
||||||
rigidbody_set_static(self->rigidbody, 1);
|
rigidbody_set_static(self->rigidbody, 1);
|
||||||
sprite_set_origin(self->sprite, MakeVector(0.5f, 1.0f));
|
sprite_set_origin(self->sprite, MakeVector(0.5f, 1.0f));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape) {
|
Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape, Vector origin) {
|
||||||
Prop* self = MakeProp(sprite, shape);
|
Prop* self = MakeProp(sprite, shape);
|
||||||
|
|
||||||
self->transform.position
|
self->transform.position
|
||||||
|
@ -27,14 +28,16 @@ Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape) {
|
||||||
|
|
||||||
game_world_add_entity(Prop_as_BehaviourEntity(self));
|
game_world_add_entity(Prop_as_BehaviourEntity(self));
|
||||||
physics_world_add_entity(Prop_as_PhysicsEntity(self));
|
physics_world_add_entity(Prop_as_PhysicsEntity(self));
|
||||||
|
|
||||||
|
sprite_set_origin(self->sprite, origin);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyProp(Prop* self) {
|
void DestroyProp(Prop* self) {
|
||||||
sprite_destroy(self->sprite);
|
sprite_destroy(self->sprite);
|
||||||
|
collider_destroy(self->collisionShape);
|
||||||
rigidbody_destroy(self->rigidbody);
|
rigidbody_destroy(self->rigidbody);
|
||||||
shape_destroy(self->collisionShape);
|
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,11 +46,11 @@ void PropUpdate(Prop* self, float deltaTime) {}
|
||||||
|
|
||||||
void PropDraw(Prop* self) {
|
void PropDraw(Prop* self) {
|
||||||
sprite_draw(self->sprite, self->transform);
|
sprite_draw(self->sprite, self->transform);
|
||||||
shape_draw(self->collisionShape, self->transform);
|
shape_draw(collider_get_shape(self->collisionShape), self->transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropOnCollision(Prop* self, Collision collision) {}
|
void PropOnCollision(Prop* self, Collision collision) {}
|
||||||
void PropOnOverlap(Prop* self, PhysicsEntity other) {}
|
void PropOnOverlap(Prop* self, Collider* other) {}
|
||||||
|
|
||||||
Transform* PropGetTransform(Prop* self) {
|
Transform* PropGetTransform(Prop* self) {
|
||||||
return &self->transform;
|
return &self->transform;
|
||||||
|
@ -56,7 +59,3 @@ Transform* PropGetTransform(Prop* self) {
|
||||||
RigidBody* PropGetRigidBody(Prop* self) {
|
RigidBody* PropGetRigidBody(Prop* self) {
|
||||||
return self->rigidbody;
|
return self->rigidbody;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape* PropGetCollisionShape(Prop* self) {
|
|
||||||
return self->collisionShape;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,17 +8,17 @@
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "rigidbody.h"
|
#include "rigidbody.h"
|
||||||
#include "shape.h"
|
#include "collider.h"
|
||||||
|
|
||||||
typedef struct Prop {
|
typedef struct Prop {
|
||||||
Transform transform;
|
Transform transform;
|
||||||
Sprite* sprite;
|
Sprite* sprite;
|
||||||
RigidBody* rigidbody;
|
RigidBody* rigidbody;
|
||||||
Shape* collisionShape;
|
Collider* collisionShape;
|
||||||
} Prop;
|
} Prop;
|
||||||
|
|
||||||
Prop* MakeProp(Sprite* sprite, Shape* shape);
|
Prop* MakeProp(Sprite* sprite, Shape* shape);
|
||||||
Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape);
|
Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape, Vector origin);
|
||||||
void DestroyProp(Prop* self);
|
void DestroyProp(Prop* self);
|
||||||
|
|
||||||
void PropStart(Prop* self);
|
void PropStart(Prop* self);
|
||||||
|
@ -26,11 +26,10 @@ void PropUpdate(Prop* self, float deltaTime);
|
||||||
void PropDraw(Prop* self);
|
void PropDraw(Prop* self);
|
||||||
|
|
||||||
void PropOnCollision(Prop* self, Collision collision);
|
void PropOnCollision(Prop* self, Collision collision);
|
||||||
void PropOnOverlap(Prop* self, PhysicsEntity other);
|
void PropOnOverlap(Prop* self, Collider* other);
|
||||||
|
|
||||||
Transform* PropGetTransform(Prop* self);
|
Transform* PropGetTransform(Prop* self);
|
||||||
RigidBody* PropGetRigidBody(Prop* self);
|
RigidBody* PropGetRigidBody(Prop* self);
|
||||||
Shape* PropGetCollisionShape(Prop* self);
|
|
||||||
|
|
||||||
static long PropGetDepth(Prop* self) { return -(int)(self->transform.position.y * 1000); }
|
static long PropGetDepth(Prop* self) { return -(int)(self->transform.position.y * 1000); }
|
||||||
|
|
||||||
|
@ -40,7 +39,6 @@ impl_Transformable_for(Prop,
|
||||||
|
|
||||||
impl_PhysicsEntity_for(Prop,
|
impl_PhysicsEntity_for(Prop,
|
||||||
PropGetRigidBody,
|
PropGetRigidBody,
|
||||||
PropGetCollisionShape,
|
|
||||||
PropOnCollision,
|
PropOnCollision,
|
||||||
PropOnOverlap
|
PropOnOverlap
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,11 +8,12 @@ void play() {
|
||||||
SpawnProp(MakeVector(2.f, 0.f),
|
SpawnProp(MakeVector(2.f, 0.f),
|
||||||
sprite_from_spritesheet(spritesheet_load("assets/bag.png", IVectorFrom(512)), 0),
|
sprite_from_spritesheet(spritesheet_load("assets/bag.png", IVectorFrom(512)), 0),
|
||||||
shape_new((Vector[]){
|
shape_new((Vector[]){
|
||||||
MakeVector(-0.25, -0.1),
|
MakeVector(-0.2, -0.1),
|
||||||
MakeVector(0.25, -0.1),
|
MakeVector( 0.2, -0.1),
|
||||||
MakeVector(0.25, 0.0),
|
MakeVector( 0.2, 0.05),
|
||||||
MakeVector(-0.25, 0.0)
|
MakeVector(-0.2, 0.05)
|
||||||
}, 4)
|
}, 4),
|
||||||
|
MakeVector(0.5f, .95f)
|
||||||
);
|
);
|
||||||
SpawnPlayer(ZeroVector);
|
SpawnPlayer(ZeroVector);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue