big refactor

This commit is contained in:
huaqo-games
2025-03-17 19:28:12 +01:00
parent 990cdc6e50
commit 2f4dc166ee
31 changed files with 6657 additions and 322 deletions
+28
View File
@@ -0,0 +1,28 @@
#ifndef ANIMATION_H
#define ANIMATION_H
typedef struct {
int currentFrame;
int maxFrame;
int framesCounter;
int framesSpeed;
float animTimer;
} Animation;
void UpdateAnimation(Animation *animation, float deltaTime) {
animation->animTimer += deltaTime;
float frameTime = 1.0f / animation->framesSpeed;
if (animation->animTimer < frameTime) {
return;
}
animation->animTimer -= frameTime;
animation->currentFrame++;
if (animation->currentFrame >= animation->maxFrame) {
animation->currentFrame = 0;
}
}
#endif // ANIMATION_H
+29
View File
@@ -0,0 +1,29 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "input.h"
Camera2D CreateCamera(int screenWidth, int screenHeight, Vector2 playerPosition, float initZoom){
return (Camera2D){
.offset = (Vector2){screenWidth / 2.0f, screenHeight / 2.0f},
.target = playerPosition,
.rotation = 0.0f,
.zoom = initZoom
};
}
void UpdateCameraTarget(Camera2D *camera, Vector2 *position, const float smoothness){
camera->target = Vector2Lerp(camera->target, *position, smoothness * GetFrameTime());
}
void UpdateCameraZoom(Camera2D *camera, const float *scaleFactor, const float *minZoom, const float *maxZoom){
float targetZoom = Clamp(camera->zoom * *scaleFactor, *minZoom, *maxZoom);
camera->zoom = Lerp(camera->zoom, targetZoom, 0.1f);
}
void UpdateCamera2D(Camera2D* camera, Vector2* position, Mouse* mouse){
UpdateCameraTarget(camera, position, 5.0f);
UpdateCameraZoom(camera, &mouse->scaleFactor, &mouse->minZoom, &mouse->maxZoom);
}
#endif // CAMERA_H
+29
View File
@@ -0,0 +1,29 @@
#ifndef GUI_H
#define GUI_H
#define RAYGUI_IMPLEMENTATION
#include "../include/raygui.h"
typedef struct
{
Rectangle rec;
const char *text;
} Button;
void initButton(Button *b, const char *text, int buttonWidth, int buttonHeight, int buttonPosX, int buttonPosY)
{
b->rec = (Rectangle){buttonPosX - buttonWidth / 2, buttonPosY - buttonHeight / 2, buttonWidth, buttonHeight};
b->text = text;
}
int isButtonClicked(Button *b)
{
return (CheckCollisionPointRec(GetMousePosition(), b->rec) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON));
}
void renderButton(Button *b)
{
GuiButton(b->rec, b->text);
}
#endif // GUI_H
+48
View File
@@ -0,0 +1,48 @@
#ifndef INPUT_H
#define INPUT_H
typedef struct {
Vector2 worldPosition;
float zoomSpeed;
float minZoom;
float maxZoom;
float scaleFactor;
float wheelMove;
bool leftButton;
bool rightButton;
} Mouse;
Mouse CreateMouse(float zoomSpeed, float minZoom, float maxZoom){
return (Mouse){
.zoomSpeed = zoomSpeed,
.minZoom = minZoom,
.maxZoom = maxZoom
};
}
void UpdateMouse(Mouse *mouse, Camera2D *camera) {
mouse->worldPosition = GetScreenToWorld2D(GetMousePosition(), *camera);
mouse->leftButton = IsMouseButtonDown(MOUSE_LEFT_BUTTON);
mouse->rightButton = IsMouseButtonDown(MOUSE_RIGHT_BUTTON);
// Calculate zoom scale factor
mouse->wheelMove = GetMouseWheelMove();
if (mouse->wheelMove != 0) {
float zoomFactor = 1.0f + (mouse->zoomSpeed * fabsf(mouse->wheelMove));
mouse->scaleFactor = (mouse->wheelMove < 0) ? (1.0f / zoomFactor) : zoomFactor;
} else {
mouse->scaleFactor = 1.0f;
}
}
Vector2 GetDirectionVector(void){
Vector2 vector = {.x = 0.0f, .y = 0.0f};
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)){vector.x += 1.0f; }
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)){ vector.x -= 1.0f; }
if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)){ vector.y += 1.0f; }
if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ vector.y -= 1.0f; }
if (Vector2Length(vector) > 0.0f) {vector = Vector2Normalize(vector); }
return vector;
}
#endif //INPUT_H
+23
View File
@@ -0,0 +1,23 @@
#ifndef MUSICMANAGER_H
#define MUSICMANAGER_H
typedef struct {
Music music;
bool playing;
} MyMusic;
MyMusic CreateMusic(char* musicPath){
MyMusic music = {
.music = LoadMusicStream(musicPath),
.playing = 0
};
PlayMusicStream(music.music);
return music;
}
void UpdateMusic(MyMusic* music){
UpdateMusicStream(music->music);
}
#endif // MUSICMANAGER_H
+129
View File
@@ -0,0 +1,129 @@
#ifndef OBJECT_H
#define OBJECT_H
#include "sprite.h"
#include "vector.h"
typedef struct {
Sprite sprite;
Vector2 position;
} Object;
typedef struct {
Object *data;
const Object *prototype;
size_t count;
} ObjectArray;
ObjectArray CreateObjectArray(const Object *prototype, const size_t count) {
ObjectArray objects = {0};
if (count == 0) {
printf("Objects size must be greater than 0.\n");
return objects;
}
objects.count = count;
objects.data = (Object* )malloc(count * sizeof(Object));
if (!objects.data) {
printf("Memory allocation of objects failed.\n");
return objects;
}
objects.prototype = prototype;
for (int i = 0; i < count; i++) {
objects.data[i].position = prototype->position;
objects.data[i].sprite = prototype->sprite;
}
return objects;
}
Object* GetRandomObject(ObjectArray *objects){
if (objects->count == 0 || objects->data == NULL) {
return NULL;
}
return &objects->data[GetRandomValue(0, (int)objects->count-1)];
}
void AddObjectToArray(ObjectArray *objects, const Object *prototype, Vector2 position) {
Object *newData = (Object* )realloc(objects->data, (objects->count + 1) * sizeof(Object));
if (newData) {
objects->data = newData;
objects->data[objects->count] = *prototype;
objects->data[objects->count].position = position;
objects->data[objects->count].sprite.destRec.x = position.x;
objects->data[objects->count].sprite.destRec.y = position.y;
objects->count++;
} else {
printf("Memory allocation failed while adding an object.\n");
}
}
void SetPositionForObjectArray(ObjectArray *objects, const Vector2Array *positions) {
if (positions->count != objects->count) {
printf("Warning: Position array size (%zu) does not match ObjectArray size (%zu)\n", positions->count, objects->count);
return;
}
for (size_t i = 0; i < objects->count; i++) {
objects->data[i].position = positions->data[i];
objects->data[i].sprite.destRec.x = positions->data[i].x;
objects->data[i].sprite.destRec.y = positions->data[i].y;
}
}
void SetRandomPositionForObjectArray(ObjectArray *objects, const Rectangle bounds){
for (int i = 0; i < objects->count; i++) {
Vector2 position = GetRandomVector(bounds);
objects->data[i].position = position;
objects->data[i].sprite.destRec.x = position.x;
objects->data[i].sprite.destRec.y = position.y;
}
}
void SwapAndPopObjectsArrayOnRecCollision(ObjectArray *objects, const Rectangle rec){
for (int i = 0; i < objects->count; i++){
if (CheckCollisionRecs(rec, objects->data[i].sprite.destRec)){
if (objects->count == 1) {
objects->count = 0;
break;
}
objects->data[i] = objects->data[objects->count - 1];
objects->count--;
i--;
}
}
objects->data = (Object*)realloc(objects->data, objects->count * sizeof(Object));
}
void SwapAndPopObjectsArrayOnPointCollision(ObjectArray *objects, const Vector2 point){
for (int i = 0; i < objects->count; i++){
if (CheckCollisionPointRec(point, objects->data[i].sprite.destRec)){
if (objects->count == 1) {
objects->count = 0;
break;
}
objects->data[i] = objects->data[objects->count - 1];
objects->count--;
i--;
}
}
objects->data = (Object*)realloc(objects->data, objects->count * sizeof(Object));
}
Vector2 GetDirectionToObject(Object *object, Vector2 position){
return Vector2Normalize(Vector2Subtract(object->position, position));
}
void RenderObjectArray(const ObjectArray *objects){
for (int i = 0; i < objects->count; i++){
RenderSprite(&objects->data[i].sprite);
}
}
#endif // OBJECT_H
+33
View File
@@ -0,0 +1,33 @@
#ifndef PHYSICS_H
#define PHYSICS_H
typedef struct {
Vector2 position;
Vector2 direction;
Vector2 velocity;
float speed;
} Physics;
void UpdatePhysicsDirection(Vector2 *direction, Vector2 vector){
*direction = vector;
}
void UpdatePhysicsVelocity(Vector2 *velocity, Vector2 *direction, float *speed){
*velocity = Vector2Scale(*direction, *speed * GetFrameTime());
}
void UpdatePhysicsPosition(Vector2 *position, Vector2 *velocity) {
*position = Vector2Add(*position, *velocity);
}
void UpdatePhysicsSpeed(float *speed, float *newSpeed){
*speed = *newSpeed;
}
void UpdatePhysics(Physics *physics, Vector2 target){
UpdatePhysicsDirection(&physics->direction, target);
UpdatePhysicsVelocity(&physics->velocity, &physics->direction, &physics->speed);
UpdatePhysicsPosition(&physics->position, &physics->velocity);
}
#endif // PHYSICS_H
+10
View File
@@ -0,0 +1,10 @@
#ifndef SCREEN_H
#define SCREEN_H
typedef enum Screen {
LOGO = 0,
MENU,
GAMEPLAY
} Screen;
#endif // SCREEN_H
+10
View File
@@ -0,0 +1,10 @@
#ifndef SETTINGS_H
#define SETTINGS_H
typedef struct {
int screenWidth;
int screenHeight;
const char* name;
} Settings;
#endif // SETTINGS_H
+40
View File
@@ -0,0 +1,40 @@
#ifndef SHADER_H
#define SHADER_H
typedef struct {
Shader shader;
int resolutionLoc;
int strengthLoc;
float strength;
} VignetteShader;
VignetteShader CreateShader(const char* shaderPath, float strength){
VignetteShader vignetteShader = {0};
vignetteShader.shader = LoadShader(NULL, shaderPath);
if (vignetteShader.shader.id == 0) {
TraceLog(LOG_ERROR, "Failed to load shader: %s", shaderPath);
return vignetteShader;
}
vignetteShader.strength = strength;
vignetteShader.resolutionLoc = GetShaderLocation(vignetteShader.shader, "resolution");
vignetteShader.strengthLoc = GetShaderLocation(vignetteShader.shader, "strength");
Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() };
SetShaderValue(vignetteShader.shader, vignetteShader.resolutionLoc, &resolution, SHADER_UNIFORM_VEC2);
return vignetteShader;
}
void UpdateShader(VignetteShader* vignetteShader){
if (vignetteShader->shader.id == 0) return;
SetShaderValue(vignetteShader->shader, vignetteShader->strengthLoc, &vignetteShader->strength, SHADER_UNIFORM_FLOAT);
Vector2 resolution = { (float)GetScreenWidth(), (float)GetScreenHeight() };
SetShaderValue(vignetteShader->shader, vignetteShader->resolutionLoc, &resolution, SHADER_UNIFORM_VEC2);
}
void UnloadVignetteShader(VignetteShader* vignetteShader){
if (vignetteShader->shader.id == 0) return;
UnloadShader(vignetteShader->shader);
}
#endif // SHADER_H
+43
View File
@@ -0,0 +1,43 @@
#ifndef SPRITE_H
#define SPRITE_H
typedef struct {
Texture2D texture;
Rectangle sourceRec;
Rectangle destRec;
Vector2 frameSize;
Vector2 origin;
float rotation;
Color color;
} Sprite;
void UpdateSpriteSourceRec(Sprite *sprite, const Vector2 *vector){
sprite->sourceRec.x = vector->x;
sprite->sourceRec.y = vector->y;
}
void UpdateSpriteDestRec(Sprite *sprite, const Vector2 *vector){
sprite->destRec.x = vector->x;
sprite->destRec.y = vector->y;
}
void UpdateSpriteRotation(Sprite *sprite, Vector2 *vector){
if(Vector2Length(*vector) <= 0.0f){
return;
}
float targetRotation = (float)atan2(vector->y, vector->x) * (180.0f / PI) + 90.0f;
sprite->rotation = Lerp(sprite->rotation, targetRotation, 0.1f);
}
void RenderSprite(const Sprite *sprite){
DrawTexturePro(
sprite->texture,
sprite->sourceRec,
sprite->destRec,
sprite->origin,
sprite->rotation,
sprite->color
);
}
#endif // SPRITE_H
+21
View File
@@ -0,0 +1,21 @@
#ifndef VECTOR_H
#define VECTOR_H
typedef struct {
Vector2 *data;
size_t count;
} Vector2Array;
bool IsVectorZero(Vector2 v) {
float epsilon = 0.01f;
return (fabs(v.x) < epsilon && fabs(v.y) < epsilon);
}
Vector2 GetRandomVector(const Rectangle bounds) {
return (Vector2){
bounds.x + (float)GetRandomValue(0, 10000) / 10000.0f * bounds.width,
bounds.y + (float)GetRandomValue(0, 10000) / 10000.0f * bounds.height
};
}
#endif // VECTOR_H
+8
View File
@@ -0,0 +1,8 @@
- Naturschuetzer in einem Brachland
- Jahreszeiten -> mehrere Generationen von Bienenstaemmen
- Kasten sauber machen
- 1. Samen saehen
- 2. Zuckerwasser aufstellen
- 3. Kaesten aufstellen
- 4. Baueme pflanzen
+72
View File
@@ -0,0 +1,72 @@
#ifndef BEE_H
#define BEE_H
#include "../engine/sprite.h"
#include "../engine/animation.h"
#include "../engine/physics.h"
#include "../engine/object.h"
typedef struct {
Sprite sprite;
Animation animation;
Physics physics;
Object target;
Object hive;
int flowerCount;
} Bee;
Bee CreateBee(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 = {
.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->sprite.frameSize.x * bee->animation.currentFrame});
}
#endif // BEE_H
+44
View File
@@ -0,0 +1,44 @@
#ifndef Floor_H
#define Floor_H
#include "../engine/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
+29
View File
@@ -0,0 +1,29 @@
#ifndef FLOWERS_H
#define FLOWERS_H
#include "../engine/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
+94
View File
@@ -0,0 +1,94 @@
#ifndef GAME_H
#define GAME_H
#include "../engine/object.h"
#include "../engine/camera.h"
#include "../engine/input.h"
#include "../engine/shader.h"
#include "../engine/musicmanager.h"
#include "floor.h"
#include "player.h"
#include "bee.h"
#include "hive.h"
#include "flowers.h"
typedef struct {
VignetteShader vignetteShader;
MyMusic ambient;
RenderTexture2D target;
Texture2D flowerTexture, beeTexture, floorTexture, hiveTexture;
Floor floor;
Object hive;
ObjectArray flowers;
Player player;
Bee bee1;
Camera2D camera;
Mouse mouse;
} GameState;
void initGame(GameState* g){
InitAudioDevice();
g->vignetteShader = CreateShader("shaders/vignette.fs", 0.3f);
g->ambient = CreateMusic("assets/beez.mp3");
g->target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight());
g->flowerTexture = LoadTexture("assets/flower.png");
g->beeTexture = LoadTexture("assets/character_bee.png");
g->floorTexture = LoadTexture("assets/grass.png");
g->hiveTexture = LoadTexture("assets/hive.png");
g->floor = CreateFloor(g->floorTexture, 16.0f);
g->flowers = CreateFlowers(g->flowerTexture, 16.0f, 45.0f, 50.0f);
g->hive = CreateHive(g->hiveTexture, 32.0f);
g->player = CreatePlayer(g->beeTexture, 16.0f, 4, 10, g->hive.position, 50.0f);
g->bee1 = CreateBee(g->beeTexture, 16.0f, 4, 10, g->hive.position, 10.0f, &g->flowers, &g->hive);
g->camera = CreateCamera(GetScreenWidth(), GetScreenHeight(), g->player.physics.position, 10.0f);
g->mouse = CreateMouse(0.10f, 5.0f, 10.0f);
}
void updateGame(GameState* g){
UpdateShader(&g->vignetteShader);
UpdateMusic(&g->ambient);
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 renderGame(GameState* g){
BeginTextureMode(g->target);
ClearBackground(BLACK);
BeginMode2D(g->camera);
RenderFloor(&g->floor);
RenderSprite(&g->hive.sprite);
RenderObjectArray(&g->flowers);
RenderSprite(&g->bee1.sprite);
RenderSprite(&g->player.sprite);
EndMode2D();
EndTextureMode();
BeginDrawing();
ClearBackground(BLACK);
BeginShaderMode(g->vignetteShader.shader);
DrawTextureRec(g->target.texture, (Rectangle){ 0, 0, g->target.texture.width, -g->target.texture.height }, (Vector2){ 0, 0 }, WHITE);
EndShaderMode();
DrawFPS(10, 10);
EndDrawing();
}
void cleanupGame(GameState* g){
UnloadVignetteShader(&g->vignetteShader);
UnloadRenderTexture(g->target);
UnloadTexture(g->floorTexture);
UnloadTexture(g->hiveTexture);
UnloadTexture(g->flowerTexture);
UnloadTexture(g->beeTexture);
UnloadMusicStream(g->ambient.music);
free(g->flowers.data);
CloseAudioDevice();
}
#endif // GAME_H
+19
View File
@@ -0,0 +1,19 @@
#ifndef HIVE_H
#define HIVE_H
#include "../engine/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
+110
View File
@@ -0,0 +1,110 @@
#ifndef LOGO_H
#define LOGO_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, Screen *currentScreen) {
l->frameCounter++; // Increment the frame counter each frame
if (l->state == 0) { // State 0: Small box blinking for 120 frames (2 seconds at 60 FPS)
if (l->frameCounter >= 120) {
l->state = 1;
l->frameCounter = 0; // Reset frame counter
}
}
else if (l->state == 1) { // State 1: Top and left bars growing
l->topSideRecWidth += 4;
l->leftSideRecHeight += 4;
if (l->topSideRecWidth >= 256) {
l->state = 2;
l->frameCounter = 0;
}
}
else if (l->state == 2) { // State 2: Bottom and right bars growing
l->bottomSideRecWidth += 4;
l->rightSideRecHeight += 4;
if (l->bottomSideRecWidth >= 256) {
l->state = 3;
l->frameCounter = 0;
}
}
else if (l->state == 3) { // State 3: Letters appearing
if (l->frameCounter % 12 == 0) { // Every 12 frames, one more letter appears
l->lettersCount++;
}
if (l->lettersCount >= 10) { // Fade out animation
l->alpha -= 0.02f;
if (l->alpha <= 0.0f) {
l->alpha = 0.0f;
l->state = 4;
}
}
}
else if (l->state == 4) { // State 4: Transition to GAMEPLAY
SetTargetFPS(0);
*currentScreen = MENU;
}
}
void renderLogo(const LogoState *l) {
BeginDrawing();
ClearBackground(RAYWHITE);
if (l->state == 0) { // Small box blinking
if ((l->frameCounter / 15) % 2 == 0) { // Blink every 15 frames
DrawRectangle(l->positionX, l->positionY, 16, 16, BLACK);
}
}
else if (l->state == 1) { // Top and left bars growing
DrawRectangle(l->positionX, l->positionY, l->topSideRecWidth, 16, BLACK);
DrawRectangle(l->positionX, l->positionY, 16, l->leftSideRecHeight, BLACK);
}
else if (l->state == 2) { // Bottom and right bars growing
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) { // Letters appearing
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));
}
EndDrawing();
}
#endif // LOGO_H
+27
View File
@@ -0,0 +1,27 @@
#ifndef MENU_H
#define MENU_H
#include "../engine/gui.h"
typedef struct {
Button startButton;
} MenuState;
void initMenu(MenuState *t){
initButton(&t->startButton, "Start Game", GetScreenWidth() / 10, GetScreenHeight() / 20, GetScreenWidth() / 2, GetScreenHeight() / 2);
}
void updateMenu(MenuState *t, Screen *currentScreen){
if (isButtonClicked(&t->startButton)) {
*currentScreen = GAMEPLAY;
}
}
void renderMenu(MenuState *t){
BeginDrawing();
ClearBackground(WHITE);
renderButton(&t->startButton);
EndDrawing();
}
#endif // MENU_H
+48
View File
@@ -0,0 +1,48 @@
#ifndef PLAYER_H
#define PLAYER_H
#include "../engine/sprite.h"
#include "../engine/animation.h"
#include "../engine/physics.h"
#include "../engine/input.h"
typedef struct {
Sprite sprite;
Animation animation;
Physics physics;
} Player;
Player CreatePlayer(Texture2D texture, float frameWidth, int maxFrame, int framesSpeed, Vector2 startPosition, float speed){
return (Player){
.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 = {
.currentFrame = 0,
.maxFrame = maxFrame,
.framesCounter = 0,
.framesSpeed = framesSpeed,
.animTimer = 0.0f
},
.physics = {
.position = startPosition,
.direction = (Vector2){0.0f,0.0f},
.speed = speed
}
};
}
void UpdatePlayer(Player* player){
UpdatePhysics(&player->physics, GetDirectionVector());
UpdateSpriteRotation(&player->sprite, &player->physics.direction);
UpdateSpriteDestRec(&player->sprite, &player->physics.position);
UpdateAnimation(&player->animation, GetFrameTime());
UpdateSpriteSourceRec(&player->sprite, &(Vector2){player->sprite.frameSize.x, player->sprite.frameSize.x * player->animation.currentFrame});
}
#endif // PLAYER_H
+5928
View File
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
#include <raylib.h>
#include <raymath.h>
#include <stdio.h>
#include <stdlib.h>
#include "engine/screen.h"
#include "engine/settings.h"
#include "game/logo.h"
#include "game/menu.h"
#include "game/game.h"
int main(void)
{
Settings settings = {
.name = "The Last Hive",
.screenWidth = 1280,
.screenHeight = 720
};
InitWindow(settings.screenWidth, settings.screenHeight, settings.name);
Screen currentScreen = LOGO;
LogoState logo;
GameState game;
MenuState menu;
initLogo(&logo);
initMenu(&menu);
initGame(&game);
while (!WindowShouldClose())
{
switch (currentScreen)
{
case LOGO:
{
updateLogo(&logo,&currentScreen);
renderLogo(&logo);
}break;
case MENU:
{
updateMenu(&menu, &currentScreen);
renderMenu(&menu);
}break;
case GAMEPLAY:
{
updateGame(&game);
renderGame(&game);
}break;
default: break;
}
}
cleanupGame(&game);
CloseWindow();
return 0;
}