tempsdedl
This commit is contained in:
parent
8c26c84821
commit
39b998d62b
290
idea/chaosDungeon.md
Normal file
290
idea/chaosDungeon.md
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
# World of Chaos : Dungeon and Knowledge
|
||||||
|
|
||||||
|
First level should be a very hard wave defense where you need to lose, but the difficulty go higher until the player cannot defend it anymore.
|
||||||
|
|
||||||
|
Add effect for item drop or mob drop for rarity with special sound and effect for legendary one.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 1. Game Overview
|
||||||
|
|
||||||
|
- Name-> World of Chaos : Dungeon and Knowledge
|
||||||
|
|
||||||
|
- Genre-> Real-time Survival Base-Builder & Defense with Sandbox Construction, Tech-Tree Progression, Wave Survival, Dungeon-Crawl
|
||||||
|
- Platform-> Desktop (Windows, Linux)
|
||||||
|
- Perspective-> 2D Top-Down, Tile-Based
|
||||||
|
- Core Experience-> Fast-paced, responsive building + combat (akin to MOBA/RTS), layered loops reward both planning (base, tech) and moment-to-moment skill (aim, positioning).
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 2. High-Level Concept
|
||||||
|
|
||||||
|
- MVP Vision:
|
||||||
|
|
||||||
|
- Sandbox Build Mode: Place walls, turrets, resource-gatherers on a grid.
|
||||||
|
|
||||||
|
- Defense Loop: Survive waves of enemies attacking your base.
|
||||||
|
|
||||||
|
- Round Survival Loop: Fixed-arena rounds with escalating difficulty.
|
||||||
|
|
||||||
|
- Dungeon Crawl Loop: Enter procedural dungeon, defeat boss; failure sends boss to assault your base in next wave.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- USP (Unique Selling Points):
|
||||||
|
|
||||||
|
- Four interlocking loops: your dungeon success directly impacts base defense.
|
||||||
|
|
||||||
|
- Deep tech-tree: unlock new defenses, units, dungeon skills.
|
||||||
|
|
||||||
|
- Responsive, omnidirectional movement & aiming—skill matters.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 3. Core Gameplay Mechanics
|
||||||
|
|
||||||
|
- Movement & Combat:
|
||||||
|
- 8-directional movement.
|
||||||
|
- real-time aiming with mouse.
|
||||||
|
- instant feedback on attacks & blocks.
|
||||||
|
- Building:
|
||||||
|
- Grid-snapping placement.
|
||||||
|
- rotate/flip tiles.
|
||||||
|
- undo/redo.
|
||||||
|
- resource cost preview.
|
||||||
|
- Resources:
|
||||||
|
- Wood, Stone, Metal.
|
||||||
|
- gathered via structures or dungeon pickups.
|
||||||
|
- Tech Tree:
|
||||||
|
- Multi-branch:
|
||||||
|
- Base Defense.
|
||||||
|
- Resource Efficiency.
|
||||||
|
- Dungeon Skills.
|
||||||
|
- Elite Units.
|
||||||
|
- Enemy Waves:
|
||||||
|
- Scripted + procedural mix.
|
||||||
|
- includes fast scouts, heavy brutes, flying units.
|
||||||
|
- Dungeon:
|
||||||
|
- Procedural rooms.
|
||||||
|
- puzzles.
|
||||||
|
- minibosses.
|
||||||
|
- culminates in boss fight with unique mechanics.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 4. Game Loops
|
||||||
|
|
||||||
|
- Sandbox Build (Persistent): Place/upgrade structures; plan defenses.
|
||||||
|
|
||||||
|
- Defense Wave (Dynamic): Enemies pathfind toward base; survive until timer.
|
||||||
|
|
||||||
|
- Round Survival (Arena): Fixed map, randomized spawn points; earn bonus resources per round.
|
||||||
|
|
||||||
|
- Dungeon Crawl: Voluntary loop—risk vs. reward. Dungeon boss grants tech unlock on success; on failure, boss invades next wave.
|
||||||
|
|
||||||
|
- Opinion: Prioritize implementing the Defense Wave & Sandbox Build first—they form the spine of player engagement. Then layer in Round Survival. Dungeon Crawl can initially be a single hand-crafted level to prove the loop.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 5. MVP Feature List
|
||||||
|
|
||||||
|
- A. Core Systems (Week 1–3)
|
||||||
|
|
||||||
|
- Tilemap rendering & collision (raylib tilemap module)
|
||||||
|
|
||||||
|
- Player movement/aim/shoot
|
||||||
|
|
||||||
|
- Basic enemy AI (pathfinding to base)
|
||||||
|
|
||||||
|
- B. Building & Resources (Week 4–6)
|
||||||
|
|
||||||
|
- Place/destroy grid-aligned buildings
|
||||||
|
|
||||||
|
- Resource spawn & collection
|
||||||
|
|
||||||
|
- C. Wave Defense Loop (Week 7–9)
|
||||||
|
|
||||||
|
- Wave spawner, UI timer, win/lose conditions
|
||||||
|
|
||||||
|
- D. Tech Tree UI & Data (Week 10–11)
|
||||||
|
|
||||||
|
- Data-driven tech nodes, unlock logic, simple UI
|
||||||
|
|
||||||
|
- E. Round Survival & Score (Week 12–13)
|
||||||
|
|
||||||
|
- F. Dungeon Prototype (Week 14–16)
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 6. Tech-Tree Design
|
||||||
|
|
||||||
|
```
|
||||||
|
[Resource Efficiency]──┐
|
||||||
|
├─[Advanced Turrets]──[Energy Shield]
|
||||||
|
[Base Armor]───────────┘ │
|
||||||
|
├─[Boss Summon Tech]
|
||||||
|
[Trap Mastery]─────────┐ │
|
||||||
|
├─[Dungeon Vision]─────┘
|
||||||
|
[Spellcraft]───────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- Node Details:
|
||||||
|
|
||||||
|
- Cost in tech-points (earned per wave/dungeon).
|
||||||
|
|
||||||
|
- Prerequisites enforce meaningful choices.
|
||||||
|
|
||||||
|
- Strong opinion: cap tech depth to 15–20 nodes for MVP.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 7. Systems Architecture
|
||||||
|
|
||||||
|
- Language: C99
|
||||||
|
|
||||||
|
- Engine: raylib (windowing, input, 2D rendering, audio)
|
||||||
|
|
||||||
|
- Modules:
|
||||||
|
|
||||||
|
```
|
||||||
|
tilemap.c/h (grid, pathfinding)
|
||||||
|
|
||||||
|
player.c/h (movement, input)
|
||||||
|
|
||||||
|
entity.c/h (enemies, projectiles)
|
||||||
|
|
||||||
|
buildings.c/h (construction, upgrades)
|
||||||
|
|
||||||
|
waves.c/h (spawn logic)
|
||||||
|
|
||||||
|
dungeon.c/h (room gen, boss logic)
|
||||||
|
|
||||||
|
tech.c/h (tech-tree data & UI)
|
||||||
|
|
||||||
|
ui.c/h (HUD, menus)
|
||||||
|
```
|
||||||
|
|
||||||
|
- Data: JSON or simple CSV for wave definitions, tech nodes, tile properties.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 8. Controls & UI
|
||||||
|
|
||||||
|
- Controls:
|
||||||
|
|
||||||
|
- WASD or arrows: Move
|
||||||
|
|
||||||
|
- Mouse: Aim & shoot
|
||||||
|
|
||||||
|
- 1–5: Hotkeys for building types
|
||||||
|
|
||||||
|
- T: Open Tech Tree
|
||||||
|
|
||||||
|
- Esc: Menu/Pause
|
||||||
|
|
||||||
|
- UI Layout:
|
||||||
|
|
||||||
|
- Top-center: Wave timer & round
|
||||||
|
|
||||||
|
- Bottom-left: Resource counters
|
||||||
|
|
||||||
|
- Bottom-right: Build hotkeys
|
||||||
|
|
||||||
|
- Center-right: Tech-tree button
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 9. Art & Audio (MVP)
|
||||||
|
|
||||||
|
- Art Style: Simple, high-contrast tiles; clear readability over detail.
|
||||||
|
|
||||||
|
- Animations: 4-frame loops for player/enemies.
|
||||||
|
|
||||||
|
- Audio:
|
||||||
|
- Looping ambient track
|
||||||
|
|
||||||
|
- SFX: construction, shooting, enemy death
|
||||||
|
|
||||||
|
- Opinion: Defer polish art until gameplay is locked; use placeholders but ensure clarity.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 10. Success Metrics & KPIs
|
||||||
|
|
||||||
|
- Playtest Goal: Survive at least 5 waves with basic defenses.
|
||||||
|
|
||||||
|
- Performance: Stable 60 FPS on moderate hardware (Intel i5, integrated GPU).
|
||||||
|
|
||||||
|
- Engagement: Test loop—players should face meaningful choices every 30 s.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 11. Risks & Mitigations
|
||||||
|
|
||||||
|
```
|
||||||
|
Risk->Mitigation:
|
||||||
|
|
||||||
|
Pathfinding stalls on large maps->Limit map size; use A* with node caching
|
||||||
|
Feature creep (dungeon complexity)->Lock dungeon to 3 room types for MVP
|
||||||
|
Balancing tech-tree overpowered->Data-driven values; expose easy tuning parameters
|
||||||
|
```
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 12. Roadmap & Milestones
|
||||||
|
|
||||||
|
- Prototype (Weeks 1–3): Movement, tilemap, enemy pathfind.
|
||||||
|
|
||||||
|
- Alpha (Weeks 4–9): Building, resources, first 3 waves.
|
||||||
|
|
||||||
|
- Beta (Weeks 10–14): Tech tree, survival rounds, basic dungeon.
|
||||||
|
|
||||||
|
- MVP Release (Week 16): All loops functional; placeholder assets.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## 13. Next Steps
|
||||||
|
|
||||||
|
- Review GDD—prioritize any missing “must-have.”
|
||||||
|
|
||||||
|
- Scaffold C modules & basic raylib window.
|
||||||
|
|
||||||
|
- Implement tilemap + player movement immediately.
|
||||||
|
|
||||||
|
- Schedule weekly playtest to validate loops.
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
## how it started
|
||||||
|
|
||||||
|
I give myself 2 mounth to finish this project, the roadmap can be seen in roguelike_projecct_roadmap.md
|
||||||
|
|
||||||
|
the point is to challenge myself to finish a simple commercial game
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef struct {
|
||||||
|
int height, width;
|
||||||
|
float rotation;
|
||||||
|
} obstacle_hitbox;
|
||||||
|
```
|
||||||
|
___
|
||||||
|
|
||||||
|
## idea
|
||||||
|
|
||||||
|
- base building and defense (kinda more like terraria)
|
||||||
|
- dungeon exploration
|
||||||
|
- wave survival
|
||||||
|
- exploration ?
|
||||||
|
- hand crafted world no procedural (only dungeon using presets parts)
|
||||||
|
- using advanced shader using normal texture and depth of object top down 2D
|
||||||
|
|
||||||
|
- load level from tiled xml
|
||||||
|
- use tile in a 3D world, but only one layer with cartoon texture
|
||||||
|
|
||||||
|
___
|
||||||
|
|
||||||
|
### refs art:
|
||||||
|
|
||||||
|
- https://www.youtube.com/watch?v=R6vQ9VmMz2w
|
||||||
|
- https://www.youtube.com/watch?v=YVUPgiyB6iM
|
||||||
|
- https://www.youtube.com/watch?v=HsOKwUwL1bE
|
||||||
97
idea/roguelike_project_roadmap.md
Normal file
97
idea/roguelike_project_roadmap.md
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# 2D Roguelike with Dual Game Loops: Roadmap & Deadline
|
||||||
|
|
||||||
|
This document outlines a detailed plan to create a simple 2D roguelike in C using raylib, featuring two distinct game loops: defending your base against hordes and pillaging a dungeon.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Realistic Deadline Estimate
|
||||||
|
|
||||||
|
- **Overall Estimate:** **80–120 hours** of focused development time
|
||||||
|
*(This can be spread over several weeks if you’re working part time.)*
|
||||||
|
|
||||||
|
> **Note:**
|
||||||
|
> If you’re new to C/game development or raylib, you may want to extend this timeline by an additional 50% or more to cover learning curves and extra debugging.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Roadmap / To-Do List
|
||||||
|
|
||||||
|
### A. Pre-Production and Planning (8–12 hours)
|
||||||
|
- **Concept Design:**
|
||||||
|
- Define the core mechanics for both game loops:
|
||||||
|
- **Base Defense Mode:** Determine horde attack wave system, enemy behavior, and defensive structure mechanics.
|
||||||
|
- **Dungeon Pillaging Mode:** Decide on dungeon layout, exploration dynamics, enemy encounters, and reward systems.
|
||||||
|
- Sketch out game flow diagrams and state transitions between modes.
|
||||||
|
- **Feature List & Scope:**
|
||||||
|
- Create a brief design document outlining gameplay, UI, and any score/progression systems.
|
||||||
|
- Prioritize features (MVP vs. additional polish) to ensure core gameplay is functional.
|
||||||
|
- **Tool Setup:**
|
||||||
|
- Install and configure raylib.
|
||||||
|
- Set up your development environment (IDE, version control, build scripts).
|
||||||
|
|
||||||
|
### B. Prototyping Basic Framework (15–20 hours)
|
||||||
|
- **Project Setup:**
|
||||||
|
- Initialize a basic C project structure and integrate raylib.
|
||||||
|
- Create a main game loop with a game state manager to switch between modes.
|
||||||
|
- **Basic Game Loop Implementation:**
|
||||||
|
- Implement a splash screen or main menu for mode selection.
|
||||||
|
- Add stubs for each mode (base defense and dungeon) to verify mode switching.
|
||||||
|
- **Input and Rendering:**
|
||||||
|
- Set up event handling using raylib for keyboard/mouse input.
|
||||||
|
- Render simple shapes or sprites as placeholders for the player, enemies, and bases.
|
||||||
|
|
||||||
|
### C. Base Defense Mode Development (25–30 hours)
|
||||||
|
- **Game Mechanics:**
|
||||||
|
- Code enemy spawning and implement wave mechanics for base defense.
|
||||||
|
- Develop basic AI for enemy movement and targeting the base.
|
||||||
|
- **Player & Base Interactions:**
|
||||||
|
- Create defensive structures or player-controlled defenses.
|
||||||
|
- Implement collision detection between enemies and the base.
|
||||||
|
- **Visual Feedback:**
|
||||||
|
- Display base health/integrity.
|
||||||
|
- Include simple animations or state feedback (damage effects, score updates).
|
||||||
|
- **Testing and Iteration:**
|
||||||
|
- Continuously test and tweak enemy behavior, spawn rates, and difficulty.
|
||||||
|
|
||||||
|
### D. Dungeon Pillaging Mode Development (25–30 hours)
|
||||||
|
- **Dungeon Generation:**
|
||||||
|
- Design a simple procedural (or pre-defined) dungeon layout.
|
||||||
|
- Implement room transitions, corridors, or tile-based map structure.
|
||||||
|
- **Player Mechanics:**
|
||||||
|
- Code player movement, attacks, and possibly a simple inventory or item system.
|
||||||
|
- Define enemy encounters with a basic combat system and AI.
|
||||||
|
- **Environment Interactions:**
|
||||||
|
- Add interactive elements such as doors, traps, or treasure chests.
|
||||||
|
- Implement transitions between rooms or levels.
|
||||||
|
- **Basic Story/Progression Elements:**
|
||||||
|
- Integrate objectives like reaching a goal or collecting treasures.
|
||||||
|
- Consider power-ups or enhancements to influence later base defense rounds.
|
||||||
|
- **Testing and Iteration:**
|
||||||
|
- Playtest exploration, tweak enemy difficulty, and adjust dungeon layouts to ensure engagement.
|
||||||
|
|
||||||
|
### E. Integration, Polish, and Debugging (10–20 hours)
|
||||||
|
- **Integration:**
|
||||||
|
- Seamlessly connect the two modes so that players can transition between them.
|
||||||
|
- Implement transitions (e.g., carrying over score or narrative cues).
|
||||||
|
- **Polish:**
|
||||||
|
- Refine graphics and animations (using temporary assets if necessary).
|
||||||
|
- Add sound effects and background music for an improved player experience.
|
||||||
|
- **Debugging & Optimization:**
|
||||||
|
- Thoroughly playtest for bugs and balance gameplay.
|
||||||
|
- Optimize performance, particularly when managing multiple on-screen entities.
|
||||||
|
- **Final Touches:**
|
||||||
|
- Develop a simple scoring or progression system, if desired.
|
||||||
|
- Implement a basic UI for health, score, and game mode transitions.
|
||||||
|
|
||||||
|
### F. Buffer and Extra Time
|
||||||
|
- **Extra Time (Optional):** Reserve an additional **10–20%** of the total planned hours for unforeseen challenges or potential extra features.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Final Considerations
|
||||||
|
|
||||||
|
- **Iteration:** Game development is iterative. Be prepared to revisit and refine early stages as new challenges or ideas arise.
|
||||||
|
- **Scope Management:** Focus initially on a minimal viable product (MVP) that covers both game modes. Additional features can be added once core gameplay is solid.
|
||||||
|
- **Learning Curve:** If you are less experienced with raylib or game development in C, consider using online tutorials and community forums for additional guidance.
|
||||||
|
|
||||||
|
Good luck with your project!
|
||||||
@ -7,6 +7,26 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "entity.h"
|
typedef enum {
|
||||||
|
STATE_RUNNING = 1 << 0,
|
||||||
|
STATE_CLOSING = 1 << 1,
|
||||||
|
} ENGINE_STATE_ENUM;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CAM_FP,
|
||||||
|
CAM_TP,
|
||||||
|
CAM_FREE
|
||||||
|
} ENGINE_CAMERA_ENUM;
|
||||||
|
|
||||||
|
#define ENGINE_CAMERA_NUMBER 3
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t w_height;
|
||||||
|
uint32_t w_width;
|
||||||
|
uint16_t state;
|
||||||
|
Camera3D camera[ENGINE_CAMERA_NUMBER];
|
||||||
|
uint8_t current_cam;
|
||||||
|
} context;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1
source/engine/ecs.c
Normal file
1
source/engine/ecs.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ecs.h"
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef ENTITY_H
|
#ifndef ENGINE_ECS_H
|
||||||
# define ENTITY_H
|
# define ENGINE_ECS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int current[MAX_ENTITY];
|
int current[MAX_ENTITY];
|
||||||
int max{MAX_ENTITY};
|
int max[MAX_ENTITY];
|
||||||
} health_array;
|
} health_array;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
19
source/engine/game_state.c
Normal file
19
source/engine/game_state.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "game_state.h"
|
||||||
|
|
||||||
|
void initialize_game(GameState *state) {
|
||||||
|
initialize_player(&state->localPlayer);
|
||||||
|
state->remoteCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_game(GameState *state, InputState *input, float delta) {
|
||||||
|
update_player_movement(&state->localPlayer, input, delta);
|
||||||
|
|
||||||
|
PlayerNetState netState = {
|
||||||
|
.id = 0,
|
||||||
|
.position = state->localPlayer.position,
|
||||||
|
.velocity = state->localPlayer.velocity,
|
||||||
|
.yaw = state->localPlayer.yaw
|
||||||
|
};
|
||||||
|
send_player_state(&netState);
|
||||||
|
receive_remote_players(state->remotePlayers, &state->remoteCount);
|
||||||
|
}
|
||||||
18
source/engine/game_state.h
Normal file
18
source/engine/game_state.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef ENGINE_GAME_STATE_H
|
||||||
|
# define ENGINE_GAME_STATE_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "player_controller.h"
|
||||||
|
#include "net_sync.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PlayerState localPlayer;
|
||||||
|
PlayerNetState remotePlayers[MAX_REMOTE_PLAYERS];
|
||||||
|
int remoteCount;
|
||||||
|
} GameState;
|
||||||
|
|
||||||
|
void initialize_game(GameState *state);
|
||||||
|
void update_game(GameState *state, InputState *input, float delta);
|
||||||
|
|
||||||
|
#endif
|
||||||
9
source/engine/net_sync.c
Normal file
9
source/engine/net_sync.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include "net_sync.h"
|
||||||
|
|
||||||
|
void send_player_state(PlayerNetState *state) {
|
||||||
|
// TODO: Serialize + UDP send
|
||||||
|
}
|
||||||
|
|
||||||
|
void receive_remote_players(PlayerNetState *players, int *count) {
|
||||||
|
// TODO: Receive + deserialize state
|
||||||
|
}
|
||||||
20
source/engine/net_sync.h
Normal file
20
source/engine/net_sync.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef ENGINE_NET_H
|
||||||
|
# define ENGINE_NET_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vector_math.h"
|
||||||
|
|
||||||
|
#define MAX_REMOTE_PLAYERS 16
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t id;
|
||||||
|
Vector3 position;
|
||||||
|
Vector3 velocity;
|
||||||
|
float yaw;
|
||||||
|
} PlayerNetState;
|
||||||
|
|
||||||
|
void send_player_state(PlayerNetState *state);
|
||||||
|
void receive_remote_players(PlayerNetState *players, int *count);
|
||||||
|
|
||||||
|
#endif
|
||||||
38
source/engine/physic.c
Normal file
38
source/engine/physic.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "physics.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
Vector3 apply_gravity(Vector3 velocity, float delta) {
|
||||||
|
velocity.y += GRAVITY * delta;
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 apply_friction(Vector3 velocity, float delta, bool grounded) {
|
||||||
|
if (!grounded) return velocity;
|
||||||
|
velocity.x *= 1.0f - delta * 6.0f;
|
||||||
|
velocity.z *= 1.0f - delta * 6.0f;
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 ground_accelerate(Vector3 velocity, Vector3 wishDir, float wishSpeed, float delta) {
|
||||||
|
float accel = 10.0f;
|
||||||
|
Vector3 change = Vector3Scale(wishDir, accel * delta);
|
||||||
|
return Vector3Add(velocity, change);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 air_accelerate(Vector3 velocity, Vector3 wishDir, float wishSpeed, float delta) {
|
||||||
|
float accel = 2.5f;
|
||||||
|
Vector3 change = Vector3Scale(wishDir, accel * delta);
|
||||||
|
return Vector3Add(velocity, change);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 calculate_wish_direction(InputState *input, float yaw) {
|
||||||
|
Vector3 forward = { sinf(yaw), 0, cosf(yaw) };
|
||||||
|
Vector3 right = { -forward.z, 0, forward.x };
|
||||||
|
Vector3 wish = {0};
|
||||||
|
|
||||||
|
if (input->forward) wish = Vector3Add(wish, forward);
|
||||||
|
if (input->backward) wish = Vector3Subtract(wish, forward);
|
||||||
|
if (input->left) wish = Vector3Subtract(wish, right);
|
||||||
|
if (input->right) wish = Vector3Add(wish, right);
|
||||||
|
return Vector3Normalize(wish);
|
||||||
|
}
|
||||||
20
source/engine/physic.h
Normal file
20
source/engine/physic.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef ENGINE_PHYSIC_H
|
||||||
|
# define ENGINE_PHYSIC_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vector_math.h"
|
||||||
|
|
||||||
|
#define GROUND_Y 0.0f
|
||||||
|
#define GRAVITY -9.81f
|
||||||
|
#define PLAYER_JUMP_VELOCITY 8.0f
|
||||||
|
#define PLAYER_WALK_SPEED 5.0f
|
||||||
|
#define PLAYER_SPRINT_SPEED 8.5f
|
||||||
|
|
||||||
|
Vector3 apply_gravity(Vector3 velocity, float delta);
|
||||||
|
Vector3 apply_friction(Vector3 velocity, float delta, bool grounded);
|
||||||
|
Vector3 ground_accelerate(Vector3 velocity, Vector3 wishDir, float wishSpeed, float delta);
|
||||||
|
Vector3 air_accelerate(Vector3 velocity, Vector3 wishDir, float wishSpeed, float delta);
|
||||||
|
Vector3 calculate_wish_direction(InputState *input, float yaw);
|
||||||
|
|
||||||
|
#endif
|
||||||
33
source/engine/player_controller.c
Normal file
33
source/engine/player_controller.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "player_controller.h"
|
||||||
|
#include "physics.h"
|
||||||
|
|
||||||
|
void initialize_player(PlayerState *player) {
|
||||||
|
player->position = (Vector3){0};
|
||||||
|
player->velocity = (Vector3){0};
|
||||||
|
player->acceleration = (Vector3){0};
|
||||||
|
player->yaw = 0.0f;
|
||||||
|
player->pitch = 0.0f;
|
||||||
|
player->isGrounded = false;
|
||||||
|
player->isSprinting = false;
|
||||||
|
player->isSliding = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_player_movement(PlayerState *player, InputState *input, float delta) {
|
||||||
|
Vector3 wishDir = calculate_wish_direction(input, player->yaw);
|
||||||
|
float wishSpeed = player->isSprinting ? PLAYER_SPRINT_SPEED : PLAYER_WALK_SPEED;
|
||||||
|
|
||||||
|
if (player->isGrounded) {
|
||||||
|
if (input->jump) {
|
||||||
|
player->velocity.y = PLAYER_JUMP_VELOCITY;
|
||||||
|
player->isGrounded = false;
|
||||||
|
}
|
||||||
|
player->velocity = ground_accelerate(player->velocity, wishDir, wishSpeed, delta);
|
||||||
|
if (input->crouch) player->isSliding = true;
|
||||||
|
} else {
|
||||||
|
player->velocity = air_accelerate(player->velocity, wishDir, wishSpeed, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
player->velocity = apply_friction(player->velocity, delta, player->isGrounded);
|
||||||
|
player->velocity = apply_gravity(player->velocity, delta);
|
||||||
|
player->position = Vector3Add(player->position, Vector3Scale(player->velocity, delta));
|
||||||
|
}
|
||||||
18
source/engine/player_controller.h
Normal file
18
source/engine/player_controller.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vector_math.h"
|
||||||
|
#include "input_state.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Vector3 position;
|
||||||
|
Vector3 velocity;
|
||||||
|
Vector3 acceleration;
|
||||||
|
float yaw;
|
||||||
|
float pitch;
|
||||||
|
bool isGrounded;
|
||||||
|
bool isSprinting;
|
||||||
|
bool isSliding;
|
||||||
|
} PlayerState;
|
||||||
|
|
||||||
|
void initialize_player(PlayerState *player);
|
||||||
|
void update_player_movement(PlayerState *player, InputState *input, float delta);
|
||||||
1
source/engine/ui.c
Normal file
1
source/engine/ui.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "ui.h"
|
||||||
24
source/engine/ui.h
Normal file
24
source/engine/ui.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef ENGINE_UI_H
|
||||||
|
# define ENGINE_UI_H
|
||||||
|
|
||||||
|
/* input */
|
||||||
|
typedef struct {
|
||||||
|
bool is_mouse;
|
||||||
|
bool repeat;
|
||||||
|
int bind;
|
||||||
|
} keybind_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* gui */
|
||||||
|
typedef struct {
|
||||||
|
Texture2D tex;
|
||||||
|
Rectangle rec;
|
||||||
|
char* str;
|
||||||
|
} button;
|
||||||
|
|
||||||
|
bool mouse_inbound(const Rectangle bound, const Vector2 mouse_pos);
|
||||||
|
button create_button(Vector2 pos, char* tex_path, char* str);
|
||||||
|
void destroy_button(button b);
|
||||||
|
bool gui_button(button b);
|
||||||
|
|
||||||
|
#endif
|
||||||
0
source/engine/world.c
Normal file
0
source/engine/world.c
Normal file
2392
source/extern/toml.c
vendored
Normal file
2392
source/extern/toml.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
175
source/extern/toml.h
vendored
Normal file
175
source/extern/toml.h
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) CK Tan
|
||||||
|
https://github.com/cktan/tomlc99
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TOML_H
|
||||||
|
#define TOML_H
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define TOML_EXTERN extern "C"
|
||||||
|
#else
|
||||||
|
#define TOML_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct toml_timestamp_t toml_timestamp_t;
|
||||||
|
typedef struct toml_table_t toml_table_t;
|
||||||
|
typedef struct toml_array_t toml_array_t;
|
||||||
|
typedef struct toml_datum_t toml_datum_t;
|
||||||
|
|
||||||
|
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||||
|
* Caller must toml_free(the-return-value) after use.
|
||||||
|
*/
|
||||||
|
TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz);
|
||||||
|
|
||||||
|
/* Parse a string containing the full config.
|
||||||
|
* Return a table on success, or 0 otherwise.
|
||||||
|
* Caller must toml_free(the-return-value) after use.
|
||||||
|
*/
|
||||||
|
TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */
|
||||||
|
char *errbuf, int errbufsz);
|
||||||
|
|
||||||
|
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
||||||
|
* this function is called, any handles accessed through this tab
|
||||||
|
* directly or indirectly are no longer valid.
|
||||||
|
*/
|
||||||
|
TOML_EXTERN void toml_free(toml_table_t *tab);
|
||||||
|
|
||||||
|
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||||
|
* fields may be NULL if they are not relevant. e.g. In a DATE
|
||||||
|
* type, the hour, minute, second and z fields will be NULLs.
|
||||||
|
*/
|
||||||
|
struct toml_timestamp_t {
|
||||||
|
struct { /* internal. do not use. */
|
||||||
|
int year, month, day;
|
||||||
|
int hour, minute, second, millisec;
|
||||||
|
char z[10];
|
||||||
|
} __buffer;
|
||||||
|
int *year, *month, *day;
|
||||||
|
int *hour, *minute, *second, *millisec;
|
||||||
|
char *z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* Enhanced access methods
|
||||||
|
*/
|
||||||
|
struct toml_datum_t {
|
||||||
|
int ok;
|
||||||
|
union {
|
||||||
|
toml_timestamp_t *ts; /* ts must be freed after use */
|
||||||
|
char *s; /* string value. s must be freed after use */
|
||||||
|
int b; /* bool value */
|
||||||
|
int64_t i; /* int value */
|
||||||
|
double d; /* double value */
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* on arrays: */
|
||||||
|
/* ... retrieve size of array. */
|
||||||
|
TOML_EXTERN int toml_array_nelem(const toml_array_t *arr);
|
||||||
|
/* ... retrieve values using index. */
|
||||||
|
TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx);
|
||||||
|
/* ... retrieve array or table using index. */
|
||||||
|
TOML_EXTERN toml_array_t *toml_array_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx);
|
||||||
|
|
||||||
|
/* on tables: */
|
||||||
|
/* ... retrieve the key in table at keyidx. Return 0 if out of range. */
|
||||||
|
TOML_EXTERN const char *toml_key_in(const toml_table_t *tab, int keyidx);
|
||||||
|
/* ... returns 1 if key exists in tab, 0 otherwise */
|
||||||
|
TOML_EXTERN int toml_key_exists(const toml_table_t *tab, const char *key);
|
||||||
|
/* ... retrieve values using key. */
|
||||||
|
TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t *arr,
|
||||||
|
const char *key);
|
||||||
|
TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key);
|
||||||
|
TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t *arr, const char *key);
|
||||||
|
TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t *arr,
|
||||||
|
const char *key);
|
||||||
|
TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t *arr,
|
||||||
|
const char *key);
|
||||||
|
/* .. retrieve array or table using key. */
|
||||||
|
TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab,
|
||||||
|
const char *key);
|
||||||
|
TOML_EXTERN toml_table_t *toml_table_in(const toml_table_t *tab,
|
||||||
|
const char *key);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* lesser used
|
||||||
|
*/
|
||||||
|
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
|
||||||
|
TOML_EXTERN char toml_array_kind(const toml_array_t *arr);
|
||||||
|
|
||||||
|
/* For array kind 'v'alue, return the type of values
|
||||||
|
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
|
||||||
|
0 if unknown
|
||||||
|
*/
|
||||||
|
TOML_EXTERN char toml_array_type(const toml_array_t *arr);
|
||||||
|
|
||||||
|
/* Return the key of an array */
|
||||||
|
TOML_EXTERN const char *toml_array_key(const toml_array_t *arr);
|
||||||
|
|
||||||
|
/* Return the number of key-values in a table */
|
||||||
|
TOML_EXTERN int toml_table_nkval(const toml_table_t *tab);
|
||||||
|
|
||||||
|
/* Return the number of arrays in a table */
|
||||||
|
TOML_EXTERN int toml_table_narr(const toml_table_t *tab);
|
||||||
|
|
||||||
|
/* Return the number of sub-tables in a table */
|
||||||
|
TOML_EXTERN int toml_table_ntab(const toml_table_t *tab);
|
||||||
|
|
||||||
|
/* Return the key of a table*/
|
||||||
|
TOML_EXTERN const char *toml_table_key(const toml_table_t *tab);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------
|
||||||
|
* misc
|
||||||
|
*/
|
||||||
|
TOML_EXTERN int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret);
|
||||||
|
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
||||||
|
TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t),
|
||||||
|
void (*xxfree)(void *));
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------
|
||||||
|
* deprecated
|
||||||
|
*/
|
||||||
|
/* A raw value, must be processed by toml_rto* before using. */
|
||||||
|
typedef const char *toml_raw_t;
|
||||||
|
TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key);
|
||||||
|
TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t *arr, int idx);
|
||||||
|
TOML_EXTERN int toml_rtos(toml_raw_t s, char **ret);
|
||||||
|
TOML_EXTERN int toml_rtob(toml_raw_t s, int *ret);
|
||||||
|
TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t *ret);
|
||||||
|
TOML_EXTERN int toml_rtod(toml_raw_t s, double *ret);
|
||||||
|
TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double *ret, char *buf, int buflen);
|
||||||
|
TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret);
|
||||||
|
|
||||||
|
#endif /* TOML_H */
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "engine.h"
|
#include <engine.h>
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int width;
|
int width;
|
||||||
@ -9,17 +9,26 @@ int main(void) {
|
|||||||
context.height = 600;
|
context.height = 600;
|
||||||
context.width = 800;
|
context.width = 800;
|
||||||
Vector2 position = (Vector2){0, 0};
|
Vector2 position = (Vector2){0, 0};
|
||||||
|
Camera2D cam = {0};
|
||||||
|
|
||||||
InitWindow(context.width, context.height, "Game");
|
InitWindow(context.width, context.height, "Game");
|
||||||
|
|
||||||
SetTargetFPS(120);
|
SetTargetFPS(120);
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
|
float delta = GetFrameTime();
|
||||||
|
process_input(&input);
|
||||||
|
update_player_movement(&localPlayer, &input, delta);
|
||||||
|
apply_ground_snap(&localPlayer);
|
||||||
|
|
||||||
BeginDrawing();
|
send_player_state(&localPlayerNet);
|
||||||
ClearBackground(BLACK);
|
receive_remote_players(remotePlayers, &remoteCount);
|
||||||
DrawFPS(10, 10);
|
|
||||||
EndDrawing();
|
begin_drawing_frame();
|
||||||
|
draw_world();
|
||||||
|
draw_player(&localPlayer);
|
||||||
|
draw_remote_players(remotePlayers, remoteCount);
|
||||||
|
draw_gui();
|
||||||
|
end_drawing_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user