JacksEscape/app_render.cpp

200 lines
5.7 KiB
C++
Raw Permalink Normal View History

2024-03-05 11:40:42 +08:00
#include "app.h"
2024-03-08 14:51:29 +08:00
#include "camera.h"
2024-04-15 16:21:24 +08:00
#include "mapper_misc.h"
#include "particle.h"
2024-03-05 11:40:42 +08:00
#include "physics.h"
2024-03-04 16:13:43 +08:00
#include "easyx.h"
2024-03-30 18:55:43 +08:00
#include "render_bundle.h"
2024-03-30 22:05:49 +08:00
#include "render_component.h"
2024-04-24 21:30:28 +08:00
#include "ui.h"
2024-03-04 16:13:43 +08:00
#include "util/tree.h"
2024-03-19 15:14:23 +08:00
#include "types.h"
#include "render_util.h"
2024-04-22 04:50:06 +08:00
#include "util/vector.h"
2024-03-04 16:13:43 +08:00
#include <math.h>
2024-04-22 05:46:05 +08:00
#include <stdio.h>
#include <graphics.h>
2024-03-19 15:14:23 +08:00
namespace {
TimePoint since = time_Now();
} // namespace
2024-04-24 21:30:28 +08:00
extern "C" void app_Render(App *app) {
2024-03-30 21:25:39 +08:00
render_SetModes(render_ModeDefault, time_Now());
2024-04-16 20:29:38 +08:00
setbkcolor(app->clear_color);
cleardevice();
2024-03-30 21:25:39 +08:00
2024-04-22 04:50:06 +08:00
// Draw fill polys & boxes first
2024-03-04 16:13:43 +08:00
for (tree_Node *i = tree_FirstNode(app->entity->entities);
i != NULL;
i = tree_Node_Next(i)) {
2024-04-16 20:29:38 +08:00
Entity *e = (Entity *)i->data;
if (e->render) {
Component_Render *r = e->render;
// Calculate global position as offset
Vec2 pos = {.x = 0.0, .y = 0.0};
if (e->position)
pos = e->position->position;
2024-04-22 04:50:06 +08:00
// Has fill polygon
if (r->fillpoly) {
static vector_Vector *buf = vector_Create(2 * sizeof(int));
vector_Clear(buf);
// Transform every point in the polygon
for (int i = 0; i < vector_Size(r->fillpoly); i++) {
Vec2 screen_point = camera_TransformVec2(app->camera, vec2_Add(*(Vec2 *)vector_At(r->fillpoly, i), pos));
int screen_point_int[2] = {
(int)round(screen_point.x),
(int)round(screen_point.y)};
vector_Push(buf, screen_point_int);
}
// Draw
setfillcolor(r->fillcolor);
solidpolygon((POINT *)vector_Data(buf), vector_Size(r->fillpoly));
}
2024-04-16 20:29:38 +08:00
// Has fillbox
if (r->fillbox.size.x > EPS) {
2024-04-22 04:50:06 +08:00
Box2 cam = camera_TransformBox2(app->camera, box2_Offset(r->fillbox, pos));
2024-04-16 20:29:38 +08:00
setfillcolor(r->fillcolor);
solidrectangle(
(int)round(cam.lefttop.x),
(int)round(cam.lefttop.y),
(int)round(cam.lefttop.x + cam.size.x),
(int)round(cam.lefttop.y + cam.size.y));
}
2024-03-04 16:13:43 +08:00
}
2024-04-16 20:29:38 +08:00
}
// Debug boxes
if (app->debugOn) {
for (tree_Node *i = tree_FirstNode(app->entity->entities);
i != NULL;
i = tree_Node_Next(i)) {
Entity *e = (Entity *)(i->data);
if (e->hitbox) {
if (e->hitbox->fixed)
setlinecolor(RGB(0, 255, 0));
else
setlinecolor(RGB(255, 255, 0));
Box2 box = camera_TransformBox2(app->camera, physics_HitboxAbsolute(e->hitbox));
rectangle(
(int)round(box.lefttop.x),
(int)round(box.lefttop.y),
(int)round(box.lefttop.x + box.size.x),
(int)round(box.lefttop.y + box.size.y));
}
if (e->misc) {
if (e->misc->textbox)
setlinecolor(RGB(0, 0, 255));
if (e->misc->respawn_pos) {
setlinecolor(RGB(255, 0, 255));
Vec2 pos;
if (e->position)
pos = camera_TransformVec2(app->camera, vec2_Add(*e->misc->respawn_pos, e->position->position));
else
pos = camera_TransformVec2(app->camera, *e->misc->respawn_pos);
line((int)round(pos.x + 12), (int)round(pos.y), (int)round(pos.x - 12), (int)round(pos.y));
line((int)round(pos.x), (int)round(pos.y + 12), (int)round(pos.x), (int)round(pos.y - 12));
}
if (e->misc->trigger_flags & misc_Hazard)
setlinecolor(RGB(255, 0, 0));
if (e->misc->trigger_flags & misc_CameraFocus)
setlinecolor(RGB(0, 255, 255));
if (e->misc->change_level)
setlinecolor(RGB(255, 255, 0));
Box2 box;
2024-04-02 15:56:49 +08:00
if (e->position)
2024-04-16 20:29:38 +08:00
box = camera_TransformBox2(app->camera, box2_Offset(e->misc->trigger, e->position->position));
2024-04-02 15:56:49 +08:00
else
2024-04-16 20:29:38 +08:00
box = camera_TransformBox2(app->camera, e->misc->trigger);
rectangle(
(int)round(box.lefttop.x),
(int)round(box.lefttop.y),
(int)round(box.lefttop.x + box.size.x),
(int)round(box.lefttop.y + box.size.y));
}
2024-03-30 21:25:39 +08:00
}
2024-04-16 20:29:38 +08:00
if (app->player->player) {
setlinecolor(RGB(255, 0, 255));
Vec2 respawn = camera_TransformVec2(app->camera, app->player->player->hazardRespawn);
circle((int)round(respawn.x), (int)round(respawn.y), 6);
}
}
2024-03-19 15:14:23 +08:00
setfillcolor(RGB(255, 255, 255));
setbkcolor(RGB(0, 0, 0));
2024-03-30 18:55:43 +08:00
2024-03-30 22:05:49 +08:00
// Draw entities
for (tree_Node *i = tree_FirstNode(app->entity->entities);
i != NULL;
i = tree_Node_Next(i)) {
Entity *e = (Entity *)i->data;
if (e->render) {
Component_Render *r = e->render;
// Calculate global position as offset
Vec2 pos = {.x = 0.0, .y = 0.0};
if (e->position)
pos = e->position->position;
// Has bundle
if (r->bundle)
render_DrawBundleW(app, r->bundle, pos);
// Has custom rendering
if (r->custom)
r->custom(app, e, camera_TransformVec2(app->camera, pos), r->custom_data);
}
}
2024-04-16 20:29:38 +08:00
// Draw player
if (app->player->player) {
setfillcolor(0xffffff);
setlinecolor(0);
Vec2 screen = camera_TransformVec2(app->camera, vec2_Add(box2_Center(app->player->player->super->hitbox->box), app->player->player->super->position->position));
fillcircle((int)round(screen.x), (int)round(screen.y), (int)round(app->player->player->super->hitbox->box.size.y / 2.0));
}
2024-03-30 18:55:43 +08:00
// Draw particles
2024-03-30 18:55:43 +08:00
setfillcolor(RGB(255, 255, 255));
setbkcolor(RGB(0, 0, 0));
particle_Render(app->particle);
2024-03-30 22:05:49 +08:00
settextcolor(RGB(255, 255, 255));
2024-04-30 15:57:40 +08:00
setbkcolor(RGB(0, 0, 0));
2024-04-22 05:28:50 +08:00
// If paused, display a text
2024-04-23 15:20:02 +08:00
if (app->paused)
2024-04-24 21:30:28 +08:00
render_DrawTextEx("Game Paused", box2(SCREEN_WIDTH / 2.0 - 10, 100, 20, 100), DT_CENTER | DT_NOCLIP);
2024-04-23 15:20:02 +08:00
if (1.0 - app->timescale > EPS) {
2024-04-22 05:46:05 +08:00
char buf[128];
snprintf(buf, sizeof(buf), "*** TIMESCALE %.2lf ***", app->timescale);
2024-04-24 21:30:28 +08:00
render_DrawTextEx(buf, box2(SCREEN_WIDTH / 2.0 - 10, 50, 20, 100), DT_CENTER | DT_NOCLIP);
2024-04-22 05:46:05 +08:00
}
2024-04-24 21:30:28 +08:00
2024-04-30 15:57:40 +08:00
// Display a Timer
if (strcmp(app->current_level, "title.txt") != 0) {
char buf[64];
snprintf(
buf, sizeof(buf),
"%02d:%02d.%02d",
app->level_playtime.microseconds / 1000 / 1000 / 60,
app->level_playtime.microseconds / 1000 / 1000 % 60,
app->level_playtime.microseconds / 10000 % 100);
render_DrawTextEx(buf, box2(0, 0, SCREEN_WIDTH, TEXTHEIGHT), DT_RIGHT);
}
2024-04-24 21:30:28 +08:00
// Draw UI
ui_Render(app->ui);
2024-03-04 15:05:21 +08:00
}