- 重构了游戏引擎的核心逻辑和架构 - 添加了新的实体组件系统(ECS) - 实现了简单的碰撞检测和响应 - 新增了地图和子弹功能 - 优化了输入处理和渲染逻辑 - 调整了游戏控制方式
111 lines
3.2 KiB
C
111 lines
3.2 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include "config.h"
|
|
#include "ge_color.h"
|
|
#include "entities/entities.h"
|
|
|
|
typedef struct {
|
|
int score;
|
|
ge_entity_t* player;
|
|
ge_entity_t* bullets[MAX_BULLET];
|
|
ge_render_rect_t screen;
|
|
ge_entity_t* tilemap;
|
|
} game_ctx_t;
|
|
|
|
void collision_response(
|
|
void* _ctx,
|
|
ge_entity_t* entity_from,
|
|
ge_entity_t* entity_to,
|
|
const ge_vector2i_t* vector // 反向推荐速度
|
|
) {
|
|
game_ctx_t* ctx = _ctx;
|
|
(void) ctx;
|
|
(void) entity_to;
|
|
// For box to box collision
|
|
if (vector == NULL) return;
|
|
|
|
switch (entity_from->user_type) {
|
|
case PLAYER:
|
|
case ENEMY:
|
|
entity_from->position = vec2i_add(entity_from->position, *vector);
|
|
break;
|
|
case BULLET:
|
|
entity_from->component_mask &= ~GE_COMPONENT_ACVIVE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void init(ge_core_t* core) {
|
|
(void)core;
|
|
|
|
static game_ctx_t ctx = { 0 };
|
|
core->_systems.collision.ctx = &ctx;
|
|
core->_systems.collision.callback = collision_response;
|
|
|
|
init_tilemap(&core->ecs, &ctx.tilemap);
|
|
init_player(&core->ecs, &ctx.player);
|
|
for (int i = 0; i < MAX_BULLET; ++i) {
|
|
init_bullet(&core->ecs, &ctx.bullets[i]);
|
|
}
|
|
|
|
ctx.screen = (ge_render_rect_t) {
|
|
.pos = {0, 0},
|
|
.size = core->_render.screen_size,
|
|
};
|
|
core->context = &ctx;
|
|
}
|
|
|
|
void process(ge_core_t* core) {
|
|
game_ctx_t* ctx = (game_ctx_t*)core->context;
|
|
core->_render.func_draw_rect(&core->_render, &ctx->screen, GE_COLOR_WHITE);
|
|
ge_vector2i_t* player_pos = &ctx->player->position;
|
|
ge_vector2i_t* player_vec = &ctx->player->physics_body.velocity;
|
|
player_vec->x = 0;
|
|
player_vec->y = 0;
|
|
|
|
core->_render.func_draw_text(&core->_render, &ctx->screen, "Press 'p' to exit", player_pos, GE_COLOR_BLACK);
|
|
ge_input_event_t key;
|
|
if (!core->_input.func_recv(&core->_input, &key)) {
|
|
switch (key.num) {
|
|
case KEY_UP:
|
|
MLOG_INFO(&logger, "KEY_UP");
|
|
player_vec->y = - BASIC_SPEED;
|
|
break;
|
|
case KEY_DOWN:
|
|
MLOG_INFO(&logger, "KEY_DOWN");
|
|
player_vec->y = BASIC_SPEED;
|
|
break;
|
|
case KEY_LEFT:
|
|
MLOG_INFO(&logger, "KEY_LEFT");
|
|
player_vec->x = - BASIC_SPEED;
|
|
break;
|
|
case KEY_RIGHT:
|
|
MLOG_INFO(&logger, "KEY_RIGHT");
|
|
player_vec->x = BASIC_SPEED;
|
|
break;
|
|
case KEY_ATTACK:
|
|
ge_entity_t* bullet = ctx->bullets[0];
|
|
bullet->component_mask |= GE_COMPONENT_ACVIVE;
|
|
bullet->position.x = player_pos->x + 4; // TODO
|
|
bullet->position.y = player_pos->y; // TODO
|
|
bullet->physics_body.velocity.x = 0;
|
|
bullet->physics_body.velocity.y = - BASIC_SPEED / 2;
|
|
break;
|
|
case KEY_EXIT:
|
|
core->state = GE_ENGINE_STATE_EXIT;
|
|
MLOG_INFO(&logger, "exit");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int ge_main(ge_core_t* core) {
|
|
core->callbacks.init = init;
|
|
core->callbacks.process = process;
|
|
ge_engine_run(core);
|
|
return 0;
|
|
}
|