gameplay: add cursor movement

This commit is contained in:
Lephenixnoir 2022-07-17 14:35:13 +01:00
parent 375bec919e
commit 7f93d324d4
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
8 changed files with 70 additions and 19 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -55,6 +55,7 @@ def mkGlyph(s):
0x21A5: 13,
0x039B: 14,
# 15 is combined with a diacritic (from CASIO's custom charset)
0x2295: 16,
0x25A1: 0x7f,
}
if ord(s) >= 0x20 and ord(s) <= 0x7f:

View File

@ -51,7 +51,8 @@ void Camera::moveToFollow(WorldCoord p)
namespace Nooncraft {
void renderCamera(int x, int y, Camera *camera, WorldCoord playerPos,
GlyphCluster playerCluster)
GlyphCluster playerCluster, WorldCoord cursorPos,
GlyphCluster cursorCluster)
{
if(!camera)
return;
@ -61,30 +62,33 @@ void renderCamera(int x, int y, Camera *camera, WorldCoord playerPos,
for(int dx = r.xmin; dx <= r.xmax; dx++) {
int wx = camera->center.x + dx;
int wy = camera->center.y + dy;
GlyphCluster c;
if(!camera->world->worldBorder.contains(WorldCoord(wx, wy))) {
continue;
}
else if(WorldCoord(wx, wy) == playerPos) {
renderCluster(x+2*dx, y+2*dy, playerCluster);
c = playerCluster;
}
else if(camera->world->isPointOnWorldBorder(wx, wy)) {
GlyphCluster c('{', '}', '{', '}');
renderCluster(x+2*dx, y+2*dy, c);
c = GlyphCluster('{', '}', '{', '}');
}
else {
Block b = camera->world->cellAt(wx, wy);
BlockInfo *info = Nooncraft::getBlockInfo(b);
if(info) {
renderCluster(x+2*dx, y+2*dy, info->cluster);
c = info->cluster;
}
else {
char str[5];
sprintf(str, "%04X", 0x55);
GlyphCluster c(str[0], str[1], str[2], str[3]);
renderCluster(x+2*dx, y+2*dy, c);
c = GlyphCluster(str[0], str[1], str[2], str[3]);
}
}
if(WorldCoord(wx, wy) == cursorPos)
c = cursorCluster.applyOver(c);
renderCluster(x+2*dx, y+2*dy, c);
}
}

View File

@ -32,6 +32,7 @@ struct Camera
namespace Nooncraft {
void renderCamera(int x, int y, Camera *camera, WorldCoord playerPos,
GlyphCluster playerCluster);
GlyphCluster playerCluster, WorldCoord cursorPos,
GlyphCluster cursorCluster);
} /* namespace Nooncraft */

View File

@ -15,5 +15,24 @@ bool Game::movePlayerBy(WorldCoord dir, bool camera_follow)
this->playerPos = candidatePos;
if(camera_follow)
this->camera->moveToFollow(this->playerPos);
this->moveCursorBy(dir);
return true;
}
bool Game::moveCursorBy(WorldCoord dir)
{
WorldCoord candidatePos = this->cursorPos + dir;
int reachDistance = 3;
WorldRect reach(
this->playerPos.x - reachDistance,
this->playerPos.x + reachDistance,
this->playerPos.y - reachDistance,
this->playerPos.y + reachDistance);
if(!reach.contains(candidatePos))
return false;
this->cursorPos = this->world->limits.clampPoint(candidatePos);
return true;
}

View File

@ -10,6 +10,7 @@ struct Game
Camera *camera;
WorldCoord playerPos;
WorldCoord cursorPos;
/* Move the player by specified amount. */
bool movePlayerBy(WorldCoord dir, bool camera_follow=true);

View File

