Skip to content

Commit

Permalink
Started inventory, re-added items
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnywycliffe committed Nov 4, 2024
1 parent a1a4135 commit 5762838
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 20 deletions.
2 changes: 1 addition & 1 deletion main/modes/games/cGrove/Docs/Tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
- Using items
- Add menu for buying items
- Add money system (Chowa grab nearby money that spawns)
- Add items
- Stats can be increased
- Save and load from NVS

## Race
- Build mode
Expand Down
83 changes: 74 additions & 9 deletions main/modes/games/cGrove/Garden/cg_Grove.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ static const char* speechBubbleSprites[] = {
"cg_text3.wsg",
};

static const char* itemSprites[] = {
"agi_book.wsg", "cha_book.wsg", "spd_book.wsg", "sta_book.wsg", "str_book.wsg", "cg_ball.wsg",
"cg_crayons.wsg", "cg_knife.wsg", "cg_toy_sword.wsg", "cake.wsg", "souffle.wsg", "DonutRing.wsg",
};

//==============================================================================
// Function Declarations
//==============================================================================
Expand Down Expand Up @@ -93,7 +98,7 @@ static void cg_setupBorders(cGrove_t* cg);

/**
* @brief Callback to restart BGM
*
*
*/
static void cg_bgmCB(void);

Expand Down Expand Up @@ -144,6 +149,11 @@ void cg_initGrove(cGrove_t* cg)
{
loadWsg(speechBubbleSprites[idx], &cg->grove.speechBubbles[idx], true);
}
cg->grove.itemsWSGs = calloc(ARRAY_SIZE(itemSprites), sizeof(wsg_t));
for (int32_t idx = 0; idx < ARRAY_SIZE(itemSprites); idx++)
{
loadWsg(itemSprites[idx], &cg->grove.itemsWSGs[idx], true);
}
// Audio
loadMidiFile("Chowa_Grove_Meadow.mid", &cg->grove.bgm, true);

Expand Down Expand Up @@ -189,7 +199,28 @@ void cg_initGrove(cGrove_t* cg)
}

// Initialize items
// TODO:
for (int idx = 0; idx < CG_GROVE_MAX_ITEMS; idx++)
{
// FIXME: Load from NVS
cg->grove.items[idx].active = true;
cg->grove.items[idx].spr = cg->grove.itemsWSGs[idx];
cg->grove.items[idx].aabb.pos.x
= 32 + (esp_random() % (cg->grove.groveBG.w - (64 + cg->grove.itemsWSGs[idx].w)));
cg->grove.items[idx].aabb.pos.y
= 32 + (esp_random() % (cg->grove.groveBG.h - (64 + cg->grove.itemsWSGs[idx].h)));
cg->grove.items[idx].aabb.height = cg->grove.itemsWSGs[idx].h;
cg->grove.items[idx].aabb.width = cg->grove.itemsWSGs[idx].w;
char buffer[32];
snprintf(buffer, sizeof(buffer) - 1, "Item_%" PRId32, idx);
strcpy(cg->grove.items[idx].name, buffer);
}

// Init Ring
cg->grove.ring.aabb.height = cg->grove.itemsWSGs[11].h;
cg->grove.ring.aabb.width = cg->grove.itemsWSGs[11].w;

// TODO: Load inventory from NVS
cg->grove.inv.money = 0;
}

