diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e3d740..4e1e533 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,10 @@ file(GLOB src "${PROJECT_SOURCE_DIR}/src/game/render/*.c" "${PROJECT_SOURCE_DIR}/src/game/resource/*.c" "${PROJECT_SOURCE_DIR}/src/game/state/*.c" + "${PROJECT_SOURCE_DIR}/src/game/state/game_over/*.c" "${PROJECT_SOURCE_DIR}/src/game/state/play/*.c" + "${PROJECT_SOURCE_DIR}/src/game/state/results/*.c" + "${PROJECT_SOURCE_DIR}/src/game/state/title/*.c" ) add_executable(cc2 ${src}) diff --git a/README.md b/README.md index e69de29..099b8d5 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,28 @@ +# "Calamity Cobra in "A Sweeter Reprise" + +My entry for the 2023 WeightGaming Gain Jam; a sequel to my last entry. A top down arcade shooter with some fetishy elements. + +## Build + +### Dependencies + + - SDL2 + - SDL_image + - SDL_mixer + - SDL_ttf + +### Linux + +This repository uses CMake to compile, so: + +`mkdir build` + +`cd build` + +`cmake ..` + +`make` + +### Windows + +I used MinGW for the Windows build, so basically the same as Linux but you'll need to use MSYS, MinGW, etc. to compile it. diff --git a/src/STRINGS.h b/src/STRINGS.h index 5902c55..d65065a 100644 --- a/src/STRINGS.h +++ b/src/STRINGS.h @@ -31,8 +31,15 @@ #define STRING_WINDOW_TITLE "Calamity Cobra in 'A Sweeter Reprise'" -#define STRING_TUTORIAL_TEXT "The Dessert Elemental is restless, and won't be calmed unless she's gotten her fill of goodies! Slaughter foes that come your way with your trusty Snekgun. Fire using LMB/space, use right mouse button/R to redirect snakes for additional damage, lock snakes in place with Q and aim them with your mouse for a damage multiplier, and recall all airborne snakes with SHIFT. You can collect goodies with your snakes, too!\n" \ +#define STRING_TUTORIAL_TEXT "The Dessert Elemental is restless, and won't be calmed unless she's gotten her fill of goodies! Slaughter foes that come your way with your trusty Snekgun. Fire using left mouse button/space, use right mouse button/R to redirect snakes for additional damage, lock snakes in place with Q and aim them with your mouse for a damage multiplier, and recall all airborne snakes with SHIFT. You can collect goodies with your snakes, too!\n" \ "\n" \ -"The Sweet Heart she left beats fervently...if you give it a squeeze with the H key, you will gain a goodie multiplier. The next wave of enemies will come right after, though, and the enemies will be more aggressive...so use with caution!\n" \ +"The Sweet Heart she left beats fervently...if you give it a squeeze with the H key, you will gain a goodie multiplier. The more times you push its limits, the better! The next wave of enemies will come right after, though, and the enemies will be more aggressive...so use with great caution!\n" \ "\n" \ -"PROTIP: Dealing twice an enemy's max health will net double the goodies...\n" +"You don't have much time to satisfy the Dessert Elemental...make this quick! Approach her to exchange goodies for upgrades, to restore your health, or to feed her.\n" \ +"\n" \ +"Good luck!\n" + +#define STRING_GAME_OVER_TITLE_TEXT "GAME OVER\n" +#define STRING_GAME_OVER_TEXT "The bounty on Calamity Cobra's head remains forever uncollected...\n" +#define STRING_RESULTS_TEXT "Congratulations on satisfying the Dessert Elemental! I would've given you a medal and told you your completion time, but I'm tired...\n" +#define STRING_TITLE_CREDITS_TEXT "WeightGaming Gain Jam 2023\nArt, Programming & Sounds: ShweetMagnet\nMusic: Nebby\nSoftware licensed under GPLv3; art licensed under CC0.\n" diff --git a/src/game/ecs/component/COMPONENT_COMMON.h b/src/game/ecs/component/COMPONENT_COMMON.h index c608dda..fd3bcf5 100644 --- a/src/game/ecs/component/COMPONENT_COMMON.h +++ b/src/game/ecs/component/COMPONENT_COMMON.h @@ -20,14 +20,30 @@ typedef enum ECSComponentType { ECS_COMPONENT_ACTION_ON_DELETE_GIVE_AMMO, ECS_COMPONENT_ACTION_ON_DELETE_DROP_GOODIES, + ECS_COMPONENT_ENEMY, ECS_COMPONENT_ACTION_SPAWN, ECS_COMPONENT_ACTION_ON_HEIGHT_DAMAGE_DISABLE, + ECS_COMPONENT_ANIMATION_IDLE, ECS_COMPONENT_ANIMATION_COLOR_CHANGE, ECS_COMPONENT_ANIMATION_LEVITATE, ECS_COMPONENT_ANIMATION_MOVE, + ECS_COMPONENT_ANIMATION_ROTATE, ECS_COMPONENT_ANIMATION_CURSOR, ECS_COMPONENT_ANIMATION_STRETCH, ECS_COMPONENT_ANIMATION_SQUASH, + ECS_COMPONENT_CONTROL_MOVE, + ECS_COMPONENT_CONTROL_SHOOT, + ECS_COMPONENT_CONTROL_AIM, + ECS_COMPONENT_CONTROL_FACE, + ECS_COMPONENT_CONTROL_REDIRECT, + ECS_COMPONENT_CONTROL_LOCK, + ECS_COMPONENT_CONTROL_RECALL, + ECS_COMPONENT_CONTROL_HEART, + ECS_COMPONENT_CONTROL_PLAYER, + ECS_COMPONENT_ACTION_SHOOT, + ECS_COMPONENT_ACTION_GRIP, + ECS_COMPONENT_ACTION_GRIPPED, + ECS_COMPONENT_PICKUP, ECS_COMPONENT_PHYSICS, ECS_COMPONENT_CIRCLE_COLLISION, ECS_COMPONENT_ACTION_KEEP_IN_RECTANGLE, @@ -35,32 +51,21 @@ typedef enum ECSComponentType ECS_COMPONENT_TEXT, ECS_COMPONENT_GAME_OBJECT, ECS_COMPONENT_CHARACTER, - ECS_COMPONENT_ENEMY, - ECS_COMPONENT_PICKUP, ECS_COMPONENT_BEHAVIOR_ACT_IN_RECTANGLE, + ECS_COMPONENT_BEHAVIOR_FACE_TARGET, ECS_COMPONENT_BEHAVIOR_HOP, ECS_COMPONENT_BEHAVIOR_BOOMERANG, ECS_COMPONENT_BEHAVIOR_CHASE, ECS_COMPONENT_BEHAVIOR_APPROACH_AND_SHOOT, + ECS_COMPONENT_ACTION_ANGLE, ECS_COMPONENT_ACTION_ON_COMBAT_HIDE, - ECS_COMPONENT_ACTION_SHOOT, ECS_COMPONENT_ACTION_LOCK, ECS_COMPONENT_ACTION_FOLLOW, ECS_COMPONENT_ACTION_POINT_TO_MOUSE, ECS_COMPONENT_ACTION_RETURN, ECS_COMPONENT_ACTION_REDIRECT, ECS_COMPONENT_ACTION_DAMAGE, - ECS_COMPONENT_ACTION_GRIP, - ECS_COMPONENT_ACTION_GRIPPED, ECS_COMPONENT_ACTION_WAVE, - ECS_COMPONENT_CONTROL_MOVE, - ECS_COMPONENT_CONTROL_SHOOT, - ECS_COMPONENT_CONTROL_AIM, - ECS_COMPONENT_CONTROL_REDIRECT, - ECS_COMPONENT_CONTROL_LOCK, - ECS_COMPONENT_CONTROL_RECALL, - ECS_COMPONENT_CONTROL_HEART, - ECS_COMPONENT_CONTROL_PLAYER, ECS_COMPONENT_SHOP, ECS_COMPONENT_SHOP_ITEM, ECS_COMPONENT_ACT_ENTITY, @@ -85,6 +90,7 @@ typedef enum ECSComponentType ECS_COMPONENT_ACTION_ON_TOUCH_GIVE_GOODIES, ECS_COMPONENT_ACTION_DELETE_ON_DEAD, ECS_COMPONENT_ACTION_DELETE_ON_TIMER, + ECS_COMPONENT_ACTION_DELETE_ON_HEART, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_GAME_ENTITY_TYPE, ECS_COMPONENT_ACTION_ON_OUT_OF_BOUNDS_DELETE diff --git a/src/game/ecs/component/action/component_action_angle.c b/src/game/ecs/component/action/component_action_angle.c new file mode 100644 index 0000000..33e3416 --- /dev/null +++ b/src/game/ecs/component/action/component_action_angle.c @@ -0,0 +1,84 @@ +#include "component_action_angle.h" + +/* DEPENDENCIES: Physics, AnimationIdle */ + +/* Ticks action angle component. */ +void +component_action_angle_tick(ComponentActionAngle* self, ECS* ecs) +{ + ComponentPhysics* physics; + ComponentSprite* sprite; + ComponentAnimationIdle* animationIdle; + + physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id); + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + animationIdle = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_IDLE, self->component.id); + + animationIdle->component.isDisabled = true; + + + if + ( + physics->angle >= 0.0f && physics->angle < PI_FOURTH + ) + { + animationIdle->baseIndex = 0; + sprite->atlas.index = 0; + } + else if + ( + physics->angle >= PI_FOURTH && physics->angle < PI_HALF + ) + { + animationIdle->baseIndex = 2; + sprite->atlas.index = 2; + } + else if + ( + physics->angle >= PI_HALF && physics->angle < (PI_HALF + PI_FOURTH) + ) + { + animationIdle->baseIndex = 4; + sprite->atlas.index = 4; + } + else if + ( + physics->angle >= (PI_HALF + PI_FOURTH) && physics->angle < PI + ) + { + animationIdle->baseIndex = 6; + sprite->atlas.index = 6; + } + else if + ( + physics->angle >= -PI && physics->angle < -(PI_HALF + PI_FOURTH) + ) + { + animationIdle->baseIndex = 8; + sprite->atlas.index = 8; + } + else if + ( + physics->angle >= -(PI_HALF + PI_FOURTH) && physics->angle < -PI_HALF + ) + { + animationIdle->baseIndex = 10; + sprite->atlas.index = 10; + } + else if + ( + physics->angle >= -PI_HALF && physics->angle < -PI_FOURTH + ) + { + animationIdle->baseIndex = 12; + sprite->atlas.index = 12; + } + else if + ( + physics->angle >= -PI_FOURTH && physics->angle < 0.0f + ) + { + animationIdle->baseIndex = 14; + sprite->atlas.index = 14; + } +} diff --git a/src/game/ecs/component/action/component_action_angle.h b/src/game/ecs/component/action/component_action_angle.h new file mode 100644 index 0000000..07dfa61 --- /dev/null +++ b/src/game/ecs/component/action/component_action_angle.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../component_physics.h" +#include "../component_sprite.h" +#include "../animation/component_animation_idle.h" + +typedef struct ComponentActionAngle +{ + ECSComponent component; +} ComponentActionAngle; + +void component_action_angle_tick(ComponentActionAngle* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_ACTION_ANGLE_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_action_angle_tick, + NULL + } + }, + .type = ECS_COMPONENT_ACTION_ANGLE, + .size = sizeof(ComponentActionAngle) +}; + + diff --git a/src/game/ecs/component/action/component_action_delete_on_dead.c b/src/game/ecs/component/action/component_action_delete_on_dead.c index d56644f..fa710ff 100644 --- a/src/game/ecs/component/action/component_action_delete_on_dead.c +++ b/src/game/ecs/component/action/component_action_delete_on_dead.c @@ -5,6 +5,27 @@ static void _dead_sound(ComponentActionDeleteOnDead* self, ECS* ecs); +/* Spawns a puff particle. */ +static void +_puff_spawn(ComponentActionDeleteOnDead* self, ECS* ecs) +{ + ComponentSprite* sprite; + vec3 position; + vec2 size; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + glm_vec3_copy(sprite->position, position); + + size[0] = sprite->size[1]; + size[1] = sprite->size[1]; + + position[1] -= (sprite->size[1] / 2); + position[2] += COMPONENT_ACTION_DELETE_ON_DEAD_PUFF_Z_OFFSET; + + entity_puff_init(ecs, ecs_entity_add(ecs), position, size); +} + static void _dead_sound(ComponentActionDeleteOnDead* self, ECS* ecs) { @@ -47,6 +68,7 @@ component_action_delete_on_dead_tick(ComponentActionDeleteOnDead* self, ECS* ecs if (health->isDead) { + _puff_spawn(self, ecs); _dead_sound(self, ecs); ecs_entity_delete(ecs, self->component.id); diff --git a/src/game/ecs/component/action/component_action_delete_on_dead.h b/src/game/ecs/component/action/component_action_delete_on_dead.h index 33dab82..1f31156 100644 --- a/src/game/ecs/component/action/component_action_delete_on_dead.h +++ b/src/game/ecs/component/action/component_action_delete_on_dead.h @@ -6,6 +6,10 @@ #include "../stat/component_health.h" #include "../stat/component_game_entity_type.h" +#include "../../entity/play/entity_puff.h" + +#define COMPONENT_ACTION_DELETE_ON_DEAD_PUFF_Z_OFFSET -0.01f + typedef struct ComponentActionDeleteOnDead { ECSComponent component; diff --git a/src/game/ecs/component/action/component_action_delete_on_heart.c b/src/game/ecs/component/action/component_action_delete_on_heart.c new file mode 100644 index 0000000..338bfd9 --- /dev/null +++ b/src/game/ecs/component/action/component_action_delete_on_heart.c @@ -0,0 +1,23 @@ +#include "component_action_delete_on_heart.h" + +/* DEPENDENCIES: Heart */ +/* This entity associated with this component will be deleted if the heart component is used. */ + +/* Initializes action delete on heart component. */ +void +component_action_delete_on_heart_init(ComponentActionDeleteOnHeart* self, u32 heartID) +{ + self->heartID = heartID; +} + +/* Ticks action delete on heart component. */ +void +component_action_delete_on_heart_tick(ComponentActionDeleteOnHeart* self, ECS* ecs) +{ + ComponentHeart* heart; + + heart = ecs_component_get(ecs, ECS_COMPONENT_HEART, self->heartID); + + if (heart->uses > 0) + ecs_entity_delete(ecs, self->component.id); +} diff --git a/src/game/ecs/component/action/component_action_delete_on_heart.h b/src/game/ecs/component/action/component_action_delete_on_heart.h new file mode 100644 index 0000000..a9c902b --- /dev/null +++ b/src/game/ecs/component/action/component_action_delete_on_heart.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../../../GAME_COMMON.h" +#include "../../ecs_entity.h" + +#include "../stat/component_heart.h" + +typedef struct ComponentActionDeleteOnHeart +{ + ECSComponent component; + u32 heartID; +} ComponentActionDeleteOnHeart; + +void component_action_delete_on_heart_init(ComponentActionDeleteOnHeart* self, u32 value); +void component_action_delete_on_heart_tick(ComponentActionDeleteOnHeart* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_ACTION_DELETE_ON_HEART_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_action_delete_on_heart_tick, + NULL + } + }, + .type = ECS_COMPONENT_ACTION_DELETE_ON_HEART, + .size = sizeof(ComponentActionDeleteOnHeart) +}; + + diff --git a/src/game/ecs/component/action/component_action_gripped.c b/src/game/ecs/component/action/component_action_gripped.c index 9c6e9ee..c5b8127 100644 --- a/src/game/ecs/component/action/component_action_gripped.c +++ b/src/game/ecs/component/action/component_action_gripped.c @@ -37,13 +37,12 @@ _component_action_gripped_set(ComponentActionGripped* self, ECS* ecs) sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); glm_vec3_copy(gripperPhysics->position, physics->position); - glm_vec3_copy(gripperPhysics->velocity, physics->velocity); gameObject->height = gripperGameObject->height + (physics->size[1] * 2); - sprite->offset[2] = gripperPhysics->position[2] + COMPONENT_ACTION_GRIPPED_Z_OFFSET; - + sprite->offset[2] = COMPONENT_ACTION_GRIPPED_Z_OFFSET; + gameObject->isBounce = gripperGameObject->isBounce; gameObject->isAffectedByGravity = gripperGameObject->isAffectedByGravity; } diff --git a/src/game/ecs/component/action/component_action_gripped.h b/src/game/ecs/component/action/component_action_gripped.h index 7ad190e..5c1cb43 100644 --- a/src/game/ecs/component/action/component_action_gripped.h +++ b/src/game/ecs/component/action/component_action_gripped.h @@ -6,7 +6,7 @@ #include "../component_game_object.h" #define COMPONENT_ACTION_GRIPPED_TIMER 15 -#define COMPONENT_ACTION_GRIPPED_Z_OFFSET -0.01f +#define COMPONENT_ACTION_GRIPPED_Z_OFFSET -0.001f typedef struct ComponentActionGripped { diff --git a/src/game/ecs/component/action/component_action_lock.c b/src/game/ecs/component/action/component_action_lock.c index 8a0df1a..39e5978 100644 --- a/src/game/ecs/component/action/component_action_lock.c +++ b/src/game/ecs/component/action/component_action_lock.c @@ -119,22 +119,32 @@ component_action_lock_lock(ComponentActionLock* self, ECS* ecs) ComponentActionReturn* actionReturn; ComponentActionDamage* actionDamage; ComponentActionDeleteOnTouchEntity* actionDeleteOnTouchEntity; + ComponentActionAngle* actionAngle; + ComponentAnimationIdle* animationIdle; + ComponentSprite* sprite; physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id); actionReturn = ecs_component_get(ecs, ECS_COMPONENT_ACTION_RETURN, self->component.id); actionDamage = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DAMAGE, self->component.id); actionDeleteOnTouchEntity = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY, self->component.id); + actionAngle = ecs_component_get(ecs, ECS_COMPONENT_ACTION_ANGLE, self->component.id); + animationIdle = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_IDLE, self->component.id); + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); glm_vec3_copy(physics->velocity, self->velocity); actionReturn->component.isDisabled = true; actionDeleteOnTouchEntity->component.isDisabled = false; actionDamage->component.isDisabled = true; + actionAngle->component.isDisabled = true; self->cooldown = self->cooldownMax; self->isLocked = true; + animationIdle->baseIndex = 16; + sprite->atlas.index = 16; + sound_play(&ecs->game->resources.sounds[SOUND_LOCK], SOUND_NO_PRIORITY); } @@ -146,15 +156,20 @@ component_action_lock_unlock(ComponentActionLock* self, ECS* ecs) ComponentActionReturn* actionReturn; ComponentActionDamage* actionDamage; ComponentActionDeleteOnTouchEntity* actionDeleteOnTouchEntity; + ComponentActionAngle* actionAngle; + ComponentAnimationIdle* animationIdle; physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id); actionReturn = ecs_component_get(ecs, ECS_COMPONENT_ACTION_RETURN, self->component.id); actionDamage = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DAMAGE, self->component.id); actionDeleteOnTouchEntity = ecs_component_get(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY, self->component.id); + actionAngle = ecs_component_get(ecs, ECS_COMPONENT_ACTION_ANGLE, self->component.id); + animationIdle = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_IDLE, self->component.id); glm_vec3_copy(self->velocity, physics->velocity); actionReturn->component.isDisabled = false; actionDamage->component.isDisabled = false; + actionAngle->component.isDisabled = false; actionDeleteOnTouchEntity->component.isDisabled = true; @@ -162,6 +177,8 @@ component_action_lock_unlock(ComponentActionLock* self, ECS* ecs) self->isRedirectAngleGiven = false; self->isLocked = false; + animationIdle->baseIndex = 0; + sound_play(&ecs->game->resources.sounds[SOUND_UNLOCK], SOUND_NO_PRIORITY); if (self->isRedirectArrowInit) diff --git a/src/game/ecs/component/action/component_action_lock.h b/src/game/ecs/component/action/component_action_lock.h index b1f5e7c..fcd68ae 100644 --- a/src/game/ecs/component/action/component_action_lock.h +++ b/src/game/ecs/component/action/component_action_lock.h @@ -9,6 +9,8 @@ #include "component_action_return.h" #include "component_action_delete_on_touch_entity.h" #include "../stat/component_redirects.h" +#include "../action/component_action_angle.h" +#include "../animation/component_animation_idle.h" #include "../../entity/play/entity_redirect_arrow.h" diff --git a/src/game/ecs/component/action/component_action_on_combat_hide.c b/src/game/ecs/component/action/component_action_on_combat_hide.c index 3830af9..9708f84 100644 --- a/src/game/ecs/component/action/component_action_on_combat_hide.c +++ b/src/game/ecs/component/action/component_action_on_combat_hide.c @@ -8,6 +8,28 @@ static void _hide(ComponentActionOnCombatHide* self, ECS* ecs); static void _unhide(ComponentActionOnCombatHide* self, ECS* ecs); +static void _puff_spawn(ComponentActionOnCombatHide* self, ECS* ecs); + +/* Spawns a puff particle. */ +static void +_puff_spawn(ComponentActionOnCombatHide* self, ECS* ecs) +{ + ComponentSprite* sprite; + vec3 position; + vec2 size; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + glm_vec3_copy(sprite->position, position); + + size[0] = sprite->size[1]; + size[1] = sprite->size[1]; + + position[1] -= (sprite->size[1] / 2); + position[2] += COMPONENT_ACTION_ON_COMBAT_HIDE_PUFF_Z_OFFSET; + + entity_puff_init(ecs, ecs_entity_add(ecs), position, size); +} /* "Hides" this component (disables drawing + collisions) */ static void @@ -29,6 +51,8 @@ _hide(ComponentActionOnCombatHide* self, ECS* ecs) shadowSprite->component.isDisabled = true; vector_clear(&physics->collisions); + + _puff_spawn(self, ecs); } /* "Unhides" this component (enables drawing + collisions) */ @@ -49,6 +73,8 @@ _unhide(ComponentActionOnCombatHide* self, ECS* ecs) physics->component.isDisabled = false; sprite->component.isDisabled = false; shadowSprite->component.isDisabled = false; + + _puff_spawn(self, ecs); } /* Initializes ActionOnCombatHide component. */ diff --git a/src/game/ecs/component/action/component_action_on_combat_hide.h b/src/game/ecs/component/action/component_action_on_combat_hide.h index 6a32b35..0d317dd 100644 --- a/src/game/ecs/component/action/component_action_on_combat_hide.h +++ b/src/game/ecs/component/action/component_action_on_combat_hide.h @@ -6,6 +6,10 @@ #include "component_action_spawn.h" #include "../component_game_object.h" +#include "../../entity/play/entity_puff.h" + +#define COMPONENT_ACTION_ON_COMBAT_HIDE_PUFF_Z_OFFSET -0.01f + typedef struct ComponentActionOnCombatHide { ECSComponent component; diff --git a/src/game/ecs/component/action/component_action_on_delete_drop_goodies.h b/src/game/ecs/component/action/component_action_on_delete_drop_goodies.h index 9929449..b82402b 100644 --- a/src/game/ecs/component/action/component_action_on_delete_drop_goodies.h +++ b/src/game/ecs/component/action/component_action_on_delete_drop_goodies.h @@ -5,6 +5,7 @@ #include "../../entity/play/entity_goodie.h" #include "../stat/component_game_entity_type.h" +#include "../entity/component_enemy.h" #define COMPONENT_ACTION_ON_DELETE_DROP_GOODIES_VELOCITY_MIN -10.0f #define COMPONENT_ACTION_ON_DELETE_DROP_GOODIES_VELOCITY_MAX 10.0f diff --git a/src/game/ecs/component/action/component_action_on_touch_give_goodies.c b/src/game/ecs/component/action/component_action_on_touch_give_goodies.c index 48d8104..1db2d01 100644 --- a/src/game/ecs/component/action/component_action_on_touch_give_goodies.c +++ b/src/game/ecs/component/action/component_action_on_touch_give_goodies.c @@ -14,7 +14,6 @@ component_action_on_touch_give_goodies_init(ComponentActionOnTouchGiveGoodies* s void component_action_on_touch_give_goodies_tick(ComponentActionOnTouchGiveGoodies* self, ECS* ecs) { - ComponentActEntity* actEntity; ComponentPhysics* physics; if (self->isGivenGoodies) @@ -25,20 +24,17 @@ component_action_on_touch_give_goodies_tick(ComponentActionOnTouchGiveGoodies* s if (physics->collisions.count == 0) return; - actEntity = ecs_component_get(ecs, ECS_COMPONENT_ACT_ENTITY, self->component.id); - for (s32 i = 0; i < (s32)physics->collisions.count; i++) { + ComponentGoodies* goodies; u32 id; id = *(u32*)vector_get(&physics->collisions, i); - if (id == actEntity->id) - { - ComponentGoodies* goodies; - - goodies = ecs_component_get(ecs, ECS_COMPONENT_GOODIES, actEntity->id); + goodies = ecs_component_get(ecs, ECS_COMPONENT_GOODIES, id); + if (goodies) + { goodies->value += self->value *= goodies->multiplier; sound_play(&ecs->game->resources.sounds[SOUND_GOODIE], SOUND_NO_PRIORITY); diff --git a/src/game/ecs/component/action/component_action_return.c b/src/game/ecs/component/action/component_action_return.c index 068a8bc..862a38c 100644 --- a/src/game/ecs/component/action/component_action_return.c +++ b/src/game/ecs/component/action/component_action_return.c @@ -100,14 +100,16 @@ component_action_return_tick(ComponentActionReturn* self, ECS* ecs) angle = ATAN ( - physics->position[0], senderPhysics->position[0], - physics->position[1], - senderPhysics->position[1] + physics->position[0], + senderPhysics->position[1], + physics->position[1] ); speed = self->speed * (self->timer * self->multiplier); - physics->velocity[0] = cos(angle) * speed; - physics->velocity[1] = sin(angle) * speed; + physics->velocity[0] = -cos(angle) * speed; + physics->velocity[1] = -sin(angle) * speed; + + physics->angle = angle; } diff --git a/src/game/ecs/component/action/component_action_spawn.c b/src/game/ecs/component/action/component_action_spawn.c index 3f4a649..4c83d7d 100644 --- a/src/game/ecs/component/action/component_action_spawn.c +++ b/src/game/ecs/component/action/component_action_spawn.c @@ -136,7 +136,6 @@ _spawn_entity(ComponentActionSpawn* self, ECS* ecs) u32 usedLevel; id = ecs_entity_add(ecs); - vector_push(&self->entities, &id); glm_vec2_zero(size); glm_vec3_zero(position); @@ -189,7 +188,7 @@ _spawn_entity(ComponentActionSpawn* self, ECS* ecs) switch (type) { case GAME_ENTITY_CUPPER: - entity_cupper_init(ecs, id, position, self->targetID, usedLevel, &self->entities); + entity_cupper_init(ecs, id, position, self->targetID, usedLevel); break; case GAME_ENTITY_CHIP: entity_chip_init(ecs, id, position, -1); @@ -217,30 +216,27 @@ _spawn_entity(ComponentActionSpawn* self, ECS* ecs) break; case GAME_ENTITY_CHIPPER: - entity_chipper_init(ecs, id, position, self->targetID, usedLevel, &self->entities); + entity_chipper_init(ecs, id, position, self->targetID, usedLevel); break; case GAME_ENTITY_CUSTARPEDO: - entity_custarpedo_init(ecs, id, position, self->targetID, usedLevel, &self->entities); + entity_custarpedo_init(ecs, id, position, self->targetID, usedLevel); break; case GAME_ENTITY_CRUMBLER: - entity_crumbler_init(ecs, id, position, usedLevel, &self->entities); + entity_crumbler_init(ecs, id, position, usedLevel); break; case GAME_ENTITY_EXCORSANT: - entity_excorsant_init(ecs, id, position, self->targetID, usedLevel, &self->entities); + entity_excorsant_init(ecs, id, position, self->targetID, usedLevel); break; default: break; } } - - /* Ticks action_spawn component. */ void component_action_spawn_add(ComponentActionSpawn* self, ECS* ecs) { vector_init(&self->types, sizeof(GameEntityType)); - vector_init(&self->entities, sizeof(u32)); ecs_component_add(ecs, ECS_COMPONENT_LEVEL, self->component.id); ecs_component_add(ecs, ECS_COMPONENT_WAVE, self->component.id); _spawn_timer_set(self, ecs); @@ -251,7 +247,6 @@ void component_action_spawn_delete(ComponentActionSpawn* self, ECS* ecs) { vector_free(&self->types); - vector_free(&self->entities); ecs_component_delete(ecs, ECS_COMPONENT_LEVEL, self->component.id); ecs_component_delete(ecs, ECS_COMPONENT_WAVE, self->component.id); } @@ -309,6 +304,7 @@ component_action_spawn_wave_add(ComponentActionSpawn* self, ECS* ecs, const Spaw music_play(&ecs->game->resources.music[MUSIC_COMBAT_ONE], true); self->isCombat = true; + self->mercyTimer = COMPONENT_ACTION_SPAWN_MERCY_TIMER_MAX; wave->value++; } @@ -321,28 +317,24 @@ component_action_spawn_tick(ComponentActionSpawn* self, ECS* ecs) { self->combatTimer--; self->timer--; - - if (self->timer <= 0) - { - self->timer = 0; - - if (self->combatTimer > 0) - { - _spawn_entity(self, ecs); - _spawn_timer_set(self, ecs); - } - } - - if (self->combatTimer <= 0 ) - self->combatTimer = 0; } - if (self->combatTimer <= 0 && self->entities.count == 0) + if (self->combatTimer <= 0) + { + self->mercyTimer--; + + if (self->mercyTimer <= 0) + { + ecs_component_list_clear(&ecs->lists[ECS_COMPONENT_ENEMY]); + self->mercyTimer = COMPONENT_ACTION_SPAWN_MERCY_TIMER_MAX; + } + } + + if (self->combatTimer <= 0 && ecs->lists[ECS_COMPONENT_ENEMY].components.count == 0) { if (self->isCombat) music_play(&ecs->game->resources.music[MUSIC_CALM], true); - vector_clear(&self->types); self->levelBonus = 0; self->isCombat = false; @@ -350,4 +342,15 @@ component_action_spawn_tick(ComponentActionSpawn* self, ECS* ecs) } + if (self->timer <= 0) + { + if (self->combatTimer > 0) + { + _spawn_entity(self, ecs); + _spawn_timer_set(self, ecs); + } + } + + if (self->combatTimer <= 0 ) + self->combatTimer = 0; } diff --git a/src/game/ecs/component/action/component_action_spawn.h b/src/game/ecs/component/action/component_action_spawn.h index 68a8d7e..e7358d5 100644 --- a/src/game/ecs/component/action/component_action_spawn.h +++ b/src/game/ecs/component/action/component_action_spawn.h @@ -16,6 +16,7 @@ #define COMPONENT_ACTION_SPAWN_TIMER_BASE 100 #define COMPONENT_ACTION_SPAWN_TIMER_LEVEL_MULTIPLIER 10 #define COMPONENT_ACTION_SPAWN_TIMER_MINIMUM 20 +#define COMPONENT_ACTION_SPAWN_MERCY_TIMER_MAX 1800 #define COMPONENT_ACTION_SPAWN_CHIP_SPEED 10 #define COMPONENT_ACTION_SPAWN_CHIP_LEVEL_VELOCITY_MULTIPLIER 1.5 @@ -61,7 +62,7 @@ typedef struct ComponentActionSpawn s32 timer; u32 targetID; u32 levelBonus; - Vector entities; /* u32 */ + u32 mercyTimer; Vector types; /* GameEntityType */ bool isSpawn; bool isCombat; diff --git a/src/game/ecs/component/action/component_action_wave.c b/src/game/ecs/component/action/component_action_wave.c index b1e2266..7f439ca 100644 --- a/src/game/ecs/component/action/component_action_wave.c +++ b/src/game/ecs/component/action/component_action_wave.c @@ -12,6 +12,7 @@ _timer_set(ComponentActionWave* self, ECS* ecs) level = ecs_component_get(ecs, ECS_COMPONENT_LEVEL, self->component.id); self->timer = COMPONENT_ACTION_WAVE_SPAWN_TIMER_BASE; + self->timer += SPAWN_WAVES[self->index].timer * COMPONENT_ACTION_WAVE_SPAWN_TIMER_MULITPLIER; self->timer -= ((level->value - 1) * COMPONENT_ACITON_WAVE_SPAWN_TIMER_LEVEL_MULTIPLIER); self->timer = MIN(self->timer, COMPONENT_ACTION_WAVE_SPAWN_TIMER_MIN); diff --git a/src/game/ecs/component/action/component_action_wave.h b/src/game/ecs/component/action/component_action_wave.h index cc75ab0..bdf0740 100644 --- a/src/game/ecs/component/action/component_action_wave.h +++ b/src/game/ecs/component/action/component_action_wave.h @@ -6,9 +6,10 @@ #include "component_action_spawn.h" #include "../stat/component_game_entity_type.h" -#define COMPONENT_ACTION_WAVE_SPAWN_TIMER_BASE 3600 +#define COMPONENT_ACTION_WAVE_SPAWN_TIMER_BASE 1800 #define COMPONENT_ACITON_WAVE_SPAWN_TIMER_LEVEL_MULTIPLIER 300 #define COMPONENT_ACTION_WAVE_SPAWN_TIMER_MIN 1800 +#define COMPONENT_ACTION_WAVE_SPAWN_TIMER_MULITPLIER 0.5 #define COMPONENT_ACTION_WAVE_COUNT 30 @@ -47,13 +48,13 @@ static const SpawnWave SPAWN_WAVES[COMPONENT_ACTION_WAVE_COUNT] = { { .types = (GameEntityType*)WAVE_ONE_ENEMIES, .typeCount = 1, .timer = 1800}, { .types = (GameEntityType*)WAVE_TWO_ENEMIES, .typeCount = 1, .timer = 1800}, - { .types = (GameEntityType*)WAVE_THREE_ENEMIES, .typeCount = 1, .timer = 3600}, + { .types = (GameEntityType*)WAVE_THREE_ENEMIES, .typeCount = 1, .timer = 1800}, { .types = (GameEntityType*)WAVE_FOUR_ENEMIES, .typeCount = 2, .timer = 1800}, - { .types = (GameEntityType*)WAVE_FIVE_ENEMIES, .typeCount = 2, .timer = 3600}, - { .types = (GameEntityType*)WAVE_SIX_ENEMIES, .typeCount = 2, .timer = 3600}, - { .types = (GameEntityType*)WAVE_SEVEN_ENEMIES, .typeCount = 3, .timer = 3600}, + { .types = (GameEntityType*)WAVE_FIVE_ENEMIES, .typeCount = 2, .timer = 1800}, + { .types = (GameEntityType*)WAVE_SIX_ENEMIES, .typeCount = 2, .timer = 1800}, + { .types = (GameEntityType*)WAVE_SEVEN_ENEMIES, .typeCount = 3, .timer = 1800}, { .types = (GameEntityType*)WAVE_EIGHT_ENEMIES, .typeCount = 3, .timer = 1800}, - { .types = (GameEntityType*)WAVE_NINE_ENEMIES, .typeCount = 1, .timer = 1800}, + { .types = (GameEntityType*)WAVE_NINE_ENEMIES, .typeCount = 1, .timer = 3600}, { .types = (GameEntityType*)WAVE_TEN_ENEMIES, .typeCount = 4, .timer = 3600}, { .types = (GameEntityType*)WAVE_ELEVEN_ENEMIES, .typeCount = 1, .timer = 1800}, { .types = (GameEntityType*)WAVE_TWELVE_ENEMIES, .typeCount = 2, .timer = 1800}, diff --git a/src/game/ecs/component/animation/component_animation_idle.c b/src/game/ecs/component/animation/component_animation_idle.c new file mode 100644 index 0000000..f7a6f24 --- /dev/null +++ b/src/game/ecs/component/animation/component_animation_idle.c @@ -0,0 +1,33 @@ +#include "component_animation_idle.h" + +/* Initializes animation idle component. */ +void +component_animation_idle_init(ComponentAnimationIdle* self, u32 baseIndex, u32 timer) +{ + self->baseIndex = baseIndex; + self->timerMax = timer; + self->timer = self->timerMax; +} + +/* Ticks animation idle component. */ +void +component_animation_idle_tick(ComponentAnimationIdle* self, ECS* ecs) +{ + ComponentSprite* sprite; + + self->timer--; + + if (self->timer <= 0) + { + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + self->isAnimate = !self->isAnimate; + + if (self->isAnimate) + sprite->atlas.index = self->baseIndex + 1; + else + sprite->atlas.index = self->baseIndex; + + self->timer = self->timerMax; + } +} diff --git a/src/game/ecs/component/animation/component_animation_idle.h b/src/game/ecs/component/animation/component_animation_idle.h new file mode 100644 index 0000000..5c57a01 --- /dev/null +++ b/src/game/ecs/component/animation/component_animation_idle.h @@ -0,0 +1,35 @@ +#pragma once + +#include "ANIMATION_COMMON.h" +#include "../../../GAME_COMMON.h" +#include "../../ecs_entity.h" + +#include "../component_sprite.h" + +typedef struct ComponentAnimationIdle +{ + ECSComponent component; + u32 baseIndex; + s32 timer; + s32 timerMax; + bool isAnimate; +} ComponentAnimationIdle; + +void component_animation_idle_init(ComponentAnimationIdle* self, u32 baseIndex, u32 timer); +void component_animation_idle_tick(ComponentAnimationIdle* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_ANIMATION_IDLE_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_animation_idle_tick, + NULL + } + }, + .type = ECS_COMPONENT_ANIMATION_IDLE, + .size = sizeof(ComponentAnimationIdle) +}; diff --git a/src/game/ecs/component/animation/component_animation_rotate.c b/src/game/ecs/component/animation/component_animation_rotate.c new file mode 100644 index 0000000..0547ba3 --- /dev/null +++ b/src/game/ecs/component/animation/component_animation_rotate.c @@ -0,0 +1,19 @@ +#include "component_animation_rotate.h" + +/* Initializes animation rotate component. */ +void +component_animation_rotate_init(ComponentAnimationRotate* self, f32 speed) +{ + self->speed = speed; +} + +/* Ticks animation rotate component. */ +void +component_animation_rotate_tick(ComponentAnimationRotate* self, ECS* ecs) +{ + ComponentSprite* sprite; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + sprite->rotation += self->speed; +} diff --git a/src/game/ecs/component/animation/component_animation_rotate.h b/src/game/ecs/component/animation/component_animation_rotate.h new file mode 100644 index 0000000..37d0c54 --- /dev/null +++ b/src/game/ecs/component/animation/component_animation_rotate.h @@ -0,0 +1,36 @@ +#pragma once + +#include "ANIMATION_COMMON.h" + +#include "../component_sprite.h" + +typedef struct ComponentAnimationRotate +{ + ECSComponent component; + f32 speed; +} ComponentAnimationRotate; + +void component_animation_rotate_init +( + ComponentAnimationRotate* self, + f32 speed +); + +void component_animation_rotate_init(ComponentAnimationRotate* self, f32 speed); +void component_animation_rotate_tick(ComponentAnimationRotate* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_ANIMATION_ROTATE_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_animation_rotate_tick, + NULL + } + }, + .type = ECS_COMPONENT_ANIMATION_ROTATE, + .size = sizeof(ComponentAnimationRotate) +}; diff --git a/src/game/ecs/component/behavior/component_behavior_approach_and_shoot.c b/src/game/ecs/component/behavior/component_behavior_approach_and_shoot.c index 9aed729..3044794 100644 --- a/src/game/ecs/component/behavior/component_behavior_approach_and_shoot.c +++ b/src/game/ecs/component/behavior/component_behavior_approach_and_shoot.c @@ -69,6 +69,7 @@ component_behavior_approach_and_shoot_init self->distance = distance; self->timerMax = timer; self->timer = self->timerMax; + self->targetID = targetID; } /* Sets behavior_approach_and_shoot component info. */ diff --git a/src/game/ecs/component/behavior/component_behavior_boomerang.c b/src/game/ecs/component/behavior/component_behavior_boomerang.c index 329bdaf..d6b2a7d 100644 --- a/src/game/ecs/component/behavior/component_behavior_boomerang.c +++ b/src/game/ecs/component/behavior/component_behavior_boomerang.c @@ -12,9 +12,13 @@ _begin(ComponentBehaviorBoomerang* self, ECS* ecs) ComponentPhysics* physics; ComponentPhysics* targetPhysics; ComponentAnimationLevitate* animationLevitate; + ComponentAnimationIdle* animationIdle; + ComponentBehaviorFaceTarget* behaviorFaceTarget; physics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->component.id); animationLevitate = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_LEVITATE, self->component.id); + animationIdle = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_IDLE, self->component.id); + behaviorFaceTarget = ecs_component_get(ecs, ECS_COMPONENT_BEHAVIOR_FACE_TARGET, self->component.id); targetPhysics = ecs_component_get(ecs, ECS_COMPONENT_PHYSICS, self->targetID); @@ -34,6 +38,11 @@ _begin(ComponentBehaviorBoomerang* self, ECS* ecs) physics->velocity[0] = -cos(self->angle) * self->initialSpeed; physics->velocity[1] = -sin(self->angle) * self->initialSpeed; + animationIdle->baseIndex = 2; + animationIdle->timerMax = COMPONENT_BEHAVIOR_BOOMERANG_ANIMATION_IDLE_TIMER_MAX; + animationIdle->timer = COMPONENT_BEHAVIOR_BOOMERANG_ANIMATION_IDLE_TIMER_MAX; + behaviorFaceTarget->component.isDisabled = true; + if (animationLevitate) { ComponentGameObject* gameObject; diff --git a/src/game/ecs/component/behavior/component_behavior_boomerang.h b/src/game/ecs/component/behavior/component_behavior_boomerang.h index d299aa5..5c25ab1 100644 --- a/src/game/ecs/component/behavior/component_behavior_boomerang.h +++ b/src/game/ecs/component/behavior/component_behavior_boomerang.h @@ -8,11 +8,14 @@ #include "../behavior/component_behavior_chase.h" #include "../stat/component_level.h" #include "../behavior/component_behavior_act_in_rectangle.h" +#include "../behavior/component_behavior_face_target.h" +#include "../animation/component_animation_idle.h" #define COMPONENT_BEHAVIOR_BOOMERANG_SOUND_TIMER_MAX 10 #define COMPONENT_BEHAVIOR_BOOMERANG_LEVEL_TIMER_MULTIPLIER 5 #define COMPONENT_BEHAVIOR_BOOMERANG_TIMER_MAX 30 +#define COMPONENT_BEHAVIOR_BOOMERANG_ANIMATION_IDLE_TIMER_MAX 5 typedef struct ComponentBehaviorBoomerang { diff --git a/src/game/ecs/component/behavior/component_behavior_chase.c b/src/game/ecs/component/behavior/component_behavior_chase.c index 0646aaa..132b278 100644 --- a/src/game/ecs/component/behavior/component_behavior_chase.c +++ b/src/game/ecs/component/behavior/component_behavior_chase.c @@ -23,17 +23,19 @@ _chase(ComponentBehaviorChase* self, ECS* ecs) angle = ATAN ( - physics->position[0], targetPhysics->position[0], - physics->position[1], - targetPhysics->position[1] + physics->position[0], + targetPhysics->position[1], + physics->position[1] ); speed = self->speed * ((COMPONENT_BEHAVIOR_CHASE_LEVEL_SPEED_MULTIPLIER * (level->value - 1)) + 1); speed = MAX(speed, COMPONENT_BEHAVIOR_CHASE_SPEED_MAX); - physics->velocity[0] = cos(angle) * speed; - physics->velocity[1] = sin(angle) * speed; + physics->velocity[0] = -cos(angle) * speed; + physics->velocity[1] = -sin(angle) * speed; + + physics->angle = angle; self->soundTimer--; diff --git a/src/game/ecs/component/behavior/component_behavior_face_target.c b/src/game/ecs/component/behavior/component_behavior_face_target.c new file mode 100644 index 0000000..4f1b802 --- /dev/null +++ b/src/game/ecs/component/behavior/component_behavior_face_target.c @@ -0,0 +1,26 @@ +#include "component_behavior_face_target.h" + +/* DEPENDENCIES: Sprite */ + +/* Sets behavior_face_target component info. */ +void +component_behavior_face_target_init(ComponentBehaviorFaceTarget* self, u32 targetID) +{ + self->targetID = targetID; +} + +/* Ticks behavior_face_target component. */ +void +component_behavior_face_target_tick(ComponentBehaviorFaceTarget* self, ECS* ecs) +{ + ComponentSprite* sprite; + ComponentSprite* targetSprite; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + targetSprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->targetID); + + if (sprite->position[0] > targetSprite->position[0]) + sprite->isFlipHorizontal = true; + else + sprite->isFlipHorizontal = false; +} diff --git a/src/game/ecs/component/behavior/component_behavior_face_target.h b/src/game/ecs/component/behavior/component_behavior_face_target.h new file mode 100644 index 0000000..a53c81b --- /dev/null +++ b/src/game/ecs/component/behavior/component_behavior_face_target.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../../../GAME_COMMON.h" +#include "../../ecs_entity.h" + +#include "../component_sprite.h" + +typedef struct ComponentBehaviorFaceTarget +{ + ECSComponent component; + u32 targetID; +} ComponentBehaviorFaceTarget; + +void component_behavior_face_target_init(ComponentBehaviorFaceTarget* self, u32 targetID); +void component_behavior_face_target_tick(ComponentBehaviorFaceTarget* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_BEHAVIOR_FACE_TARGET_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_behavior_face_target_tick, + NULL + } + }, + .type = ECS_COMPONENT_BEHAVIOR_FACE_TARGET, + .size = sizeof(ComponentBehaviorFaceTarget) +}; + + diff --git a/src/game/ecs/component/component_game_object.c b/src/game/ecs/component/component_game_object.c index 956ce09..549decb 100644 --- a/src/game/ecs/component/component_game_object.c +++ b/src/game/ecs/component/component_game_object.c @@ -32,7 +32,8 @@ _component_game_object_sprite_tick(ComponentGameObject* self, ECS* ecs) /* (0.9f, 1.0f) reserved for HUD elements, etc. */ spriteYPercent = (sprite->position[1] / ecs->game->renderer.camera.orthographic.size[1]); - sprite->position[2] = (1 - (COMPONENT_GAME_OBJECT_DEPTH_MAX * spriteYPercent)) + sprite->offset[2]; + sprite->position[2] = COMPONENT_GAME_OBJECT_DEPTH_MAX - ((COMPONENT_GAME_OBJECT_DEPTH_RANGE) * spriteYPercent); + sprite->position[2] += sprite->offset[2]; } /* Tick's a game object's height and related properties. */ @@ -74,7 +75,7 @@ _component_game_object_shadow_tick(ComponentGameObject* self, ECS* ecs) glm_vec2_copy(physics->size, shadowSprite->size); glm_vec3_copy(physics->position, shadowSprite->position); - shadowSprite->position[2] = sprite->position[2] + COMPONENT_GAME_OBJECT_SHADOW_Z_OFFSET; + shadowSprite->position[2] = sprite->position[2] - COMPONENT_GAME_OBJECT_SHADOW_Z_OFFSET; heightPercent = 1 - (self->height / COMPONENT_GAME_OBJECT_HEIGHT_MAX); diff --git a/src/game/ecs/component/component_game_object.h b/src/game/ecs/component/component_game_object.h index 4d2f9c9..63d4463 100644 --- a/src/game/ecs/component/component_game_object.h +++ b/src/game/ecs/component/component_game_object.h @@ -10,11 +10,12 @@ #include "../entity/play/entity_shadow.h" #define COMPONENT_GAME_OBJECT_DEPTH_MAX 0.9f -#define COMPONENT_GAME_OBJECT_DEPTH_MIN 0.1f +#define COMPONENT_GAME_OBJECT_DEPTH_MIN 0.8f +#define COMPONENT_GAME_OBJECT_DEPTH_RANGE COMPONENT_GAME_OBJECT_DEPTH_MAX - COMPONENT_GAME_OBJECT_DEPTH_MIN #define COMPONENT_GAME_OBJECT_GRAVITY -1.0f #define COMPONENT_GAME_OBJECT_BOUNCE_FRICTION 0.8f #define COMPONENT_GAME_OBJECT_HEIGHT_MAX 2500.0f -#define COMPONENT_GAME_OBJECT_SHADOW_Z_OFFSET 0.01f +#define COMPONENT_GAME_OBJECT_SHADOW_Z_OFFSET -0.01f typedef struct ComponentGameObject { diff --git a/src/game/ecs/component/component_sprite.c b/src/game/ecs/component/component_sprite.c index f123f8b..1bf07e8 100644 --- a/src/game/ecs/component/component_sprite.c +++ b/src/game/ecs/component/component_sprite.c @@ -111,6 +111,7 @@ component_sprite_draw(ComponentSprite* self, ECS* ecs) &self->atlas, model, size, - self->color + self->color, + self->isFlipHorizontal ); } diff --git a/src/game/ecs/component/component_sprite.h b/src/game/ecs/component/component_sprite.h index 33e3835..bd83ad7 100644 --- a/src/game/ecs/component/component_sprite.h +++ b/src/game/ecs/component/component_sprite.h @@ -21,6 +21,8 @@ typedef struct ComponentSprite Atlas atlas; vec2 size; f32 rotation; + bool isFlipHorizontal; + bool isFlipVertical; } ComponentSprite; void component_sprite_rectangle_get(ComponentSprite* self, Rectangle* rectangle); diff --git a/src/game/ecs/component/component_text.c b/src/game/ecs/component/component_text.c index 916e26a..787d6ae 100644 --- a/src/game/ecs/component/component_text.c +++ b/src/game/ecs/component/component_text.c @@ -56,7 +56,8 @@ _component_text_glyph_draw(ComponentText* self, ECS* ecs, Texture texture, vec3 &atlas, model, size, - self->color + self->color, + false ); } diff --git a/src/game/ecs/component/control/component_control_face.c b/src/game/ecs/component/control/component_control_face.c new file mode 100644 index 0000000..2367a8d --- /dev/null +++ b/src/game/ecs/component/control/component_control_face.c @@ -0,0 +1,17 @@ +#include "component_control_face.h" + +/* DEPENDENCIES: Physics, Sprite */ + +/* Ticks control_face component. Flips sprite based on mouse position. */ +void +component_control_face_tick(ComponentControlFace* self, ECS* ecs) +{ + ComponentSprite* sprite; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + if (input_held(&ecs->game->input, INPUT_LEFT)) + sprite->isFlipHorizontal = true; + else if (input_held(&ecs->game->input, INPUT_RIGHT)) + sprite->isFlipHorizontal = false; +} diff --git a/src/game/ecs/component/control/component_control_face.h b/src/game/ecs/component/control/component_control_face.h new file mode 100644 index 0000000..8f3aaa7 --- /dev/null +++ b/src/game/ecs/component/control/component_control_face.h @@ -0,0 +1,32 @@ +#pragma once + +#include "../../../GAME_COMMON.h" +#include "../../ecs_entity.h" + +#include "../../../input/input.h" + +#include "../component_physics.h" +#include "../component_sprite.h" + +typedef struct ComponentControlFace +{ + ECSComponent component; +} ComponentControlFace; + +void component_control_face_tick(ComponentControlFace* self, ECS* ecs); + +static const ECSComponentInfo COMPONENT_CONTROL_FACE_INFO = +{ + .system = + { + .functions = + { + NULL, + NULL, + (ECSFunction)component_control_face_tick, + NULL + } + }, + .type = ECS_COMPONENT_CONTROL_FACE, + .size = sizeof(ComponentControlFace) +}; diff --git a/src/game/ecs/component/control/component_control_move.c b/src/game/ecs/component/control/component_control_move.c index 552346d..9c42d52 100644 --- a/src/game/ecs/component/control/component_control_move.c +++ b/src/game/ecs/component/control/component_control_move.c @@ -47,6 +47,7 @@ void component_control_move_init(ComponentControlMove* self, f32 speed) { self->speed = speed; + self->timer = COMPONENT_CONTROL_MOVE_TIMER_MAX; } /* Ticks control_move component. */ @@ -59,7 +60,15 @@ component_control_move_tick(ComponentControlMove* self, ECS* ecs) if (stun) if (stun->isStun) + { + ComponentSprite* sprite; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + sprite->atlas.index = COMPONENT_CONTROL_STUN_SPRITE_INDEX; + return; + } if ( @@ -81,5 +90,21 @@ component_control_move_tick(ComponentControlMove* self, ECS* ecs) physics->velocity[0] += delta[0]; physics->velocity[1] += delta[1]; + + self->timer--; + + if (self->timer <= 0) + { + ComponentSprite* sprite; + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, self->component.id); + + self->timer = COMPONENT_CONTROL_MOVE_TIMER_MAX; + + if (sprite->atlas.index != 0) + sprite->atlas.index = 0; + else + sprite->atlas.index = 1; + } } } diff --git a/src/game/ecs/component/control/component_control_move.h b/src/game/ecs/component/control/component_control_move.h index 02eb6b8..aa573a3 100644 --- a/src/game/ecs/component/control/component_control_move.h +++ b/src/game/ecs/component/control/component_control_move.h @@ -5,13 +5,18 @@ #include "../../../input/input.h" #include "../component_physics.h" +#include "../component_sprite.h" #include "../stat/component_stun.h" +#define COMPONENT_CONTROL_MOVE_TIMER_MAX 10 +#define COMPONENT_CONTROL_STUN_SPRITE_INDEX 2 + typedef struct ComponentControlMove { ECSComponent component; f32 speed; Direction direction; + s32 timer; bool directionInput[DIRECTION_COUNT]; bool previousDirectionInput[DIRECTION_COUNT]; } ComponentControlMove; diff --git a/src/game/ecs/component/control/component_control_player.c b/src/game/ecs/component/control/component_control_player.c index 040e5db..0e5f3df 100644 --- a/src/game/ecs/component/control/component_control_player.c +++ b/src/game/ecs/component/control/component_control_player.c @@ -41,6 +41,7 @@ component_control_player_add(ComponentControlPlayer* self, ECS* ecs) ecs_component_add(ecs, ECS_COMPONENT_CONTROL_LOCK, self->component.id); ecs_component_add(ecs, ECS_COMPONENT_CONTROL_RECALL, self->component.id); ecs_component_add(ecs, ECS_COMPONENT_CONTROL_HEART, self->component.id); + ecs_component_add(ecs, ECS_COMPONENT_CONTROL_FACE, self->component.id); } /* Ticks control_player component. */ @@ -54,4 +55,5 @@ component_control_player_delete(ComponentControlPlayer* self, ECS* ecs) ecs_component_delete(ecs, ECS_COMPONENT_CONTROL_LOCK, self->component.id); ecs_component_delete(ecs, ECS_COMPONENT_CONTROL_RECALL, self->component.id); ecs_component_delete(ecs, ECS_COMPONENT_CONTROL_HEART, self->component.id); + ecs_component_delete(ecs, ECS_COMPONENT_CONTROL_FACE, self->component.id); } diff --git a/src/game/ecs/component/control/component_control_player.h b/src/game/ecs/component/control/component_control_player.h index 2f822a3..5cd55cc 100644 --- a/src/game/ecs/component/control/component_control_player.h +++ b/src/game/ecs/component/control/component_control_player.h @@ -11,6 +11,7 @@ #include "component_control_recall.h" #include "component_control_lock.h" #include "component_control_heart.h" +#include "component_control_face.h" typedef struct ComponentControlPlayer { diff --git a/src/game/ecs/component/entity/component_enemy.c b/src/game/ecs/component/entity/component_enemy.c index 381855e..4fee0da 100644 --- a/src/game/ecs/component/entity/component_enemy.c +++ b/src/game/ecs/component/entity/component_enemy.c @@ -21,8 +21,7 @@ component_enemy_init bool isAffectedByGravity, bool isSolid, u32 goodieCount, - u32 levelValue, - Vector* entityList + u32 levelValue ) { ComponentCharacter* character; @@ -73,8 +72,6 @@ component_enemy_init ); component_level_init(level, levelValue); - - self->entityList = entityList; } /* Runs on character add. */ @@ -93,20 +90,6 @@ component_enemy_add(ComponentEnemy* self, ECS* ecs) void component_enemy_delete(ComponentEnemy* self, ECS* ecs) { - if (self->entityList) - { - for (s32 i = 0; i < (s32)self->entityList->count; i++) - { - u32 id; - - id = *(u32*)vector_get(self->entityList, i); - - if (id == self->component.id) - vector_remove(self->entityList, i); - - } - } - ecs_component_delete(ecs, ECS_COMPONENT_ACTION_DELETE_ON_DEAD, self->component.id); ecs_component_delete(ecs, ECS_COMPONENT_CHARACTER, self->component.id); ecs_component_delete(ecs, ECS_COMPONENT_ACTION_ON_OUT_OF_BOUNDS_DELETE, self->component.id); diff --git a/src/game/ecs/component/entity/component_enemy.h b/src/game/ecs/component/entity/component_enemy.h index 74b1d79..358ac4a 100644 --- a/src/game/ecs/component/entity/component_enemy.h +++ b/src/game/ecs/component/entity/component_enemy.h @@ -19,7 +19,6 @@ typedef struct ComponentEnemy { ECSComponent component; - Vector* entityList; } ComponentEnemy; void @@ -40,8 +39,7 @@ component_enemy_init bool isAffectedByGravity, bool isSolid, u32 goodieCount, - u32 levelValue, - Vector* entityList + u32 levelValue ); static const Rectangle ENEMY_ACTION_ON_OUT_OF_BOUNDS_DELETE_RECTANGLE = diff --git a/src/game/ecs/component/stat/component_fatness.c b/src/game/ecs/component/stat/component_fatness.c index b6d4d08..c62b1a4 100644 --- a/src/game/ecs/component/stat/component_fatness.c +++ b/src/game/ecs/component/stat/component_fatness.c @@ -1,8 +1,48 @@ #include "component_fatness.h" +/* Sets fatness level. */ +static void +_fatness_set(ComponentFatness* self, ECS* ecs) +{ + ComponentAnimationIdle* animationIdle; + + animationIdle = ecs_component_get(ecs, ECS_COMPONENT_ANIMATION_IDLE, self->component.id); + + animationIdle->baseIndex = animationIdle->baseIndex + 2; + animationIdle->timerMax = animationIdle->timerMax * 2; + + sound_play(&ecs->game->resources.sounds[SOUND_GROW], SOUND_SPECIAL); +} + +/* Initializes fatness component. */ +void +component_fatness_init(ComponentFatness* self, u32* thresholds, u32 thresholdCount) +{ + self->thresholds = thresholds; + self->thresholdCount = thresholdCount; +} + /* Ticks fatness component. */ void component_fatness_tick(ComponentFatness* self, ECS* ecs) { + ComponentGoodies* goodies; + goodies = ecs_component_get(ecs, ECS_COMPONENT_GOODIES, self->component.id); + + for (s32 i = 0; i < (s32)self->thresholdCount; i++) + { + if + ( + goodies->value >= self->thresholds[i] && + (s32)self->previousValue < i + ) + { + self->value = i; + _fatness_set(self, ecs); + } + } + + + self->previousValue = self->value; } diff --git a/src/game/ecs/component/stat/component_fatness.h b/src/game/ecs/component/stat/component_fatness.h index d917d50..e66630c 100644 --- a/src/game/ecs/component/stat/component_fatness.h +++ b/src/game/ecs/component/stat/component_fatness.h @@ -3,12 +3,19 @@ #include "../../../GAME_COMMON.h" #include "../../ecs_entity.h" +#include "../animation/component_animation_idle.h" +#include "component_goodies.h" + typedef struct ComponentFatness { ECSComponent component; u32 value; + u32 previousValue; + u32* thresholds; + u32 thresholdCount; } ComponentFatness; +void component_fatness_init(ComponentFatness* self, u32* thresholds, u32 thresholdCount); void component_fatness_tick(ComponentFatness* self, ECS* ecs); static const ECSComponentInfo COMPONENT_FATNESS_INFO = diff --git a/src/game/ecs/component/stat/component_heart.c b/src/game/ecs/component/stat/component_heart.c index 1f2095a..d077405 100644 --- a/src/game/ecs/component/stat/component_heart.c +++ b/src/game/ecs/component/stat/component_heart.c @@ -33,7 +33,7 @@ component_heart_tick(ComponentHeart* self, ECS* ecs) goodies = ecs_component_get(ecs, ECS_COMPONENT_GOODIES, self->component.id); if (self->concurrentUses > 1) - self->multiplier = self->uses + self->concurrentUses; + self->multiplier = self->uses + pow(self->concurrentUses, 2); else self->multiplier = self->uses + 1; diff --git a/src/game/ecs/component/stat/component_shop.c b/src/game/ecs/component/stat/component_shop.c index 1ede622..3d8c47a 100644 --- a/src/game/ecs/component/stat/component_shop.c +++ b/src/game/ecs/component/stat/component_shop.c @@ -2,12 +2,12 @@ static void _shop_item_init(ComponentShop* self, ECS* ecs); static void _shop_button_init(ComponentShop* self, ECS* ecs); -static void _disable(ComponentShop* self, ECS* ecs); -static void _enable(ComponentShop* self, ECS* ecs); +static void _shop_disable(ComponentShop* self, ECS* ecs); +static void _shop_enable(ComponentShop* self, ECS* ecs); /* Disables shop. */ static void -_disable(ComponentShop* self, ECS* ecs) +_shop_disable(ComponentShop* self, ECS* ecs) { ComponentShopButton* buttonUpgradeLifetime; ComponentShopButton* buttonUpgradeRedirects; @@ -30,7 +30,7 @@ _disable(ComponentShop* self, ECS* ecs) /* Enables shop. */ static void -_enable(ComponentShop* self, ECS* ecs) +_shop_enable(ComponentShop* self, ECS* ecs) { ComponentShopButton* buttonUpgradeLifetime; ComponentShopButton* buttonUpgradeRedirects; @@ -84,7 +84,7 @@ component_shop_init(ComponentShop* self, ECS* ecs, u32 affectedID, u32 affectedI _shop_item_init(self, ecs); _shop_button_init(self, ecs); - _disable(self, ecs); + _shop_disable(self, ecs); } /* Runs on addition of component shop entity. */ @@ -156,9 +156,9 @@ component_shop_tick(ComponentShop* self, ECS* ecs) if (self->isActive != self->isActivePrevious) { if (self->isActive) - _enable(self, ecs); + _shop_enable(self, ecs); else - _disable(self, ecs); + _shop_disable(self, ecs); } self->isActivePrevious = self->isActive; diff --git a/src/game/ecs/component/stat/component_shop_item.c b/src/game/ecs/component/stat/component_shop_item.c index 6f15fba..2a868a3 100644 --- a/src/game/ecs/component/stat/component_shop_item.c +++ b/src/game/ecs/component/stat/component_shop_item.c @@ -76,7 +76,7 @@ _shop_item_bought(ComponentShopItem* self, ECS* ecs) self->purchaseCount++; - self->price = pow(self->basePrice, self->exponent * self->purchaseCount); + self->price = self->basePrice * pow((self->purchaseCount + 1), self->exponent); sound_play(&ecs->game->resources.sounds[SOUND_UPGRADE], SOUND_SPECIAL); } diff --git a/src/game/ecs/ecs.c b/src/game/ecs/ecs.c index 2b8bde4..845602c 100644 --- a/src/game/ecs/ecs.c +++ b/src/game/ecs/ecs.c @@ -87,6 +87,7 @@ ecs_draw(ECS* self) drawFunction = drawEntry->drawFunction; drawFunction(drawEntry->componentPointer, self); + } vector_free(&drawEntries); @@ -108,6 +109,8 @@ ecs_clear(ECS* self) { for (s32 i = 0 ; i < ECS_COMPONENT_COUNT; i++) ecs_component_list_clear(&self->lists[i]); + + self->nextID = 0; } /* Frees ECS. */ diff --git a/src/game/ecs/ecs.h b/src/game/ecs/ecs.h index 8132c66..75aeaa7 100644 --- a/src/game/ecs/ecs.h +++ b/src/game/ecs/ecs.h @@ -1,8 +1,10 @@ #pragma once +#include "component/action/component_action_angle.h" #include "component/action/component_action_damage.h" #include "component/action/component_action_delete_on_dead.h" #include "component/action/component_action_delete_on_timer.h" +#include "component/action/component_action_delete_on_heart.h" #include "component/action/component_action_delete_on_touch_entity.h" #include "component/action/component_action_delete_on_touch_game_entity_type.h" #include "component/action/component_action_grip.h" @@ -21,13 +23,16 @@ #include "component/action/component_action_shoot.h" #include "component/action/component_action_spawn.h" #include "component/action/component_action_wave.h" +#include "component/animation/component_animation_idle.h" #include "component/animation/component_animation_color_change.h" #include "component/animation/component_animation_cursor.h" #include "component/animation/component_animation_levitate.h" #include "component/animation/component_animation_move.h" +#include "component/animation/component_animation_rotate.h" #include "component/animation/component_animation_squash.h" #include "component/animation/component_animation_stretch.h" #include "component/behavior/component_behavior_act_in_rectangle.h" +#include "component/behavior/component_behavior_face_target.h" #include "component/behavior/component_behavior_approach_and_shoot.h" #include "component/behavior/component_behavior_boomerang.h" #include "component/behavior/component_behavior_chase.h" @@ -38,6 +43,7 @@ #include "component/component_sprite.h" #include "component/component_text.h" #include "component/control/component_control_aim.h" +#include "component/control/component_control_face.h" #include "component/control/component_control_lock.h" #include "component/control/component_control_move.h" #include "component/control/component_control_player.h" @@ -83,14 +89,30 @@ static const ECSComponentInfo ECS_COMPONENT_INFO[ECS_COMPONENT_COUNT] = { COMPONENT_ACTION_ON_DELETE_GIVE_AMMO_INFO, COMPONENT_ACTION_ON_DELETE_DROP_GOODIES_INFO, + COMPONENT_ENEMY_INFO, COMPONENT_ACTION_SPAWN_INFO, COMPONENT_ACTION_ON_HEIGHT_DAMAGE_DISABLE_INFO, + COMPONENT_ANIMATION_IDLE_INFO, COMPONENT_ANIMATION_COLOR_CHANGE_INFO, COMPONENT_ANIMATION_LEVITATE_INFO, COMPONENT_ANIMATION_MOVE_INFO, + COMPONENT_ANIMATION_ROTATE_INFO, COMPONENT_ANIMATION_CURSOR_INFO, COMPONENT_ANIMATION_STRETCH_INFO, COMPONENT_ANIMATION_SQUASH_INFO, + COMPONENT_CONTROL_MOVE_INFO, + COMPONENT_CONTROL_SHOOT_INFO, + COMPONENT_CONTROL_AIM_INFO, + COMPONENT_CONTROL_FACE_INFO, + COMPONENT_CONTROL_REDIRECT_INFO, + COMPONENT_CONTROL_LOCK_INFO, + COMPONENT_CONTROL_RECALL_INFO, + COMPONENT_CONTROL_HEART_INFO, + COMPONENT_CONTROL_PLAYER_INFO, + COMPONENT_ACTION_SHOOT_INFO, + COMPONENT_ACTION_GRIP_INFO, + COMPONENT_ACTION_GRIPPED_INFO, + COMPONENT_PICKUP_INFO, COMPONENT_PHYSICS_INFO, COMPONENT_CIRCLE_COLLISION_INFO, COMPONENT_ACTION_KEEP_IN_RECTANGLE_INFO, @@ -98,32 +120,21 @@ static const ECSComponentInfo ECS_COMPONENT_INFO[ECS_COMPONENT_COUNT] = COMPONENT_TEXT_INFO, COMPONENT_GAME_OBJECT_INFO, COMPONENT_CHARACTER_INFO, - COMPONENT_ENEMY_INFO, - COMPONENT_PICKUP_INFO, COMPONENT_BEHAVIOR_ACT_IN_RECTANGLE_INFO, + COMPONENT_BEHAVIOR_FACE_TARGET_INFO, COMPONENT_BEHAVIOR_HOP_INFO, COMPONENT_BEHAVIOR_BOOMERANG_INFO, COMPONENT_BEHAVIOR_CHASE_INFO, COMPONENT_BEHAVIOR_APPROACH_AND_SHOOT_INFO, + COMPONENT_ACTION_ANGLE_INFO, COMPONENT_ACTION_ON_COMBAT_HIDE_INFO, - COMPONENT_ACTION_SHOOT_INFO, COMPONENT_ACTION_LOCK_INFO, COMPONENT_ACTION_FOLLOW_INFO, COMPONENT_ACTION_POINT_TO_MOUSE_INFO, COMPONENT_ACTION_RETURN_INFO, COMPONENT_ACTION_REDIRECT_INFO, COMPONENT_ACTION_DAMAGE_INFO, - COMPONENT_ACTION_GRIP_INFO, - COMPONENT_ACTION_GRIPPED_INFO, COMPONENT_ACTION_WAVE_INFO, - COMPONENT_CONTROL_MOVE_INFO, - COMPONENT_CONTROL_SHOOT_INFO, - COMPONENT_CONTROL_AIM_INFO, - COMPONENT_CONTROL_REDIRECT_INFO, - COMPONENT_CONTROL_LOCK_INFO, - COMPONENT_CONTROL_RECALL_INFO, - COMPONENT_CONTROL_HEART_INFO, - COMPONENT_CONTROL_PLAYER_INFO, COMPONENT_SHOP_INFO, COMPONENT_SHOP_ITEM_INFO, COMPONENT_ACT_ENTITY_INFO, @@ -148,6 +159,7 @@ static const ECSComponentInfo ECS_COMPONENT_INFO[ECS_COMPONENT_COUNT] = COMPONENT_ACTION_ON_TOUCH_GIVE_GOODIES_INFO, COMPONENT_ACTION_DELETE_ON_DEAD_INFO, COMPONENT_ACTION_DELETE_ON_TIMER_INFO, + COMPONENT_ACTION_DELETE_ON_HEART_INFO, COMPONENT_ACTION_DELETE_ON_TOUCH_ENTITY_INFO, COMPONENT_ACTION_DELETE_ON_TOUCH_GAME_ENTITY_TYPE_INFO, COMPONENT_ACTION_ON_OUT_OF_BOUNDS_DELETE_INFO diff --git a/src/game/ecs/entity/entity_menu_button.c b/src/game/ecs/entity/entity_menu_button.c new file mode 100644 index 0000000..ae559eb --- /dev/null +++ b/src/game/ecs/entity/entity_menu_button.c @@ -0,0 +1,26 @@ +#include "entity_menu_button.h" + +/* Initializes a menu_button entity. */ +void +entity_menu_button_init(ECS* ecs, u32 id, vec3 position, MenuButtonType type) +{ + ComponentButton* button; + ComponentSprite* sprite; + + button = ecs_component_add(ecs, ECS_COMPONENT_BUTTON, id); + + component_button_init + ( + button, + ecs, + ecs->game->resources.textures[TEXTURE_MENU_BUTTONS], + (s32*)MENU_BUTTON_FRAME_SIZE, + (s32*)MENU_BUTTON_ATLAS_SIZE, + (f32*)MENU_BUTTON_SIZE, + position + ); + + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, id); + + sprite->atlas.index = type; +} diff --git a/src/game/ecs/entity/entity_menu_button.h b/src/game/ecs/entity/entity_menu_button.h new file mode 100644 index 0000000..1be4cbc --- /dev/null +++ b/src/game/ecs/entity/entity_menu_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "../ecs_component.h" +#include "../component/hud/component_button.h" + +typedef enum MenuButtonType +{ + MENU_BUTTON_START = 0, + MENU_BUTTON_RETRY = 1, + MENU_BUTTON_OK = 2, + MENU_BUTTON_NEXT = 3 +} MenuButtonType; + +static const ivec2 MENU_BUTTON_FRAME_SIZE = {512, 512}; +static const ivec2 MENU_BUTTON_ATLAS_SIZE = {1, 4}; +static const vec2 MENU_BUTTON_SIZE = {256.0f, 256.0f}; + +void entity_menu_button_init(ECS* ecs, u32 id, vec3 position, MenuButtonType type); diff --git a/src/game/ecs/entity/entity_state_fade.c b/src/game/ecs/entity/entity_state_fade.c new file mode 100644 index 0000000..432ebe3 --- /dev/null +++ b/src/game/ecs/entity/entity_state_fade.c @@ -0,0 +1,47 @@ +#include "entity_state_fade.h" + +/* Initializes a state_fade entity. */ +void +entity_state_fade_init(ECS* ecs, u32 id, bool isFadeIn) +{ + ComponentSprite* sprite; + ComponentAnimationColorChange* animationColorChange; + + sprite = ecs_component_add(ecs, ECS_COMPONENT_SPRITE, id); + animationColorChange = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_COLOR_CHANGE, id); + + component_sprite_init + ( + sprite, + ecs->game->resources.textures[TEXTURE_STATE_FADE], + (f32*)STATE_FADE_SIZE, + (f32*)STATE_FADE_POSITION + ); + + if (isFadeIn) + { + component_animation_color_change_init + ( + animationColorChange, + (f32*)COLOR_TRANSPARENT, + (f32*)COLOR_OPAQUE, + STATE_FADE_TIMER, + ANIMATION_COLOR_CHANGE_MODE_STICK + ); + + glm_vec4_copy((f32*)COLOR_OPAQUE, sprite->color); + } + else + { + component_animation_color_change_init + ( + animationColorChange, + (f32*)COLOR_OPAQUE, + (f32*)COLOR_TRANSPARENT, + STATE_FADE_TIMER, + ANIMATION_COLOR_CHANGE_MODE_STICK + ); + + glm_vec4_copy((f32*)COLOR_TRANSPARENT, sprite->color); + } +} diff --git a/src/game/ecs/entity/entity_state_fade.h b/src/game/ecs/entity/entity_state_fade.h new file mode 100644 index 0000000..40d96dd --- /dev/null +++ b/src/game/ecs/entity/entity_state_fade.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../ecs_component.h" +#include "../component/component_sprite.h" +#include "../component/animation/component_animation_color_change.h" + +#define STATE_FADE_TIMER 30 + +static const vec2 STATE_FADE_SIZE = {1920.0f, 1080.0f}; +static const vec3 STATE_FADE_POSITION = {960.0f, 540.0f, 0.0f}; + +void entity_state_fade_init(ECS* ecs, u32 id, bool isFadeIn); diff --git a/src/game/ecs/entity/play/entity_chip.c b/src/game/ecs/entity/play/entity_chip.c index 3d23b43..fa7124c 100644 --- a/src/game/ecs/entity/play/entity_chip.c +++ b/src/game/ecs/entity/play/entity_chip.c @@ -6,9 +6,12 @@ entity_chip_init(ECS* ecs, u32 id, vec3 position, u32 sender) { ComponentEnemy* enemy; ComponentActionDeleteOnTouchGameEntityType* actionDeleteOnTouchGameEntityType; + ComponentAnimationRotate* animationRotate; + ComponentSprite* sprite; enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); actionDeleteOnTouchGameEntityType = ecs_component_add(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TOUCH_GAME_ENTITY_TYPE, id); + animationRotate = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_ROTATE, id); component_enemy_init ( @@ -27,10 +30,11 @@ entity_chip_init(ECS* ecs, u32 id, vec3 position, u32 sender) CHIP_IS_AFFECTED_BY_GRAVITY, CHIP_IS_SOLID, CHIP_GOODIE_COUNT, - 1, - NULL + 1 ); + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, id); + component_action_delete_on_touch_game_entity_type_init ( actionDeleteOnTouchGameEntityType, @@ -46,4 +50,7 @@ entity_chip_init(ECS* ecs, u32 id, vec3 position, u32 sender) gameEntityType, GAME_ENTITY_CHIP ); + + sprite->rotation = RANDOM_F32(0, TAU); + component_animation_rotate_init(animationRotate, CHIP_ROTATION_SPEED); } diff --git a/src/game/ecs/entity/play/entity_chip.h b/src/game/ecs/entity/play/entity_chip.h index c312840..d617817 100644 --- a/src/game/ecs/entity/play/entity_chip.h +++ b/src/game/ecs/entity/play/entity_chip.h @@ -2,6 +2,7 @@ #include "../../ecs_component.h" #include "../../component/entity/component_enemy.h" +#include "../../component/animation/component_animation_rotate.h" #include "../../component/action/component_action_delete_on_touch_game_entity_type.h" #include "../../component/stat/component_game_entity_type.h" @@ -13,6 +14,7 @@ #define CHIP_IS_BOUNCE false #define CHIP_IS_SOLID false #define CHIP_GOODIE_COUNT 0 +#define CHIP_ROTATION_SPEED 0.05 #define CHIP_ACTION_DELETE_ON_TOUCH_GAME_ENTITY_TYPE GAME_ENTITY_PLAYER diff --git a/src/game/ecs/entity/play/entity_chipper.c b/src/game/ecs/entity/play/entity_chipper.c index 27ce203..b0bfa02 100644 --- a/src/game/ecs/entity/play/entity_chipper.c +++ b/src/game/ecs/entity/play/entity_chipper.c @@ -2,15 +2,17 @@ /* Initializes a Chipper entity. */ void -entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList) +entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level) { ComponentEnemy* enemy; ComponentBehaviorApproachAndShoot* behaviorApproachAndShoot; ComponentBehaviorActInRectangle* behaviorActInRectangle; + ComponentBehaviorFaceTarget* behaviorFaceTarget; enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); behaviorApproachAndShoot = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_APPROACH_AND_SHOOT, id); behaviorActInRectangle = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_ACT_IN_RECTANGLE, id); + behaviorFaceTarget = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_FACE_TARGET, id); component_enemy_init ( @@ -29,8 +31,7 @@ entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Ve CHIPPER_GAME_OBJECT_IS_AFFECTED_BY_GRAVITY, CHIPPER_GAME_OBJECT_IS_SOLID, CHIPPER_GOODIE_COUNT, - level, - entityList + level ); component_behavior_approach_and_shoot_init @@ -48,6 +49,7 @@ entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Ve ); component_behavior_act_in_rectangle_init(behaviorActInRectangle, CHIPPER_ACT_RECTANGLE); + component_behavior_face_target_init(behaviorFaceTarget, targetID); ComponentGameEntityType* gameEntityType; diff --git a/src/game/ecs/entity/play/entity_chipper.h b/src/game/ecs/entity/play/entity_chipper.h index 22d798c..78e6f49 100644 --- a/src/game/ecs/entity/play/entity_chipper.h +++ b/src/game/ecs/entity/play/entity_chipper.h @@ -4,11 +4,12 @@ #include "../../component/entity/component_enemy.h" #include "../../component/behavior/component_behavior_approach_and_shoot.h" #include "../../component/behavior/component_behavior_act_in_rectangle.h" +#include "../../component/behavior/component_behavior_face_target.h" #include "../../component/stat/component_game_entity_type.h" #include "entity_chip.h" -#define CHIPPER_BEHAVIOR_APPROACH_AND_SHOOT_DISTANCE 1000.0f +#define CHIPPER_BEHAVIOR_APPROACH_AND_SHOOT_DISTANCE 750.0f #define CHIPPER_BEHAVIOR_APPROACH_AND_SHOOT_HEIGHT 10.0f #define CHIPPER_BEHAVIOR_APPROACH_AND_SHOOT_OFFSET 30.0f #define CHIPPER_BEHAVIOR_APPROACH_AND_SHOOT_PROJECTILE_SPEED 10.0f @@ -35,8 +36,8 @@ static const Rectangle CHIPPER_ACT_RECTANGLE = }; static const ivec2 CHIPPER_FRAME_SIZE = {512, 512}; -static const ivec2 CHIPPER_ATLAS_SIZE = {1, 1}; -static const vec2 CHIPPER_SIZE = {100.0f, 100.0f}; +static const ivec2 CHIPPER_ATLAS_SIZE = {1, 5}; +static const vec2 CHIPPER_SIZE = {150.0f, 150.0f}; static const vec2 CHIPPER_PHYSICS_SIZE = {75.0f, 25.0f}; -void entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList); +void entity_chipper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level); diff --git a/src/game/ecs/entity/play/entity_crumbler.c b/src/game/ecs/entity/play/entity_crumbler.c index a4be580..70ba226 100644 --- a/src/game/ecs/entity/play/entity_crumbler.c +++ b/src/game/ecs/entity/play/entity_crumbler.c @@ -2,11 +2,12 @@ /* Initializes a Crumbler entity. */ void -entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level, Vector* entityList) +entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level) { ComponentEnemy* enemy; ComponentLevel* componentLevel; ComponentGameObject* gameObject; + ComponentSprite* sprite; ComponentActionOnHeightDamageDisable* actionOnHeightDamageDisable; enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); @@ -30,8 +31,7 @@ entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level, Vector* entityL CRUMBLER_IS_AFFECTED_BY_GRAVITY, CRUMBLER_IS_SOLID, CRUMBLER_GOODIE_COUNT, - level, - entityList + level ); componentLevel = ecs_component_get(ecs, ECS_COMPONENT_LEVEL, id); @@ -43,6 +43,10 @@ entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level, Vector* entityL component_action_on_height_damage_disable_init(actionOnHeightDamageDisable, CRUMBLER_DAMAGE_HEIGHT); + sprite = ecs_component_get(ecs, ECS_COMPONENT_SPRITE, id); + + sprite->atlas.index = 2; + ComponentGameEntityType* gameEntityType; gameEntityType = ecs_component_add(ecs, ECS_COMPONENT_GAME_ENTITY_TYPE, id); diff --git a/src/game/ecs/entity/play/entity_crumbler.h b/src/game/ecs/entity/play/entity_crumbler.h index 6d27feb..7d2672a 100644 --- a/src/game/ecs/entity/play/entity_crumbler.h +++ b/src/game/ecs/entity/play/entity_crumbler.h @@ -19,8 +19,8 @@ #define CRUMBLER_DAMAGE_HEIGHT 100.0f static const ivec2 CRUMBLER_FRAME_SIZE = {512, 512}; -static const ivec2 CRUMBLER_ATLAS_SIZE = {1, 1}; -static const vec2 CRUMBLER_SIZE = {200.0f, 125.0f}; +static const ivec2 CRUMBLER_ATLAS_SIZE = {1, 3}; +static const vec2 CRUMBLER_SIZE = {200.0f, 200.0f}; static const vec2 CRUMBLER_PHYSICS_SIZE = {150.0f, 50.0f}; -void entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level, Vector* entityList); +void entity_crumbler_init(ECS* ecs, u32 id, vec3 position, u32 level); diff --git a/src/game/ecs/entity/play/entity_cupper.c b/src/game/ecs/entity/play/entity_cupper.c index 6607ffc..baedbd0 100644 --- a/src/game/ecs/entity/play/entity_cupper.c +++ b/src/game/ecs/entity/play/entity_cupper.c @@ -2,13 +2,17 @@ /* Initializes a Cupper entity. */ void -entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList) +entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level) { ComponentEnemy* enemy; ComponentBehaviorHop* behaviorHop; + ComponentBehaviorFaceTarget* behaviorFaceTarget; + ComponentAnimationIdle* animationIdle; behaviorHop = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_HOP, id); + behaviorFaceTarget = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_FACE_TARGET, id); enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); + animationIdle = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_IDLE, id); component_enemy_init ( @@ -27,8 +31,7 @@ entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vec CUPPER_IS_AFFECTED_BY_GRAVITY, CUPPER_IS_SOLID, CUPPER_GOODIE_COUNT, - level, - entityList + level ); component_behavior_hop_init @@ -40,6 +43,15 @@ entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vec targetID ); + component_animation_idle_init + ( + animationIdle, + CUPPER_ANIMATION_IDLE_BASE_INDEX, + CUPPER_ANIMATION_IDLE_TIMER + ); + + component_behavior_face_target_init(behaviorFaceTarget, targetID); + ComponentGameEntityType* gameEntityType; gameEntityType = ecs_component_add(ecs, ECS_COMPONENT_GAME_ENTITY_TYPE, id); diff --git a/src/game/ecs/entity/play/entity_cupper.h b/src/game/ecs/entity/play/entity_cupper.h index 3828b96..f0f686e 100644 --- a/src/game/ecs/entity/play/entity_cupper.h +++ b/src/game/ecs/entity/play/entity_cupper.h @@ -2,8 +2,10 @@ #include "../../component/entity/component_enemy.h" #include "../../component/behavior/component_behavior_hop.h" +#include "../../component/behavior/component_behavior_face_target.h" #include "../../ecs_component.h" #include "../../component/stat/component_game_entity_type.h" +#include "../../component/animation/component_animation_idle.h" #define CUPPER_IS_SOLID false #define CUPPER_IS_BOUNCE false @@ -15,10 +17,12 @@ #define CUPPER_HEALTH_MAX 3 #define CUPPER_FRICTION 0.9 #define CUPPER_GOODIE_COUNT 1 +#define CUPPER_ANIMATION_IDLE_TIMER 10 +#define CUPPER_ANIMATION_IDLE_BASE_INDEX 0 static const ivec2 CUPPER_FRAME_SIZE = {512, 512}; -static const ivec2 CUPPER_ATLAS_SIZE = {1, 1}; -static const vec2 CUPPER_SIZE = {75.0f, 75.0f}; +static const ivec2 CUPPER_ATLAS_SIZE = {1, 4}; +static const vec2 CUPPER_SIZE = {100.0f, 100.0f}; static const vec2 CUPPER_PHYSICS_SIZE = {60.0f, 20.0f}; -void entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList); +void entity_cupper_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level); diff --git a/src/game/ecs/entity/play/entity_custarpedo.c b/src/game/ecs/entity/play/entity_custarpedo.c index b31615e..172773d 100644 --- a/src/game/ecs/entity/play/entity_custarpedo.c +++ b/src/game/ecs/entity/play/entity_custarpedo.c @@ -2,16 +2,21 @@ /* Initializes a Custarpedo entity. */ void -entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList) +entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level) { ComponentEnemy* enemy; ComponentBehaviorChase* behaviorChase; + ComponentAnimationIdle* animationIdle; ComponentGameObject* gameObject; behaviorChase = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_CHASE, id); enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); + animationIdle = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_IDLE, id); + gameObject = ecs_component_get(ecs, ECS_COMPONENT_GAME_OBJECT, id); + ecs_component_add(ecs, ECS_COMPONENT_ACTION_ANGLE, id); + component_enemy_init ( enemy, @@ -29,8 +34,7 @@ entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, CUSTARPEDO_IS_AFFECTED_BY_GRAVITY, CUSTARPEDO_IS_SOLID, CUSTARPEDO_GOODIE_COUNT, - level, - entityList + level ); component_behavior_chase_init @@ -40,6 +44,13 @@ entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, targetID ); + component_animation_idle_init + ( + animationIdle, + CUSTARPEDO_ANIMATION_IDLE_BASE_INDEX, + CUSTARPEDO_ANIMATION_IDLE_TIMER + ); + gameObject->height = CUSTARPEDO_HEIGHT; ComponentGameEntityType* gameEntityType; diff --git a/src/game/ecs/entity/play/entity_custarpedo.h b/src/game/ecs/entity/play/entity_custarpedo.h index 0d94960..b0a4507 100644 --- a/src/game/ecs/entity/play/entity_custarpedo.h +++ b/src/game/ecs/entity/play/entity_custarpedo.h @@ -1,6 +1,8 @@ #pragma once +#include "../../component/animation/component_animation_idle.h" #include "../../component/behavior/component_behavior_chase.h" +#include "../../component/action/component_action_angle.h" #include "../../component/entity/component_enemy.h" #include "../../ecs_component.h" #include "../../component/stat/component_game_entity_type.h" @@ -14,10 +16,12 @@ #define CUSTARPEDO_HEALTH_MAX 2 #define CUSTARPEDO_GOODIE_COUNT 1 #define CUSTARPEDO_HEIGHT 30 +#define CUSTARPEDO_ANIMATION_IDLE_BASE_INDEX 0 +#define CUSTARPEDO_ANIMATION_IDLE_TIMER 30 static const ivec2 CUSTARPEDO_FRAME_SIZE = {512, 512}; -static const ivec2 CUSTARPEDO_ATLAS_SIZE = {1, 1}; +static const ivec2 CUSTARPEDO_ATLAS_SIZE = {8, 2}; static const vec2 CUSTARPEDO_SIZE = {100.0f, 100.0f}; static const vec2 CUSTARPEDO_PHYSICS_SIZE = {60.0f, 20.0f}; -void entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList); +void entity_custarpedo_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level); diff --git a/src/game/ecs/entity/play/entity_damage_number.c b/src/game/ecs/entity/play/entity_damage_number.c index 051c2e3..2949619 100644 --- a/src/game/ecs/entity/play/entity_damage_number.c +++ b/src/game/ecs/entity/play/entity_damage_number.c @@ -12,6 +12,7 @@ entity_damage_number_init(ECS* ecs, u32 id, vec3 position, u32 damage) ComponentText* text; char string[ENTITY_DAMAGE_NUMBER_TEXT_MAX]; f32 base; + vec3 numberPosition; base = ENTITY_DAMAGE_NUMBER_SCALE + ((damage - 1) * ENTITY_DAMAGE_NUMBER_SCALE_MULTIPLIER); @@ -24,6 +25,10 @@ entity_damage_number_init(ECS* ecs, u32 id, vec3 position, u32 damage) animationSquash = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_SQUASH, id); animationStretch = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_STRETCH, id); + glm_vec3_copy(position, numberPosition); + + numberPosition[2] += ENTITY_DAMAGE_NUMBER_Z_OFFSET; + snprintf ( string, @@ -39,7 +44,7 @@ entity_damage_number_init(ECS* ecs, u32 id, vec3 position, u32 damage) string, strlen(string), -1, - position, + numberPosition, (f32*)ENTITY_DAMAGE_NUMBER_COLOR ); diff --git a/src/game/ecs/entity/play/entity_damage_number.h b/src/game/ecs/entity/play/entity_damage_number.h index ede5aa6..808688a 100644 --- a/src/game/ecs/entity/play/entity_damage_number.h +++ b/src/game/ecs/entity/play/entity_damage_number.h @@ -18,6 +18,7 @@ #define ENTITY_DAMAGE_NUMBER_SQUASH_SPEED 0.05f #define ENTITY_DAMAGE_NUMBER_STRETCH_MULTIPLIER 0.5f #define ENTITY_DAMAGE_NUMBER_STRETCH_SPEED 0.05f +#define ENTITY_DAMAGE_NUMBER_Z_OFFSET -0.01f static const vec4 ENTITY_DAMAGE_NUMBER_COLOR = {1.0f, 0.0f, 0.0f, 1.0f}; static const vec3 ENTITY_DAMAGE_NUMBER_MOVE_VELOCITY = {0.0f, -1.0f, 0.0f}; diff --git a/src/game/ecs/entity/play/entity_elemental.c b/src/game/ecs/entity/play/entity_elemental.c index 8bf610a..dd5fb69 100644 --- a/src/game/ecs/entity/play/entity_elemental.c +++ b/src/game/ecs/entity/play/entity_elemental.c @@ -11,16 +11,18 @@ entity_elemental_init(ECS* ecs, u32 id, vec3 position, u32 spawnID, u32 playerID ComponentGoodies* goodies; ComponentShop* shop; ComponentAnimationStretch* animationStretch; + ComponentAnimationIdle* animationIdle; + ComponentFatness* fatness; gameObject = ecs_component_add(ecs, ECS_COMPONENT_GAME_OBJECT, id); actionOnCombatHide = ecs_component_add(ecs, ECS_COMPONENT_ACTION_ON_COMBAT_HIDE, id); animationSquash = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_SQUASH, id); animationStretch = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_STRETCH, id); + animationIdle = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_IDLE, id); circleCollision = ecs_component_add(ecs, ECS_COMPONENT_CIRCLE_COLLISION, id); goodies = ecs_component_add(ecs, ECS_COMPONENT_GOODIES, id); shop = ecs_component_add(ecs, ECS_COMPONENT_SHOP, id); - - ecs_component_add(ecs, ECS_COMPONENT_FATNESS, id); + fatness = ecs_component_add(ecs, ECS_COMPONENT_FATNESS, id); component_game_object_atlas_init ( @@ -66,6 +68,13 @@ entity_elemental_init(ECS* ecs, u32 id, vec3 position, u32 spawnID, u32 playerID ELEMENTAL_ANIMATION_STRETCH_SPEED ); + component_animation_idle_init + ( + animationIdle, + ELEMENTAL_ANIMATION_IDLE_BASE_INDEX, + ELEMENTAL_ANIMATION_IDLE_TIMER + ); + component_circle_collision_init ( circleCollision, @@ -73,6 +82,13 @@ entity_elemental_init(ECS* ecs, u32 id, vec3 position, u32 spawnID, u32 playerID ELEMENTAL_CIRCLE_RADIUS ); + component_fatness_init + ( + fatness, + (u32*)ELEMENTAL_FATNESS_THRESHOLDS, + ELEMENTAL_FATNESS_THRESHOLD_COUNT + ); + goodies->max = ELEMENTAL_GOODIES_MAX; entity_elemental_goodie_display_init(ecs, ecs_entity_add(ecs), id); diff --git a/src/game/ecs/entity/play/entity_elemental.h b/src/game/ecs/entity/play/entity_elemental.h index af114c0..2659da7 100644 --- a/src/game/ecs/entity/play/entity_elemental.h +++ b/src/game/ecs/entity/play/entity_elemental.h @@ -3,6 +3,7 @@ #include "../../component/action/component_action_on_combat_hide.h" #include "../../component/animation/component_animation_squash.h" #include "../../component/animation/component_animation_stretch.h" +#include "../../component/animation/component_animation_idle.h" #include "../../component/component_game_object.h" #include "../../component/stat/component_fatness.h" #include "../../component/stat/component_game_entity_type.h" @@ -20,17 +21,26 @@ #define ELEMENTAL_GAME_OBJECT_IS_SOLID true #define ELEMENTAL_ACTION_ON_COMBAT_HIDE_TIMER 60 #define ELEMENTAL_ANIMATION_SQUASH_BASE 1.0f -#define ELEMENTAL_ANIMATION_SQUASH_MULTIPLIER 0.05f -#define ELEMENTAL_ANIMATION_SQUASH_SPEED 0.05f +#define ELEMENTAL_ANIMATION_SQUASH_MULTIPLIER 0.025f +#define ELEMENTAL_ANIMATION_SQUASH_SPEED 0.01f #define ELEMENTAL_ANIMATION_STRETCH_BASE 1.0f -#define ELEMENTAL_ANIMATION_STRETCH_MULTIPLIER 0.05f -#define ELEMENTAL_ANIMATION_STRETCH_SPEED 0.05f +#define ELEMENTAL_ANIMATION_STRETCH_MULTIPLIER 0.025f +#define ELEMENTAL_ANIMATION_STRETCH_SPEED 0.01f #define ELEMENTAL_GOODIES_MAX 1000000 -#define ELEMENTAL_CIRCLE_RADIUS 300.0f +#define ELEMENTAL_CIRCLE_RADIUS 150.0f +#define ELEMENTAL_ANIMATION_IDLE_BASE_INDEX 0 +#define ELEMENTAL_ANIMATION_IDLE_TIMER 30 +#define ELEMENTAL_FATNESS_THRESHOLD_COUNT 2 -static const ivec2 ELEMENTAL_FRAME_SIZE = {512, 512}; -static const ivec2 ELEMENTAL_ATLAS_SIZE = {1, 1}; -static const vec2 ELEMENTAL_SIZE = {75.0f, 150.0f}; -static const vec2 ELEMENTAL_PHYSICS_SIZE = {60.0f, 20.0f}; +static const ivec2 ELEMENTAL_FRAME_SIZE = {1024, 1024}; +static const ivec2 ELEMENTAL_ATLAS_SIZE = {1, 6}; +static const vec2 ELEMENTAL_SIZE = {300.0f, 300.0f}; +static const vec2 ELEMENTAL_PHYSICS_SIZE = {120.0f, 40.0f}; + +static const u32 ELEMENTAL_FATNESS_THRESHOLDS[ELEMENTAL_FATNESS_THRESHOLD_COUNT] = +{ + 10000, + 100000, +}; void entity_elemental_init(ECS* ecs, u32 id, vec3 position, u32 spawnID, u32 playerID); diff --git a/src/game/ecs/entity/play/entity_excorsant.c b/src/game/ecs/entity/play/entity_excorsant.c index 7f3f265..490d34b 100644 --- a/src/game/ecs/entity/play/entity_excorsant.c +++ b/src/game/ecs/entity/play/entity_excorsant.c @@ -2,18 +2,22 @@ /* Initializes an Excorsant entity. */ void -entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList) +entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level) { ComponentEnemy* enemy; ComponentBehaviorBoomerang* behaviorBoomerang; ComponentBehaviorActInRectangle* behaviorActInRectangle; ComponentAnimationLevitate* animationLevitate; + ComponentAnimationIdle* animationIdle; + ComponentBehaviorFaceTarget* behaviorFaceTarget; behaviorBoomerang = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_BOOMERANG, id); behaviorActInRectangle = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_ACT_IN_RECTANGLE, id); enemy = ecs_component_add(ecs, ECS_COMPONENT_ENEMY, id); animationLevitate = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_LEVITATE, id); + animationIdle = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_IDLE, id); + behaviorFaceTarget = ecs_component_add(ecs, ECS_COMPONENT_BEHAVIOR_FACE_TARGET, id); component_enemy_init ( @@ -32,8 +36,7 @@ entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, EXCORSANT_IS_AFFECTED_BY_GRAVITY, EXCORSANT_IS_SOLID, EXCORSANT_GOODIE_COUNT, - level, - entityList + level ); component_behavior_boomerang_init @@ -55,6 +58,14 @@ entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, EXCORSANT_ANIMATION_LEVITATE_SPEED ); + component_animation_idle_init + ( + animationIdle, + EXCORSANT_ANIMATION_IDLE_BASE_INDEX, + EXCORSANT_ANIMATION_IDLE_TIMER + ); + + component_behavior_face_target_init(behaviorFaceTarget, targetID); component_behavior_act_in_rectangle_init(behaviorActInRectangle, EXCORSANT_ACT_RECTANGLE); ComponentGameEntityType* gameEntityType; diff --git a/src/game/ecs/entity/play/entity_excorsant.h b/src/game/ecs/entity/play/entity_excorsant.h index ec4d89e..6653e74 100644 --- a/src/game/ecs/entity/play/entity_excorsant.h +++ b/src/game/ecs/entity/play/entity_excorsant.h @@ -2,11 +2,15 @@ #include "../../component/animation/component_animation_levitate.h" #include "../../component/behavior/component_behavior_boomerang.h" +#include "../../component/animation/component_animation_idle.h" #include "../../component/behavior/component_behavior_act_in_rectangle.h" +#include "../../component/behavior/component_behavior_face_target.h" #include "../../component/entity/component_enemy.h" #include "../../ecs_component.h" #include "../../component/stat/component_game_entity_type.h" +#define EXCORSANT_ANIMATION_IDLE_BASE_INDEX 0 +#define EXCORSANT_ANIMATION_IDLE_TIMER 15 #define EXCORSANT_IS_SOLID false #define EXCORSANT_IS_BOUNCE false #define EXCORSANT_IS_AFFECTED_BY_GRAVITY false @@ -31,8 +35,8 @@ static const Rectangle EXCORSANT_ACT_RECTANGLE = }; static const ivec2 EXCORSANT_FRAME_SIZE = {512, 512}; -static const ivec2 EXCORSANT_ATLAS_SIZE = {1, 1}; -static const vec2 EXCORSANT_SIZE = {100.0f, 100.0f}; +static const ivec2 EXCORSANT_ATLAS_SIZE = {1, 4}; +static const vec2 EXCORSANT_SIZE = {150.0f, 150.0f}; static const vec2 EXCORSANT_PHYSICS_SIZE = {60.0f, 20.0f}; -void entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level, Vector* entityList); +void entity_excorsant_init(ECS* ecs, u32 id, vec3 position, u32 targetID, u32 level); diff --git a/src/game/ecs/entity/play/entity_player.c b/src/game/ecs/entity/play/entity_player.c index db03a06..679b430 100644 --- a/src/game/ecs/entity/play/entity_player.c +++ b/src/game/ecs/entity/play/entity_player.c @@ -15,6 +15,8 @@ entity_player_init(ECS* ecs, u32 id, vec3 position, u32 spawnID) ComponentRedirects* redirects; ComponentCircleCollision* circleCollision; ComponentStun* stun; + ComponentAnimationSquash* animationSquash; + ComponentAnimationStretch* animationStretch; actionShoot = ecs_component_add(ecs, ECS_COMPONENT_ACTION_SHOOT, id); actionKeepInRectangle = ecs_component_add(ecs, ECS_COMPONENT_ACTION_KEEP_IN_RECTANGLE, id); @@ -26,6 +28,8 @@ entity_player_init(ECS* ecs, u32 id, vec3 position, u32 spawnID) redirects = ecs_component_add(ecs, ECS_COMPONENT_REDIRECTS, id); stun = ecs_component_add(ecs, ECS_COMPONENT_STUN, id); circleCollision = ecs_component_add(ecs, ECS_COMPONENT_CIRCLE_COLLISION, id); + animationSquash = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_SQUASH, id); + animationStretch = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_STRETCH, id); ecs_component_add(ecs, ECS_COMPONENT_GOODIES, id); ecs_component_add(ecs, ECS_COMPONENT_UPGRADES, id); @@ -69,6 +73,22 @@ entity_player_init(ECS* ecs, u32 id, vec3 position, u32 spawnID) spawnID ); + component_animation_squash_init + ( + animationSquash, + PLAYER_ANIMATION_SQUASH_BASE, + PLAYER_ANIMATION_SQUASH_MULTIPLIER, + PLAYER_ANIMATION_SQUASH_SPEED + ); + + component_animation_stretch_init + ( + animationStretch, + PLAYER_ANIMATION_STRETCH_BASE, + PLAYER_ANIMATION_STRETCH_MULTIPLIER, + PLAYER_ANIMATION_STRETCH_SPEED + ); + component_ammo_init(ammo, PLAYER_AMMO_START); component_invincibility_init(invincibility, PLAYER_INVINCIBILITY_TIMER); component_stun_init(stun, PLAYER_STUN_TIMER); diff --git a/src/game/ecs/entity/play/entity_player.h b/src/game/ecs/entity/play/entity_player.h index dce7d87..70fd3d4 100644 --- a/src/game/ecs/entity/play/entity_player.h +++ b/src/game/ecs/entity/play/entity_player.h @@ -27,8 +27,8 @@ #define PLAYER_FRICTION 0.875 #define PLAYER_VELOCITY_MAX 10 #define PLAYER_ACTION_SHOOT_SPEED 15 -#define PLAYER_ACTION_SHOOT_HEIGHT 25.0f -#define PLAYER_ACTION_SHOOT_OFFSET 100.0f +#define PLAYER_ACTION_SHOOT_HEIGHT 60.0f +#define PLAYER_ACTION_SHOOT_OFFSET 225.0f #define PLAYER_CONTROL_SHOOT_COOLDOWN 12 #define PLAYER_CONTROL_REDIRECT_ANGLE_THRESHOLD 20 // Degrees #define PLAYER_AMMO_START 1 @@ -39,6 +39,12 @@ #define PLAYER_INVINCIBILITY_TIMER 120 #define PLAYER_STUN_TIMER 30 #define PLAYER_CIRCLE_RADIUS 75.0f +#define PLAYER_ANIMATION_SQUASH_BASE 1.0f +#define PLAYER_ANIMATION_SQUASH_MULTIPLIER 0.01f +#define PLAYER_ANIMATION_SQUASH_SPEED 0.01f +#define PLAYER_ANIMATION_STRETCH_BASE 1.0f +#define PLAYER_ANIMATION_STRETCH_MULTIPLIER 0.01f +#define PLAYER_ANIMATION_STRETCH_SPEED 0.01f static const Rectangle PLAYER_ACTION_KEEP_IN_RECTANGLE = { @@ -48,9 +54,9 @@ static const Rectangle PLAYER_ACTION_KEEP_IN_RECTANGLE = .h = 930 }; -static const ivec2 PLAYER_FRAME_SIZE = {512, 512}; -static const ivec2 PLAYER_ATLAS_SIZE = {1, 1}; -static const vec2 PLAYER_SIZE = {75.0f, 150.0f}; +static const ivec2 PLAYER_FRAME_SIZE = {1024, 1024}; +static const ivec2 PLAYER_ATLAS_SIZE = {1, 3}; +static const vec2 PLAYER_SIZE = {300.0f, 300.0f}; static const vec2 PLAYER_PHYSICS_SIZE = {60.0f, 20.0f}; void entity_player_init(ECS* ecs, u32 id, vec3 position, u32 spawnID); diff --git a/src/game/ecs/entity/play/entity_player_ammo_display.h b/src/game/ecs/entity/play/entity_player_ammo_display.h index 6d8d778..628238d 100644 --- a/src/game/ecs/entity/play/entity_player_ammo_display.h +++ b/src/game/ecs/entity/play/entity_player_ammo_display.h @@ -3,6 +3,6 @@ #include "../../component/hud/component_stat_display.h" #include "../../ecs_component.h" -static const vec3 PLAYER_AMMO_DISPLAY_OFFSET = {0.0f, -200.0f, 0.095f}; +static const vec3 PLAYER_AMMO_DISPLAY_OFFSET = {0.0f, -225.0f, 0.095f}; void entity_player_ammo_display_init(ECS* ecs, u32 id, u32 playerID); diff --git a/src/game/ecs/entity/play/entity_player_health_display.h b/src/game/ecs/entity/play/entity_player_health_display.h index 2580d3b..198a97f 100644 --- a/src/game/ecs/entity/play/entity_player_health_display.h +++ b/src/game/ecs/entity/play/entity_player_health_display.h @@ -5,6 +5,6 @@ #include "entity_icon.h" -static const vec3 PLAYER_HEALTH_DISPLAY_OFFSET = {0.0f, -225.0f, 0.1f}; +static const vec3 PLAYER_HEALTH_DISPLAY_OFFSET = {0.0f, -250.0f, 0.09f}; void entity_player_health_display_init(ECS* ecs, u32 id, u32 playerID); diff --git a/src/game/ecs/entity/play/entity_player_redirect_display.h b/src/game/ecs/entity/play/entity_player_redirect_display.h index 09b877d..d25f34b 100644 --- a/src/game/ecs/entity/play/entity_player_redirect_display.h +++ b/src/game/ecs/entity/play/entity_player_redirect_display.h @@ -3,6 +3,6 @@ #include "../../component/hud/component_stat_display.h" #include "../../ecs_component.h" -static const vec3 PLAYER_REDIRECT_DISPLAY_OFFSET = {0.0f, -175.0f, 0.090f}; +static const vec3 PLAYER_REDIRECT_DISPLAY_OFFSET = {0.0f, -200.0f, 0.090f}; void entity_player_redirect_display_init(ECS* ecs, u32 id, u32 playerID); diff --git a/src/game/ecs/entity/play/entity_puff.c b/src/game/ecs/entity/play/entity_puff.c new file mode 100644 index 0000000..0b75a7f --- /dev/null +++ b/src/game/ecs/entity/play/entity_puff.c @@ -0,0 +1,37 @@ +#include "entity_puff.h" + +/* Initializes a puff entity. */ +void +entity_puff_init(ECS* ecs, u32 id, vec3 position, vec2 size) +{ + ComponentActionDeleteOnTimer* actionDeleteOnTimer; + ComponentAnimationColorChange* animationColorChange; + ComponentSprite* sprite; + + sprite = ecs_component_add(ecs, ECS_COMPONENT_SPRITE, id); + actionDeleteOnTimer = ecs_component_add(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TIMER, id); + animationColorChange = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_COLOR_CHANGE, id); + + component_sprite_init + ( + sprite, + ecs->game->resources.textures[TEXTURE_PUFF], + size, + position + ); + + component_action_delete_on_timer_init + ( + actionDeleteOnTimer, + ENTITY_PUFF_TIMER + ); + + component_animation_color_change_init + ( + animationColorChange, + (f32*)COLOR_TRANSPARENT, + (f32*)COLOR_OPAQUE, + ENTITY_PUFF_TIMER, + ANIMATION_COLOR_CHANGE_MODE_STICK + ); +} diff --git a/src/game/ecs/entity/play/entity_puff.h b/src/game/ecs/entity/play/entity_puff.h new file mode 100644 index 0000000..de694ae --- /dev/null +++ b/src/game/ecs/entity/play/entity_puff.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../../component/action/component_action_delete_on_timer.h" +#include "../../component/animation/component_animation_color_change.h" +#include "../../ecs_component.h" + +#define ENTITY_PUFF_TIMER 15 + +static const vec3 ENTITY_PUFF_MOVE_VELOCITY = {0.0f, -1.0f, 0.0f}; +static const vec2 ENTITY_PUFF_SIZE = {64.0f, 64.0f}; + +void entity_puff_init(ECS* ecs, u32 id, vec3 position, vec2 size); diff --git a/src/game/ecs/entity/play/entity_shop_item_health.h b/src/game/ecs/entity/play/entity_shop_item_health.h index 0cd4116..142ebe1 100644 --- a/src/game/ecs/entity/play/entity_shop_item_health.h +++ b/src/game/ecs/entity/play/entity_shop_item_health.h @@ -3,7 +3,7 @@ #include "../../ecs_component.h" #include "../../component/stat/component_shop_item.h" -#define ENTITY_SHOP_ITEM_HEALTH_PRICE 100 -#define ENTITY_SHOP_ITEM_HEALTH_EXPONENT 1.15 +#define ENTITY_SHOP_ITEM_HEALTH_PRICE 300 +#define ENTITY_SHOP_ITEM_HEALTH_EXPONENT 4 void entity_shop_item_health_init(ECS* ecs, u32 id, u32 affectedID, u32 affectedID2); diff --git a/src/game/ecs/entity/play/entity_shop_item_upgrade_ammo.h b/src/game/ecs/entity/play/entity_shop_item_upgrade_ammo.h index 3e22b62..ab1cfb6 100644 --- a/src/game/ecs/entity/play/entity_shop_item_upgrade_ammo.h +++ b/src/game/ecs/entity/play/entity_shop_item_upgrade_ammo.h @@ -4,6 +4,6 @@ #include "../../component/stat/component_shop_item.h" #define ENTITY_SHOP_ITEM_UPGRADE_AMMO_PRICE 100 -#define ENTITY_SHOP_ITEM_UPGRADE_AMMO_EXPONENT 1.15 +#define ENTITY_SHOP_ITEM_UPGRADE_AMMO_EXPONENT 4 void entity_shop_item_upgrade_ammo_init(ECS* ecs, u32 id, u32 affectedID, u32 affectedID2); diff --git a/src/game/ecs/entity/play/entity_shop_item_upgrade_lifetime.h b/src/game/ecs/entity/play/entity_shop_item_upgrade_lifetime.h index b4a97f0..184fab9 100644 --- a/src/game/ecs/entity/play/entity_shop_item_upgrade_lifetime.h +++ b/src/game/ecs/entity/play/entity_shop_item_upgrade_lifetime.h @@ -4,6 +4,6 @@ #include "../../component/stat/component_shop_item.h" #define ENTITY_SHOP_ITEM_UPGRADE_LIFETIME_PRICE 100 -#define ENTITY_SHOP_ITEM_UPGRADE_LIFETIME_EXPONENT 1.15 +#define ENTITY_SHOP_ITEM_UPGRADE_LIFETIME_EXPONENT 4 void entity_shop_item_upgrade_lifetime_init(ECS* ecs, u32 id, u32 affectedID, u32 affectedID2); diff --git a/src/game/ecs/entity/play/entity_shop_item_upgrade_redirects.h b/src/game/ecs/entity/play/entity_shop_item_upgrade_redirects.h index ed0b2ba..de52346 100644 --- a/src/game/ecs/entity/play/entity_shop_item_upgrade_redirects.h +++ b/src/game/ecs/entity/play/entity_shop_item_upgrade_redirects.h @@ -4,6 +4,6 @@ #include "../../component/stat/component_shop_item.h" #define ENTITY_SHOP_ITEM_UPGRADE_REDIRECTS_PRICE 100 -#define ENTITY_SHOP_ITEM_UPGRADE_REDIRECTS_EXPONENT 1.15 +#define ENTITY_SHOP_ITEM_UPGRADE_REDIRECTS_EXPONENT 4 void entity_shop_item_upgrade_redirects_init(ECS* ecs, u32 id, u32 affectedID, u32 affectedID2); diff --git a/src/game/ecs/entity/play/entity_snake.c b/src/game/ecs/entity/play/entity_snake.c index 9a50af4..c30b72f 100644 --- a/src/game/ecs/entity/play/entity_snake.c +++ b/src/game/ecs/entity/play/entity_snake.c @@ -11,6 +11,7 @@ entity_snake_init(ECS* ecs, u32 id, vec3 position, u32 sender) ComponentActionOnDeleteGiveAmmo* actionOnDeleteGiveAmmo; ComponentActionDamage* actionDamage; ComponentAllegiance* allegiance; + ComponentAnimationIdle* animationIdle; gameObject = ecs_component_add(ecs, ECS_COMPONENT_GAME_OBJECT, id); actionReturn = ecs_component_add(ecs, ECS_COMPONENT_ACTION_RETURN, id); @@ -18,15 +19,19 @@ entity_snake_init(ECS* ecs, u32 id, vec3 position, u32 sender) actionOnDeleteGiveAmmo = ecs_component_add(ecs, ECS_COMPONENT_ACTION_ON_DELETE_GIVE_AMMO, id); actionDamage = ecs_component_add(ecs, ECS_COMPONENT_ACTION_DAMAGE, id); actionLock = ecs_component_add(ecs, ECS_COMPONENT_ACTION_LOCK, id); + animationIdle = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_IDLE, id); allegiance = ecs_component_add(ecs, ECS_COMPONENT_ALLEGIANCE, id); ecs_component_add(ecs, ECS_COMPONENT_ACTION_GRIP, id); + ecs_component_add(ecs, ECS_COMPONENT_ACTION_ANGLE, id); - component_game_object_init + component_game_object_atlas_init ( gameObject, ecs, ecs->game->resources.textures[TEXTURE_SNAKE], + (s32*)SNAKE_FRAME_SIZE, + (s32*)SNAKE_ATLAS_SIZE, (f32*)SNAKE_SIZE, (f32*)SNAKE_PHYSICS_SIZE, position, @@ -51,6 +56,7 @@ entity_snake_init(ECS* ecs, u32 id, vec3 position, u32 sender) component_action_redirect_init(actionRedirect, SNAKE_ACTION_REDIRECT_MULTIPLIER, sender); component_action_lock_init(actionLock, SNAKE_ACTION_LOCK_COOLDOWN, SNAKE_ACTION_LOCK_SELECT_RADIUS, sender); component_action_on_delete_give_ammo_init(actionOnDeleteGiveAmmo, SNAKE_ACTION_ON_DELETE_GIVE_AMMO_VALUE); + component_animation_idle_init(animationIdle, SNAKE_ANIMATION_IDLE_BASE_INDEX, SNAKE_ANIMATION_IDLE_TIMER); component_action_damage_init ( actionDamage, diff --git a/src/game/ecs/entity/play/entity_snake.h b/src/game/ecs/entity/play/entity_snake.h index 953e73e..27e1ba5 100644 --- a/src/game/ecs/entity/play/entity_snake.h +++ b/src/game/ecs/entity/play/entity_snake.h @@ -4,12 +4,17 @@ #include "../../component/component_game_object.h" #include "../../component/action/component_action_return.h" #include "../../component/action/component_action_redirect.h" +#include "../../component/action/component_action_angle.h" +#include "../../component/animation/component_animation_idle.h" #include "../../component/action/component_action_on_delete_give_ammo.h" #include "../../component/action/component_action_lock.h" #include "../../component/action/component_action_damage.h" #include "../../component/action/component_action_grip.h" #include "../../component/stat/component_game_entity_type.h" +#define SNAKE_ANIMATION_IDLE_BASE_INDEX 0 +#define SNAKE_ANIMATION_IDLE_TIMER 5 + #define SNAKE_SPEED 1 #define SNAKE_FRICTION 1 #define SNAKE_VELOCITY_MAX 50 @@ -30,7 +35,9 @@ #define SNAKE_GAME_OBJECT_IS_BOUNCE false #define SNAKE_GAME_OBJECT_IS_SOLID false -static const vec2 SNAKE_SIZE = {75.0f, 75.0f}; +static const vec2 SNAKE_SIZE = {100.0f, 100.0f}; static const vec2 SNAKE_PHYSICS_SIZE = {60.0f, 20.0f}; +static const ivec2 SNAKE_ATLAS_SIZE = {9, 2}; +static const ivec2 SNAKE_FRAME_SIZE = {512, 512}; void entity_snake_init(ECS* ecs, u32 id, vec3 position, u32 sender); diff --git a/src/game/ecs/entity/play/entity_timer_display.h b/src/game/ecs/entity/play/entity_timer_display.h index cdce122..1854d7a 100644 --- a/src/game/ecs/entity/play/entity_timer_display.h +++ b/src/game/ecs/entity/play/entity_timer_display.h @@ -4,7 +4,7 @@ #include "../../component/stat/component_timer.h" #include "../../ecs_component.h" -#define TIMER_DISPLAY_TIME (HOUR_TICK) +#define TIMER_DISPLAY_TIME 108000 static const vec3 ENTITY_TIMER_DISPLAY_POSITION = {1724.0f, 48.0f, 0.05f}; diff --git a/src/game/ecs/entity/play/entity_tutorial_text.c b/src/game/ecs/entity/play/entity_tutorial_text.c index 505fc9a..57e35ad 100644 --- a/src/game/ecs/entity/play/entity_tutorial_text.c +++ b/src/game/ecs/entity/play/entity_tutorial_text.c @@ -2,21 +2,23 @@ /* Initializes a player entity. */ void -entity_tutorial_text_init(ECS* ecs, u32 id, vec3 position) +entity_tutorial_text_init(ECS* ecs, u32 id, vec3 position, u32 heartID) { ComponentActionDeleteOnTimer* actionDeleteOnTimer; + ComponentActionDeleteOnHeart* actionDeleteOnHeart; ComponentAnimationColorChange* animationColorChange; ComponentText* text; f32 base; text = ecs_component_add(ecs, ECS_COMPONENT_TEXT, id); actionDeleteOnTimer = ecs_component_add(ecs, ECS_COMPONENT_ACTION_DELETE_ON_TIMER, id); + actionDeleteOnHeart = ecs_component_add(ecs, ECS_COMPONENT_ACTION_DELETE_ON_HEART, id); animationColorChange = ecs_component_add(ecs, ECS_COMPONENT_ANIMATION_COLOR_CHANGE, id); component_text_init ( text, - &ecs->game->resources.fonts[FONT_HUD], + &ecs->game->resources.fonts[FONT_TUTORIAL], STRING_TUTORIAL_TEXT, strlen(STRING_TUTORIAL_TEXT), ENTITY_TUTORIAL_TEXT_WRAP, @@ -30,6 +32,12 @@ entity_tutorial_text_init(ECS* ecs, u32 id, vec3 position) ENTITY_TUTORIAL_TEXT_TIMER ); + component_action_delete_on_heart_init + ( + actionDeleteOnHeart, + heartID + ); + component_animation_color_change_init ( animationColorChange, diff --git a/src/game/ecs/entity/play/entity_tutorial_text.h b/src/game/ecs/entity/play/entity_tutorial_text.h index ae6a7c8..bfbddb2 100644 --- a/src/game/ecs/entity/play/entity_tutorial_text.h +++ b/src/game/ecs/entity/play/entity_tutorial_text.h @@ -2,10 +2,11 @@ #include "../../component/component_text.h" #include "../../component/action/component_action_delete_on_timer.h" +#include "../../component/action/component_action_delete_on_heart.h" #include "../../component/animation/component_animation_color_change.h" #include "../../ecs_component.h" -#define ENTITY_TUTORIAL_TEXT_TIMER 1800 +#define ENTITY_TUTORIAL_TEXT_TIMER 1200 #define ENTITY_TUTORIAL_TEXT_WRAP 1600 -void entity_tutorial_text_init(ECS* ecs, u32 id, vec3 position); +void entity_tutorial_text_init(ECS* ecs, u32 id, vec3 position, u32 heartID); diff --git a/src/game/game.c b/src/game/game.c index 20bcde7..4b99bc2 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -27,6 +27,8 @@ _game_quit(Game* self) static void _game_tick(Game* self) { + state_tick(&self->state); + if (!self->isPaused) ecs_tick(&self->ecs); @@ -83,7 +85,7 @@ game_init(Game* self) ecs_init(&self->ecs, self); - state_init(&self->state, self, STATE_PLAY); + state_init(&self->state, self, STATE_TITLE); } /* Main game loop. */ diff --git a/src/game/render/texture_quad.c b/src/game/render/texture_quad.c index a43292c..688e896 100644 --- a/src/game/render/texture_quad.c +++ b/src/game/render/texture_quad.c @@ -2,22 +2,22 @@ /* Draws a textured quad. */ void -texture_quad_draw(Renderer* renderer, Shader* shader, Atlas* atlas, mat4 model, vec2 size, vec4 color) +texture_quad_draw +( + Renderer* renderer, + Shader* shader, + Atlas* atlas, + mat4 model, + vec2 size, + vec4 color, + bool isFlipHorizontal +) { vec2 uvMin; vec2 uvMax; mat4 view; mat4 projection; - - atlas_uv_get(atlas, uvMin, uvMax); - - f32 vertices[4][5] = - { - {0.0f , 0.0f , 0.0f, uvMin[0], uvMin[1]}, - {0.0f , size[1], 0.0f, uvMin[0], uvMax[1]}, - {size[0], size[1], 0.0f, uvMax[0], uvMax[1]}, - {size[0], 0.0f , 0.0f, uvMax[0], uvMin[1]}, - }; + f32 verticesFinal[4][5]; u32 indices[2][3] = { @@ -25,13 +25,44 @@ texture_quad_draw(Renderer* renderer, Shader* shader, Atlas* atlas, mat4 model, {0, 1, 3} }; + atlas_uv_get(atlas, uvMin, uvMax); + + if (isFlipHorizontal) + { + f32 vertices[4][5] = + { + {size[0], 0.0f , 0.0f, uvMin[0], uvMin[1]}, + {size[0], size[1], 0.0f, uvMin[0], uvMax[1]}, + {0.0f, size[1], 0.0f, uvMax[0], uvMax[1]}, + {0.0f, 0.0f , 0.0f, uvMax[0], uvMin[1]} + }; + + memcpy(verticesFinal, vertices, sizeof(verticesFinal)); + } + else + { + f32 vertices[4][5] = + { + {0.0f , 0.0f , 0.0f, uvMin[0], uvMin[1]}, + {0.0f , size[1], 0.0f, uvMin[0], uvMax[1]}, + {size[0], size[1], 0.0f, uvMax[0], uvMax[1]}, + {size[0], 0.0f , 0.0f, uvMax[0], uvMin[1]} + }; + + memcpy(verticesFinal, vertices, sizeof(verticesFinal)); + } + camera_view_get(&renderer->camera, view); camera_projection_get(&renderer->camera, projection); + vec3 scale = {1, 1, 1}; + + glm_scale(projection, scale); + vao_bind(&renderer->vao); vbo_bind(&renderer->vbo); - vbo_buffer(&renderer->vbo, sizeof(vertices), vertices); + vbo_buffer(&renderer->vbo, sizeof(verticesFinal), verticesFinal); vbo_bind(&renderer->ebo); vbo_buffer(&renderer->ebo, sizeof(indices), indices); diff --git a/src/game/render/texture_quad.h b/src/game/render/texture_quad.h index b7a35dd..9593fa1 100644 --- a/src/game/render/texture_quad.h +++ b/src/game/render/texture_quad.h @@ -8,4 +8,13 @@ #define TEXTURE_QUAD_UNIFORM_TEXTURE "uTexture" #define TEXTURE_QUAD_UNIFORM_VIEW "uView" -void texture_quad_draw(Renderer* renderer, Shader* shader, Atlas* atlas, mat4 model, vec2 size, vec4 color); +void texture_quad_draw +( + Renderer* renderer, + Shader* shader, + Atlas* atlas, + mat4 model, + vec2 size, + vec4 color, + bool isFlipHorizontal +); diff --git a/src/game/resource/RESOURCE_COMMON.h b/src/game/resource/RESOURCE_COMMON.h index b7f082b..d6e4d1e 100644 --- a/src/game/resource/RESOURCE_COMMON.h +++ b/src/game/resource/RESOURCE_COMMON.h @@ -35,9 +35,14 @@ static const ShaderPaths SHADER_PATHS[SHADER_COUNT] = #define TEXTURE_COUNT TEXTURE_GOODIES + 1 typedef enum TextureType { - TEXTURE_BLACK, + TEXTURE_STATE_FADE, TEXTURE_CURSOR, + TEXTURE_MENU_BUTTONS, TEXTURE_ICONS, + TEXTURE_LOGO, + TEXTURE_GAME_OVER, + TEXTURE_PUFF, + TEXTURE_OVERLAY, TEXTURE_REDIRECT_ARROW, TEXTURE_STREAK, TEXTURE_STREAK_SQUARE, @@ -62,9 +67,14 @@ typedef enum TextureType static const char* TEXTURE_PATHS[TEXTURE_COUNT] = { - "res/gfx/black.png", + "res/gfx/stateFade.png", "res/gfx/cursor.png", + "res/gfx/menuButtons.png", "res/gfx/icons.png", + "res/gfx/title/logo.png", + "res/gfx/gameOver/gameOver.png", + "res/gfx/play/puff.png", + "res/gfx/play/overlay.png", "res/gfx/play/redirectArrow.png", "res/gfx/play/streak.png", "res/gfx/play/streakSquare.png", @@ -87,14 +97,18 @@ static const char* TEXTURE_PATHS[TEXTURE_COUNT] = "res/gfx/play/goodies.png" }; -#define FONT_COUNT FONT_SHOP + 1 +#define FONT_COUNT FONT_SMALL + 1 typedef enum FontType { FONT_NORMAL, FONT_STAT_DISPLAY, FONT_DAMAGE_NUMBER, FONT_HUD, - FONT_SHOP + FONT_SHOP, + FONT_TUTORIAL, + FONT_CREDITS, + FONT_BIG, + FONT_SMALL } FontType; static const char* FONT_PATHS[FONT_COUNT] = @@ -104,6 +118,10 @@ static const char* FONT_PATHS[FONT_COUNT] = "res/font/upheaval.ttf", "res/font/upheaval.ttf", "res/font/upheaval.ttf", + "res/font/upheaval.ttf", + "res/font/upheaval.ttf", + "res/font/upheaval.ttf", + "res/font/upheaval.ttf" }; static const u32 FONT_SIZES[FONT_COUNT] = @@ -111,7 +129,12 @@ static const u32 FONT_SIZES[FONT_COUNT] = 64, 32, 32, - 32 + 32, + 32, + 24, + 24, + 128, + 24 }; #define SOUND_COUNT SOUND_EZ_ACHE_READY + 1 diff --git a/src/game/state/STATE_COMMON.h b/src/game/state/STATE_COMMON.h index b988b14..6c15ccc 100644 --- a/src/game/state/STATE_COMMON.h +++ b/src/game/state/STATE_COMMON.h @@ -1,6 +1,9 @@ #pragma once #include "play/PLAY_COMMON.h" +#include "title/TITLE_COMMON.h" +#include "game_over/GAME_OVER_COMMON.h" +#include "results/RESULTS_COMMON.h" #define STATE_COUNT STATE_RESULTS + 1 typedef enum StateType @@ -17,8 +20,14 @@ typedef struct State { Game* game; StateType type; + StateType setType; + bool isChanging; + u32 fadeID; union { Play play; - }; + Title title; + GameOver gameOver; + Results results; + } states; } State; diff --git a/src/game/state/game_over/GAME_OVER_COMMON.h b/src/game/state/game_over/GAME_OVER_COMMON.h new file mode 100644 index 0000000..3691de3 --- /dev/null +++ b/src/game/state/game_over/GAME_OVER_COMMON.h @@ -0,0 +1,17 @@ +#pragma once + +#include "../../resource/resource_shader.h" +#include "../../resource/resource_texture.h" + +typedef struct State State; + +typedef struct GameOver +{ + State* state; + u32 textID; + u32 imageID; + u32 descriptionID; + u32 backgroundID; + u32 menuButtonID; + bool isChange; +} GameOver; diff --git a/src/game/state/game_over/game_over.c b/src/game/state/game_over/game_over.c new file mode 100644 index 0000000..c107073 --- /dev/null +++ b/src/game/state/game_over/game_over.c @@ -0,0 +1,92 @@ +#include "game_over.h" + +static void _game_over_entity_init(GameOver* self); + +/* Initializes entities for the gameover state. */ +static void +_game_over_entity_init(GameOver* self) +{ + self->backgroundID = ecs_entity_add(&self->state->game->ecs); + self->textID = ecs_entity_add(&self->state->game->ecs); + self->imageID = ecs_entity_add(&self->state->game->ecs); + self->descriptionID = ecs_entity_add(&self->state->game->ecs); + self->menuButtonID = ecs_entity_add(&self->state->game->ecs); + + entity_sprite_init + ( + &self->state->game->ecs, + self->backgroundID, + self->state->game->resources.textures[TEXTURE_STATE_FADE], + (f32*)GAME_OVER_BACKGROUND_SIZE, + (f32*)GAME_OVER_BACKGROUND_POSITION + ); + + entity_text_init + ( + &self->state->game->ecs, + self->textID, + &self->state->game->resources.fonts[FONT_BIG], + STRING_GAME_OVER_TITLE_TEXT, + strlen(STRING_GAME_OVER_TITLE_TEXT), + -1, + (f32*)GAME_OVER_TITLE_TEXT_POSITION, + (f32*)COLOR_OPAQUE + ); + + entity_sprite_init + ( + &self->state->game->ecs, + self->textID, + self->state->game->resources.textures[TEXTURE_GAME_OVER], + (f32*)GAME_OVER_IMAGE_SIZE, + (f32*)GAME_OVER_IMAGE_POSITION + ); + + entity_text_init + ( + &self->state->game->ecs, + self->descriptionID, + &self->state->game->resources.fonts[FONT_SMALL], + STRING_GAME_OVER_TEXT, + strlen(STRING_GAME_OVER_TEXT), + -1, + (f32*)GAME_OVER_TEXT_POSITION, + (f32*)COLOR_OPAQUE + ); + + entity_menu_button_init + ( + &self->state->game->ecs, + self->menuButtonID, + (f32*)GAME_OVER_MENU_BUTTON_POSITION, + MENU_BUTTON_RETRY + ); +} + +/* Initializes gameover state. */ +void +game_over_init(GameOver* self, State* state) +{ + memset(self, '\0', sizeof(GameOver)); + + self->state = state; + + _game_over_entity_init(self); + + music_play(&self->state->game->resources.music[MUSIC_GAME_OVER], true); +} + +/* Ticks gameover state. */ +void +game_over_tick(GameOver* self) +{ + ComponentButton* button; + + button = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_BUTTON, self->menuButtonID); + + if (button->state == BUTTON_PRESSED) + { + sound_play(&self->state->game->resources.sounds[SOUND_SELECT], SOUND_PRIORITY); + self->isChange = true; + } +} diff --git a/src/game/state/game_over/game_over.h b/src/game/state/game_over/game_over.h new file mode 100644 index 0000000..f3d0f42 --- /dev/null +++ b/src/game/state/game_over/game_over.h @@ -0,0 +1,56 @@ +#pragma once + +#include "../STATE_COMMON.h" + +#include "../../ecs/ecs.h" + +#include "../../ecs/entity/entity_cursor.h" +#include "../../ecs/entity/entity_sprite.h" +#include "../../ecs/entity/entity_text.h" +#include "../../ecs/entity/entity_menu_button.h" + +static const vec2 GAME_OVER_BACKGROUND_SIZE = {1920.0f, 1080.0f}; +static const vec3 GAME_OVER_BACKGROUND_POSITION = {960.0f, 540.0f, 0.2f}; +static const vec3 GAME_OVER_TITLE_TEXT_POSITION = {600.0f, 0.0f, 0.09f}; +static const vec2 GAME_OVER_IMAGE_SIZE = {1920.0f, 660.0f}; +static const vec3 GAME_OVER_IMAGE_POSITION = {960.0f, 450.0f, 0.09f}; +static const vec3 GAME_OVER_TEXT_POSITION = {500.0f, 800.0f, 0.1f}; +static const vec3 GAME_OVER_MENU_BUTTON_POSITION = {960.0f, 950.0f, 0.1f}; + +#define GAME_OVER_SHADER_COUNT 2 +static const ShaderType GAME_OVER_SHADERS[GAME_OVER_SHADER_COUNT] = +{ + SHADER_TEXTURE_QUAD, + SHADER_COLOR_QUAD +}; + +#define GAME_OVER_TEXTURE_COUNT 4 +static const TextureType GAME_OVER_TEXTURES[GAME_OVER_TEXTURE_COUNT] = +{ + TEXTURE_STATE_FADE, + TEXTURE_CURSOR, + TEXTURE_MENU_BUTTONS, + TEXTURE_GAME_OVER +}; + +#define GAME_OVER_FONT_COUNT 2 +static const FontType GAME_OVER_FONTS[GAME_OVER_FONT_COUNT] = +{ + FONT_SMALL, + FONT_BIG +}; + +#define GAME_OVER_SOUND_COUNT 1 +static const SoundType GAME_OVER_SOUNDS[GAME_OVER_SOUND_COUNT] = +{ + SOUND_SELECT +}; + +#define GAME_OVER_MUSIC_COUNT 1 +static const MusicType GAME_OVER_MUSIC[GAME_OVER_MUSIC_COUNT] = +{ + MUSIC_GAME_OVER +}; + +void game_over_init(GameOver* self, State* state); +void game_over_tick(GameOver* self); diff --git a/src/game/state/play/PLAY_COMMON.h b/src/game/state/play/PLAY_COMMON.h index 9490d04..2c043e2 100644 --- a/src/game/state/play/PLAY_COMMON.h +++ b/src/game/state/play/PLAY_COMMON.h @@ -18,4 +18,8 @@ typedef struct Play u32 waveDisplay; u32 heartDisplay; u32 waveTimerDisplay; + u32 overlay; + u32 tutorialText; + bool isGameOver; + bool isResults; } Play; diff --git a/src/game/state/play/play.c b/src/game/state/play/play.c index 9bebbc7..d7bf150 100644 --- a/src/game/state/play/play.c +++ b/src/game/state/play/play.c @@ -15,6 +15,8 @@ _play_entity_init(Play* self) self->waveDisplay = ecs_entity_add(&self->state->game->ecs); self->waveTimerDisplay = ecs_entity_add(&self->state->game->ecs); self->heartDisplay = ecs_entity_add(&self->state->game->ecs); + self->tutorialText = ecs_entity_add(&self->state->game->ecs); + self->overlay = ecs_entity_add(&self->state->game->ecs); entity_spawner_init ( @@ -91,11 +93,19 @@ _play_entity_init(Play* self) entity_tutorial_text_init ( &self->state->game->ecs, - ecs_entity_add(&self->state->game->ecs), - (f32*)PLAY_TUTORIAL_TEXT_POSITION + self->tutorialText, + (f32*)PLAY_TUTORIAL_TEXT_POSITION, + self->player ); - music_play(&self->state->game->resources.music[MUSIC_CALM], true); + entity_sprite_init + ( + &self->state->game->ecs, + self->overlay, + self->state->game->resources.textures[TEXTURE_OVERLAY], + (f32*)PLAY_OVERLAY_SIZE, + (f32*)PLAY_OVERLAY_POSITION + ); } /* Initializes play state. */ @@ -107,4 +117,28 @@ play_init(Play* self, State* state) self->state = state; _play_entity_init(self); + + music_play(&self->state->game->resources.music[MUSIC_CALM], true); +} + +/* Ticks play state. */ +void +play_tick(Play* self) +{ + ComponentGoodies* goodies; + ComponentHealth* health; + ComponentTimer* timer; + + goodies = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_GOODIES, self->elemental); + health = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_HEALTH, self->player); + timer = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_TIMER, self->timerDisplay); + + if (goodies->value >= goodies->max) + self->isResults = true; + else if + ( + health->isDead || + timer->isDone + ) + self->isGameOver = true; } diff --git a/src/game/state/play/play.h b/src/game/state/play/play.h index 09806b5..a42d41e 100644 --- a/src/game/state/play/play.h +++ b/src/game/state/play/play.h @@ -16,11 +16,15 @@ #include "../../ecs/entity/play/entity_shop_button.h" #include "../../ecs/entity/play/entity_tutorial_text.h" #include "../../ecs/entity/entity_cursor.h" +#include "../../ecs/entity/entity_sprite.h" -static const vec3 PLAY_PLAYER_POSITION = {960.0f, 1000.0f, 0.0f}; -static const vec3 PLAY_ELEMENTAL_POSITION = {960.0f, 500.0f, 0.0f}; +static const vec3 PLAY_PLAYER_POSITION = {960.0f, 1000.0f, 0.8f}; +static const vec3 PLAY_ELEMENTAL_POSITION = {960.0f, 500.0f, 0.8f}; static const vec3 PLAY_TUTORIAL_TEXT_POSITION = {128.0f, 128.0f, 0.05f}; +static const vec3 PLAY_OVERLAY_POSITION = {960.0f, 540.0f, 0.09999f}; +static const vec3 PLAY_OVERLAY_SIZE = {1920.0f, 1080.0f}; + #define PLAY_SHADER_COUNT 2 static const ShaderType PLAY_SHADERS[PLAY_SHADER_COUNT] = { @@ -28,12 +32,15 @@ static const ShaderType PLAY_SHADERS[PLAY_SHADER_COUNT] = SHADER_COLOR_QUAD }; -#define PLAY_TEXTURE_COUNT 22 +#define PLAY_TEXTURE_COUNT 25 static const TextureType PLAY_TEXTURES[PLAY_TEXTURE_COUNT] = { + TEXTURE_STATE_FADE, TEXTURE_CURSOR, - TEXTURE_REDIRECT_ARROW, + TEXTURE_OVERLAY, TEXTURE_ICONS, + TEXTURE_PUFF, + TEXTURE_REDIRECT_ARROW, TEXTURE_STREAK, TEXTURE_STREAK_SQUARE, TEXTURE_SHADOW, @@ -55,14 +62,15 @@ static const TextureType PLAY_TEXTURES[PLAY_TEXTURE_COUNT] = TEXTURE_GOODIES }; -#define PLAY_FONT_COUNT 5 +#define PLAY_FONT_COUNT 6 static const FontType PLAY_FONTS[PLAY_FONT_COUNT] = { FONT_NORMAL, FONT_STAT_DISPLAY, FONT_DAMAGE_NUMBER, FONT_HUD, - FONT_SHOP + FONT_SHOP, + FONT_TUTORIAL }; #define PLAY_SOUND_COUNT 27 @@ -110,3 +118,4 @@ static const MusicType PLAY_MUSIC[PLAY_MUSIC_COUNT] = }; void play_init(Play* play, State* state); +void play_tick(Play* play); diff --git a/src/game/state/results/RESULTS_COMMON.h b/src/game/state/results/RESULTS_COMMON.h new file mode 100644 index 0000000..61d6c3f --- /dev/null +++ b/src/game/state/results/RESULTS_COMMON.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../../resource/resource_shader.h" +#include "../../resource/resource_texture.h" + +typedef struct State State; + +typedef struct Results +{ + State* state; + u32 textID; + u32 menuButtonID; + u32 backgroundID; + bool isChange; +} Results; diff --git a/src/game/state/results/results.c b/src/game/state/results/results.c new file mode 100644 index 0000000..f9da523 --- /dev/null +++ b/src/game/state/results/results.c @@ -0,0 +1,69 @@ +#include "results.h" + +static void _results_entity_init(Results* self); + +/* Initializes entities for the results state. */ +static void +_results_entity_init(Results* self) +{ + self->menuButtonID = ecs_entity_add(&self->state->game->ecs); + self->backgroundID = ecs_entity_add(&self->state->game->ecs); + self->textID = ecs_entity_add(&self->state->game->ecs); + + entity_sprite_init + ( + &self->state->game->ecs, + self->backgroundID, + self->state->game->resources.textures[TEXTURE_STATE_FADE], + (f32*)RESULTS_BACKGROUND_SIZE, + (f32*)RESULTS_BACKGROUND_POSITION + ); + + entity_text_init + ( + &self->state->game->ecs, + self->textID, + &self->state->game->resources.fonts[FONT_SMALL], + STRING_RESULTS_TEXT, + strlen(STRING_RESULTS_TEXT), + -1, + (f32*)RESULTS_TEXT_POSITION, + (f32*)COLOR_OPAQUE + ); + + entity_menu_button_init + ( + &self->state->game->ecs, + self->menuButtonID, + (f32*)RESULTS_MENU_BUTTON_POSITION, + MENU_BUTTON_OK + ); +} + +/* Initializes results state. */ +void +results_init(Results* self, State* state) +{ + memset(self, '\0', sizeof(Results)); + + self->state = state; + + _results_entity_init(self); + + music_play(&self->state->game->resources.music[MUSIC_RESULTS], true); +} + +/* Ticks results state. */ +void +results_tick(Results* self) +{ + ComponentButton* button; + + button = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_BUTTON, self->menuButtonID); + + if (button->state == BUTTON_PRESSED) + { + sound_play(&self->state->game->resources.sounds[SOUND_SELECT], SOUND_PRIORITY); + self->isChange = true; + } +} diff --git a/src/game/state/results/results.h b/src/game/state/results/results.h new file mode 100644 index 0000000..b7c9b55 --- /dev/null +++ b/src/game/state/results/results.h @@ -0,0 +1,49 @@ +#pragma once + +#include "../STATE_COMMON.h" + +#include "../../ecs/ecs.h" + +#include "../../ecs/entity/entity_cursor.h" +#include "../../ecs/entity/entity_sprite.h" +#include "../../ecs/entity/entity_menu_button.h" + +static const vec2 RESULTS_BACKGROUND_SIZE = {1920.0f, 1080.0f}; +static const vec3 RESULTS_BACKGROUND_POSITION = {960.0f, 540.0f, 0.2f}; +static const vec3 RESULTS_MENU_BUTTON_POSITION = {960.0f, 800.0f, 0.1f}; +static const vec3 RESULTS_TEXT_POSITION = {100.0f, 500.0f, 0.1f}; + +#define RESULTS_SHADER_COUNT 2 +static const ShaderType RESULTS_SHADERS[RESULTS_SHADER_COUNT] = +{ + SHADER_TEXTURE_QUAD, + SHADER_COLOR_QUAD +}; + +#define RESULTS_TEXTURE_COUNT 2 +static const TextureType RESULTS_TEXTURES[RESULTS_TEXTURE_COUNT] = +{ + TEXTURE_STATE_FADE, + TEXTURE_MENU_BUTTONS +}; + +#define RESULTS_FONT_COUNT 1 +static const FontType RESULTS_FONTS[RESULTS_FONT_COUNT] = +{ + FONT_SMALL +}; + +#define RESULTS_SOUND_COUNT 1 +static const SoundType RESULTS_SOUNDS[RESULTS_SOUND_COUNT] = +{ + SOUND_SELECT +}; + +#define RESULTS_MUSIC_COUNT 1 +static const MusicType RESULTS_MUSIC[RESULTS_MUSIC_COUNT] = +{ + MUSIC_RESULTS +}; + +void results_init(Results* self, State* state); +void results_tick(Results* self); diff --git a/src/game/state/state.c b/src/game/state/state.c index c114aa0..e696403 100644 --- a/src/game/state/state.c +++ b/src/game/state/state.c @@ -1,115 +1,197 @@ #include "state.h" -static void _state_set(State* state, StateType type); +static void _state_set(State* self, StateType type); + +static void +_fade_add(State* self, bool isFadeIn) +{ + self->fadeID = ecs_entity_add(&self->game->ecs); + + entity_state_fade_init + ( + &self->game->ecs, + self->fadeID, + isFadeIn + ); +} /* Sets the game state. */ static void -_state_set(State* state, StateType type) +_state_set(State* self, StateType type) { - state->type = type; + self->type = type; resource_shader_state_init ( - &state->game->resources, - STATE_SHADERS[state->type], - STATE_SHADER_COUNT[state->type] + &self->game->resources, + STATE_SHADERS[self->type], + STATE_SHADER_COUNT[self->type] ); resource_texture_state_init ( - &state->game->resources, - STATE_TEXTURES[state->type], - STATE_TEXTURE_COUNT[state->type] + &self->game->resources, + STATE_TEXTURES[self->type], + STATE_TEXTURE_COUNT[self->type] ); resource_font_state_init ( - &state->game->resources, - STATE_FONTS[state->type], - STATE_FONT_COUNT[state->type] + &self->game->resources, + STATE_FONTS[self->type], + STATE_FONT_COUNT[self->type] ); resource_sound_state_init ( - &state->game->resources, - STATE_SOUNDS[state->type], - STATE_SOUND_COUNT[state->type] + &self->game->resources, + STATE_SOUNDS[self->type], + STATE_SOUND_COUNT[self->type] ); resource_music_state_init ( - &state->game->resources, - STATE_MUSIC[state->type], - STATE_MUSIC_COUNT[state->type] + &self->game->resources, + STATE_MUSIC[self->type], + STATE_MUSIC_COUNT[self->type] ); - switch (state->type) + switch (self->type) { case STATE_PLAY: - play_init(&state->play, state); + play_init(&self->states.play, self); + break; + case STATE_TITLE: + title_init(&self->states.title, self); + break; + case STATE_GAME_OVER: + game_over_init(&self->states.gameOver, self); + break; + case STATE_RESULTS: + results_init(&self->states.results, self); break; default: break; } + + _fade_add(self, true); } /* Initializes game state; does not free past resources. */ void -state_init(State* state, Game* game, StateType type) +state_init(State* self, Game* game, StateType type) { - memset(state, '\0', sizeof(State)); + memset(self, '\0', sizeof(State)); - state->game = game; + self->game = game; - _state_set(state, type); + _state_set(self, type); } /* Frees current stare resources. */ void -state_free(State* state) +state_free(State* self) { - ecs_clear(&state->game->ecs); + ecs_clear(&self->game->ecs); resource_shader_state_free ( - &state->game->resources, - STATE_SHADERS[state->type], - STATE_SHADER_COUNT[state->type] + &self->game->resources, + STATE_SHADERS[self->type], + STATE_SHADER_COUNT[self->type] ); resource_texture_state_free ( - &state->game->resources, - STATE_TEXTURES[state->type], - STATE_TEXTURE_COUNT[state->type] + &self->game->resources, + STATE_TEXTURES[self->type], + STATE_TEXTURE_COUNT[self->type] ); resource_font_state_free ( - &state->game->resources, - STATE_FONTS[state->type], - STATE_FONT_COUNT[state->type] + &self->game->resources, + STATE_FONTS[self->type], + STATE_FONT_COUNT[self->type] ); resource_sound_state_free ( - &state->game->resources, - STATE_SOUNDS[state->type], - STATE_SOUND_COUNT[state->type] + &self->game->resources, + STATE_SOUNDS[self->type], + STATE_SOUND_COUNT[self->type] ); resource_music_state_free ( - &state->game->resources, - STATE_MUSIC[state->type], - STATE_MUSIC_COUNT[state->type] + &self->game->resources, + STATE_MUSIC[self->type], + STATE_MUSIC_COUNT[self->type] ); } /* Changes game state and initializes new resources. */ void -state_change(State* state, StateType type) +state_change(State* self, StateType type) { - state_free(state); - _state_set(state, type); + _fade_add(self, false); + + self->setType = type; + + self->isChanging = true; +} + +/* Ticks state. */ +void +state_tick(State* self) +{ + if (self->isChanging) + { + ComponentAnimationColorChange* animationColorChange; + animationColorChange = ecs_component_get(&self->game->ecs, ECS_COMPONENT_ANIMATION_COLOR_CHANGE, self->fadeID); + + if (animationColorChange->isDone) + { + self->isChanging = false; + state_free(self); + + memset(&self->states, '\0', sizeof(self->states)); + + _state_set(self, self->setType); + } + } + else + { + switch (self->type) + { + case STATE_PLAY: + play_tick(&self->states.play); + + if (self->states.play.isResults) + state_change(self, STATE_RESULTS); + else if (self->states.play.isGameOver) + state_change(self, STATE_GAME_OVER); + break; + case STATE_TITLE: + title_tick(&self->states.title); + + if (self->states.title.isChange) + state_change(self, STATE_PLAY); + break; + case STATE_GAME_OVER: + game_over_tick(&self->states.gameOver); + + if (self->states.gameOver.isChange) + state_change(self, STATE_PLAY); + break; + case STATE_RESULTS: + results_tick(&self->states.results); + + if (self->states.results.isChange) + state_change(self, STATE_TITLE); + break; + default: + break; + } + } } diff --git a/src/game/state/state.h b/src/game/state/state.h index 35d838a..db847cc 100644 --- a/src/game/state/state.h +++ b/src/game/state/state.h @@ -1,6 +1,9 @@ #pragma once #include "play/play.h" +#include "title/title.h" +#include "game_over/game_over.h" +#include "results/results.h" #include "../resource/resource_shader.h" #include "../resource/resource_texture.h" @@ -8,56 +11,89 @@ #include "../resource/resource_music.h" #include "../resource/resource_sound.h" +#include "../ecs/entity/entity_state_fade.h" + static const ShaderType* STATE_SHADERS[STATE_COUNT] = { - PLAY_SHADERS + PLAY_SHADERS, + TITLE_SHADERS, + GAME_OVER_SHADERS, + RESULTS_SHADERS }; static const u32 STATE_SHADER_COUNT[STATE_COUNT] = { - PLAY_SHADER_COUNT + PLAY_SHADER_COUNT, + TITLE_SHADER_COUNT, + GAME_OVER_SHADER_COUNT, + RESULTS_SHADER_COUNT }; static const TextureType* STATE_TEXTURES[STATE_COUNT] = { - PLAY_TEXTURES + PLAY_TEXTURES, + TITLE_TEXTURES, + GAME_OVER_TEXTURES, + RESULTS_TEXTURES, }; static const u32 STATE_TEXTURE_COUNT[STATE_COUNT] = { - PLAY_TEXTURE_COUNT + PLAY_TEXTURE_COUNT, + TITLE_TEXTURE_COUNT, + GAME_OVER_TEXTURE_COUNT, + RESULTS_TEXTURE_COUNT, }; static const FontType* STATE_FONTS[STATE_COUNT] = { - PLAY_FONTS + PLAY_FONTS, + TITLE_FONTS, + GAME_OVER_FONTS, + RESULTS_FONTS }; static const u32 STATE_FONT_COUNT[STATE_COUNT] = { - PLAY_FONT_COUNT + PLAY_FONT_COUNT, + TITLE_FONT_COUNT, + GAME_OVER_FONT_COUNT, + RESULTS_FONT_COUNT }; static const SoundType* STATE_SOUNDS[STATE_COUNT] = { - PLAY_SOUNDS + PLAY_SOUNDS, + TITLE_SOUNDS, + GAME_OVER_SOUNDS, + RESULTS_SOUNDS }; static const u32 STATE_SOUND_COUNT[STATE_COUNT] = { - PLAY_SOUND_COUNT + PLAY_SOUND_COUNT, + TITLE_SOUND_COUNT, + GAME_OVER_SOUND_COUNT, + RESULTS_SOUND_COUNT }; static const MusicType* STATE_MUSIC[STATE_COUNT] = { - PLAY_MUSIC + PLAY_MUSIC, + TITLE_MUSIC, + GAME_OVER_MUSIC, + RESULTS_MUSIC }; static const u32 STATE_MUSIC_COUNT[STATE_COUNT] = { - PLAY_MUSIC_COUNT + PLAY_MUSIC_COUNT, + TITLE_MUSIC_COUNT, + GAME_OVER_MUSIC_COUNT, + RESULTS_MUSIC_COUNT }; -void state_change(State* state, StateType type); -void state_init(State* state, Game* game, StateType type); -void state_free(State* state); +void state_change(State* self, StateType type); +void state_init(State* self, Game* game, StateType type); +void state_free(State* self); +void state_tick(State* self); diff --git a/src/game/state/title/TITLE_COMMON.h b/src/game/state/title/TITLE_COMMON.h new file mode 100644 index 0000000..0aa4aa7 --- /dev/null +++ b/src/game/state/title/TITLE_COMMON.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../../resource/resource_shader.h" +#include "../../resource/resource_texture.h" + +typedef struct State State; + +typedef struct Title +{ + State* state; + u32 logoID; + u32 menuButtonID; + u32 textID; + bool isChange; +} Title; diff --git a/src/game/state/title/title.c b/src/game/state/title/title.c new file mode 100644 index 0000000..5817722 --- /dev/null +++ b/src/game/state/title/title.c @@ -0,0 +1,69 @@ +#include "title.h" + +static void _title_entity_init(Title* self); + +/* Initializes entities for the title state. */ +static void +_title_entity_init(Title* self) +{ + self->logoID = ecs_entity_add(&self->state->game->ecs); + self->menuButtonID = ecs_entity_add(&self->state->game->ecs); + self->textID = ecs_entity_add(&self->state->game->ecs); + + entity_sprite_init + ( + &self->state->game->ecs, + self->logoID, + self->state->game->resources.textures[TEXTURE_LOGO], + (f32*)TITLE_LOGO_SIZE, + (f32*)TITLE_LOGO_POSITION + ); + + entity_menu_button_init + ( + &self->state->game->ecs, + self->menuButtonID, + (f32*)TITLE_MENU_BUTTON_POSITION, + MENU_BUTTON_START + ); + + entity_text_init + ( + &self->state->game->ecs, + self->textID, + &self->state->game->resources.fonts[FONT_CREDITS], + STRING_TITLE_CREDITS_TEXT, + strlen(STRING_TITLE_CREDITS_TEXT), + -1, + (f32*)TITLE_CREDITS_POSITION, + (f32*)COLOR_OPAQUE + ); +} + +/* Initializes title state. */ +void +title_init(Title* self, State* state) +{ + memset(self, '\0', sizeof(Title)); + + self->state = state; + + _title_entity_init(self); + + music_play(&self->state->game->resources.music[MUSIC_TITLE], true); +} + +/* Ticks title state. */ +void +title_tick(Title* self) +{ + ComponentButton* button; + + button = ecs_component_get(&self->state->game->ecs, ECS_COMPONENT_BUTTON, self->menuButtonID); + + if (button->state == BUTTON_PRESSED) + { + sound_play(&self->state->game->resources.sounds[SOUND_SELECT], SOUND_PRIORITY); + self->isChange = true; + } +} diff --git a/src/game/state/title/title.h b/src/game/state/title/title.h new file mode 100644 index 0000000..f90c66f --- /dev/null +++ b/src/game/state/title/title.h @@ -0,0 +1,52 @@ +#pragma once + +#include "../STATE_COMMON.h" + +#include "../../ecs/ecs.h" + +#include "../../ecs/entity/entity_cursor.h" +#include "../../ecs/entity/entity_text.h" +#include "../../ecs/entity/entity_sprite.h" +#include "../../ecs/entity/entity_menu_button.h" + +static const vec2 TITLE_LOGO_SIZE = {1024.0f, 512.0f}; +static const vec3 TITLE_LOGO_POSITION = {960.0f, 400.0f, 0.1f}; +static const vec3 TITLE_MENU_BUTTON_POSITION = {960.0f, 800.0f, 0.1f}; +static const vec3 TITLE_CREDITS_POSITION = {32.0f, 32.0f, 0.1f}; + +#define TITLE_SHADER_COUNT 2 +static const ShaderType TITLE_SHADERS[TITLE_SHADER_COUNT] = +{ + SHADER_TEXTURE_QUAD, + SHADER_COLOR_QUAD +}; + +#define TITLE_TEXTURE_COUNT 4 +static const TextureType TITLE_TEXTURES[TITLE_TEXTURE_COUNT] = +{ + TEXTURE_STATE_FADE, + TEXTURE_CURSOR, + TEXTURE_MENU_BUTTONS, + TEXTURE_LOGO +}; + +#define TITLE_FONT_COUNT 1 +static const FontType TITLE_FONTS[TITLE_FONT_COUNT] = +{ + FONT_CREDITS +}; + +#define TITLE_SOUND_COUNT 1 +static const SoundType TITLE_SOUNDS[TITLE_SOUND_COUNT] = +{ + SOUND_SELECT +}; + +#define TITLE_MUSIC_COUNT 1 +static const MusicType TITLE_MUSIC[TITLE_MUSIC_COUNT] = +{ + MUSIC_TITLE +}; + +void title_init(Title* self, State* state); +void title_tick(Title* self);