camera: debug controls

This commit is contained in:
Lephenixnoir 2022-07-16 22:44:58 +01:00
parent b92cbcec5b
commit 8b1eb85c51
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 111 additions and 25 deletions

View File

@ -4,6 +4,7 @@ project(Nooncraft LANGUAGES CXX)
include(GenerateG3A)
include(Fxconv)
find_package(Gint 2.8 REQUIRED)
find_package(LibProf 2.1 REQUIRED)
set(SOURCES
src/block.cpp
@ -20,7 +21,7 @@ fxconv_declare_converters(converters.py)
add_executable(addin ${SOURCES} ${ASSETS})
target_compile_options(addin PRIVATE -Wall -Wextra -Wno-narrowing -Os -std=c++20)
target_link_libraries(addin Gint::Gint -lsupc++)
target_link_libraries(addin LibProf::LibProf Gint::Gint -lsupc++)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
message(FATAL_ERROR "This game is not supported on fx-9860G!")

View File

@ -1,5 +1,19 @@
#include "graphics.h"
#include "render.h"
#include <stdio.h>
WorldRect Camera::validCenters() const
{
WorldRect b = this->world->worldBorder;
/* Allow up to just next to the world border */
return WorldRect(b.xmin + 1, b.xmax - 1, b.ymin + 1, b.ymax - 1);
}
void Camera::moveBy(WorldCoord direction)
{
this->center = this->validCenters().clampPoint(this->center + direction);
}
namespace Nooncraft {
@ -8,11 +22,25 @@ void renderCamera(int x, int y, Camera *camera)
if(!camera)
return;
WorldRect r = camera->region;
WorldRect r = camera->visible;
for(int dy = r.ymin; dy <= r.ymax; dy++)
for(int dx = r.xmin; dx <= r.xmax; dx++) {
GlyphCluster c('@', '#', '~', '&');
renderCluster(x+2*dx, y+2*dy, c);
int wx = camera->center.x + dx;
int wy = camera->center.y + dy;
if(!camera->world->worldBorder.contains(WorldCoord(wx, wy))) {
continue;
}
else if(camera->world->isPointOnWorldBorder(wx, wy)) {
GlyphCluster c('{', '}', '{', '}');
renderCluster(x+2*dx, y+2*dy, c);
}
else {
char str[5];
sprintf(str, "%02X%02X", wx & 0xff, wy & 0xff);
GlyphCluster c(str[0], str[1], str[2], str[3]);
renderCluster(x+2*dx, y+2*dy, c);
}
}
}

View File

@ -5,7 +5,7 @@
struct Camera
{
Camera(World const *w): world {w}, center {0,0}, region {-1,1,-1,1} {}
Camera(World const *w): world {w}, center {0,0}, visible {-1,1,-1,1} {}
/* Underlying world object */
World const *world;
@ -14,7 +14,13 @@ struct Camera
WorldCoord center;
/* Local rectangle around center at (0,0). This influences how much of the
screen the camera will take up when rendered */
WorldRect region;
WorldRect visible;
/* Range of possible values for center */
WorldRect validCenters() const;
/* Move the camera by a fixed vector */
void moveBy(WorldCoord direction);
};
namespace Nooncraft {

View File

@ -2,21 +2,13 @@
#include "world.h"
#include "graphics.h"
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <gint/cpu.h>
#include <libprof.h>
#include <string.h>
int main(void)
static void renderGame(Camera *camera, int frameDuration)
{
World *world = Nooncraft::mkWorld(128, 128);
if(!world)
return 0;
Nooncraft::genWorld(world);
Camera *camera = new Camera(world);
camera->region = WorldRect(-13, 14, -6, 6);
// -
char separator[57];
memset(separator, '-', 56);
separator[56] = 0;
@ -24,30 +16,72 @@ int main(void)
renderClear();
Nooncraft::renderCamera(26, 12, camera);
// HUD
GlyphCluster invLeft(' ', GLYPH_PARALLEL_TO, ' ', GLYPH_PARALLEL_TO);
GlyphCluster invRight(GLYPH_PARALLEL_TO, ' ', GLYPH_PARALLEL_TO, ' ');
int hudY = 27;
renderText(0, hudY, separator);
renderText(24, hudY+1, "COBBLESTONE");
renderFormat(24, hudY+2, "FRAME: %d MS", frameDuration);
renderCluster(0, hudY+1, invLeft);
renderCluster(2, hudY+1, Nooncraft::getBlockInfo(2)->cluster);
renderCluster(20, hudY+1, invRight);
renderText(2, hudY+3, "1 2 3 4 5 6 7 8 9");
}
// -
int main(void)
{
prof_init();
renderText(0, 0, "NOONCRAFT");
renderUpdate();
World *world = Nooncraft::mkWorld(128, 128);
if(!world)
return 0;
getkey();
Nooncraft::genWorld(world);
//-
Camera *camera = new Camera(world);
camera->visible = WorldRect(-13, 14, -6, 6);
volatile int nextFrame = 1;
int t = timer_configure(TIMER_ANY, 1000000/20, GINT_CALL_SET(&nextFrame));
timer_start(t);
bool runMainLoop = true;
int frameDuration = 0;
while(runMainLoop) {
while(!nextFrame)
sleep();
nextFrame = 0;
frameDuration = prof_exec({
renderGame(camera, frameDuration);
renderUpdate();
}) / 1000;
key_event_t ev;
while((ev = pollevent()).type != KEYEV_NONE) {
if(ev.type == KEYEV_UP)
continue;
if(ev.key == KEY_MENU)
runMainLoop = false;
}
if(keydown(KEY_LEFT))
camera->moveBy(WorldCoord::Left);
if(keydown(KEY_RIGHT))
camera->moveBy(WorldCoord::Right);
if(keydown(KEY_UP))
camera->moveBy(WorldCoord::Up);
if(keydown(KEY_DOWN))
camera->moveBy(WorldCoord::Down);
}
timer_stop(t);
delete camera;
delete world;
prof_quit();
return 1;
}

View File

@ -4,6 +4,7 @@
#include "block.h"
#include <stddef.h>
#include <gint/defs/attributes.h>
#include <gint/defs/util.h>
struct WorldCoord
{
@ -50,6 +51,17 @@ struct WorldRect
int height() const {
return ymax - ymin + 1;
}
WorldCoord clampPoint(WorldCoord p) const {
p.x = max(p.x, xmin);
p.x = min(p.x, xmax);
p.y = max(p.y, ymin);
p.y = min(p.y, ymax);
return p;
}
bool contains(WorldCoord p) const {
return xmin <= p.x && p.x <= xmax && ymin <= p.y && p.y <= ymax;
}
};
struct World
@ -76,6 +88,11 @@ struct World
int ix = (x + limits.xmin) + (y + limits.ymin) * limits.width();
return cells[ix];
}
bool isPointOnWorldBorder(int16_t x, int16_t y) const {
return x == worldBorder.xmin || x == worldBorder.xmax
|| y == worldBorder.ymin || y == worldBorder.ymax;
}
};
namespace Nooncraft {