/**
Expand All @@ -203,6 +234,11 @@ void cg_deInitGrove(cGrove_t* cg)
// Audio
unloadMidiFile(&cg->grove.bgm);
// WSGs
for (uint8_t i = 0; i < ARRAY_SIZE(itemSprites); i++)
{
freeWsg(&cg->grove.itemsWSGs[i]);
}
free(cg->grove.itemsWSGs);
for (uint8_t i = 0; i < ARRAY_SIZE(speechBubbleSprites); i++)
{
freeWsg(&cg->grove.speechBubbles[i]);
Expand Down Expand Up @@ -241,7 +277,7 @@ void cg_runGrove(cGrove_t* cg, int64_t elapsedUS)
// Play BGM if it's not playing
if (!isBGMPlaying)
{
soundPlayBgmCb(&cg->grove.bgm, MIDI_BGM, cg_bgmCB);
// soundPlayBgmCb(&cg->grove.bgm, MIDI_BGM, cg_bgmCB);
isBGMPlaying = true;
}

Expand All @@ -258,6 +294,28 @@ void cg_runGrove(cGrove_t* cg, int64_t elapsedUS)
cg->grove.heldChowa->aabb.pos = addVec2d(cg->grove.cursor.pos, cg->grove.camera.pos);
}

// Resurface items dropped in the water
vec_t temp;
for (int idx = 0; idx < CG_GROVE_MAX_ITEMS; idx++)
{
if (&cg->grove.items[idx] != cg->grove.heldItem
&& rectRectIntersection(cg->grove.items[idx].aabb, cg->grove.boundaries[CG_WATER], &temp))
{
cg->grove.items[idx].aabb.pos.x
= 32 + (esp_random() % (cg->grove.groveBG.w - (64 + cg->grove.itemsWSGs[idx].w)));
cg->grove.items[idx].aabb.pos.y
= 32 + (esp_random() % (cg->grove.groveBG.h - (64 + cg->grove.itemsWSGs[idx].h)));
}
}

// Spawn Rings
if (esp_random() % 512 == 0)
{
cg->grove.ring.aabb.pos.x = 32 + (esp_random() % (cg->grove.groveBG.w - (64 + cg->grove.itemsWSGs[11].w)));
cg->grove.ring.aabb.pos.y = 32 + (esp_random() % (cg->grove.groveBG.h - (64 + cg->grove.itemsWSGs[11].h)));
cg->grove.ring.active = true;
}

// Chowa AI
for (int32_t idx = 0; idx < CG_MAX_CHOWA + CG_GROVE_MAX_GUEST_CHOWA; idx++)
{
Expand Down Expand Up @@ -337,6 +395,7 @@ static void cg_handleInputGarden(cGrove_t* cg)
if (cg->grove.holdingItem)
{
cg->grove.holdingItem = false;
cg->grove.heldItem = NULL;
}
else if (cg->grove.holdingChowa)
{
Expand All @@ -359,7 +418,7 @@ static void cg_handleInputGarden(cGrove_t* cg)
// Chowa
if (rectRectIntersection(rect, cg->grove.chowa[idx].aabb, &temp))
{
cg->grove.chowa[idx].gState = CHOWA_PET;
cg->grove.chowa[idx].gState = CHOWA_PET;
cg->grove.chowa[idx].timeLeft = 1000000;
}
}
Expand All @@ -368,6 +427,10 @@ static void cg_handleInputGarden(cGrove_t* cg)
}
else
{
vec_t temp;
rectangle_t rect = {.pos = addVec2d(cg->grove.cursor.pos, cg->grove.camera.pos),
.height = cg->grove.cursor.height,
.width = cg->grove.cursor.width};
while (checkButtonQueueWrapper(&evt))
{
if (evt.button & PB_RIGHT)
Expand All @@ -391,12 +454,18 @@ static void cg_handleInputGarden(cGrove_t* cg)
if (cg->grove.holdingItem)
{
cg->grove.holdingItem = false;
cg->grove.heldItem = NULL;
}
else if (cg->grove.holdingChowa)
{
cg->grove.holdingChowa = false;
cg->grove.heldChowa->gState = CHOWA_IDLE;
}
else if (cg->grove.ring.active && rectRectIntersection(rect, cg->grove.ring.aabb, &temp))
{
cg->grove.ring.active = false;
cg->grove.inv.money += 1;
}
else
{
cg_attemptGrab(cg);
Expand All @@ -406,14 +475,10 @@ static void cg_handleInputGarden(cGrove_t* cg)
{
for (int idx = 0; idx < CG_MAX_CHOWA + CG_GROVE_MAX_GUEST_CHOWA; idx++)
{
vec_t temp;
rectangle_t rect = {.pos = addVec2d(cg->grove.cursor.pos, cg->grove.camera.pos),
.height = cg->grove.cursor.height,
.width = cg->grove.cursor.width};
// Chowa
if (rectRectIntersection(rect, cg->grove.chowa[idx].aabb, &temp))
{
cg->grove.chowa[idx].gState = CHOWA_PET;
cg->grove.chowa[idx].gState = CHOWA_PET;
cg->grove.chowa[idx].timeLeft = 1000000;
}
}
Expand Down
2 changes: 1 addition & 1 deletion main/modes/games/cGrove/Garden/cg_GroveAI.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static cgChowaStateGarden_t cg_getNewTask(cGrove_t* cg, cgGroveChowa_t* c)
// Check player affinity
if (c->chowa->playerAffinity > 100 && esp_random() % 6 == 0)
{
c->precision = 32.0f;
c->precision = 16.0f;
c->nextTimeLeft = SECOND * (1 + (esp_random() % 3));
c->nextState = CHOWA_GIFT;
return CHOWA_CHASE;
Expand Down
58 changes: 51 additions & 7 deletions main/modes/games/cGrove/Garden/cg_GroveDraw.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ static void cg_drawHand(cGrove_t* cg);
*/
static void cg_drawItem(cGrove_t* cg, int8_t idx);

