From 1a6cea1e19f6c020d74fc66fe2baac8f65fd6d17 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 17 Jul 2022 14:58:19 +0100 Subject: [PATCH] gameplay: add block breaking --- src/game.cpp | 32 ++++++++++++++++++++++++++++++++ src/game.h | 16 ++++++++++++++++ src/main.cpp | 25 +++++++++++++++++++++++-- src/world.cpp | 14 ++++++++++++++ src/world.h | 4 ++++ 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 2949aee..8add8c3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -36,3 +36,35 @@ bool Game::moveCursorBy(WorldCoord dir) this->cursorPos = this->world->limits.clampPoint(candidatePos); return true; } + +int Game::blockBreakingDuration() const +{ + BlockInfo *info = this->world->blockInfoAt(this->cursorPos); + if(!info) + return -1; + + /* Determine how many ticks would be needed with the current tool */ + // TODO: Query the user's current tool + int requiredTicks = info->baseBreakDurationTicks; + return requiredTicks; +} + +int8_t Game::blockBreakingProgress() const +{ + return this->damageTicks * 4 / this->blockBreakingDuration(); +} + +void Game::updateBlockBreaking() +{ + if(this->damageTicks < 0) + return; + this->damageTicks++; + + int requiredTicks = this->blockBreakingDuration(); + + if(this->damageTicks >= requiredTicks) { + this->world->trySetCellAt(this->cursorPos.x, this->cursorPos.y, + BlockID(AIR)); + this->damageTicks = -1; + } +} diff --git a/src/game.h b/src/game.h index 9d884a0..e6ef3b7 100644 --- a/src/game.h +++ b/src/game.h @@ -9,11 +9,27 @@ struct Game World *world; Camera *camera; + /* Current player/cursor positions (they are linked) */ WorldCoord playerPos; WorldCoord cursorPos; + /* Current ticks spent damaging the pointed block, ≥ 0 when breaking */ + int damageTicks; + + bool isBreakingBlock() const { + return this->damageTicks >= 0; + } + /* Time required to break currently selected block */ + int blockBreakingDuration() const; + /* Block breaking progress as a range 0-3 */ + int8_t blockBreakingProgress() const; + /* Move the player by specified amount. */ bool movePlayerBy(WorldCoord dir, bool camera_follow=true); /* Move the cursor by the specified amount. */ bool moveCursorBy(WorldCoord dir); + + // --== Tick update functions ==-- + + void updateBlockBreaking(); }; diff --git a/src/main.cpp b/src/main.cpp index 9f5d9ed..7efd998 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,6 +57,15 @@ static void renderGame(Game *game) GlyphCluster playerCluster(GLYPH_DEGREE_UNDERLINE, ' ', GLYPH_CAPITAL_LAMBDA, ' '); GlyphCluster cursorCluster(0, GLYPH_OPLUS, 0, 0); + + if(game->isBreakingBlock()) { + static Glyph breakingGlyphs[4] = { + GLYPH_MIDDLE_DOT, GLYPH_SMALL_SQUARE, GLYPH_CURRENCY_SIGN, 0x7f, + }; + int stage = game->blockBreakingProgress(); + cursorCluster.glyphs[1] = breakingGlyphs[stage]; + } + Nooncraft::renderCamera(26, 12, camera, game->playerPos, playerCluster, game->cursorPos, cursorCluster); @@ -105,6 +114,7 @@ int main(void) game.playerPos = world->findSpawnPoint(); // TODO: Potential world border overflow here (unlikely) game.cursorPos = game.playerPos + WorldCoord::Right; + game.damageTicks = -1; volatile int nextFrame = 1; int t = timer_configure(TIMER_ANY, 1000000/20, GINT_CALL_SET(&nextFrame)); @@ -129,17 +139,26 @@ int main(void) key_event_t ev; while((ev = pollevent()).type != KEYEV_NONE) { - if(ev.type == KEYEV_UP) + if(ev.type == KEYEV_UP) { + if(ev.key == KEY_OPTN) { + game.damageTicks = -1; + continue; + } continue; + } if(getkey_global_shortcuts(ev)) continue; if(ev.key == KEY_MENU) runMainLoop = false; + if(ev.key == KEY_OPTN) { + if(game.world->canBreakBlock(game.cursorPos)) + game.damageTicks = 0; + } } /* Clamp speed to 10 blocks/s */ - if(tick % 2 == 0) { + if(tick % 2 == 0 && !game.isBreakingBlock()) { if(keydown(KEY_LEFT) && !keydown(KEY_SHIFT)) game.movePlayerBy(WorldCoord::Left); if(keydown(KEY_RIGHT) && !keydown(KEY_SHIFT)) @@ -158,6 +177,8 @@ int main(void) if(keydown(KEY_DOWN) && keydown(KEY_SHIFT)) game.moveCursorBy(WorldCoord::Down); } + + game.updateBlockBreaking(); } timer_stop(t); diff --git a/src/world.cpp b/src/world.cpp index 10fca3f..b43bd88 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -213,6 +213,20 @@ WorldCoord World::findSpawnPoint() return WorldCoord(0, 0); } +BlockInfo *World::blockInfoAt(WorldCoord p) const +{ + if(!this->limits.contains(p)) + return nullptr; + return Nooncraft::getBlockInfo(this->cellAt(p.x, p.y)); +} + +bool World::canBreakBlock(WorldCoord p) const +{ + BlockInfo *info = blockInfoAt(p); + return info && info->breakability != Breakability::Fluid + && info->breakability != Breakability::Unbreakable; +} + namespace Nooncraft { World *mkWorld(int width, int height) diff --git a/src/world.h b/src/world.h index c82ac82..76a4ed9 100644 --- a/src/world.h +++ b/src/world.h @@ -121,6 +121,10 @@ struct World bool validSpawn(int x, int y) const; WorldCoord findSpawnPoint(); + + BlockInfo *blockInfoAt(WorldCoord p) const; + + bool canBreakBlock(WorldCoord p) const; }; namespace Nooncraft {