big refactor

This commit is contained in:
2025-04-11 22:01:30 +02:00
parent 68412a7d7a
commit 928842c4c2
42 changed files with 1429 additions and 3312 deletions
+73
View File
@@ -0,0 +1,73 @@
#ifndef APP_H
#define APP_H
#include <config.h>
#include <display.h>
#include "screen.h"
#include "applicationstate.h"
#include "font.h"
#include "logo.h"
#include "menu.h"
#include "game.h"
typedef struct {
Config config;
State state;
Display display;
Font font;
LogoState logo;
GameState game;
MenuState menu;
} Application;
void ConfigApp(Application* app){
InitConfig(&app->config, "config/config.ini");
app->state.currentScreen = GetConfigInt(&app->config, "startScreen");
app->state.running = true;
app->state.gameStarted = false;
app->state.flagFPS = GetConfigInt(&app->config, "showFPS");
app->display.title = GetConfigString(&app->config, "display_title");
app->display.width = GetConfigInt(&app->config, "display_width");
app->display.height = GetConfigInt(&app->config, "display_height");
}
void InitApp(Application *app){
InitFont(&app->font);
InitLogo(&app->logo);
InitMenu(&app->menu);
InitGame(&app->game,&app->display);
}
void UpdateApp(Application *app){
while (app->state.running)
{
switch (app->state.currentScreen)
{
case LOGO:
{
UpdateLogo(&app->logo, &app->state);
RenderLogo(&app->logo, &app->state);
}break;
case MENU:
{
UpdateMenu(&app->menu, &app->state);
RenderMenu(&app->menu, &app->state, &app->font, app->display.title);
}break;
case GAMEPLAY:
{
UpdateGame(&app->game, &app->state);
RenderGame(&app->game, &app->state);
}break;
default: break;
}
}
}
void CleanupApp(Application *app){
CleanupMenu(&app->menu);
CleanupGame(&app->game);
CleanupFont(&app->font);
}
#endif //APP_H
+13
View File
@@ -0,0 +1,13 @@
#ifndef APPLICATIONSTATE_H
#define APPLICATIONSTATE_H
#include "screen.h"
typedef struct {
Screen currentScreen;
bool running;
bool gameStarted;
bool flagFPS;
} State;
#endif // APPLICATIONSTATE_H
+70
View File
@@ -0,0 +1,70 @@
#ifndef BACKGROUND_H
#define BACKGROUND_H
#include <sprite.h>
#include <raylib.h>
typedef struct {
Sprite sprite;
float scrolling;
float scale;
float scrollSpeed;
Vector2 pos;
} Background;
void InitBackground(float scrollSpeed, Background *bg, Texture2D *texture, const TextureAsset *backgroundAsset){
bg->scrolling = 0.0f;
bg->scrollSpeed = scrollSpeed;
bg->scale = 1.0f;
bg->sprite = (Sprite){
.texture = *texture,
.sourceRec = (Rectangle){0.0f,0.0f,backgroundAsset->frameWidth, backgroundAsset->frameHeight},
.destRec = (Rectangle){0.0f,0.0f,(float)GetScreenWidth(),(float)GetScreenHeight()},
.origin = (Vector2){0.0f,0.0f},
.rotation = 0.0f,
.color = WHITE
};
}
void UpdateBackground(Background *bg){
bg->scrolling -= bg->scrollSpeed;
if (bg->scrolling <= -bg->sprite.texture.width * bg->scale) {
bg->scrolling = 0;
}
bg->pos = (Vector2){ bg->scrolling, 0.0f };
UpdateSpriteDestRec(&bg->sprite, &bg->pos);
}
void RenderBackground(Background *bg){
Sprite temp0 = bg->sprite;
float newX0 = bg->sprite.destRec.x + bg->sprite.texture.width * bg->scale * 2;
Vector2 newPos0 = {newX0, bg->sprite.destRec.y};
UpdateSpriteDestRec(&temp0, &newPos0);
RenderSprite(&temp0);
Sprite temp = bg->sprite;
float newX = bg->sprite.destRec.x + bg->sprite.texture.width * bg->scale;
Vector2 newPos = {newX, bg->sprite.destRec.y};
UpdateSpriteDestRec(&temp, &newPos);
RenderSprite(&temp);
RenderSprite(&bg->sprite);
Sprite temp2 = bg->sprite;
float newX2 = bg->sprite.destRec.x - bg->sprite.texture.width * bg->scale;
Vector2 newPos2 = {newX2, bg->sprite.destRec.y};
UpdateSpriteDestRec(&temp2, &newPos2);
RenderSprite(&temp2);
Sprite temp3 = bg->sprite;
float newX3 = bg->sprite.destRec.x - bg->sprite.texture.width * bg->scale * 2;
Vector2 newPos3 = {newX3, bg->sprite.destRec.y};
UpdateSpriteDestRec(&temp3, &newPos3);
RenderSprite(&temp3);
}
#endif // BACKGROUND_H
+76
View File
@@ -0,0 +1,76 @@
#ifndef BEE_H
#define BEE_H
#include <sprite.h>
#include <animation.h>
#include <physics.h>
#include <object.h>
typedef enum {
FLYING
} BeeAnimationState;
typedef struct {
Sprite sprite;
Animation animation;
Physics physics;
Object target;
Object hive;
int flowerCount;
} Bee;
Bee CreateBee(BeeAnimationState animState, Texture2D texture, float frameWidth, int maxFrame, int framesSpeed, Vector2 position, float speed, ObjectArray* target, Object* base){
return (Bee){
.sprite = {
.texture = texture,
.frameSize = {frameWidth, frameWidth},
.sourceRec = {0.0f, 0.0f, frameWidth, frameWidth},
.destRec = {0.0f, 0.0f, frameWidth, frameWidth},
.origin = {frameWidth / 2, frameWidth / 2},
.rotation = 0.0f,
.color = WHITE
},
.animation = {
.state = animState,
.currentFrame = 0,
.maxFrame = maxFrame,
.framesCounter = 0,
.framesSpeed = framesSpeed,
.animTimer = 0.0f
},
.physics = {
.position = position,
.direction = (Vector2){0.0f,0.0f},
.speed = speed
},
.target = *GetRandomObject(target),
.hive = *base
};
}
void UpdateBee(Bee* bee, ObjectArray* flowers, Object* hive){
const float tolerance = 1.0f;
if (bee->flowerCount < 4){
if (fabs(bee->physics.position.x - bee->target.position.x) < tolerance &&
fabs(bee->physics.position.y - bee->target.position.y) < tolerance) {
bee->target = *GetRandomObject(flowers);
bee->flowerCount++;
} else {
}
} else {
bee->target = *hive;
if (fabs(bee->physics.position.x - bee->target.position.x) < tolerance &&
fabs(bee->physics.position.y - bee->target.position.y) < tolerance) {
bee->physics.speed = 0.0f;
} else {
}
}
UpdatePhysics(&bee->physics, GetDirectionToObject(&bee->target, bee->physics.position));
UpdateSpriteRotation(&bee->sprite, &bee->physics.direction);
UpdateSpriteDestRec(&bee->sprite, &bee->physics.position);
UpdateAnimation(&bee->animation, GetFrameTime());
UpdateSpriteSourceRec(&bee->sprite, &(Vector2){bee->sprite.frameSize.x * bee->animation.state, bee->sprite.frameSize.x * bee->animation.currentFrame});
}
#endif // BEE_H
+20
View File
@@ -0,0 +1,20 @@
// initButton(&m->startButton, "Start Game", GetScreenWidth() / 10, GetScreenHeight() / 20, GetScreenWidth() / 2, GetScreenHeight() / 2);
// initButton(&m->quitButton, "Quit Game", GetScreenWidth() / 10, GetScreenHeight() / 20, GetScreenWidth() / 2,
// GetScreenHeight() / 2 + (GetScreenHeight() / 20 * 2));
// if (isButtonClicked(&m->startButton)) {
// state->gameStarted = true;
// m->startButton.text = "Continue";
// state->currentScreen = GAMEPLAY;
// }
// if (isButtonClicked(&m->quitButton) || (WindowShouldClose() && !IsKeyPressed(KEY_ESCAPE))) {
// state->running = false;
// }
// if (state->gameStarted){
// if (IsKeyPressed(KEY_ESCAPE)){
// state->currentScreen = GAMEPLAY;
// }
// }
// renderButton(&m->startButton);
// renderButton(&m->quitButton);
+7
View File
@@ -0,0 +1,7 @@
#ifndef COLORS_H
#define COLORS_H
#define TEXT_COLOR_DARK (Color){ 182, 137, 98, 255}
#define TEXT_COLOR_LIGHT (Color){ 243, 229, 194, 255}
#endif // COLORS_H
+46
View File
@@ -0,0 +1,46 @@
#ifndef Floor_H
#define Floor_H
#include <sprite.h>
typedef struct
{
Sprite sprite;
Rectangle bounds;
} Floor;
Floor CreateFloor(Texture2D texture, float textureWidth)
{
return (Floor){
.sprite = {
.texture = texture,
.frameSize = {textureWidth, textureWidth},
.sourceRec = {0.0f, 0.0f, textureWidth, textureWidth},
.destRec = {0.0f, 0.0f, textureWidth, textureWidth},
.origin = {textureWidth / 2, textureWidth / 2},
.rotation = 0.0f,
.color = WHITE},
.bounds = {0.0f, 0.0f, 0.0f, 0.0f}};
}
void UpdateFloor(Floor *floor, const Camera2D *camera)
{
floor->bounds.x = (int)((camera->target.x - (GetScreenWidth() / 2.0f / camera->zoom)) / floor->sprite.frameSize.x) - 1;
floor->bounds.width = (int)((camera->target.x + (GetScreenWidth() / 2.0f / camera->zoom)) / floor->sprite.frameSize.x) + 1;
floor->bounds.y = (int)((camera->target.y - (GetScreenHeight() / 2.0f / camera->zoom)) / floor->sprite.frameSize.y) - 1;
floor->bounds.height = (int)((camera->target.y + (GetScreenHeight() / 2.0f / camera->zoom)) / floor->sprite.frameSize.y) + 1;
}
void RenderFloor(Floor *floor)
{
for (int y = (int)floor->bounds.y; y <= (int)floor->bounds.height; y++)
{
for (int x = (int)floor->bounds.x; x <= (int)floor->bounds.width; x++)
{
Vector2 floorPosition = {x * floor->sprite.frameSize.x, y * floor->sprite.frameSize.y};
UpdateSpriteDestRec(&floor->sprite, &floorPosition);
RenderSprite(&floor->sprite);
}
}
}
#endif // Floor_H
+30
View File
@@ -0,0 +1,30 @@
#ifndef FLOWERS_H
#define FLOWERS_H
#include <object.h>
ObjectArray CreateFlowers(Texture2D texture, float frameWidth, float rotation, float fieldSize)
{
ObjectArray flowers = CreateObjectArray(&(Object){
.sprite = {
.texture = texture,
.sourceRec = {0.0f, 0.0f, frameWidth, frameWidth},
.destRec = {0.0f, 0.0f, frameWidth, frameWidth},
.origin = {frameWidth / 2, frameWidth / 2},
.rotation = rotation,
.color = WHITE},
.position = {0.0f, 0.0f}},
10);
if (!flowers.data)
{
printf("Memory allocation failed.\n");
exit(1);
}
SetRandomPositionForObjectArray(&flowers, (Rectangle){-fieldSize, -fieldSize, fieldSize * 2, fieldSize * 2});
return flowers;
}
#endif // FLOWERS_H
+13
View File
@@ -0,0 +1,13 @@
#ifndef FONT_H
#define FONT_H
void InitFont(Font *font){
*font = LoadFont("assets/SproutLandsUI/fonts/pixelFont-7-8x14-sproutLands.fnt");
SetTextureFilter(font->texture, TEXTURE_FILTER_POINT);
}
void CleanupFont(Font *font){
UnloadFont(*font);
}
#endif //FONT_H
+162
View File
@@ -0,0 +1,162 @@
#ifndef GAME_H
#define GAME_H
#include <object.h>
#include <camera.h>
#include <input.h>
#include <postfx.h>
#include <soundtrack.h>
#include <asset.h>
#include "applicationstate.h"
#include "gameassets.h"
#include "floor.h"
#include "player.h"
#include "bee.h"
#include "hive.h"
#include "flowers.h"
typedef struct
{
Assets assets;
Texture2D textures[TEX_COUNT];
PostProcessing postFX[SHADER_COUNT];
Soundtrack soundtracks[SOUNDTRACK_COUNT];
RenderTexture2D target;
Floor floor;
Object hive;
ObjectArray flowers;
Player player;
Bee bee1;
Camera2D camera;
Mouse mouse;
Image image;
} GameState;
void InitGame(GameState *g, Display *display)
{
g->assets = (Assets){
.textureAssets = texAssets,
.shaderAssets = shaderAssets,
.soundtrackAssets = soundtrackAssets};
for (int i = 0; i < TEX_COUNT; i++)
{
g->textures[i] = LoadTexture(g->assets.textureAssets[i].path);
}
for (int i = 0; i < SHADER_COUNT; i++)
{
g->postFX[i] = CreatePostFX(g->assets.shaderAssets[i].path);
}
for (int i = 0; i < SOUNDTRACK_COUNT; i++)
{
g->soundtracks[i] = LoadSoundtrack(g->assets.soundtrackAssets[i].path);
}
// Target texture
g->target = LoadRenderTexture(display->width, display->height);
// Static Entities
g->flowers = CreateFlowers(g->textures[FLOWER], g->assets.textureAssets[FLOWER].frameWidth, g->assets.textureAssets[FLOWER].rotation, 50.0f);
g->floor = CreateFloor(g->textures[GRASS], g->assets.textureAssets[GRASS].frameWidth);
g->hive = CreateHive(g->textures[HIVE], g->assets.textureAssets[HIVE].frameWidth);
// Animated Entities
g->player = CreatePlayer(IDLE_DOWN, HOE, g->textures[PLAYER], g->assets.textureAssets[PLAYER].frameWidth, 4, 2, g->hive.position, g->assets.textureAssets[PLAYER].rotation, 50.0f);
g->bee1 = CreateBee(FLYING, g->textures[BEE], g->assets.textureAssets[BEE].frameWidth, 4, 10, g->hive.position, 10.0f, &g->flowers, &g->hive);
// I/O
g->camera = CreateCamera(display->width, display->height, g->player.physics.position, 10.0f);
g->mouse = CreateMouse(0.10f, 5.0f, 10.0f, &g->textures[CURSOR]);
}
void UpdateGame(GameState *g, State *state)
{
if (GetFPS() <= 60)
{
SetTargetFPS(0);
}
if (IsKeyPressed(KEY_ESCAPE))
{
state->currentScreen = MENU;
}
if (WindowShouldClose() && !IsKeyPressed(KEY_ESCAPE))
{
state->running = false;
}
for (int i = 0; i < SHADER_COUNT; i++)
{
UpdatePostFX(&g->postFX[i]);
}
for (int i = 0; i < SOUNDTRACK_COUNT; i++)
{
UpdateSoundtrack(&g->soundtracks[i]);
}
UpdateMouse(&g->mouse, &g->camera);
UpdateCamera2D(&g->camera, &g->player.physics.position, &g->mouse);
UpdateFloor(&g->floor, &g->camera);
UpdatePlayer(&g->player);
UpdateBee(&g->bee1, &g->flowers, &g->hive);
}
void RenderComponents(GameState *g)
{
RenderFloor(&g->floor);
RenderSprite(&g->hive.sprite);
RenderObjectArray(&g->flowers);
RenderSprite(&g->player.sprite);
RenderSprite(&g->bee1.sprite);
}
void RenderGame(GameState *g, const State *appState)
{
BeginTextureMode(g->target);
ClearBackground(BLACK);
BeginMode2D(g->camera);
RenderComponents(g);
EndMode2D();
DrawTextureRec(g->mouse.cursorTexture, (Rectangle){0, 0, g->mouse.cursorTexture.width, g->mouse.cursorTexture.height}, (Vector2){g->mouse.screenPosition.x, g->mouse.screenPosition.y}, WHITE);
EndTextureMode();
BeginDrawing();
ClearBackground(BLACK);
for (int i = 0; i < SHADER_COUNT; i++)
{
RenderPostFX(&g->postFX[i], &g->target);
}
DrawText(TextFormat("%d", g->player.inventar.seedCount), 10, 10, 50, WHITE);
if (appState->flagFPS)
{
DrawFPS(10, 10);
}
EndDrawing();
}
void CleanupGame(GameState *g)
{
for (int i = 0; i < SHADER_COUNT; i++)
{
UnloadPostFX(&g->postFX[i]);
}
for (int i = 0; i < TEX_COUNT; i++)
{
if (g->textures[i].id > 0)
{
UnloadTexture(g->textures[i]);
}
}
for (int i = 0; i < SOUNDTRACK_COUNT; i++)
{
UnloadMusicStream(g->soundtracks[i].music);
}
UnloadRenderTexture(g->target);
free(g->flowers.data);
}
#endif // GAME_H
+54
View File
@@ -0,0 +1,54 @@
#ifndef GAMEASSETS_H
#define GAMEASSETS_H
#include <asset.h>
////////////////////////////////////////////////////////////////////////////
typedef enum
{
PLAYER,
PLAYER_ACTIONS,
TOOLS,
FLOWER,
BEE,
GRASS,
HIVE,
CURSOR,
TEX_COUNT
} TextureID;
const TextureAsset texAssets[TEX_COUNT] = {
{"assets/SproutLandsBasic/Characters/character.png", 48.0f, 48.0f, 0.0f},
{"assets/SproutLandsBasic/Characters/BasicCharakterActions.png", 48.0f, 48.0f, 0.0f},
{"assets/SproutLandsBasic/Objects/tools.png", 48.0f, 16.0f, 0.0f},
{"assets/flower.png", 16.0f, 16.0f, 45.0f},
{"assets/character_bee.png", 16.0f, 16.0f, 0.0f},
{"assets/grass.png", 16.0f, 16.0f, 0.0f},
{"assets/hive.png", 32.0f, 32.0f, 0.0f},
{"assets/SproutLandsUI/Spritesheets/Mouse sprites/TriangleMouseicon1.png", 16.0f, 16.0f, 0.0f}};
////////////////////////////////////////////////////////////////////////////
typedef enum
{
POST_FX,
SHADER_COUNT
} ShaderID;
const ShaderAsset shaderAssets[SHADER_COUNT] = {
{"shaders/postfx.fs"}};
////////////////////////////////////////////////////////////////////////////
typedef enum
{
BEE_AMBIENT,
SOUNDTRACK_COUNT
} SoundtrackID;
const SoundtrackAsset soundtrackAssets[SOUNDTRACK_COUNT] = {
{"assets/beez.mp3"}};
////////////////////////////////////////////////////////////////////////////
#endif // GAMEASSETS_H
+18
View File
@@ -0,0 +1,18 @@
#ifndef HIVE_H
#define HIVE_H
#include <object.h>
Object CreateHive(Texture2D texture, float frameWidth)
{
return (Object){
.sprite = {
.texture = texture,
.sourceRec = (Rectangle){0.0f, 0.0f, frameWidth, frameWidth},
.destRec = (Rectangle){0.0f, 0.0f, frameWidth, frameWidth},
.origin = (Vector2){frameWidth / 2, frameWidth / 2},
.rotation = 0.0f,
.color = WHITE},
.position = (Vector2){0.0f, 0.0f}};
}
#endif // HIVE_H
+9
View File
@@ -0,0 +1,9 @@
#ifndef INVENTAR_H
#define INVENTAR_H
typedef struct{
int seedCount;
} Inventar;
#endif // INVENTAR_H
+119
View File
@@ -0,0 +1,119 @@
#ifndef LOGO_H
#define LOGO_H
#include "applicationstate.h"
typedef struct {
int frameCounter;
int positionX;
int positionY;
int lettersCount;
int topSideRecWidth;
int leftSideRecHeight;
int bottomSideRecWidth;
int rightSideRecHeight;
int state;
float alpha;
} LogoState;
void InitLogo(LogoState *l) {
SetTargetFPS(60);
l->frameCounter = 0;
l->positionX = GetScreenWidth() / 2 - 128;
l->positionY = GetScreenHeight() / 2 - 128;
l->lettersCount = 0;
l->topSideRecWidth = 16;
l->leftSideRecHeight = 16;
l->bottomSideRecWidth = 16;
l->rightSideRecHeight = 16;
l->state = 0;
l->alpha = 1.0f;
}
void UpdateLogo(LogoState *l, State *state) {
if (WindowShouldClose() && !IsKeyPressed(KEY_ESCAPE)) {
state->running = false;
}
l->frameCounter++;
if (l->state == 0) {
if (l->frameCounter >= 120) {
l->state = 1;
l->frameCounter = 0;
}
}
else if (l->state == 1) {
l->topSideRecWidth += 4;
l->leftSideRecHeight += 4;
if (l->topSideRecWidth >= 256) {
l->state = 2;
l->frameCounter = 0;
}
}
else if (l->state == 2) {
l->bottomSideRecWidth += 4;
l->rightSideRecHeight += 4;
if (l->bottomSideRecWidth >= 256) {
l->state = 3;
l->frameCounter = 0;
}
}
else if (l->state == 3) {
if (l->frameCounter % 12 == 0) {
l->lettersCount++;
}
if (l->lettersCount >= 10) {
l->alpha -= 0.02f;
if (l->alpha <= 0.0f) {
l->alpha = 0.0f;
l->state = 4;
}
}
}
else if (l->state == 4) {
state->currentScreen = MENU;
}
}
void RenderLogo(const LogoState *l, const State *appState) {
BeginDrawing();
ClearBackground(RAYWHITE);
if (l->state == 0) {
if ((l->frameCounter / 15) % 2 == 0) {
DrawRectangle(l->positionX, l->positionY, 16, 16, BLACK);
}
}
else if (l->state == 1) {
DrawRectangle(l->positionX, l->positionY, l->topSideRecWidth, 16, BLACK);
DrawRectangle(l->positionX, l->positionY, 16, l->leftSideRecHeight, BLACK);
}
else if (l->state == 2) {
DrawRectangle(l->positionX, l->positionY, l->topSideRecWidth, 16, BLACK);
DrawRectangle(l->positionX, l->positionY, 16, l->leftSideRecHeight, BLACK);
DrawRectangle(l->positionX + 240, l->positionY, 16, l->rightSideRecHeight, BLACK);
DrawRectangle(l->positionX, l->positionY + 240, l->bottomSideRecWidth, 16, BLACK);
}
else if (l->state == 3) {
DrawRectangle(l->positionX, l->positionY, l->topSideRecWidth, 16, Fade(BLACK, l->alpha));
DrawRectangle(l->positionX, l->positionY + 16, 16, l->leftSideRecHeight - 32, Fade(BLACK, l->alpha));
DrawRectangle(l->positionX + 240, l->positionY + 16, 16, l->rightSideRecHeight - 32, Fade(BLACK, l->alpha));
DrawRectangle(l->positionX, l->positionY + 240, l->bottomSideRecWidth, 16, Fade(BLACK, l->alpha));
DrawRectangle(GetScreenWidth() / 2 - 112, GetScreenHeight() / 2 - 112, 224, 224, Fade(RAYWHITE, l->alpha));
DrawText(TextSubtext("raylib", 0, l->lettersCount), GetScreenWidth() / 2 - 44, GetScreenHeight() / 2 + 48, 50, Fade(BLACK, l->alpha));
}
if (appState->flagFPS){
DrawFPS(10, 10);
}
EndDrawing();
}
#endif // LOGO_H
+179
View File
@@ -0,0 +1,179 @@
#ifndef MENU_H
#define MENU_H
#include <gui.h>
#include <asset.h>
#include <gamegui.h>
#include <input.h>
#include <soundtrack.h>
#include "applicationstate.h"
#include "menuassets.h"
#include "colors.h"
#include "background.h"
typedef struct
{
Assets assets;
Mouse mouse;
Texture2D textures[MENU_TEX_COUNT];
Sound sounds[MENU_SOUND_COUNT];
Soundtrack soundtracks[MENU_SOUNDTRACK_COUNT];
ImageElement board;
ImageButton playButton;
ImageButton quitButton;
int menuScale;
Background background;
Background midground;
Background foreground;
} MenuState;
void InitMenu(MenuState *m)
{
m->assets = (Assets){
.textureAssets = menuTextureAssets,
.soundAssets = menuSoundAssets,
.soundtrackAssets = menuSoundtrackAssets};
for (int i = 0; i < MENU_TEX_COUNT; i++)
{
m->textures[i] = LoadTexture(m->assets.textureAssets[i].path);
}
for (int i = 0; i < MENU_SOUND_COUNT; i++)
{
m->sounds[i] = LoadSound(m->assets.soundAssets[i].path);
}
for (int i = 0; i < MENU_SOUNDTRACK_COUNT; i++)
{
m->soundtracks[i] = LoadSoundtrack(m->assets.soundtrackAssets[i].path);
}
InitBackground(0.1f, &m->background, &m->textures[MENU_CLOUD_BACKGROUND], &m->assets.textureAssets[MENU_CLOUD_BACKGROUND]);
InitBackground(0.2f, &m->midground, &m->textures[MENU_CLOUD_MIDGROUND], &m->assets.textureAssets[MENU_CLOUD_MIDGROUND]);
InitBackground(0.3f, &m->foreground, &m->textures[MENU_CLOUD_FOREGROUND], &m->assets.textureAssets[MENU_CLOUD_FOREGROUND]);
m->mouse = CreateMouse(0.10f, 5.0f, 10.0f, &m->textures[MENU_CURSOR_TEX]);
m->menuScale = 4;
int screenWidth = GetScreenWidth();
int screenHeight = GetScreenHeight();
Vector2 screenCenter = {screenWidth / 2, screenHeight / 2};
int boardWidth = screenWidth / m->menuScale * 2.5f;
float boardScaleFactor = (float)boardWidth / m->assets.textureAssets[MENU_BOARD_TEX].frameWidth;
int boardHeight = (int)(m->assets.textureAssets[MENU_BOARD_TEX].frameHeight * boardScaleFactor);
Vector2 boardSource = {128.0f, 0.0f};
Rectangle boardDestRec = {
.x = screenCenter.x - (boardWidth / 2),
.y = screenCenter.y - (boardHeight / 2),
.width = boardWidth,
.height = boardHeight};
m->board = CreateImageElement(&m->textures[MENU_BOARD_TEX], &m->assets.textureAssets[MENU_BOARD_TEX], &boardSource, &boardDestRec);
int buttonWidth = screenWidth / m->menuScale;
float buttonScaleFactor = (float)buttonWidth / m->assets.textureAssets[MENU_BIG_BUTTONS_TEX].frameWidth;
int buttonHeight = (int)(m->assets.textureAssets[MENU_BIG_BUTTONS_TEX].frameHeight * buttonScaleFactor);
int buttonSpacing = buttonHeight;
Vector2 playButtonNotPressed = {0.0f, 96.0f};
Vector2 quitButtonNotPressed = {0.0f, 0.0f};
Vector2 playButtonHover = {96.0f, 96.0f};
Vector2 quitButtonHover = {96.0f, 0.0f};
Vector2 playButtonPressed = {192.0f, 96.0f};
Vector2 quitButtonPressed = {192.0f, 0.0f};
Rectangle playButtonDestRec = {
.x = screenCenter.x - (buttonWidth / 2),
.y = screenCenter.y - (buttonHeight / 2),
.width = buttonWidth,
.height = buttonHeight};
Rectangle quitButtonDestRec = {
.x = screenCenter.x - (buttonWidth / 2),
.y = screenCenter.y - (buttonHeight / 2) + buttonSpacing,
.width = buttonWidth,
.height = buttonHeight};
m->playButton = CreateImageButton(NOT_CLICKED, &m->textures[MENU_BIG_BUTTONS_TEX], &m->assets.textureAssets[MENU_BIG_BUTTONS_TEX], &playButtonNotPressed, &playButtonPressed, &playButtonHover, &playButtonDestRec);
m->quitButton = CreateImageButton(NOT_CLICKED, &m->textures[MENU_BIG_BUTTONS_TEX], &m->assets.textureAssets[MENU_BIG_BUTTONS_TEX], &quitButtonNotPressed, &quitButtonPressed, &quitButtonHover, &quitButtonDestRec);
}
void UpdateMenu(MenuState *m, State *state)
{
for (int i = 0; i < MENU_SOUNDTRACK_COUNT; i++)
{
UpdateSoundtrack(&m->soundtracks[i]);
}
UpdateBackground(&m->background);
UpdateBackground(&m->midground);
UpdateBackground(&m->foreground);
UpdateMouseScreen(&m->mouse);
if (isImageButtonClicked(&m->playButton, m->sounds[HOVER_SOUND], m->sounds[CLICK_SOUND]))
{
state->gameStarted = true;
state->currentScreen = GAMEPLAY;
}
if (isImageButtonClicked(&m->quitButton, m->sounds[HOVER_SOUND], m->sounds[CLICK_SOUND]) || (WindowShouldClose() && !IsKeyPressed(KEY_ESCAPE)))
{
state->running = false;
}
}
void RenderMenu(MenuState *m, State *appState, Font *font, const char *title)
{
BeginDrawing();
ClearBackground(WHITE);
RenderBackground(&m->background);
RenderBackground(&m->midground);
RenderBackground(&m->foreground);
renderImageElement(&m->board);
renderImageButton(&m->playButton);
renderImageButton(&m->quitButton);
int textWidth = MeasureText(title, font->baseSize);
DrawTextEx(*font, title, (Vector2){GetScreenWidth() / 2 - textWidth / 2, textWidth / 4}, (float)font->baseSize, 2, WHITE);
DrawTexturePro(
m->mouse.cursorTexture,
(Rectangle){0, 0, m->mouse.cursorTexture.width, m->mouse.cursorTexture.height},
(Rectangle){m->mouse.screenPosition.x, m->mouse.screenPosition.y, m->mouse.cursorTexture.width, m->mouse.cursorTexture.height},
(Vector2){0.0f, 0.0f},
0.0f,
WHITE);
if (appState->flagFPS)
{
DrawFPS(10, 10);
}
EndDrawing();
}
void CleanupMenu(MenuState *m)
{
for (int i = 0; i < MENU_SOUND_COUNT; i++)
{
UnloadSound(m->sounds[i]);
}
for (int i = 0; i < MENU_TEX_COUNT; i++)
{
if (m->textures[i].id > 0)
{
UnloadTexture(m->textures[i]);
}
}
for (int i = 0; i < MENU_SOUNDTRACK_COUNT; i++)
{
UnloadMusicStream(m->soundtracks[i].music);
}
}
#endif // MENU_H
+44
View File
@@ -0,0 +1,44 @@
#ifndef MENUASSETS_H
#define MENUASSETS_H
#include <asset.h>
typedef enum
{
MENU_CURSOR_TEX,
MENU_BIG_BUTTONS_TEX,
MENU_BOARD_TEX,
MENU_CLOUD_BACKGROUND,
MENU_CLOUD_MIDGROUND,
MENU_CLOUD_FOREGROUND,
MENU_TEX_COUNT
} MenuTextureID;
const TextureAsset menuTextureAssets[MENU_TEX_COUNT] = {
{"assets/SproutLandsUI/Spritesheets/Mouse sprites/TriangleMouseicon1.png", 16.0f, 16.0f, 0.0f},
{"assets/SproutLandsUI/Spritesheets/UIBigPlayButtonHover.png", 96.0f, 32.0f, 0.0f},
{"assets/SproutLandsUI/Spritesheets/Settingmenu.png", 128.0f, 144.0f, 0.0f},
{"assets/Clouds/Clouds1/1.png", 576.0f, 324.0f, 0.0f},
{"assets/Clouds/Clouds1/2.png", 576.0f, 324.0f, 0.0f},
{"assets/Clouds/Clouds1/4.png", 576.0f, 324.0f, 0.0f}};
typedef enum
{
MENU_MUSIC,
MENU_SOUNDTRACK_COUNT
} MenuSoundtrackID;
const SoundtrackAsset menuSoundtrackAssets[MENU_SOUNDTRACK_COUNT] = {
{"assets/merrygoround.wav"}};
typedef enum
{
HOVER_SOUND,
CLICK_SOUND,
MENU_SOUND_COUNT
} MenuSoundID;
const SoundAsset menuSoundAssets[MENU_SOUND_COUNT] = {
{"assets/audio/WAV/Minimalist1.wav"},
{"assets/audio/WAV/Abstract1.wav"}};
#endif // MENUASSETS_H
+146
View File
@@ -0,0 +1,146 @@
#ifndef PLAYER_H
#define PLAYER_H
#include <sprite.h>
#include <animation.h>
#include <physics.h>
#include <input.h>
#include "inventar.h"
typedef enum
{
IDLE,
WALKING,
USING_TOOL
} PlayerState;
typedef enum
{
NO_TOOL,
HOE,
AXT,
CAN
} SelectedTool;
typedef enum
{
IDLE_DOWN,
IDLE_UP,
IDLE_LEFT,
IDLE_RIGHT,
WALKING_DOWN,
WALKING_UP,
WALKING_LEFT,
WALKING_RIGHT,
HOE_DOWN,
HOE_UP,
HOE_RIGHT,
HOE_LEFT,
AXT_DOWN,
AXT_UP,
AXT_RIGHT,
AXT_LEFT,
CAN_DOWN,
CAN_UP,
CAN_RIGHT,
CAN_LEFT,
} PlayerAnimationState;
typedef struct
{
SelectedTool selectedTool;
Sprite sprite;
Animation animation;
Physics physics;
Inventar inventar;
} Player;
Player CreatePlayer(PlayerAnimationState animState, SelectedTool selectedTool, Texture2D texture, float frameWidth, int maxFrame, int framesSpeed, Vector2 startPosition, float rotation, float speed)
{
return (Player){
.selectedTool = selectedTool,
.sprite = {
.texture = texture,
.frameSize = {frameWidth, frameWidth},
.sourceRec = {0.0f, 0.0f, frameWidth, frameWidth},
.destRec = {0.0f, 0.0f, frameWidth, frameWidth},
.origin = {frameWidth / 2, frameWidth / 2},
.rotation = rotation,
.color = WHITE},
.animation = {.state = animState, .currentFrame = 0, .maxFrame = maxFrame, .framesCounter = 0, .framesSpeed = framesSpeed, .animTimer = 0.0f},
.physics = {.position = startPosition, .direction = (Vector2){0.0f, 0.0f}, .speed = speed},
.inventar = {.seedCount = 6}};
}
void UpdatePlayerAnimationState(int *state, SelectedTool *selectedTool, Vector2 *dir)
{
if (IsKeyPressed(KEY_ZERO))
{
*selectedTool = NO_TOOL;
}
if (IsKeyPressed(KEY_ONE))
{
*selectedTool = HOE;
}
if (IsKeyPressed(KEY_TWO))
{
*selectedTool = AXT;
}
if (IsKeyPressed(KEY_THREE))
{
*selectedTool = CAN;
}
if (dir->x == 0 && dir->y == 0)
{
switch (*state)
{
case WALKING_DOWN:
*state = IDLE_DOWN;
break;
case WALKING_UP:
*state = IDLE_UP;
break;
case WALKING_LEFT:
*state = IDLE_LEFT;
break;
case WALKING_RIGHT:
*state = IDLE_RIGHT;
break;
default:
break;
}
}
else
{
if (dir->y == 1)
*state = WALKING_DOWN;
else if (dir->y == -1)
*state = WALKING_UP;
else if (dir->x == -1)
*state = WALKING_LEFT;
else if (dir->x == 1)
*state = WALKING_RIGHT;
}
}
void UpdatePlayer(Player *player)
{
if (IsKeyPressed(KEY_SPACE) && player->inventar.seedCount > 0)
{
player->inventar.seedCount--;
}
Vector2 dir = GetDirectionVector();
UpdatePlayerAnimationState(&player->animation.state, &player->selectedTool, &dir);
UpdatePhysics(&player->physics, dir);
UpdateSpriteDestRec(&player->sprite, &player->physics.position);
UpdateAnimation(&player->animation, GetFrameTime());
UpdateSpriteSourceRec(&player->sprite, &(Vector2){player->sprite.frameSize.x * player->animation.currentFrame, player->sprite.frameSize.y * player->animation.state});
}
#endif // PLAYER_H
-5932
View File
File diff suppressed because it is too large Load Diff
-2966
View File
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
#ifndef SCREEN_H
#define SCREEN_H
typedef enum Screen {
LOGO = 0,
MENU = 1,
GAMEPLAY = 2
} Screen;
#endif // SCREEN_H