/**
* @brief Draws the ring
*
* @param cg Game Data
*/
static void cg_drawRing(cGrove_t* cg);

/**
* @brief Draws a Chowa
*
Expand All @@ -57,6 +64,13 @@ static void cg_drawChowaGrove(cGrove_t* cg, int64_t elapsedUS);
*/
static void cg_groveDebug(cGrove_t* cg);

/**
* @brief Draws the UI elements
*
* @param cg Game Data
*/
static void cg_drawUI(cGrove_t* cg);

//==============================================================================
// Functions
//==============================================================================
Expand All @@ -82,11 +96,14 @@ void cg_groveDraw(cGrove_t* cg, int64_t elapsedUs)
}
}

cg_drawRing(cg);

// Draw Chowa
cg_drawChowaGrove(cg, elapsedUs);

// Draw UI
cg_drawHand(cg);
cg_drawUI(cg);

// Debug draw
cg_groveDebug(cg);
Expand All @@ -104,26 +121,35 @@ static void cg_drawHand(cGrove_t* cg)
drawWsgSimple(&cg->grove.cursors[2], cg->grove.cursor.pos.x, cg->grove.cursor.pos.y);
return;
}
vec_t temp;
rectangle_t rect = {.pos = addVec2d(cg->grove.cursor.pos, cg->grove.camera.pos),
.height = cg->grove.cursor.height,
.width = cg->grove.cursor.width};
// If hovering over
for (int idx = 0; idx < CG_MAX_CHOWA + CG_GROVE_MAX_GUEST_CHOWA; idx++)
{
vec_t temp;
rectangle_t rect = {.pos = addVec2d(cg->grove.cursor.pos, cg->grove.camera.pos),
.height = cg->grove.cursor.height,
.width = cg->grove.cursor.width};
// Chowa
if (rectRectIntersection(rect, cg->grove.chowa[idx].aabb, &temp))
{
drawWsgSimple(&cg->grove.cursors[1], cg->grove.cursor.pos.x, cg->grove.cursor.pos.y);
return;
}
}
for (int idx = 0; idx < CG_GROVE_MAX_ITEMS; idx++)
{
// Items
if (rectRectIntersection(cg->grove.cursor, cg->grove.items[idx].aabb, &temp))
if (rectRectIntersection(rect, cg->grove.items[idx].aabb, &temp))
{
drawWsgSimple(&cg->grove.cursors[1], cg->grove.cursor.pos.x, cg->grove.cursor.pos.y);
return;
}
}
// Ring
if (rectRectIntersection(rect, cg->grove.ring.aabb, &temp))
{
drawWsgSimple(&cg->grove.cursors[1], cg->grove.cursor.pos.x, cg->grove.cursor.pos.y);
return;
}
// Otherwise
drawWsgSimple(&cg->grove.cursors[0], cg->grove.cursor.pos.x, cg->grove.cursor.pos.y);
}
Expand All @@ -136,6 +162,16 @@ static void cg_drawItem(cGrove_t* cg, int8_t idx)
drawText(&cg->menuFont, c555, cg->grove.items[idx].name, xOffset, yOffset - 16);
}

static void cg_drawRing(cGrove_t* cg)
{
int16_t xOffset = cg->grove.ring.aabb.pos.x - cg->grove.camera.pos.x;
int16_t yOffset = cg->grove.ring.aabb.pos.y - cg->grove.camera.pos.y;
if (cg->grove.ring.active)
{
drawWsgSimple(&cg->grove.itemsWSGs[11], xOffset, yOffset);
}
}

