feat(game_core): 重构游戏引擎并添加新功能

- 重构了游戏引擎的核心逻辑和架构
- 添加了新的实体组件系统(ECS)
- 实现了简单的碰撞检测和响应
- 新增了地图和子弹功能
- 优化了输入处理和渲染逻辑
- 调整了游戏控制方式
This commit is contained in:
ZZY
2025-07-02 12:14:57 +08:00
parent 89bede93a9
commit b5b2c90e75
32 changed files with 856 additions and 441 deletions

View File

@@ -0,0 +1,33 @@
#include "entities.h"
void init_bullet(ge_ecs_t* ecs, ge_entity_t **_bullet) {
Assert(ecs != NULL && _bullet != NULL);
ge_ecs_add_entity(ecs, _bullet);
ge_entity_t* bullet = *_bullet;
Assert(bullet != NULL);
*bullet = (ge_entity_t) {
.user_type = BULLET,
.component_mask = GE_RENDERABLE_MASK | GE_PHYSICS_MASK | GE_COLLIDER_MASK,
.renderable = (ge_render_component_t) {
.type = GE_RENDER_COMP_TYPE_RECT,
.data.rect = {
.size = { 2, 2 },
.color = GE_COLOR_RED,
}
},
.physics_body = (ge_physics_component_t) {
.type = GE_PHYSICS_COMP_TYPE_VELOCITY,
.velocity = { 0, 0 },
},
.collision = (ge_collision_component_t) {
.type = GE_COLLISION_COMP_TYPE_BOX,
.layers = LAYER_PLAYER_PROJECTILE,
.mask = LAYER_WALL | LAYER_ENEMY_HITBOX,
.collider.box = {
.relative_pos = { 0, 0 },
.size = { 2, 2 },
},
},
};
}

View File

View File

@@ -0,0 +1,19 @@
#ifndef __ENTITY_H__
#define __ENTITY_H__
#include "tilemap.h"
#include "layer.h"
enum {
PLAYER,
ENEMY,
BULLET,
};
void init_player(ge_ecs_t* ecs, ge_entity_t **_player);
#define MAX_BULLET 16
#define BASIC_SPEED (1 << GE_PHYSICS_VELOCITY_BIT)
void init_bullet(ge_ecs_t* ecs, ge_entity_t **_bullet);
#endif

View File

@@ -0,0 +1,13 @@
#ifndef __LAYER_H__
#define __LAYER_H__
enum {
LAYER_WALL = 1 << 0,
LAYER_PLAYER_HITBOX = 1 << 1,
LAYER_ENEMY_HITBOX = 1 << 2,
LAYER_PLAYER_PROJECTILE = 1 << 3,
LAYER_ENEMY_PROJECTILE = 1 << 4,
LAYER_POWERUP = 1 << 5,
};
#endif /* __LAYER_H__ */

View File

@@ -0,0 +1,32 @@
#include "entities.h"
void init_player(ge_ecs_t* ecs, ge_entity_t **_player) {
Assert(ecs != NULL && _player != NULL);
ge_ecs_add_entity(ecs, _player);
ge_entity_t* player = *_player;
Assert(player != NULL);
player->user_type = PLAYER;
player->component_mask = GE_COMPONENT_ACVIVE | GE_RENDERABLE_MASK | GE_PHYSICS_MASK | GE_COLLIDER_MASK;
player->position = (ge_vector2i_t){ TILEMAP_SIZE * 8, TILEMAP_SIZE * 8 };
player->renderable = (ge_render_component_t) {
.type = GE_RENDER_COMP_TYPE_RECT,
.data.rect = {
.size = {TILEMAP_SIZE, TILEMAP_SIZE},
.color = GE_COLOR_BLUE,
}
};
player->physics_body = (ge_physics_component_t) {
.type = GE_PHYSICS_COMP_TYPE_VELOCITY,
.velocity = {0, 0},
};
player->collision = (ge_collision_component_t) {
.type = GE_COLLISION_COMP_TYPE_BOX,
.layers = LAYER_PLAYER_HITBOX,
.mask = LAYER_WALL,
.collider.box = {
.relative_pos = {0, 0},
.size = {TILEMAP_SIZE, TILEMAP_SIZE},
}
};
}

View File

