[jasper/world] Get animations working
All checks were successful
Build / build (push) Successful in 3m43s
All checks were successful
Build / build (push) Successful in 3m43s
This commit is contained in:
@ -14,13 +14,16 @@ namespace ncore = nostalgia::core;
|
||||
|
||||
class World {
|
||||
private:
|
||||
struct ObjState {
|
||||
uint16_t objIdx{};
|
||||
uint16_t frame{};
|
||||
turbine::TimeMs nextUpdateTime{};
|
||||
};
|
||||
ncore::Context &m_nctx;
|
||||
WorldStatic const&m_worldStatic;
|
||||
ox::Vector<keel::AssetRef<ncore::CompactTileSheet>, 32> m_tilesheets;
|
||||
#ifndef OX_OS_BareMetal
|
||||
//turbine::TimeMs m_prevUpdateTime{};
|
||||
turbine::TimeMs m_nextUpdateTime{};
|
||||
#endif
|
||||
ox::Vector<ObjState, 128> m_objStates;
|
||||
turbine::TimeMs m_currentTicks{};
|
||||
|
||||
public:
|
||||
explicit World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept;
|
||||
@ -29,16 +32,14 @@ class World {
|
||||
|
||||
ox::Result<int> update() noexcept;
|
||||
|
||||
#ifndef OX_OS_BareMetal
|
||||
ox::Result<int> editorModeUpdate() noexcept;
|
||||
#endif
|
||||
|
||||
void setupTiles() noexcept;
|
||||
|
||||
void setupTile(uint32_t lyr, uint32_t x, uint32_t y) const noexcept;
|
||||
void setupTile(uint32_t lyr, uint32_t x, uint32_t y) noexcept;
|
||||
|
||||
private:
|
||||
void setupLayer(uint_t lyr, uint_t cbb) const noexcept;
|
||||
turbine::TimeMs updateObj(ObjState &state) noexcept;
|
||||
|
||||
void setupLayer(uint_t lyr, uint_t cbb) noexcept;
|
||||
|
||||
};
|
||||
|
||||
|
@ -91,6 +91,7 @@ struct ObjTileRefSet {
|
||||
uint8_t tileCnt{};
|
||||
// each successive frame will use tileIdx[i] + tileCnt * frameNo for the tileIdx
|
||||
uint8_t frames{};
|
||||
uint16_t intervalMs{};
|
||||
};
|
||||
|
||||
OX_MODEL_BEGIN(ObjTileRefSet)
|
||||
@ -101,6 +102,7 @@ OX_MODEL_BEGIN(ObjTileRefSet)
|
||||
OX_MODEL_FIELD(tilesheetId)
|
||||
OX_MODEL_FIELD(tileCnt)
|
||||
OX_MODEL_FIELD(frames)
|
||||
OX_MODEL_FIELD(intervalMs)
|
||||
OX_MODEL_END()
|
||||
|
||||
[[nodiscard]]
|
||||
|
@ -17,7 +17,7 @@ WorldEditorView::WorldEditorView(studio::StudioContext &sctx, WorldStatic const&
|
||||
ox::Error WorldEditorView::setupTile(
|
||||
uint32_t const lyr,
|
||||
uint32_t const x,
|
||||
uint32_t const y) const noexcept {
|
||||
uint32_t const y) noexcept {
|
||||
m_world.setupTile(lyr, x, y);
|
||||
return {};
|
||||
}
|
||||
@ -46,7 +46,7 @@ void WorldEditorView::draw(ox::Size const&targetSz) noexcept {
|
||||
}
|
||||
glutils::FrameBufferBind const frameBufferBind(m_frameBuffer);
|
||||
if (m_animateWorld) {
|
||||
auto const wakeUp = m_world.editorModeUpdate();
|
||||
auto const wakeUp = m_world.update();
|
||||
if (wakeUp.ok()) {
|
||||
turbine::setRefreshWithin(m_sctx.tctx, wakeUp.value);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class WorldEditorView: public ox::SignalHandler {
|
||||
public:
|
||||
WorldEditorView(studio::StudioContext &ctx, WorldStatic const&worldStatic);
|
||||
|
||||
ox::Error setupTile(uint32_t lyr, uint32_t x, uint32_t y) const noexcept;
|
||||
ox::Error setupTile(uint32_t lyr, uint32_t x, uint32_t y) noexcept;
|
||||
|
||||
void setupTiles() noexcept;
|
||||
|
||||
|
@ -10,6 +10,11 @@
|
||||
|
||||
namespace jasper::world {
|
||||
|
||||
[[nodiscard]]
|
||||
static bool isUpdatingObj(ObjTileRefSet const&obj) noexcept {
|
||||
return obj.frames > 1;
|
||||
}
|
||||
|
||||
World::World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept:
|
||||
m_nctx(nctx),
|
||||
m_worldStatic(worldStatic) {}
|
||||
@ -46,7 +51,17 @@ ox::Error World::setupDisplay() noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Result<int> World::update() noexcept {
|
||||
turbine::TimeMs nextUpdateTime = ox::MaxValue<turbine::TimeMs>;
|
||||
m_currentTicks = ticksMs(turbineCtx(m_nctx));
|
||||
for (auto &state : m_objStates) {
|
||||
nextUpdateTime = ox::min(nextUpdateTime, updateObj(state));
|
||||
}
|
||||
return static_cast<int>(nextUpdateTime - m_currentTicks);
|
||||
}
|
||||
|
||||
void World::setupTiles() noexcept {
|
||||
m_currentTicks = ticksMs(turbineCtx(m_nctx));
|
||||
ncore::setBgStatus(m_nctx, 0); // disable all backgrounds
|
||||
for (auto layerNo = 0u; auto const&layer : m_worldStatic.map) {
|
||||
setupLayer(layerNo, layer.cbb);
|
||||
@ -57,7 +72,7 @@ void World::setupTiles() noexcept {
|
||||
void World::setupTile(
|
||||
uint32_t const lyr,
|
||||
uint32_t const x,
|
||||
uint32_t const y) const noexcept {
|
||||
uint32_t const y) noexcept {
|
||||
auto &t = tile(m_worldStatic, lyr, x, y);
|
||||
auto const tx = static_cast<int>(x) * 2;
|
||||
auto const ty = static_cast<int>(y) * 2;
|
||||
@ -78,11 +93,37 @@ void World::setupTile(
|
||||
.tileIdx = static_cast<uint_t>(obj.cbbIdx + 3),
|
||||
.palBank = obj.palBank,
|
||||
});
|
||||
if (isUpdatingObj(obj)) {
|
||||
m_objStates.emplace_back(ObjState{
|
||||
.objIdx = t.objIdxRefSet,
|
||||
.frame = 0,
|
||||
.nextUpdateTime = m_currentTicks + obj.intervalMs,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
turbine::TimeMs World::updateObj(ObjState &state) noexcept {
|
||||
if (state.nextUpdateTime <= m_currentTicks) {
|
||||
auto &obj = m_worldStatic.objTileRefSets[state.objIdx];
|
||||
++state.frame;
|
||||
if (state.frame >= obj.frames) {
|
||||
state.frame = 0;
|
||||
}
|
||||
std::ignore = ncore::loadBgTileSheet(
|
||||
m_nctx,
|
||||
obj.cbb,
|
||||
*m_tilesheets[obj.tilesheetId],
|
||||
obj.cbbIdx,
|
||||
static_cast<size_t>(obj.tilesheetIdx + state.frame * static_cast<uint16_t>(obj.tileCnt)),
|
||||
obj.tileCnt);
|
||||
state.nextUpdateTime = m_currentTicks + obj.intervalMs;
|
||||
}
|
||||
return state.nextUpdateTime;
|
||||
}
|
||||
|
||||
void World::setupLayer(
|
||||
uint_t const lyr,
|
||||
uint_t const cbb) const noexcept {
|
||||
uint_t const cbb) noexcept {
|
||||
ncore::clearBg(m_nctx, lyr);
|
||||
ncore::setBgStatus(m_nctx, lyr, true);
|
||||
ncore::setBgCbb(m_nctx, lyr, cbb);
|
||||
@ -95,20 +136,4 @@ void World::setupLayer(
|
||||
}
|
||||
}
|
||||
|
||||
ox::Result<int> World::update() noexcept {
|
||||
int expiresIn = 60'000;
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
#ifndef OX_OS_BareMetal
|
||||
ox::Result<int> World::editorModeUpdate() noexcept {
|
||||
auto const time = ticksMs(turbineCtx(m_nctx));
|
||||
if (time >= m_nextUpdateTime) {
|
||||
turbine::TimeMs expiresIn = 60'000;
|
||||
m_nextUpdateTime = time + expiresIn;
|
||||
}
|
||||
return static_cast<int>(m_nextUpdateTime - time);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -167,6 +167,7 @@ ox::Result<uint8_t> WorldStaticLoader::setupTileResrc(DocObjRef const&docObjRef)
|
||||
.tilesheetId = tsIdx,
|
||||
.tileCnt = subsheetTileCnt(*subsheet),
|
||||
.frames = obj->frames,
|
||||
.intervalMs = obj->intervalMs,
|
||||
});
|
||||
m_cbbIt += refSet.tileCnt;
|
||||
m_resourcesChanged = true;
|
||||
|
@ -43,11 +43,11 @@ ox::Error run(
|
||||
}
|
||||
setUpdateHandler(*tctx, [](turbine::Context &tctx) -> int {
|
||||
auto &world = *applicationData<world::World>(tctx);
|
||||
auto [sleepTime, err] = world.update();
|
||||
auto const [sleepTime, err] = world.update();
|
||||
if (err) {
|
||||
oxLogError(err);
|
||||
}
|
||||
return 0;
|
||||
return sleepTime;
|
||||
});
|
||||
OX_RETURN_ERROR(turbine::run(*tctx));
|
||||
oxOut("Exiting...\n");
|
||||
|
Reference in New Issue
Block a user