static void cg_drawChowaGrove(cGrove_t* cg, int64_t elapsedUS)
{
for (int idx = 0; idx < CG_MAX_CHOWA + CG_GROVE_MAX_GUEST_CHOWA; idx++)
Expand Down Expand Up @@ -424,11 +460,20 @@ static void cg_drawChowaGrove(cGrove_t* cg, int64_t elapsedUS)
}
}

static void cg_drawUI(cGrove_t* cg)
{
// Draw image
drawWsgSimple(&cg->grove.itemsWSGs[11], 15, 15);
// Draw amount of rings
char buffer[24];
snprintf(buffer, sizeof(buffer) - 1, "%" PRId16, cg->grove.inv.money);
drawText(&cg->menuFont, c555, buffer, 45, 23);
}

static void cg_groveDebug(cGrove_t* cg)
{
int16_t xOffset = -cg->grove.camera.pos.x;
int16_t yOffset = -cg->grove.camera.pos.y;
char buffer[32];
// draw AABBs for grove
for (int32_t i = 0; i < 3; i++)
{
Expand All @@ -445,7 +490,6 @@ static void cg_groveDebug(cGrove_t* cg)
cg->grove.chowa[i].aabb.pos.x + cg->grove.chowa[i].aabb.width + xOffset,
cg->grove.chowa[i].aabb.pos.y + cg->grove.chowa[i].aabb.height + yOffset, c500);
drawCircle(cg->grove.chowa[i].targetPos.x + xOffset, cg->grove.chowa[i].targetPos.y + yOffset, 12, c500);
drawText(&cg->menuFont, c550, buffer, 24, 24);
drawLineFast(cg->grove.chowa[i].aabb.pos.x + xOffset, cg->grove.chowa[i].aabb.pos.y + yOffset,
cg->grove.cursor.pos.x, cg->grove.cursor.pos.y, c505);
}
Expand Down
21 changes: 19 additions & 2 deletions main/modes/games/cGrove/cg_Typedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ typedef struct
//==============================================================================

// Defines =============================
#define CG_GROVE_MAX_ITEMS 10 ///< Max number of items. Cannot assume unique
#define CG_GROVE_MAX_ITEMS 11 ///< Max number of items. Cannot assume unique
#define CG_GROVE_MAX_GUEST_CHOWA 5 ///< Maximum number of Chowa allowed to be in the grove at once

#define CG_GROVE_SCREEN_BOUNDARY 32 ///< How close the cursor can get to the edge of the screen
Expand Down Expand Up @@ -256,6 +256,21 @@ typedef enum
} cgChowaStateGarden_t;

// Structs ==============================
typedef struct
{
int16_t money; ///< Money
cgItem_t items[CG_GROVE_MAX_ITEMS]; ///< Item IDs
uint8_t quantities[CG_GROVE_MAX_ITEMS]; ///< Item qtys
} cgInventory_t;

typedef struct
{
rectangle_t aabb; ///< Position and bounding box
int64_t despawnTimer; ///< Time left until money despawns
int8_t animFrame; ///< Sparkle animation frames
bool active; ///< If the ring is active
} cgGroveMoney_t;

typedef struct
{
// Basic data
Expand Down Expand Up @@ -293,15 +308,17 @@ typedef struct
wsg_t* questionMarks; ///< Question mark sprites
wsg_t* notes; ///< Musical notes
wsg_t* speechBubbles; ///< Speech Bubbles for Chowa
wsg_t* itemsWSGs; ///< Item sprites
// Audio
midiFile_t bgm; ///< Main BGM for the Grove


// Field data
cgItem_t items[CG_GROVE_MAX_ITEMS]; ///< Items present in the Grove
rectangle_t boundaries[3]; ///< Boundary boxes
cgGroveChowa_t chowa[CG_MAX_CHOWA + CG_GROVE_MAX_GUEST_CHOWA]; ///< List of all chowa in the garden
bool bgmPlaying; ///< If the BGM is active
cgInventory_t inv; ///< Inventory struct
cgGroveMoney_t ring; ///< Rings available to collect

// Player resources
rectangle_t camera; ///< In-garden camera viewport
Expand Down

0 comments on commit 5762838

Please sign in to comment.