@@ -0,0 +1,81 @@
#include "tilemap.h"
#include <ecs/ge_render_component.h>
#include <ecs/ge_collision_component.h>
static ge_render_component_t* tilemap_render[TILEMAP_Y_HEIGHT][TILEMAP_X_WIDTH];
static ge_layers_t tilemap_layers[TILEMAP_Y_HEIGHT][TILEMAP_X_WIDTH];
static int real_map[TILEMAP_Y_HEIGHT][TILEMAP_X_WIDTH] = {
{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}, // 第0行: 顶部边界
{2,0,0,1,1,0,0,0,0,0,0,1,1,0,0,2}, // 第1行: 敌方出生点预留
{2,0,0,1,1,0,0,0,0,0,0,1,1,0,0,2}, // 第2行
{2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,2},
{2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,2},
{2,0,1,1,0,0,0,0,0,0,0,0,1,1,0,2},
{2,0,1,1,0,0,0,0,0,0,0,0,1,1,0,2},
{2,0,0,0,0,0,1,1,1,1,0,0,0,0,0,2}, // 中央障碍
{2,0,0,0,0,0,1,0,0,1,0,0,0,0,0,2}, // 中央基地区域
{2,0,1,1,0,0,1,0,0,1,0,0,1,1,0,2},
{2,0,1,1,0,0,0,0,0,0,0,0,1,1,0,2},
{2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
{2,0,0,1,1,0,0,0,0,0,0,1,1,0,0,2}, // 第12行: 玩家出生点预留
{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}, // 第13行: 底部边界
};
static inline void fill_render(void) {
// FIXME you can using ecs to store the entity
static ge_render_component_t render_wall = {
.type = GE_RENDER_COMP_TYPE_RECT,
.data.rect.size.x = TILEMAP_SIZE,
.data.rect.size.y = TILEMAP_SIZE,
.data.rect.color = GE_COLOR_GRAY,
};
for (int y = 0; y < TILEMAP_Y_HEIGHT; y++) {
for (int x = 0; x < TILEMAP_X_WIDTH; x++) {
if (real_map[y][x] == 0) {
continue;
}
tilemap_render[y][x] = &render_wall;
tilemap_layers[y][x] = LAYER_WALL;
/**
* the global variable default value is NULL
* tilemap_render[y][x] = NULL;
*/
}
}
}
void init_tilemap(ge_ecs_t* ecs, ge_entity_t **_tilemap) {
Assert(ecs != NULL && _tilemap != NULL);
ge_ecs_add_entity(ecs, _tilemap);
ge_entity_t* tilemap = *_tilemap;
Assert(tilemap != NULL);
tilemap->component_mask = (
GE_COMPONENT_ACVIVE |
GE_COMPONENT_POSITION |
GE_COMPONENT_RENDERABLE |
GE_COMPONENT_COLLIDER
);
/**
* y = 16
*/
tilemap->position = (ge_vector2i_t) {.x = 0, .y = 16};
tilemap->renderable = (ge_render_component_t) {
.type = GE_RENDER_COMP_TYPE_TILEMAP,
.data.tilemap.tile_size = TILEMAP_SIZE,
.data.tilemap.map_size.x = TILEMAP_X_WIDTH,
.data.tilemap.map_size.y = TILEMAP_Y_HEIGHT,
.data.tilemap.components = (ge_render_component_t**)tilemap_render,
};
tilemap->collision = (ge_collision_component_t) {
.type = GE_COLLISION_COMP_TYPE_TILEMAP,
.layers = LAYER_WALL,
.collider.tilemap = {
.tile_size = TILEMAP_SIZE,
.map_size = { TILEMAP_X_WIDTH, TILEMAP_Y_HEIGHT },
.layers = (ge_layers_t*)tilemap_layers,
},
};
fill_render();
}

View File

@@ -0,0 +1,15 @@
#ifndef __TILEMAP_H__
#define __TILEMAP_H__
#include "../ge_color.h"
#include "layer.h"
#include <ecs/ge_entity.h>
#include <pynic_log/pynic_log.h>
#define TILEMAP_SIZE 8
#define TILEMAP_X_WIDTH 16
#define TILEMAP_Y_HEIGHT 14
void init_tilemap(ge_ecs_t* ecs, ge_entity_t **_tilemap);
#endif // __TILEMAP_H__