@ -56,7 +56,9 @@ static void renderGame(Game *game)
GlyphCluster playerCluster(GLYPH_DEGREE_UNDERLINE, ' ',
GLYPH_CAPITAL_LAMBDA, ' ');
Nooncraft::renderCamera(26, 12, camera, game->playerPos, playerCluster);
GlyphCluster cursorCluster(0, GLYPH_OPLUS, 0, 0);
Nooncraft::renderCamera(26, 12, camera, game->playerPos, playerCluster,
game->cursorPos, cursorCluster);
GlyphCluster invLeft(' ', GLYPH_PARALLEL_TO, ' ', GLYPH_PARALLEL_TO);
GlyphCluster invRight(GLYPH_PARALLEL_TO, ' ', GLYPH_PARALLEL_TO, ' ');
@ -101,6 +103,8 @@ int main(void)
game.world = world;
game.camera = camera;
game.playerPos = world->findSpawnPoint();
// TODO: Potential world border overflow here (unlikely)
game.cursorPos = game.playerPos + WorldCoord::Right;
volatile int nextFrame = 1;
int t = timer_configure(TIMER_ANY, 1000000/20, GINT_CALL_SET(&nextFrame));
@ -135,14 +139,25 @@ int main(void)
}
/* Clamp speed to 10 blocks/s */
if(keydown(KEY_LEFT) && (tick % 2) == 0)
game.movePlayerBy(WorldCoord::Left);
if(keydown(KEY_RIGHT) && (tick % 2) == 0)
game.movePlayerBy(WorldCoord::Right);
if(keydown(KEY_UP) && (tick % 2) == 0)
game.movePlayerBy(WorldCoord::Up);
if(keydown(KEY_DOWN) && (tick % 2) == 0)
game.movePlayerBy(WorldCoord::Down);
if(tick % 2 == 0) {
if(keydown(KEY_LEFT) && !keydown(KEY_SHIFT))
game.movePlayerBy(WorldCoord::Left);
if(keydown(KEY_RIGHT) && !keydown(KEY_SHIFT))
game.movePlayerBy(WorldCoord::Right);
if(keydown(KEY_UP) && !keydown(KEY_SHIFT))
game.movePlayerBy(WorldCoord::Up);
if(keydown(KEY_DOWN) && !keydown(KEY_SHIFT))
game.movePlayerBy(WorldCoord::Down);
if(keydown(KEY_LEFT) && keydown(KEY_SHIFT))
game.moveCursorBy(WorldCoord::Left);
if(keydown(KEY_RIGHT) && keydown(KEY_SHIFT))
game.moveCursorBy(WorldCoord::Right);
if(keydown(KEY_UP) && keydown(KEY_SHIFT))
game.moveCursorBy(WorldCoord::Up);
if(keydown(KEY_DOWN) && keydown(KEY_SHIFT))
game.moveCursorBy(WorldCoord::Down);
}
}
timer_stop(t);

View File

@ -32,15 +32,17 @@ enum {
GLYPH_UP_ARROW_BAR = 13, /* U+21A5 UPWARDS ARROW FROM BAR */
GLYPH_CAPITAL_LAMBDA = 14, /* U+039B GREEK CAPITAL LETTER LAMBDA */
GLYPH_DEGREE_UNDERLINE = 15, /* U+00B0 U+0331 */
GLYPH_OPLUS = 16, /* U+2295 CIRCLED PLUS */
};
/* A cluster of 4 glyphs. Can be conversion-constructed from a multi-byte
character literal like 'AXE '. */
struct GlyphCluster
{
GlyphCluster(): glyphs {0,0,0,0} {}
GlyphCluster(Glyph g1, Glyph g2, Glyph g3, Glyph g4):
glyphs {g1, g2, g3, g4}
{}
glyphs {g1, g2, g3, g4} {}
GlyphCluster(int mbliteral) {
this->glyphs[0] = mbliteral >> 24;
@ -49,6 +51,14 @@ struct GlyphCluster
this->glyphs[3] = mbliteral & 0xff;
}
GlyphCluster applyOver(GlyphCluster const &other) {
return GlyphCluster(
this->glyphs[0] ? this->glyphs[0] : other.glyphs[0],
this->glyphs[1] ? this->glyphs[1] : other.glyphs[1],
this->glyphs[2] ? this->glyphs[2] : other.glyphs[2],
this->glyphs[3] ? this->glyphs[3] : other.glyphs[3]);
}
Glyph glyphs[4];
};