feat: separated combat and movement collision layers
This commit is contained in:
parent
8a05984afa
commit
46ef92ef92
|
@ -7,6 +7,9 @@
|
|||
|
||||
typedef struct DamageEventData {
|
||||
int damageAmount;
|
||||
int knockdown;
|
||||
float stun;
|
||||
float knockback;
|
||||
Vector origin;
|
||||
} DamageEventData;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "Enemy.h"
|
||||
#include "Layers.h"
|
||||
#include "debug.h"
|
||||
#include "game_world.h"
|
||||
#include "physics.h"
|
||||
|
@ -46,9 +47,10 @@ Enemy* MakeEnemy() {
|
|||
.behaviour = NULL,
|
||||
.rigidbody = NULL,
|
||||
.collider = NULL,
|
||||
.hitbox = NULL,
|
||||
.sprite = sprite_new_empty(),
|
||||
.hurt = 0,
|
||||
.facing = 1,
|
||||
.stun_time = 0.f,
|
||||
.idleAnim = NULL,
|
||||
.walkAnim = NULL,
|
||||
.hurtAnim = NULL,
|
||||
|
@ -57,7 +59,15 @@ Enemy* MakeEnemy() {
|
|||
};
|
||||
|
||||
self->rigidbody = rigidbody_make(Enemy_as_PhysicsEntity(self));
|
||||
self->collider = collider_new(Enemy_as_PhysicsEntity(self), shape_new_square(MakeVector(0.2f, 0.05f)), 0, PHYSICS_LAYER_DEFAULT | PHYSICS_LAYER_DEFAULT);
|
||||
self->collider = collider_new(Enemy_as_PhysicsEntity(self), shape_new_square(MakeVector(0.2f, 0.05f)), 0, PHYSICS_LAYER_DEFAULT);
|
||||
self->collider = collider_new(Enemy_as_PhysicsEntity(self), shape_new((Vector[]){
|
||||
MakeVector(-0.2f, -0.95f),
|
||||
MakeVector( 0.2f, -0.95f),
|
||||
MakeVector( 0.2f, 0.0f),
|
||||
MakeVector(-0.2f, 0.0f),
|
||||
}, 4), 1, PHYSICS_LAYER_COMBAT);
|
||||
PhysicsEntity pe = Enemy_as_PhysicsEntity(self);
|
||||
LOG_INFO("enemy instantiated mirroring as: %s", pe.mirror->get_typestring(pe.data));
|
||||
|
||||
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
||||
|
||||
|
@ -81,6 +91,8 @@ void EnemyStart(Enemy* self) {}
|
|||
|
||||
void EnemyUpdate(Enemy* self, float deltaTime) {
|
||||
state_machine_update(self->behaviour, deltaTime);
|
||||
if(self->stun_time > 0.0f)
|
||||
self->stun_time -= deltaTime;
|
||||
}
|
||||
|
||||
void EnemyDraw(Enemy* self) {
|
||||
|
@ -116,8 +128,10 @@ int EnemyDamage(Enemy* self, DamageEventData* data) {
|
|||
game_world_destroy_entity(Enemy_as_BehaviourEntity(self));
|
||||
return 1;
|
||||
} else {
|
||||
self->hurt = 1;
|
||||
self->facing = ((data->origin.x - self->transform.position.x) > 0) * 2 - 1;
|
||||
self->stun_time = data->stun;
|
||||
float direction = ((data->origin.x - self->transform.position.x) > 0) * 2 - 1;
|
||||
self->facing = direction;
|
||||
rigidbody_get_transform(self->rigidbody)->position = vaddf(self->transform.position, MakeVector(-direction * data->knockback, 0));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,12 +22,14 @@ typedef struct Enemy {
|
|||
|
||||
RigidBody* rigidbody;
|
||||
Collider* collider;
|
||||
Collider* hitbox;
|
||||
|
||||
Sprite* sprite;
|
||||
|
||||
int hurt;
|
||||
int facing;
|
||||
|
||||
float stun_time;
|
||||
|
||||
AnimationSprite* idleAnim;
|
||||
AnimationSprite* walkAnim;
|
||||
AnimationSprite* hurtAnim;
|
||||
|
|
|
@ -10,7 +10,7 @@ void EnemyIdle_Enter(Enemy* self) {
|
|||
}
|
||||
|
||||
const State* EnemyIdle_Update(Enemy* self, float deltaTime) {
|
||||
if(self->hurt)
|
||||
if(self->stun_time > 0.f)
|
||||
return EnemyHurt();
|
||||
return EnemyIdle();
|
||||
}
|
||||
|
@ -25,15 +25,13 @@ const State* EnemyWalk_Update(Enemy* self, float deltaTime) {
|
|||
}
|
||||
|
||||
void EnemyHurt_Enter(Enemy* self) {
|
||||
self->hurt = 0;
|
||||
|
||||
self->currentAnimation = self->hurtAnim;
|
||||
animation_sprite_play_from(self->currentAnimation, 0.f);
|
||||
}
|
||||
|
||||
const State* EnemyHurt_Update(Enemy* self, float deltaTime) {
|
||||
const float ntime = animation_sprite_get_time_normalized(self->currentAnimation);
|
||||
if(ntime > 1.0f)
|
||||
const float time = animation_sprite_get_time(self->currentAnimation);
|
||||
if(self->stun_time < 0.f)
|
||||
return EnemyIdle();
|
||||
return EnemyHurt();
|
||||
}
|
||||
|
|
36
game/src/Hurtbox.c
Normal file
36
game/src/Hurtbox.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "Hurtbox.h"
|
||||
#include "Damagable.h"
|
||||
#include "transformable.h"
|
||||
#include "transform.h"
|
||||
#include "physics_entity.h"
|
||||
#include "physics_world.h"
|
||||
#include "collider.h"
|
||||
#include "Layers.h"
|
||||
|
||||
static inline
|
||||
void Internal_HurtboxDealDamage(const Hurtbox* self, List* colliders, float min_y, float max_y) {
|
||||
DamageEventData data = self->damage;
|
||||
list_foreach(Collider**, collider, colliders) {
|
||||
PhysicsEntity entity = collider_get_owner(*collider);
|
||||
const IDamagable* damagable = mirror_get_typeclass(entity.data, entity.mirror, "Damagable");
|
||||
const Transform* transform = entity.transformable->get_transform(entity.data);
|
||||
if(damagable && transform->position.y >= min_y && transform->position.y <= max_y) damagable->damage(entity.data, &data);
|
||||
}
|
||||
}
|
||||
|
||||
int HurtboxCast(Hurtbox* self, float facing_dir) {
|
||||
const IPhysicsEntity* physics_entity = mirror_get_typeclass(self->owner.data, self->owner.mirror, "PhysicsEntity");
|
||||
const ITransformable* transformable = mirror_get_typeclass(self->owner.data, self->owner.mirror, "Transformable");
|
||||
|
||||
if(physics_entity == NULL || transformable == NULL)
|
||||
return -1;
|
||||
|
||||
RigidBody* body = physics_entity->get_rigidbody(self->owner.data);
|
||||
const Transform* transform = transformable->get_transform(self->owner.data);
|
||||
self->damage.origin = transform->position;
|
||||
|
||||
const Vector offset = vaddf(transform->position, MakeVector(facing_dir * self->offset.x, self->offset.y));
|
||||
List found = physics_world_box_query_all(offset, self->size, PHYSICS_LAYER_COMBAT, body);
|
||||
Internal_HurtboxDealDamage(self, &found, transform->position.y - self->depth_extent, transform->position.y + self->depth_extent);
|
||||
return found.len;
|
||||
}
|
18
game/src/Hurtbox.h
Normal file
18
game/src/Hurtbox.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef FIGHT_HURTBOX_H
|
||||
#define FIGHT_HURTBOX_H
|
||||
|
||||
#include "Damagable.h"
|
||||
#include "behaviour_entity.h"
|
||||
#include "vmath.h"
|
||||
|
||||
typedef struct Hurtbox {
|
||||
BehaviourEntity owner;
|
||||
DamageEventData damage;
|
||||
Vector size;
|
||||
Vector offset;
|
||||
float depth_extent;
|
||||
} Hurtbox;
|
||||
|
||||
int HurtboxCast(Hurtbox* self, float facing_dir);
|
||||
|
||||
#endif // !FIGHT_HURTBOX_H
|
|
@ -13,6 +13,7 @@ START_REFLECT(Player)
|
|||
REFLECT_TYPECLASS(Player, Drop)
|
||||
REFLECT_TYPECLASS(Player, PhysicsEntity)
|
||||
REFLECT_TYPECLASS(Player, BehaviourEntity)
|
||||
REFLECT_TYPECLASS(Player, Transformable)
|
||||
END_REFLECT(Player)
|
||||
|
||||
impl_Drop_for(Player,
|
||||
|
@ -61,6 +62,7 @@ Player* MakePlayer() {
|
|||
|
||||
.rigidbody = NULL,
|
||||
.physicsCollider = NULL,
|
||||
.hitbox = NULL,
|
||||
|
||||
.playerInput = playerinput_new(self, -1),
|
||||
.moveInput = ZeroVector,
|
||||
|
@ -86,7 +88,13 @@ Player* MakePlayer() {
|
|||
MakeVector( 0.2f, -0.065f),
|
||||
MakeVector( 0.2f, 0.065f),
|
||||
MakeVector(-0.2f, 0.065f)
|
||||
}, 4), 0, PHYSICS_LAYER_DEFAULT | PHYSICS_LAYER_COMBAT);
|
||||
}, 4), 0, PHYSICS_LAYER_DEFAULT);
|
||||
self->hitbox = collider_new(Player_as_PhysicsEntity(self), shape_new((Vector[]){
|
||||
MakeVector(-0.2f, -0.95f),
|
||||
MakeVector( 0.2f, -0.95f),
|
||||
MakeVector( 0.2f, 0.00f),
|
||||
MakeVector(-0.2f, 0.00f)
|
||||
}, 3), 1, PHYSICS_LAYER_COMBAT);
|
||||
|
||||
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
||||
|
||||
|
@ -128,6 +136,18 @@ void DestroyPlayer(Player* self) {
|
|||
state_machine_destroy(self->animationStateMachine);
|
||||
}
|
||||
|
||||
void PlayerStart(Player* self) {
|
||||
animation_sprite_play_from(self->currentAnimation, 0.0f);
|
||||
}
|
||||
|
||||
void PlayerUpdate(Player* self, float deltaTime) {
|
||||
state_machine_update(self->animationStateMachine, deltaTime);
|
||||
}
|
||||
|
||||
void PlayerDraw(Player* self) {
|
||||
animation_sprite_draw(self->currentAnimation, &self->transform);
|
||||
}
|
||||
|
||||
void PlayerHorizontalInput(Player* self, InputEvent value) {
|
||||
self->moveInput.x = value.as_float;
|
||||
}
|
||||
|
@ -146,17 +166,8 @@ void PlayerHeavyAttackInput(Player* self, InputEvent value) {
|
|||
self->attackInput = 2;
|
||||
}
|
||||
|
||||
void PlayerStart(Player* self) {
|
||||
animation_sprite_play_from(self->currentAnimation, 0.0f);
|
||||
}
|
||||
|
||||
void PlayerUpdate(Player* self, float deltaTime) {
|
||||
state_machine_update(self->animationStateMachine, deltaTime);
|
||||
}
|
||||
|
||||
void PlayerDraw(Player* self) {
|
||||
animation_sprite_draw(self->currentAnimation, &self->transform);
|
||||
}
|
||||
void PlayerOnCollision(Player* self, Collision collision) {}
|
||||
void PlayerOnOverlap(Player* self, Collider* other) {}
|
||||
|
||||
Transform* PlayerGetTransform(Player* self) {
|
||||
return &self->transform;
|
||||
|
@ -165,6 +176,3 @@ Transform* PlayerGetTransform(Player* self) {
|
|||
RigidBody* PlayerGetRigidBody(Player* self) {
|
||||
return self->rigidbody;
|
||||
}
|
||||
|
||||
void PlayerOnCollision(Player* self, Collision collision) {}
|
||||
void PlayerOnOverlap(Player* self, Collider* other) {}
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef struct Player {
|
|||
|
||||
RigidBody* rigidbody;
|
||||
Collider* physicsCollider;
|
||||
Collider* hitbox;
|
||||
|
||||
PlayerInput* playerInput;
|
||||
|
||||
|
@ -29,6 +30,7 @@ typedef struct Player {
|
|||
int facing;
|
||||
|
||||
Sprite* sprite;
|
||||
Transform sprite_local_transform;
|
||||
|
||||
AnimationSprite* idle;
|
||||
AnimationSprite* walk;
|
||||
|
@ -45,21 +47,22 @@ Player* MakePlayer();
|
|||
Player* SpawnPlayer(Vector location);
|
||||
void DestroyPlayer(Player* self);
|
||||
|
||||
void PlayerStart(Player* self);
|
||||
void PlayerUpdate(Player* self, float deltaTime);
|
||||
void PlayerDraw(Player* self);
|
||||
|
||||
void PlayerHorizontalInput(Player* self, InputEvent value);
|
||||
void PlayerVerticalInput(Player* self, InputEvent value);
|
||||
void PlayerLightAttackInput(Player* self, InputEvent value);
|
||||
void PlayerHeavyAttackInput(Player* self, InputEvent value);
|
||||
|
||||
void PlayerStart(Player* self);
|
||||
void PlayerUpdate(Player* self, float deltaTime);
|
||||
void PlayerDraw(Player* self);
|
||||
|
||||
Transform* PlayerGetTransform(Player* self);
|
||||
|
||||
RigidBody* PlayerGetRigidBody(Player* self);
|
||||
void PlayerOnCollision(Player* self, Collision collision);
|
||||
void PlayerOnOverlap(Player* self, Collider* other);
|
||||
|
||||
Transform* PlayerGetTransform(Player* self);
|
||||
RigidBody* PlayerGetRigidBody(Player* self);
|
||||
|
||||
|
||||
static long PlayerGetDepth(Player* self) { return (int)(-10-self->transform.position.y * 1000); }
|
||||
|
||||
DECL_REFLECT(Player);
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#include "PlayerStates.h"
|
||||
#include "mirror.h"
|
||||
#include "physics_world.h"
|
||||
#include "Hurtbox.h"
|
||||
|
||||
#include "Damagable.h"
|
||||
#include "Player.h"
|
||||
#include "Layers.h"
|
||||
|
||||
static inline
|
||||
void InternalSpriteFlipWithMovement(Player* self) {
|
||||
|
@ -60,17 +58,14 @@ void PlayerAttackEnter(Player* self) {
|
|||
|
||||
static
|
||||
void PlayerHurtbox(Player* self, DamageEventData damage, Vector hitbox_size, Vector offset) {
|
||||
offset.x *= self->facing;
|
||||
offset = vaddf(self->transform.position, offset);
|
||||
Collider* found = physics_world_box_query(offset, hitbox_size, PHYSICS_LAYER_COMBAT, self->rigidbody);
|
||||
if(found != NULL) {
|
||||
PhysicsEntity entity = collider_get_owner(found);
|
||||
const IDamagable* damagable = mirror_get_typeclass(entity.data, entity.mirror, "Damagable");
|
||||
if(damagable) {
|
||||
damage.origin = self->transform.position;
|
||||
damagable->damage(entity.data, &damage);
|
||||
}
|
||||
}
|
||||
Hurtbox box = {
|
||||
.owner = Player_as_BehaviourEntity(self),
|
||||
.damage = damage,
|
||||
.size = hitbox_size,
|
||||
.offset = offset,
|
||||
.depth_extent = 0.15f,
|
||||
};
|
||||
HurtboxCast(&box, self->facing);
|
||||
}
|
||||
|
||||
void PlayerJabA_Enter(Player* self) {
|
||||
|
@ -80,10 +75,15 @@ void PlayerJabA_Enter(Player* self) {
|
|||
}
|
||||
|
||||
const State* PlayerJabA_Update(Player* self, float deltaTime) {
|
||||
const static DamageEventData damage = {.damageAmount = 1};
|
||||
const static DamageEventData damage = {
|
||||
.damageAmount = 1,
|
||||
.knockdown = 0,
|
||||
.stun = 0.1f,
|
||||
.knockback = 0.05f,
|
||||
};
|
||||
const float ntime = animation_sprite_get_time_normalized(self->currentAnimation);
|
||||
if(self->animationTriggers == 0 && ntime > 0.33f) {
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, 0.06f));
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, -0.6f));
|
||||
++self->animationTriggers;
|
||||
}
|
||||
if(ntime > 1.0f) {
|
||||
|
@ -106,10 +106,15 @@ void PlayerJabB_Enter(Player* self) {
|
|||
}
|
||||
|
||||
const State* PlayerJabB_Update(Player* self, float deltaTime) {
|
||||
static const DamageEventData damage = {.damageAmount = 1};
|
||||
static const DamageEventData damage = {
|
||||
.damageAmount = 1,
|
||||
.knockdown = 0,
|
||||
.stun = 0.1f,
|
||||
.knockback = 0.05f,
|
||||
};
|
||||
const float ntime = animation_sprite_get_time_normalized(self->currentAnimation);
|
||||
if(self->animationTriggers == 0 && ntime > 0.33f) {
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, 0.0f));
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, -0.6f));
|
||||
++self->animationTriggers;
|
||||
}
|
||||
if(ntime > 1.0f) {
|
||||
|
@ -132,10 +137,15 @@ void PlayerKickA_Enter(Player* self) {
|
|||
}
|
||||
|
||||
const State* PlayerKickA_Update(Player* self, float deltaTime) {
|
||||
static const DamageEventData damage = {.damageAmount = 3};
|
||||
static const DamageEventData damage = {
|
||||
.damageAmount = 3,
|
||||
.knockdown = 1,
|
||||
.stun = 0.5f,
|
||||
.knockback = 0.15f,
|
||||
};
|
||||
const float ntime = animation_sprite_get_time_normalized(self->currentAnimation);
|
||||
if(ntime > 0.25f && self->animationTriggers == 0) {
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, 0.0f));
|
||||
PlayerHurtbox(self, damage, MakeVector(0.1f, 0.06f), MakeVector(0.3f, -0.4f));
|
||||
++self->animationTriggers;
|
||||
}
|
||||
if(ntime > 1.0f && self->attackInput == 1)
|
||||
|
|
Loading…
Reference in a new issue