From c42ee94e02005091b631350255c877d9f0b65119 Mon Sep 17 00:00:00 2001 From: fallahn Date: Mon, 8 Jan 2024 21:13:33 +0000 Subject: [PATCH 01/19] bump version number fix zooming map overview on certain controllers --- libsocial/include/Social.hpp | 8 ++++---- samples/golf/buildnumber.h | 4 ++-- samples/golf/golf.aps | Bin 295000 -> 294872 bytes samples/golf/golf.rc | 10 +++++----- samples/golf/src/golf/MapOverviewState.cpp | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libsocial/include/Social.hpp b/libsocial/include/Social.hpp index 1243b9fcf..e90c0393b 100644 --- a/libsocial/include/Social.hpp +++ b/libsocial/include/Social.hpp @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -Matt Marchant 2022 - 2023 +Matt Marchant 2022 - 2024 http://trederia.blogspot.com Super Video Golf - zlib licence. @@ -48,11 +48,11 @@ source distribution. //(player avatar data format changed 1110 -> 1120) //(ball started sending wind effect 1120 -> 1124) //(added night mode/weather 1141 -> 1150) -static constexpr std::uint16_t CURRENT_VER = 1150; +static constexpr std::uint16_t CURRENT_VER = 1151; #ifdef __APPLE__ -static const std::string StringVer("1.15.0 (macOS beta)"); +static const std::string StringVer("1.15.1 (macOS beta)"); #else -static const std::string StringVer("1.15.0"); +static const std::string StringVer("1.15.1"); #endif struct HallEntry final diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 1f2c669cc..7b2d48741 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3690 -#define BUILDNUMBER_STR "3690" +#define BUILDNUMBER 3694 +#define BUILDNUMBER_STR "3694" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/golf.aps b/samples/golf/golf.aps index 65aee58d23bb7fcf9a1937b6562303452e8ca5ff..1783b2ab51454afd6eaf2d57c90d02ef71f15902 100644 GIT binary patch delta 428 zcmaJ+ze|E)5Wf4qQ?wARA&STpEkp7b*^o4aK|wzpg8Ua68Y~?${XW6Kt&~?d1PPm3 zYzPGR)}q;fKw68hO;(yZ1V;jl?=%<{IBxXOphJuCCMa<}+K$-0LhrPQ8} TxUcLKJ4zJMUr&g4^ECAh?u}yO delta 553 zcmah_yGjF55IwUy3PA}fB3c-CeKx*`R+dJ=h=_&agKa{H#KMhavxSM-2ntrd*y8?x zg@q`BkV1bze3pKM7J`LcoV8Fy(7DXxoO=dl=BZNuwApZAQ2fyB=$a}rVk6d^lgc_) zEU}hLtk^~@>)Oe*HI_-bt0_C@98PwhXBLSr{cGAc|CReoTK_WI3Frhcfq9Hdu2cqu z0S43s-)8EruiTxAZA>J~0$6ylI#Pzbl{O*Rr2<9M!%VwUdh=x^9fp=&~ofY^-P+@~z zimTTR?x73SQsfTpihPeE)tAy&tNHg7DFxd-YkzMyBl2O{_4@*SUl)+pPiq$D_=l$d zm!?LPZ&ko7#<3tVj%igXa+l1y=y9tW^|*;PgL;UL)UL;ET5pXy^*BOr>P{eCsh5D| jZ51vFd#n0N0vk;=El{%@We4=5+AZ;bp3bv+Sm%}x LeftThumbDeadZone) { - zoom /= cro::GameController::AxisMax; - m_zoomScale = std::clamp(m_zoomScale + (2.f * zoom * m_zoomScale * dt), MinZoom, MaxZoom); + float zoomRatio = static_cast(zoom) / cro::GameController::AxisMax; + m_zoomScale = std::clamp(m_zoomScale + (2.f * zoomRatio * m_zoomScale * dt), MinZoom, MaxZoom); rescaleMap(); } } From 50c45b5b59f02c32d2efcf4d1df9e406d78558ee Mon Sep 17 00:00:00 2001 From: fallahn Date: Tue, 9 Jan 2024 16:25:13 +0000 Subject: [PATCH 02/19] more track shenanigans --- samples/golf/buildnumber.h | 4 +- samples/scratchpad/scratchpad.vcxproj | 3 + samples/scratchpad/scratchpad.vcxproj.filters | 9 + .../src/endless/EndlessDrivingState.cpp | 180 ++++++++++-------- .../src/endless/EndlessDrivingState.hpp | 8 + samples/scratchpad/src/endless/Track.hpp | 98 ++++++++++ .../scratchpad/src/endless/TrackCamera.hpp | 90 +++++++++ .../scratchpad/src/endless/TrackSegment.hpp | 48 +++++ 8 files changed, 356 insertions(+), 84 deletions(-) create mode 100644 samples/scratchpad/src/endless/Track.hpp create mode 100644 samples/scratchpad/src/endless/TrackCamera.hpp create mode 100644 samples/scratchpad/src/endless/TrackSegment.hpp diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 7b2d48741..a397552c4 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3694 -#define BUILDNUMBER_STR "3694" +#define BUILDNUMBER 3695 +#define BUILDNUMBER_STR "3695" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/scratchpad/scratchpad.vcxproj b/samples/scratchpad/scratchpad.vcxproj index 4f8205883..a7efca71c 100644 --- a/samples/scratchpad/scratchpad.vcxproj +++ b/samples/scratchpad/scratchpad.vcxproj @@ -371,6 +371,9 @@ + + + diff --git a/samples/scratchpad/scratchpad.vcxproj.filters b/samples/scratchpad/scratchpad.vcxproj.filters index 1c45a6517..d06856439 100644 --- a/samples/scratchpad/scratchpad.vcxproj.filters +++ b/samples/scratchpad/scratchpad.vcxproj.filters @@ -434,6 +434,15 @@ Header Files\endless + + Header Files\endless + + + Header Files\endless + + + Header Files\endless + diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 9428b7896..c9f73f26e 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include namespace { @@ -28,24 +30,25 @@ namespace //TODO encapsulate in relative classes //rendering - float roadWidth = 2000.f; //road is +/- this - constexpr float segmentLength = 200.f; - constexpr std::int32_t rumbleLength = 3; //number of segs per strip - constexpr std::int32_t drawDistance = 100; //max number of road segments to process and draw + //float roadWidth = 2000.f; //road is +/- this + //constexpr float segmentLength = 200.f; + //constexpr std::int32_t rumbleLength = 3; //number of segs per strip + //constexpr std::int32_t drawDistance = 100; //max number of road segments to process and draw float trackLength = 100000.f; //total length before looping - float lanes = 3.f; //might be superfluous - float fov = 60.f; + //constexpr float laneCount = 3.f; + //float fogDensity = 5.f; + //float fov = 60.f; float cameraHeight = 1000.f; - float cameraDepth = 0.f; - float fogDensity = 5.f; + float cameraDepth = 1.f; + float camZ = 0.f; //add player z to get absolute player pos + //player specific float playerX = 0.f; //+/- 1 from X centre float playerZ = 0.f; //rel distance from camera - float camZ = 0.f; //add player z to get absolute player pos float speed = 0.f; //TODO constify these - current non-const so we can play with imgui - constexpr float MaxSpeed = segmentLength * 60.f; //60 is our frame time + constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time float acceleration = MaxSpeed / 5.f; float braking = -MaxSpeed; float deceleration = -acceleration; @@ -115,9 +118,6 @@ namespace playerX = std::clamp(playerX, -2.f, 2.f); speed = std::clamp(speed, 0.f, MaxSpeed); - //TODO only update on FOV change - //TODO set fov in rads so we don't have to keep converting - cameraDepth = 1.f / std::tan((fov / 2.f) * cro::Util::Const::degToRad); playerZ = cameraHeight * cameraDepth; //TODO rotate player model with steering @@ -126,77 +126,12 @@ namespace const float x = ((RenderSizeFloat.x / 4.f) * playerX) + (RenderSizeFloat.x / 2.f); const float scale = cameraDepth / playerZ; entity.getComponent().setPosition(glm::vec2(x, 0.f)); - //entity.getComponent().setScale(glm::vec2(scale)); //TODO fix this - } - - - - //TODO move this to own file - struct Point final - { - glm::vec3 world = glm::vec3(0.f); - glm::vec3 camera = glm::vec3(0.f); - glm::vec4 screen = glm::vec4(0.f); - float scale = 1.f; - }; - void project(Point& p, glm::vec3 camera, float cameraDepth) - { - p.camera = p.world - camera; - p.scale = cameraDepth / p.camera.z; - - const auto screenCentre = RenderSizeFloat / 2.f; - p.screen.x = std::round(screenCentre.x + (p.scale * p.camera.x * screenCentre.x)); - p.screen.y = std::round(screenCentre.y + (p.scale * p.camera.y * screenCentre.y)); - p.screen.w = std::round(p.scale * roadWidth * screenCentre.x); - } - - struct Segment final - { - Point p0; - Point p1; - cro::Colour colour; - }; - std::vector road; - - void createRoad() - { - static constexpr std::int32_t SegmentCount = 250; - - for (auto i = 0; i < SegmentCount; ++i) - { - auto& seg = road.emplace_back(); - seg.p0.world.z = i * segmentLength; - seg.p1.world.z = (i + 1) * segmentLength; - - seg.colour = ((i / rumbleLength) % 2) ? cro::Colour::White : cro::Colour::LightGrey; - } - - trackLength = SegmentCount * segmentLength; + entity.getComponent().setScale(glm::vec2(scale)); //TODO fix this } - void updateRoad(float dt, cro::Entity entity) - { - const std::int32_t baseSeg = std::int32_t(camZ / segmentLength) % road.size(); - float maxY = RenderSizeFloat.y; - - for (auto i = 0; i < drawDistance; ++i) - { - //TODO maintain these camera positions somewhere - auto& seg = road[(baseSeg + i) % road.size()]; - project(seg.p0, { playerX * roadWidth, cameraHeight, camZ }, cameraDepth); - project(seg.p1, { playerX * roadWidth, cameraHeight, camZ }, cameraDepth); - if (seg.p0.camera.z < cameraDepth //behind us - || seg.p1.screen.y > maxY) //out of view - { - continue; - } - //TODO insert into vertex array - maxY = seg.p1.screen.y; - } - } } EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Context context) @@ -243,6 +178,11 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::Text("Speed %3.3f", speed); ImGui::Text("PlayerX %3.3f", playerX); + + //ImGui::Text("Camera depth %3.3f", cameraDepth); + ImGui::SliderFloat("Cam height", &cameraHeight, 1.f, 1000.f); + ImGui::SliderFloat("Cam depth", &cameraDepth, 1.f, 1000.f); + ImGui::Text("Scale %3.3f", cameraDepth / playerZ); } ImGui::End(); }); @@ -419,12 +359,29 @@ void EndlessDrivingState::createScene() m_playerEntity = entity; //road - createRoad(); entity = m_gameScene.createEntity(); - entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -8.f)); - entity.addComponent(); + entity.addComponent().setPosition(glm::vec3(320.f, 224.f, -8.f)); + entity.addComponent().setPrimitiveType(GL_TRIANGLES); + //entity.getComponent().setFacing(cro::Drawable2D::Facing::Back); + entity.getComponent().setCullingEnabled(false); //assume we're always visible and skip bounds checking m_roadEntity = entity; + + + auto segmentCount = cro::Util::Random::value(5, 20); + for (auto i = 0; i < segmentCount; ++i) + { + const auto enter = cro::Util::Random::value(EnterMin, EnterMax); + const auto hold = cro::Util::Random::value(HoldMin, HoldMax); + const auto exit = cro::Util::Random::value(ExitMin, ExitMax); + + const float curve = cro::Util::Random::value(0, 1) ? cro::Util::Random::value(CurveMin, CurveMax) : 0.f; + const float hill = cro::Util::Random::value(0, 1) ? cro::Util::Random::value(HillMin, HillMax) * SegmentLength : 0.f; + + m_road.addSegment(enter, hold, exit, curve, hill); + } + + auto resize = [](cro::Camera& cam) { cam.viewport = { 0.f, 0.f, 1.f, 1.f }; @@ -463,4 +420,63 @@ void EndlessDrivingState::createUI() auto& cam = m_uiScene.getActiveCamera().getComponent(); cam.resizeCallback = resize; resize(cam); +} + +void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) +{ + m_trackCamera.move(glm::vec3(0.f, 0.f, speed * dt)); + + const float maxLen = m_road.getSegmentCount() * SegmentLength; + if (m_trackCamera.getPosition().z > maxLen) + { + m_trackCamera.move(glm::vec3(0.f, 0.f, - maxLen)); + } + + std::size_t start = static_cast(m_trackCamera.getPosition().z / SegmentLength); + float x = 0.f; + float dx = 0.f; + auto camPos = m_trackCamera.getPosition(); + float maxY = RenderSizeFloat.y; + + const auto trackHeight = m_road[start % m_road.getSegmentCount()].position.y; + m_trackCamera.move(glm::vec3(0.f, trackHeight, 0.f)); + + for (auto i = start; i < start + DrawDistance; ++i) + { + //TODO as this is a loop we can just save the current to prev + //every iteration. + const auto& prev = m_road[(i - 1) % m_road.getSegmentCount()]; + const auto& curr = m_road[i % m_road.getSegmentCount()]; + + if (i - 1 >= m_road.getSegmentCount()) + { + m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); + } + m_trackCamera.setX(camPos.x - x); + auto prevProj = m_trackCamera.getScreenProjection(prev, glm::vec3(0.f), RenderSizeFloat); + + + //increment + dx += curr.curve; + x += dx; + + if (i >= m_road.getSegmentCount()) + { + m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); + } + m_trackCamera.setX(camPos.x - x); + auto currProj = m_trackCamera.getScreenProjection(curr, glm::vec3(0.f), RenderSizeFloat); + + //cull OOB segments + if (currProj.z < m_trackCamera.getDepth() + || currProj.y > maxY) + { + continue; + } + + + //TODO update vertex array + } + + m_trackCamera.setPosition(camPos); } \ No newline at end of file diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index fdfbf0388..c23ef1558 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -3,6 +3,8 @@ #pragma once #include "../StateIDs.hpp" +#include "TrackCamera.hpp" +#include "Track.hpp" #include #include @@ -41,10 +43,16 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient cro::RenderTexture m_gameTexture; cro::Entity m_gameEntity; + //logic ents + TrackCamera m_trackCamera; + Track m_road; + void addSystems(); void loadAssets(); void createPlayer(); void createScene(); void createUI(); + + void updateRoad(float dt, cro::Entity entity); }; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp new file mode 100644 index 000000000..4143e260c --- /dev/null +++ b/samples/scratchpad/src/endless/Track.hpp @@ -0,0 +1,98 @@ +/*----------------------------------------------------------------------- + +Matt Marchant 2024 +http://trederia.blogspot.com + +crogine application - Zlib license. + +This software is provided 'as-is', without any express or +implied warranty.In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions : + +1. The origin of this software must not be misrepresented; +you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment +in the product documentation would be appreciated but +is not required. + +2. Altered source versions must be plainly marked as such, +and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any +source distribution. + + +Based on articles: http://www.extentofthejam.com/pseudo/ + https://codeincomplete.com/articles/javascript-racer/ + +-----------------------------------------------------------------------*/ + +#pragma once + +#include "TrackSegment.hpp" + +#include +#include + +#include + +static inline constexpr float SegmentLength = 250.f; +static inline constexpr float RoadWidth = 2500.f; + +static inline constexpr std::size_t EnterMin = 30; +static inline constexpr std::size_t EnterMax = 100; +static inline constexpr std::size_t HoldMin = 150; +static inline constexpr std::size_t HoldMax = 500; +static inline constexpr std::size_t ExitMin = EnterMin; +static inline constexpr std::size_t ExitMax = EnterMax; + +static inline constexpr float CurveMin = -10.f; +static inline constexpr float CurveMax = 10.f; +static inline constexpr float HillMin = -60.f; +static inline constexpr float HillMax = 60.f; + +static inline constexpr std::int32_t DrawDistance = 100; //number of segs + +class Track final +{ +public: + std::size_t getSegmentCount() const { return m_segments.size(); } + + void addSegment(std::size_t enter, std::size_t hold, std::size_t exit, float curve, float hill) + { + const float z = m_segments.size() * SegmentLength; + std::size_t i = 0; + std::size_t end = enter; + + for (; i < end; ++i) + { + const float progress = static_cast(i) / enter; + glm::vec3 pos(0.f, hill * cro::Util::Easing::easeInOutSine(progress), z + (i * SegmentLength)); + m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * cro::Util::Easing::easeInSine(progress)); + } + + end += hold; + for (; i < end; ++i) + { + glm::vec3 pos(0.f, hill, z + (i * SegmentLength)); + m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve); + } + + end += exit; + for (; i < end; ++i) + { + const float progress = static_cast(i - enter - hold) / exit; + glm::vec3 pos(0.f, 1.f - (hill * cro::Util::Easing::easeInOutSine(progress)), z + (i * SegmentLength)); + m_segments.emplace_back(pos, SegmentLength, RoadWidth, 1.f - (curve * cro::Util::Easing::easeOutSine(progress))); + } + } + + const TrackSegment& operator[](std::size_t i)const { return m_segments[i]; } + +private: + std::vector m_segments; +}; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp new file mode 100644 index 000000000..ca8a9b1cd --- /dev/null +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -0,0 +1,90 @@ +/*----------------------------------------------------------------------- + +Matt Marchant 2024 +http://trederia.blogspot.com + +crogine application - Zlib license. + +This software is provided 'as-is', without any express or +implied warranty.In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions : + +1. The origin of this software must not be misrepresented; +you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment +in the product documentation would be appreciated but +is not required. + +2. Altered source versions must be plainly marked as such, +and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any +source distribution. + + +Based on articles: http://www.extentofthejam.com/pseudo/ + https://codeincomplete.com/articles/javascript-racer/ + +-----------------------------------------------------------------------*/ + +#pragma once + +#include "TrackSegment.hpp" + +#include +#include + +#include + +#include + +class TrackCamera final +{ +public: + TrackCamera() + { + setFOV(m_fov); + } + + glm::vec3 getPosition() const { return m_position; } + float getFOV() const { return m_fov; } + float getDepth() const { return m_depth; } + + glm::vec3 getScreenProjection(const TrackSegment segment, glm::vec3 playerPos, glm::vec2 screenSize) + { + auto translation = segment.position - m_position; + translation.x -= playerPos.x; + + const float scale = (m_depth / translation.z); + auto projection = translation * scale; + projection.z = segment.width * scale; + + //scale to the output + return glm::vec3( + (screenSize.x / 2.f) * (1.f + projection.x), + (screenSize.y / 2.f) * (1.f + projection.y), + (screenSize.x / 2.f) * projection.z); + } + + void setPosition(glm::vec3 p) { m_position = p; } + void setFOV(float fov) + { + m_fov = fov; + m_depth = 1.f / std::tan((m_fov / 2.f) * cro::Util::Const::degToRad); + } + + void move(glm::vec3 m) { m_position += m; } + void setX(float f) { m_position.x = f; } + void setY(float f) { m_position.y = f; } + void setZ(float f) { m_position.z = f; } + +private: + float m_fov = 80.f; + float m_depth = 1.f; //normalised + + glm::vec3 m_position = glm::vec3(0.f); +}; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/TrackSegment.hpp b/samples/scratchpad/src/endless/TrackSegment.hpp new file mode 100644 index 000000000..4e3aa6f26 --- /dev/null +++ b/samples/scratchpad/src/endless/TrackSegment.hpp @@ -0,0 +1,48 @@ +/*----------------------------------------------------------------------- + +Matt Marchant 2024 +http://trederia.blogspot.com + +crogine application - Zlib license. + +This software is provided 'as-is', without any express or +implied warranty.In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions : + +1. The origin of this software must not be misrepresented; +you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment +in the product documentation would be appreciated but +is not required. + +2. Altered source versions must be plainly marked as such, +and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any +source distribution. + + +Based on articles: http://www.extentofthejam.com/pseudo/ + https://codeincomplete.com/articles/javascript-racer/ + +-----------------------------------------------------------------------*/ + +#pragma once + +#include + +struct TrackSegment final +{ + glm::vec3 position = glm::vec3(0.f); + float length = 200.f; + float width = 2000.f; + float curve = 0.f; + + TrackSegment() = default; + TrackSegment(glm::vec3 p, float l, float w, float c) + : position(p), length(l), width(w), curve(c) {} +}; \ No newline at end of file From 1e5e269630c8b255fe066600c861b93fb7fa47f5 Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 10:02:51 +0000 Subject: [PATCH 03/19] add random weather option --- samples/golf/buildnumber.h | 4 ++-- samples/golf/src/golf/GameConsts.hpp | 4 +++- samples/golf/src/golf/GolfState.cpp | 5 +++++ samples/golf/src/golf/GolfStateUI.cpp | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index a397552c4..1b96f1fed 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3695 -#define BUILDNUMBER_STR "3695" +#define BUILDNUMBER 3696 +#define BUILDNUMBER_STR "3696" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/golf/GameConsts.hpp b/samples/golf/src/golf/GameConsts.hpp index 008c4521e..53f4bfc91 100644 --- a/samples/golf/src/golf/GameConsts.hpp +++ b/samples/golf/src/golf/GameConsts.hpp @@ -150,6 +150,7 @@ struct WeatherType final enum { Clear, Rain, Showers, Mist, + Random, Count, Snow }; @@ -157,7 +158,8 @@ struct WeatherType final static inline const std::array WeatherStrings = { "Clear", "Rain", - "Showers", "Mist" + "Showers", "Mist", + "Random" }; struct MRTIndex final diff --git a/samples/golf/src/golf/GolfState.cpp b/samples/golf/src/golf/GolfState.cpp index cafc15959..d252afdad 100644 --- a/samples/golf/src/golf/GolfState.cpp +++ b/samples/golf/src/golf/GolfState.cpp @@ -194,6 +194,11 @@ GolfState::GolfState(cro::StateStack& stack, cro::State::Context context, Shared m_courseIndex (getCourseIndex(sd.mapDirectory.toAnsiString())), m_emoteWheel (sd, m_currentPlayer, m_textChat) { + if (sd.weatherType == WeatherType::Random) + { + sd.weatherType = cro::Util::Random::value(WeatherType::Clear, WeatherType::Mist); + } + sd.holesPlayed = 0; m_cpuGolfer.setFastCPU(m_sharedData.fastCPU); diff --git a/samples/golf/src/golf/GolfStateUI.cpp b/samples/golf/src/golf/GolfStateUI.cpp index ad5d2ae46..5c6406152 100644 --- a/samples/golf/src/golf/GolfStateUI.cpp +++ b/samples/golf/src/golf/GolfStateUI.cpp @@ -1693,7 +1693,7 @@ void GolfState::showCountdown(std::uint8_t seconds) Achievements::incrementStat(StatStrings[StatID::PlaysInClearWeather + m_sharedData.weatherType]); std::int32_t weatherProgress = 0; - for (auto i = 0; i < WeatherType::Count; ++i) + for (auto i = 0; i < WeatherType::Random; ++i) { if (Achievements::getStat(StatStrings[StatID::PlaysInClearWeather + i])->value != 0) { From 06eaf0fed3c40a8c0e68d112246f2d8927ef2b2f Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 10:14:12 +0000 Subject: [PATCH 04/19] only track playtime for workshop items on the local client --- samples/golf/buildnumber.h | 4 ++-- samples/golf/src/golf/GolfState.cpp | 3 ++- samples/golf/src/golf/GolfStateAssets.cpp | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 1b96f1fed..0833f5865 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3696 -#define BUILDNUMBER_STR "3696" +#define BUILDNUMBER 3697 +#define BUILDNUMBER_STR "3697" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/golf/GolfState.cpp b/samples/golf/src/golf/GolfState.cpp index d252afdad..8b1a04df5 100644 --- a/samples/golf/src/golf/GolfState.cpp +++ b/samples/golf/src/golf/GolfState.cpp @@ -3150,7 +3150,8 @@ void GolfState::spawnBall(const ActorInfo& info) m_ballModels[ballID]->createModel(entity); applyMaterialData(*m_ballModels[ballID], material); #ifdef USE_GNS - if (ball->workshopID) + if (ball->workshopID + && info.clientID == m_sharedData.localConnectionData.connectionID) { std::vector v; v.push_back(ball->workshopID); diff --git a/samples/golf/src/golf/GolfStateAssets.cpp b/samples/golf/src/golf/GolfStateAssets.cpp index 3b990d596..98c521d39 100644 --- a/samples/golf/src/golf/GolfStateAssets.cpp +++ b/samples/golf/src/golf/GolfStateAssets.cpp @@ -1893,7 +1893,8 @@ void GolfState::loadModels() e.getComponent().setHidden(entity.getComponent().isHidden()); }; - if (m_sharedData.hairInfo[hairID].workshopID) + if (m_sharedData.hairInfo[hairID].workshopID + && i == m_sharedData.localConnectionData.connectionID) { m_modelStats.push_back(m_sharedData.hairInfo[hairID].workshopID); } @@ -1905,7 +1906,8 @@ void GolfState::loadModels() entity.getComponent().setRenderFlags(~RenderFlags::CubeMap); m_avatars[i][j].model = entity; - if (m_sharedData.avatarInfo[avatarIndex].workshopID) + if (m_sharedData.avatarInfo[avatarIndex].workshopID + && i == m_sharedData.localConnectionData.connectionID) { m_modelStats.push_back(m_sharedData.avatarInfo[avatarIndex].workshopID); } From a5fe8c12cf16b4d7ecd48e1d9efdfcb81f3e18d8 Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 10:47:12 +0000 Subject: [PATCH 05/19] fix hole numbering on overviw image when playing in reverse --- samples/golf/buildnumber.h | 4 ++-- samples/golf/src/golf/GameConsts.hpp | 2 +- samples/golf/src/golf/GolfState.cpp | 3 ++- samples/golf/src/golf/GolfStateAssets.cpp | 2 +- samples/golf/src/golf/MapOverviewState.cpp | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 0833f5865..daa316c2d 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3697 -#define BUILDNUMBER_STR "3697" +#define BUILDNUMBER 3699 +#define BUILDNUMBER_STR "3699" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/golf/GameConsts.hpp b/samples/golf/src/golf/GameConsts.hpp index 53f4bfc91..aa63f16cc 100644 --- a/samples/golf/src/golf/GameConsts.hpp +++ b/samples/golf/src/golf/GameConsts.hpp @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -Matt Marchant 2021 - 2023 +Matt Marchant 2021 - 2024 http://trederia.blogspot.com Super Video Golf - zlib licence. diff --git a/samples/golf/src/golf/GolfState.cpp b/samples/golf/src/golf/GolfState.cpp index 8b1a04df5..aacfbcc9c 100644 --- a/samples/golf/src/golf/GolfState.cpp +++ b/samples/golf/src/golf/GolfState.cpp @@ -4928,7 +4928,8 @@ void GolfState::setCurrentHole(std::uint16_t holeInfo) #ifdef USE_GNS m_sharedData.minimapData.courseName += Social::getLeader(m_sharedData.mapDirectory, m_sharedData.holeCount); #endif - m_sharedData.minimapData.courseName += "\nHole: " + std::to_string(m_sharedData.minimapData.holeNumber + 2); //this isn't updated until the map texture is + std::int32_t offset = m_sharedData.reverseCourse ? 0 : 2; + m_sharedData.minimapData.courseName += "\nHole: " + std::to_string(m_sharedData.minimapData.holeNumber + offset); //this isn't updated until the map texture is m_sharedData.minimapData.courseName += "\nPar: " + std::to_string(m_holeData[m_currentHole].par); m_gameScene.getDirector()->setCrowdPositions(m_holeData[m_currentHole].crowdPositions); } diff --git a/samples/golf/src/golf/GolfStateAssets.cpp b/samples/golf/src/golf/GolfStateAssets.cpp index 98c521d39..c796e586b 100644 --- a/samples/golf/src/golf/GolfStateAssets.cpp +++ b/samples/golf/src/golf/GolfStateAssets.cpp @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -Matt Marchant 2021 - 2023 +Matt Marchant 2021 - 2024 http://trederia.blogspot.com Super Video Golf - zlib licence. diff --git a/samples/golf/src/golf/MapOverviewState.cpp b/samples/golf/src/golf/MapOverviewState.cpp index 641c3e7aa..38f84d031 100644 --- a/samples/golf/src/golf/MapOverviewState.cpp +++ b/samples/golf/src/golf/MapOverviewState.cpp @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -Matt Marchant 2021 - 2023 +Matt Marchant 2021 - 2024 http://trederia.blogspot.com Super Video Golf - zlib licence. From b232841da3bf47547f1c8cdaa6397861b30242ba Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 13:04:40 +0000 Subject: [PATCH 06/19] track rendering (ish) --- .../src/endless/EndlessDrivingState.cpp | 60 +++++++++++++++---- .../src/endless/EndlessDrivingState.hpp | 2 + .../scratchpad/src/endless/TrackCamera.hpp | 2 +- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index c9f73f26e..fbcde81f2 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -72,11 +72,11 @@ namespace void updatePlayer(float dt, cro::Entity entity) { //I'm sure there are better ways to wrap around but meh - camZ += speed * dt; + /*camZ += speed * dt; if (camZ > trackLength) { camZ -= trackLength; - } + }*/ const float dx = dt * 2.f * (speed / MaxSpeed); if (inputFlags.flags & InputFlags::Left) @@ -360,14 +360,13 @@ void EndlessDrivingState::createScene() //road entity = m_gameScene.createEntity(); - entity.addComponent().setPosition(glm::vec3(320.f, 224.f, -8.f)); + entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -8.f)); entity.addComponent().setPrimitiveType(GL_TRIANGLES); - //entity.getComponent().setFacing(cro::Drawable2D::Facing::Back); + entity.getComponent().setFacing(cro::Drawable2D::Facing::Back); entity.getComponent().setCullingEnabled(false); //assume we're always visible and skip bounds checking m_roadEntity = entity; - auto segmentCount = cro::Util::Random::value(5, 20); for (auto i = 0; i < segmentCount; ++i) { @@ -381,6 +380,7 @@ void EndlessDrivingState::createScene() m_road.addSegment(enter, hold, exit, curve, hill); } + //m_road.addSegment(EnterMin, HoldMin, ExitMin, 0.f, 0.f); auto resize = [](cro::Camera& cam) { @@ -425,7 +425,7 @@ void EndlessDrivingState::createUI() void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) { m_trackCamera.move(glm::vec3(0.f, 0.f, speed * dt)); - + //return; const float maxLen = m_road.getSegmentCount() * SegmentLength; if (m_trackCamera.getPosition().z > maxLen) { @@ -438,14 +438,15 @@ void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) auto camPos = m_trackCamera.getPosition(); float maxY = RenderSizeFloat.y; + std::vector verts; + const float halfWidth = RenderSizeFloat.x / 2.f; + const auto trackHeight = m_road[start % m_road.getSegmentCount()].position.y; m_trackCamera.move(glm::vec3(0.f, trackHeight, 0.f)); + auto prev = m_road[(start - 1) % m_road.getSegmentCount()]; for (auto i = start; i < start + DrawDistance; ++i) { - //TODO as this is a loop we can just save the current to prev - //every iteration. - const auto& prev = m_road[(i - 1) % m_road.getSegmentCount()]; const auto& curr = m_road[i % m_road.getSegmentCount()]; if (i - 1 >= m_road.getSegmentCount()) @@ -467,16 +468,51 @@ void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) m_trackCamera.setX(camPos.x - x); auto currProj = m_trackCamera.getScreenProjection(curr, glm::vec3(0.f), RenderSizeFloat); + prev = curr; + //cull OOB segments - if (currProj.z < m_trackCamera.getDepth() - || currProj.y > maxY) + if (currProj.z <= m_trackCamera.getDepth() + || currProj.y >= maxY) { continue; } + maxY = RenderSizeFloat.y - currProj.y; + + //update vertex array + cro::Colour roadColour = ((i / 3) % 2) ? cro::Colour(std::uint8_t(100), 100, 100) : cro::Colour(std::uint8_t(120), 120, 120); + cro::Colour grassColour = ((i / 3) % 2) ? cro::Colour(std::uint8_t(0), 168, 0) : cro::Colour(std::uint8_t(0), 190, 0); + cro::Colour rumbleColour = ((i / 9) % 2) ? cro::Colour::Red : cro::Colour::White; + + bool roadLine = ((i / 6) % 2); + + //grass + addRoadQuad(halfWidth, halfWidth, prevProj.y, currProj.y, halfWidth, halfWidth, grassColour, verts); + //rumble strip + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 1.1f, currProj.z * 1.1f, rumbleColour, verts); - //TODO update vertex array + //road + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z, currProj.z, roadColour, verts); + + //markings + if (roadLine) + { + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 0.02f, currProj.z * 0.02f, cro::Colour::White, verts); + } } + //addRoadQuad(320.f, 320.f, 0.f, 100.f, 320.f, 320.f, cro::Colour::Magenta, verts); + m_roadEntity.getComponent().getVertexData().swap(verts); m_trackCamera.setPosition(camPos); +} + +void EndlessDrivingState::addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour c, std::vector& dst) +{ + dst.emplace_back(glm::vec2(x1 - w1, y1), c); + dst.emplace_back(glm::vec2(x2 - w2, y2), c); + dst.emplace_back(glm::vec2(x1 + w1, y1), c); + + dst.emplace_back(glm::vec2(x1 + w1, y1), c); + dst.emplace_back(glm::vec2(x2 - w2, y2), c); + dst.emplace_back(glm::vec2(x2 + w2, y2), c); } \ No newline at end of file diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index c23ef1558..fd2546e3c 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -11,6 +11,7 @@ #include #include #include +#include class EndlessDrivingState final : public cro::State, public cro::GuiClient { @@ -55,4 +56,5 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void updateRoad(float dt, cro::Entity entity); + void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); }; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp index ca8a9b1cd..248d5ce90 100644 --- a/samples/scratchpad/src/endless/TrackCamera.hpp +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -86,5 +86,5 @@ class TrackCamera final float m_fov = 80.f; float m_depth = 1.f; //normalised - glm::vec3 m_position = glm::vec3(0.f); + glm::vec3 m_position = glm::vec3(0.f, 1800.f, 0.f); }; \ No newline at end of file From c61e2d1ad8f01be3c821362738932558cdacdaef Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 15:47:24 +0000 Subject: [PATCH 07/19] update track rendering --- .../src/endless/EndlessDrivingState.cpp | 85 +++++++++++++------ .../src/endless/EndlessDrivingState.hpp | 15 ++++ samples/scratchpad/src/endless/Track.hpp | 34 +++++--- .../scratchpad/src/endless/TrackSegment.hpp | 6 ++ 4 files changed, 103 insertions(+), 37 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index fbcde81f2..168e16b3c 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -23,8 +23,8 @@ namespace { //TODO move these to some Const header - constexpr glm::uvec2 PlayerSize = glm::uvec2(160); - constexpr glm::uvec2 RenderSize = glm::uvec2(640, 448); + constexpr glm::uvec2 PlayerSize = glm::uvec2(80); + constexpr glm::uvec2 RenderSize = glm::uvec2(320, 224); constexpr glm::vec2 RenderSizeFloat = glm::vec2(RenderSize); //TODO encapsulate in relative classes @@ -71,13 +71,6 @@ namespace //TODO move this to player class void updatePlayer(float dt, cro::Entity entity) { - //I'm sure there are better ways to wrap around but meh - /*camZ += speed * dt; - if (camZ > trackLength) - { - camZ -= trackLength; - }*/ - const float dx = dt * 2.f * (speed / MaxSpeed); if (inputFlags.flags & InputFlags::Left) { @@ -130,8 +123,18 @@ namespace } + constexpr float fogDensity = 5.f; + float expFog(float distance, float density) + { + float fogAmount = 1.f / (std::pow(cro::Util::Const::E, (distance * distance * density))); + fogAmount = (0.5f * (1.f - fogAmount)); + fogAmount = std::round(fogAmount * 25.f); + fogAmount /= 25.f; + return fogAmount; + } + const cro::Colour FogColour = cro::Colour::Teal; } EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Context context) @@ -334,21 +337,35 @@ void EndlessDrivingState::createPlayer() void EndlessDrivingState::createScene() { //background + auto* tex = &m_resources.textures.get("assets/cars/sky.png"); + tex->setRepeated(true); auto entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.5f)); entity.addComponent(); - entity.addComponent(m_resources.textures.get("assets/cars/sky.png")); + entity.addComponent(*tex); + m_background[BackgroundLayer::Sky].entity = entity; + m_background[BackgroundLayer::Sky].textureRect = entity.getComponent().getTextureRect(); + m_background[BackgroundLayer::Sky].speed = 0.04f; + tex = &m_resources.textures.get("assets/cars/hills.png"); + tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.4f)); entity.addComponent(); - entity.addComponent(m_resources.textures.get("assets/cars/hills.png")); + entity.addComponent(*tex); + m_background[BackgroundLayer::Hills].entity = entity; + m_background[BackgroundLayer::Hills].textureRect = entity.getComponent().getTextureRect(); + m_background[BackgroundLayer::Hills].speed = 0.08f; + tex = &m_resources.textures.get("assets/cars/trees.png"); + tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.3f)); entity.addComponent(); - entity.addComponent(m_resources.textures.get("assets/cars/trees.png")); - + entity.addComponent(*tex); + m_background[BackgroundLayer::Trees].entity = entity; + m_background[BackgroundLayer::Trees].textureRect = entity.getComponent().getTextureRect(); + m_background[BackgroundLayer::Trees].speed = 0.12f; //player entity = m_gameScene.createEntity(); @@ -379,6 +396,8 @@ void EndlessDrivingState::createScene() m_road.addSegment(enter, hold, exit, curve, hill); } + m_road[m_road.getSegmentCount() - 1].roadColour = cro::Colour::White; + m_road[m_road.getSegmentCount() - 1].rumbleColour = cro::Colour::Blue; //m_road.addSegment(EnterMin, HoldMin, ExitMin, 0.f, 0.f); @@ -424,8 +443,10 @@ void EndlessDrivingState::createUI() void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) { - m_trackCamera.move(glm::vec3(0.f, 0.f, speed * dt)); - //return; + const float s = /*speed*/ MaxSpeed; + + m_trackCamera.move(glm::vec3(0.f, 0.f, s * dt)); + const float maxLen = m_road.getSegmentCount() * SegmentLength; if (m_trackCamera.getPosition().z > maxLen) { @@ -471,38 +492,48 @@ void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) prev = curr; //cull OOB segments - if (currProj.z <= m_trackCamera.getDepth() - || currProj.y >= maxY) + if (prevProj.z < m_trackCamera.getDepth() + || currProj.y > maxY) { continue; } maxY = RenderSizeFloat.y - currProj.y; //update vertex array - cro::Colour roadColour = ((i / 3) % 2) ? cro::Colour(std::uint8_t(100), 100, 100) : cro::Colour(std::uint8_t(120), 120, 120); - cro::Colour grassColour = ((i / 3) % 2) ? cro::Colour(std::uint8_t(0), 168, 0) : cro::Colour(std::uint8_t(0), 190, 0); - cro::Colour rumbleColour = ((i / 9) % 2) ? cro::Colour::Red : cro::Colour::White; - - bool roadLine = ((i / 6) % 2); - + float fogAmount = expFog(static_cast(i - start) / DrawDistance, fogDensity); + //grass - addRoadQuad(halfWidth, halfWidth, prevProj.y, currProj.y, halfWidth, halfWidth, grassColour, verts); + auto colour = glm::mix(curr.grassColour.getVec4(), FogColour.getVec4(), fogAmount); + addRoadQuad(halfWidth, halfWidth, prevProj.y, currProj.y, halfWidth, halfWidth, colour, verts); //rumble strip - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 1.1f, currProj.z * 1.1f, rumbleColour, verts); + colour = glm::mix(curr.rumbleColour.getVec4(), FogColour.getVec4(), fogAmount); + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 1.1f, currProj.z * 1.1f, curr.rumbleColour, verts); //road - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z, currProj.z, roadColour, verts); + colour = glm::mix(curr.roadColour.getVec4(), FogColour.getVec4(), fogAmount); + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z, currProj.z, curr.roadColour, verts); //markings - if (roadLine) + if (curr.roadMarking) { addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 0.02f, currProj.z * 0.02f, cro::Colour::White, verts); } + } //addRoadQuad(320.f, 320.f, 0.f, 100.f, 320.f, 320.f, cro::Colour::Magenta, verts); m_roadEntity.getComponent().getVertexData().swap(verts); + + //update the background + const float speedRatio = s / MaxSpeed; + for (auto& layer : m_background) + { + //TODO scroll vertically with hills + layer.textureRect.left += layer.speed * m_road[start].curve * speedRatio; + layer.entity.getComponent().setTextureRect(layer.textureRect); + } + m_trackCamera.setPosition(camPos); } diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index fd2546e3c..1aa780ca9 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -13,6 +13,8 @@ #include #include +#include + class EndlessDrivingState final : public cro::State, public cro::GuiClient { public: @@ -34,6 +36,19 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient cro::Scene m_uiScene; cro::ResourceCollection m_resources; + struct BackgroundLayer final + { + cro::Entity entity; + cro::FloatRect textureRect; + float speed = 0.f; + enum + { + Sky, Hills, Trees, + Count + }; + }; + std::array m_background = {}; + //buffer for player sprite cro::RenderTexture m_playerTexture; cro::Entity m_playerEntity; diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 4143e260c..ea59a7f57 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -35,13 +35,14 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #include "TrackSegment.hpp" +#include #include #include #include static inline constexpr float SegmentLength = 250.f; -static inline constexpr float RoadWidth = 2500.f; +static inline constexpr float RoadWidth = 1500.f; static inline constexpr std::size_t EnterMin = 30; static inline constexpr std::size_t EnterMax = 100; @@ -50,12 +51,12 @@ static inline constexpr std::size_t HoldMax = 500; static inline constexpr std::size_t ExitMin = EnterMin; static inline constexpr std::size_t ExitMax = EnterMax; -static inline constexpr float CurveMin = -10.f; -static inline constexpr float CurveMax = 10.f; -static inline constexpr float HillMin = -60.f; -static inline constexpr float HillMax = 60.f; +static inline constexpr float CurveMin = -5.f; +static inline constexpr float CurveMax = 5.f; +static inline constexpr float HillMin = -30.f; +static inline constexpr float HillMax = 30.f; -static inline constexpr std::int32_t DrawDistance = 100; //number of segs +static inline constexpr std::int32_t DrawDistance = 200; //number of segs class Track final { @@ -65,33 +66,46 @@ class Track final void addSegment(std::size_t enter, std::size_t hold, std::size_t exit, float curve, float hill) { const float z = m_segments.size() * SegmentLength; + const std::size_t start = m_segments.size(); + std::size_t i = 0; std::size_t end = enter; + const auto setColour = + [&](TrackSegment& seg) + { + seg.roadColour = (((start + i) / 3) % 2) ? cro::Colour(0.45f, 0.45f, 0.45f) : cro::Colour(0.4f, 0.4f, 0.4f); + seg.grassColour = (((start + i) / 3) % 2) ? cro::Colour(0.f, 0.65f, 0.f) : cro::Colour(0.f, 0.75f, 0.f); + seg.rumbleColour = (((start + i) / 9) % 2) ? cro::Colour::Red : cro::Colour::White; + + seg.roadMarking = (((start + i) / 6) % 2); + }; + for (; i < end; ++i) { const float progress = static_cast(i) / enter; glm::vec3 pos(0.f, hill * cro::Util::Easing::easeInOutSine(progress), z + (i * SegmentLength)); - m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * cro::Util::Easing::easeInSine(progress)); + setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * cro::Util::Easing::easeInSine(progress))); } end += hold; for (; i < end; ++i) { glm::vec3 pos(0.f, hill, z + (i * SegmentLength)); - m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve); + setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve)); } end += exit; for (; i < end; ++i) { const float progress = static_cast(i - enter - hold) / exit; - glm::vec3 pos(0.f, 1.f - (hill * cro::Util::Easing::easeInOutSine(progress)), z + (i * SegmentLength)); - m_segments.emplace_back(pos, SegmentLength, RoadWidth, 1.f - (curve * cro::Util::Easing::easeOutSine(progress))); + glm::vec3 pos(0.f, hill * (1.f - cro::Util::Easing::easeInOutSine(progress)), z + (i * SegmentLength)); + setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * (1.f - cro::Util::Easing::easeOutSine(progress)))); } } const TrackSegment& operator[](std::size_t i)const { return m_segments[i]; } + TrackSegment& operator[](std::size_t i) { return m_segments[i]; } private: std::vector m_segments; diff --git a/samples/scratchpad/src/endless/TrackSegment.hpp b/samples/scratchpad/src/endless/TrackSegment.hpp index 4e3aa6f26..aded88533 100644 --- a/samples/scratchpad/src/endless/TrackSegment.hpp +++ b/samples/scratchpad/src/endless/TrackSegment.hpp @@ -33,6 +33,7 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #pragma once +#include #include struct TrackSegment final @@ -42,6 +43,11 @@ struct TrackSegment final float width = 2000.f; float curve = 0.f; + cro::Colour roadColour; + cro::Colour rumbleColour; + cro::Colour grassColour; + bool roadMarking = false; + TrackSegment() = default; TrackSegment(glm::vec3 p, float l, float w, float c) : position(p), length(l), width(w), curve(c) {} From 1874094a2b0738d80f6fd9c5cee901f5b793e8b5 Mon Sep 17 00:00:00 2001 From: fallahn Date: Wed, 10 Jan 2024 16:03:57 +0000 Subject: [PATCH 08/19] begin refactor of player sprite --- .../src/endless/EndlessDrivingState.cpp | 143 ++++++++---------- .../src/endless/EndlessDrivingState.hpp | 4 +- 2 files changed, 63 insertions(+), 84 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 168e16b3c..962c89cd5 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -28,26 +28,12 @@ namespace constexpr glm::vec2 RenderSizeFloat = glm::vec2(RenderSize); //TODO encapsulate in relative classes - - //rendering - //float roadWidth = 2000.f; //road is +/- this - //constexpr float segmentLength = 200.f; - //constexpr std::int32_t rumbleLength = 3; //number of segs per strip - //constexpr std::int32_t drawDistance = 100; //max number of road segments to process and draw - float trackLength = 100000.f; //total length before looping - //constexpr float laneCount = 3.f; - //float fogDensity = 5.f; - //float fov = 60.f; - float cameraHeight = 1000.f; - float cameraDepth = 1.f; - float camZ = 0.f; //add player z to get absolute player pos - - + //player specific float playerX = 0.f; //+/- 1 from X centre float playerZ = 0.f; //rel distance from camera float speed = 0.f; - //TODO constify these - current non-const so we can play with imgui + //TODO constify these - currently non-const so we can play with imgui constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time float acceleration = MaxSpeed / 5.f; float braking = -MaxSpeed; @@ -68,61 +54,6 @@ namespace std::uint16_t prevFlags = 0; }inputFlags; - //TODO move this to player class - void updatePlayer(float dt, cro::Entity entity) - { - const float dx = dt * 2.f * (speed / MaxSpeed); - if (inputFlags.flags & InputFlags::Left) - { - playerX -= dx; - } - - if (inputFlags.flags & InputFlags::Right) - { - playerX += dx; - } - - - if ((inputFlags.flags & (InputFlags::Up | InputFlags::Down)) == 0) - { - //free wheel decel - speed += deceleration * dt; - } - else - { - if (inputFlags.flags & InputFlags::Up) - { - speed += acceleration * dt; - } - if (inputFlags.flags & InputFlags::Down) - { - speed += braking * dt; - } - } - - //+/-1 is off road - if ((playerX < -1 || playerX > 1) - && (speed > offroadMaxSpeed)) - { - //slow down - speed += offroadDeceleration * dt; - } - - playerX = std::clamp(playerX, -2.f, 2.f); - speed = std::clamp(speed, 0.f, MaxSpeed); - - playerZ = cameraHeight * cameraDepth; - - //TODO rotate player model with steering - - //update sprite ent position (playerX is +/- 2) - const float x = ((RenderSizeFloat.x / 4.f) * playerX) + (RenderSizeFloat.x / 2.f); - const float scale = cameraDepth / playerZ; - entity.getComponent().setPosition(glm::vec2(x, 0.f)); - entity.getComponent().setScale(glm::vec2(scale)); //TODO fix this - } - - constexpr float fogDensity = 5.f; float expFog(float distance, float density) { @@ -181,11 +112,6 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::Text("Speed %3.3f", speed); ImGui::Text("PlayerX %3.3f", playerX); - - //ImGui::Text("Camera depth %3.3f", cameraDepth); - ImGui::SliderFloat("Cam height", &cameraHeight, 1.f, 1000.f); - ImGui::SliderFloat("Cam depth", &cameraDepth, 1.f, 1000.f); - ImGui::Text("Scale %3.3f", cameraDepth / playerZ); } ImGui::End(); }); @@ -261,8 +187,8 @@ void EndlessDrivingState::handleMessage(const cro::Message& msg) bool EndlessDrivingState::simulate(float dt) { - updateRoad(dt, m_roadEntity); - updatePlayer(dt, m_playerEntity); + updateRoad(dt); + updatePlayer(dt); m_playerScene.simulate(dt); m_gameScene.simulate(dt); @@ -441,9 +367,62 @@ void EndlessDrivingState::createUI() resize(cam); } -void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) +void EndlessDrivingState::updatePlayer(float dt) +{ + const float dx = dt * 2.f * (speed / MaxSpeed); + if (inputFlags.flags & InputFlags::Left) + { + playerX -= dx; + } + + if (inputFlags.flags & InputFlags::Right) + { + playerX += dx; + } + + + if ((inputFlags.flags & (InputFlags::Up | InputFlags::Down)) == 0) + { + //free wheel decel + speed += deceleration * dt; + } + else + { + if (inputFlags.flags & InputFlags::Up) + { + speed += acceleration * dt; + } + if (inputFlags.flags & InputFlags::Down) + { + speed += braking * dt; + } + } + + //is off road + if ((playerX < -1.7f || playerX > 1.7f) + && (speed > offroadMaxSpeed)) + { + //slow down + speed += offroadDeceleration * dt; + } + + playerX = std::clamp(playerX, -2.f, 2.f); + speed = std::clamp(speed, 0.f, MaxSpeed); + + playerZ = m_trackCamera.getDepth() + 0.5f; + + //TODO rotate player model with steering + + //update sprite ent position (playerX is +/- 2) + const float x = ((RenderSizeFloat.x / 4.f) * playerX) + (RenderSizeFloat.x / 2.f); + const float scale = m_trackCamera.getDepth() / playerZ; + m_playerEntity.getComponent().setPosition(glm::vec2(x, 10.f)); + m_playerEntity.getComponent().setScale(glm::vec2(scale)); //TODO fix this +} + +void EndlessDrivingState::updateRoad(float dt) { - const float s = /*speed*/ MaxSpeed; + const float s = speed /*MaxSpeed*/; m_trackCamera.move(glm::vec3(0.f, 0.f, s * dt)); @@ -475,7 +454,7 @@ void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto prevProj = m_trackCamera.getScreenProjection(prev, glm::vec3(0.f), RenderSizeFloat); + auto prevProj = m_trackCamera.getScreenProjection(prev, glm::vec3(playerX, 0.f, playerZ), RenderSizeFloat); //increment @@ -487,7 +466,7 @@ void EndlessDrivingState::updateRoad(float dt, cro::Entity entity) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto currProj = m_trackCamera.getScreenProjection(curr, glm::vec3(0.f), RenderSizeFloat); + auto currProj = m_trackCamera.getScreenProjection(curr, glm::vec3(playerX, 0.f, playerZ), RenderSizeFloat); prev = curr; diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 1aa780ca9..6ea133a41 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -69,7 +69,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void createScene(); void createUI(); - - void updateRoad(float dt, cro::Entity entity); + void updatePlayer(float dt); + void updateRoad(float dt); void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); }; \ No newline at end of file From 2f7354209337a841c7f8eaafe6ca7630c237f906 Mon Sep 17 00:00:00 2001 From: fallahn Date: Thu, 11 Jan 2024 13:35:00 +0000 Subject: [PATCH 09/19] tidy up player rendering tidy up player controls --- samples/golf/buildnumber.h | 4 +- .../src/endless/EndlessDrivingState.cpp | 162 +++++++++--------- .../src/endless/EndlessDrivingState.hpp | 40 ++++- samples/scratchpad/src/endless/Track.hpp | 12 +- .../scratchpad/src/endless/TrackCamera.hpp | 10 +- 5 files changed, 131 insertions(+), 97 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index daa316c2d..9e6b7f1b0 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3699 -#define BUILDNUMBER_STR "3699" +#define BUILDNUMBER 3701 +#define BUILDNUMBER_STR "3701" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 962c89cd5..0df32eb04 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -19,40 +19,14 @@ #include #include #include +#include namespace { - //TODO move these to some Const header constexpr glm::uvec2 PlayerSize = glm::uvec2(80); constexpr glm::uvec2 RenderSize = glm::uvec2(320, 224); constexpr glm::vec2 RenderSizeFloat = glm::vec2(RenderSize); - - //TODO encapsulate in relative classes - - //player specific - float playerX = 0.f; //+/- 1 from X centre - float playerZ = 0.f; //rel distance from camera - float speed = 0.f; - //TODO constify these - currently non-const so we can play with imgui - constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time - float acceleration = MaxSpeed / 5.f; - float braking = -MaxSpeed; - float deceleration = -acceleration; - float offroadDeceleration = -MaxSpeed / 2.f; - float offroadMaxSpeed = MaxSpeed / 4.f; - - struct InputFlags final - { - enum - { - Up = 0x1, - Down = 0x2, - Left = 0x4, - Right = 0x8 - }; - std::uint16_t flags = 0; - std::uint16_t prevFlags = 0; - }inputFlags; + constexpr float fogDensity = 5.f; float expFog(float distance, float density) @@ -88,7 +62,7 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con { static const auto Red = ImVec4(1.f, 0.f, 0.f, 1.f); static const auto Green = ImVec4(0.f, 1.f, 0.f, 1.f); - if (inputFlags.flags & InputFlags::Left) + if (m_inputFlags.flags & InputFlags::Left) { ImGui::PushStyleColor(ImGuiCol_Text, Green); } @@ -99,7 +73,7 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::Text("Left"); ImGui::PopStyleColor(); - if (inputFlags.flags & InputFlags::Right) + if (m_inputFlags.flags & InputFlags::Right) { ImGui::PushStyleColor(ImGuiCol_Text, Green); } @@ -110,8 +84,8 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::Text("Right"); ImGui::PopStyleColor(); - ImGui::Text("Speed %3.3f", speed); - ImGui::Text("PlayerX %3.3f", playerX); + ImGui::Text("Speed %3.3f", m_player.speed); + ImGui::Text("PlayerX %3.3f", m_player.x); } ImGui::End(); }); @@ -138,16 +112,16 @@ bool EndlessDrivingState::handleEvent(const cro::Event& evt) //TODO move this to player/input and read keybinds case SDLK_w: - inputFlags.flags |= InputFlags::Up; + m_inputFlags.flags |= InputFlags::Up; break; case SDLK_s: - inputFlags.flags |= InputFlags::Down; + m_inputFlags.flags |= InputFlags::Down; break; case SDLK_a: - inputFlags.flags |= InputFlags::Left; + m_inputFlags.flags |= InputFlags::Left; break; case SDLK_d: - inputFlags.flags |= InputFlags::Right; + m_inputFlags.flags |= InputFlags::Right; break; } } @@ -158,16 +132,16 @@ bool EndlessDrivingState::handleEvent(const cro::Event& evt) default: break; //TODO move this to player/input and read keybinds case SDLK_w: - inputFlags.flags &= ~InputFlags::Up; + m_inputFlags.flags &= ~InputFlags::Up; break; case SDLK_s: - inputFlags.flags &= ~InputFlags::Down; + m_inputFlags.flags &= ~InputFlags::Down; break; case SDLK_a: - inputFlags.flags &= ~InputFlags::Left; + m_inputFlags.flags &= ~InputFlags::Left; break; case SDLK_d: - inputFlags.flags &= ~InputFlags::Right; + m_inputFlags.flags &= ~InputFlags::Right; break; } } @@ -198,7 +172,7 @@ bool EndlessDrivingState::simulate(float dt) void EndlessDrivingState::render() { - m_playerTexture.clear(cro::Colour::Transparent); + m_playerTexture.clear(cro::Colour::Transparent/*Blue*/); m_playerScene.render(); m_playerTexture.display(); @@ -235,27 +209,29 @@ void EndlessDrivingState::createPlayer() { m_playerTexture.create(PlayerSize.x, PlayerSize.y); + auto entity = m_playerScene.createEntity(); + entity.addComponent(); + cro::ModelDefinition md(m_resources); if (md.loadFromFile("assets/cars/cart.cmt")) { - auto entity = m_playerScene.createEntity(); - entity.addComponent(); md.createModel(entity); } + m_playerEntity = entity; - auto resize = [](cro::Camera& cam) + auto resize = [&](cro::Camera& cam) { cam.viewport = { 0.f, 0.f, 1.f, 1.f }; - cam.setPerspective(cro::Util::Const::degToRad * 54.f, 1.f, 0.1f, 10.f); + cam.setPerspective(cro::Util::Const::degToRad * m_trackCamera.getFOV(), 1.f, 0.1f, 10.f); }; auto& cam = m_playerScene.getActiveCamera().getComponent(); cam.resizeCallback = resize; resize(cam); - m_playerScene.getActiveCamera().getComponent().setPosition({ -2.6f, 1.5f, 0.f }); + m_playerScene.getActiveCamera().getComponent().setPosition({ -2.3f, 1.9f, 0.f }); m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::Y_AXIS, -cro::Util::Const::PI / 2.f); - m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::X_AXIS, -0.28f); + m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::X_AXIS, -0.58f); m_playerScene.getSunlight().getComponent().setRotation(cro::Transform::X_AXIS, -cro::Util::Const::PI / 2.f); } @@ -282,6 +258,7 @@ void EndlessDrivingState::createScene() m_background[BackgroundLayer::Hills].entity = entity; m_background[BackgroundLayer::Hills].textureRect = entity.getComponent().getTextureRect(); m_background[BackgroundLayer::Hills].speed = 0.08f; + m_background[BackgroundLayer::Hills].verticalSpeed = 0.04f; tex = &m_resources.textures.get("assets/cars/trees.png"); tex->setRepeated(true); @@ -292,14 +269,15 @@ void EndlessDrivingState::createScene() m_background[BackgroundLayer::Trees].entity = entity; m_background[BackgroundLayer::Trees].textureRect = entity.getComponent().getTextureRect(); m_background[BackgroundLayer::Trees].speed = 0.12f; + m_background[BackgroundLayer::Trees].verticalSpeed = 0.06f; //player entity = m_gameScene.createEntity(); - entity.addComponent().setPosition(glm::vec3(320.f, 0.f, -0.1f)); + entity.addComponent().setPosition(glm::vec3(160.f, 10.f, -0.1f)); entity.getComponent().setOrigin(glm::vec2(static_cast(PlayerSize.x / 2u), 0.f)); entity.addComponent(); entity.addComponent(m_playerTexture.getTexture()); - m_playerEntity = entity; + //road entity = m_gameScene.createEntity(); @@ -369,60 +347,78 @@ void EndlessDrivingState::createUI() void EndlessDrivingState::updatePlayer(float dt) { - const float dx = dt * 2.f * (speed / MaxSpeed); - if (inputFlags.flags & InputFlags::Left) - { - playerX -= dx; - } + const float speedRatio = (m_player.speed / Player::MaxSpeed); + const float dx = dt * 2.f * speedRatio; - if (inputFlags.flags & InputFlags::Right) + if ((m_inputFlags.flags & (InputFlags::Left | InputFlags::Right)) == 0) { - playerX += dx; + m_player.model.rotationY *= 1.f - (0.1f * speedRatio); } + else + { + if (m_inputFlags.flags & InputFlags::Left) + { + m_player.x -= dx; + m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + dx); + } + if (m_inputFlags.flags & InputFlags::Right) + { + m_player.x += dx; + m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - dx); + } + } + + //centrifuge on curves + static constexpr float Centrifuge = 0.3f; + const std::size_t segID = static_cast(m_trackCamera.getPosition().z / SegmentLength); + m_player.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; + + //uphill/downhill anim + const auto nextID = (segID - 1) % m_road.getSegmentCount(); + m_player.model.rotationX = std::clamp((m_road[segID].position.y - m_road[nextID].position.y) * dt, -Player::Model::MaxX, Player::Model::MaxX); + m_player.model.rotationX *= 1.f - (0.1f * speedRatio); + - if ((inputFlags.flags & (InputFlags::Up | InputFlags::Down)) == 0) + if ((m_inputFlags.flags & (InputFlags::Up | InputFlags::Down)) == 0) { //free wheel decel - speed += deceleration * dt; + m_player.speed += Player::Deceleration * dt; } else { - if (inputFlags.flags & InputFlags::Up) + if (m_inputFlags.flags & InputFlags::Up) { - speed += acceleration * dt; + m_player.speed += Player::Acceleration * dt; } - if (inputFlags.flags & InputFlags::Down) + if (m_inputFlags.flags & InputFlags::Down) { - speed += braking * dt; + m_player.speed += Player::Braking * dt; } } //is off road - if ((playerX < -1.7f || playerX > 1.7f) - && (speed > offroadMaxSpeed)) + if ((m_player.x < -1.f || m_player.x > 1.f) + && (m_player.speed > Player::OffroadMaxSpeed)) { //slow down - speed += offroadDeceleration * dt; + m_player.speed += Player::OffroadDeceleration * dt; } - playerX = std::clamp(playerX, -2.f, 2.f); - speed = std::clamp(speed, 0.f, MaxSpeed); - - playerZ = m_trackCamera.getDepth() + 0.5f; + m_player.x = std::clamp(m_player.x, -2.f, 2.f); + m_player.speed = std::clamp(m_player.speed, 0.f, Player::MaxSpeed); - //TODO rotate player model with steering + m_player.z = m_trackCamera.getDepth() + 0.5f; - //update sprite ent position (playerX is +/- 2) - const float x = ((RenderSizeFloat.x / 4.f) * playerX) + (RenderSizeFloat.x / 2.f); - const float scale = m_trackCamera.getDepth() / playerZ; - m_playerEntity.getComponent().setPosition(glm::vec2(x, 10.f)); - m_playerEntity.getComponent().setScale(glm::vec2(scale)); //TODO fix this + //rotate player model with steering + //TODO X rot needs to account for the inverse of Y + glm::quat r = glm::toQuat(glm::orientate3(glm::vec3(0.f, /*m_player.model.rotationX*/0.f, m_player.model.rotationY))); + m_playerEntity.getComponent().setRotation(r); } void EndlessDrivingState::updateRoad(float dt) { - const float s = speed /*MaxSpeed*/; + const float s = m_player.speed /*Player::MaxSpeed*/; m_trackCamera.move(glm::vec3(0.f, 0.f, s * dt)); @@ -432,11 +428,11 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.move(glm::vec3(0.f, 0.f, - maxLen)); } - std::size_t start = static_cast(m_trackCamera.getPosition().z / SegmentLength); + const std::size_t start = static_cast(m_trackCamera.getPosition().z / SegmentLength); float x = 0.f; float dx = 0.f; auto camPos = m_trackCamera.getPosition(); - float maxY = RenderSizeFloat.y; + float maxY = 0.f;// RenderSizeFloat.y; std::vector verts; const float halfWidth = RenderSizeFloat.x / 2.f; @@ -454,7 +450,7 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto prevProj = m_trackCamera.getScreenProjection(prev, glm::vec3(playerX, 0.f, playerZ), RenderSizeFloat); + auto prevProj = m_trackCamera.getScreenProjection(prev, m_player.x * prev.width, RenderSizeFloat); //increment @@ -466,13 +462,13 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto currProj = m_trackCamera.getScreenProjection(curr, glm::vec3(playerX, 0.f, playerZ), RenderSizeFloat); + auto currProj = m_trackCamera.getScreenProjection(curr, m_player.x * curr.width, RenderSizeFloat); prev = curr; //cull OOB segments if (prevProj.z < m_trackCamera.getDepth() - || currProj.y > maxY) + || currProj.y >= maxY) { continue; } @@ -505,11 +501,11 @@ void EndlessDrivingState::updateRoad(float dt) //update the background - const float speedRatio = s / MaxSpeed; + const float speedRatio = s / Player::MaxSpeed; for (auto& layer : m_background) { - //TODO scroll vertically with hills layer.textureRect.left += layer.speed * m_road[start].curve * speedRatio; + layer.textureRect.bottom = layer.verticalSpeed * m_road[start].position.y * 0.05f; layer.entity.getComponent().setTextureRect(layer.textureRect); } diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 6ea133a41..6a4a2eb1e 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -41,6 +41,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient cro::Entity entity; cro::FloatRect textureRect; float speed = 0.f; + float verticalSpeed = 0.f; enum { Sky, Hills, Trees, @@ -51,7 +52,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient //buffer for player sprite cro::RenderTexture m_playerTexture; - cro::Entity m_playerEntity; + cro::Entity m_playerEntity; //3D model cro::Entity m_roadEntity; //texture is fixed size and game is rendered to this @@ -63,6 +64,43 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient TrackCamera m_trackCamera; Track m_road; + struct Player final + { + float x = 0.f; //+/- 1 from X centre + float z = 0.f; //rel distance from camera + float speed = 0.f; + + static inline constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time + static inline constexpr float Acceleration = MaxSpeed / 5.f; + static inline constexpr float Braking = -MaxSpeed; + static inline constexpr float Deceleration = -Acceleration; + static inline constexpr float OffroadDeceleration = -MaxSpeed / 2.f; + static inline constexpr float OffroadMaxSpeed = MaxSpeed / 4.f; + + struct Model final + { + float rotationX = 0.f; + float rotationY = 0.f; + + static constexpr float MaxX = 0.1f; + static constexpr float MaxY = 0.4f; + }model; + }m_player; + + struct InputFlags final + { + enum + { + Up = 0x1, + Down = 0x2, + Left = 0x4, + Right = 0x8 + }; + std::uint16_t flags = 0; + std::uint16_t prevFlags = 0; + }m_inputFlags; + + void addSystems(); void loadAssets(); void createPlayer(); diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index ea59a7f57..94765acfc 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -42,7 +42,7 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #include static inline constexpr float SegmentLength = 250.f; -static inline constexpr float RoadWidth = 1500.f; +static inline constexpr float RoadWidth = 2500.f; static inline constexpr std::size_t EnterMin = 30; static inline constexpr std::size_t EnterMax = 100; @@ -51,8 +51,8 @@ static inline constexpr std::size_t HoldMax = 500; static inline constexpr std::size_t ExitMin = EnterMin; static inline constexpr std::size_t ExitMax = EnterMax; -static inline constexpr float CurveMin = -5.f; -static inline constexpr float CurveMax = 5.f; +static inline constexpr float CurveMin = -4.f; +static inline constexpr float CurveMax = 4.f; static inline constexpr float HillMin = -30.f; static inline constexpr float HillMax = 30.f; @@ -84,7 +84,7 @@ class Track final for (; i < end; ++i) { const float progress = static_cast(i) / enter; - glm::vec3 pos(0.f, hill * cro::Util::Easing::easeInOutSine(progress), z + (i * SegmentLength)); + glm::vec3 pos(0.f, hill * cro::Util::Easing::easeOutSine(progress), z + (i * SegmentLength)); setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * cro::Util::Easing::easeInSine(progress))); } @@ -99,8 +99,8 @@ class Track final for (; i < end; ++i) { const float progress = static_cast(i - enter - hold) / exit; - glm::vec3 pos(0.f, hill * (1.f - cro::Util::Easing::easeInOutSine(progress)), z + (i * SegmentLength)); - setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * (1.f - cro::Util::Easing::easeOutSine(progress)))); + glm::vec3 pos(0.f, hill * (cro::Util::Easing::easeOutSine(1.f - progress)), z + (i * SegmentLength)); + setColour(m_segments.emplace_back(pos, SegmentLength, RoadWidth, curve * (cro::Util::Easing::easeOutSine(1.f - progress)))); } } diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp index 248d5ce90..9128f4488 100644 --- a/samples/scratchpad/src/endless/TrackCamera.hpp +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -54,10 +54,10 @@ class TrackCamera final float getFOV() const { return m_fov; } float getDepth() const { return m_depth; } - glm::vec3 getScreenProjection(const TrackSegment segment, glm::vec3 playerPos, glm::vec2 screenSize) + glm::vec3 getScreenProjection(const TrackSegment& segment, float playerX, glm::vec2 screenSize) { auto translation = segment.position - m_position; - translation.x -= playerPos.x; + translation.x -= playerX; const float scale = (m_depth / translation.z); auto projection = translation * scale; @@ -83,8 +83,8 @@ class TrackCamera final void setZ(float f) { m_position.z = f; } private: - float m_fov = 80.f; - float m_depth = 1.f; //normalised + float m_fov = 65.f; + float m_depth = 1.f; - glm::vec3 m_position = glm::vec3(0.f, 1800.f, 0.f); + glm::vec3 m_position = glm::vec3(0.f, 1800.f, 300.f); }; \ No newline at end of file From fe0aeb9f3f4e4a794923c4e60e64f2c29fdc98d8 Mon Sep 17 00:00:00 2001 From: fallahn Date: Thu, 11 Jan 2024 16:02:46 +0000 Subject: [PATCH 10/19] fix road culling improve player camera calculate player world height --- .../src/endless/EndlessDrivingState.cpp | 94 ++++++++++++++----- .../src/endless/EndlessDrivingState.hpp | 9 +- samples/scratchpad/src/endless/Track.hpp | 4 +- .../scratchpad/src/endless/TrackCamera.hpp | 9 +- 4 files changed, 82 insertions(+), 34 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 0df32eb04..b3ca30ac2 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -23,10 +23,11 @@ namespace { - constexpr glm::uvec2 PlayerSize = glm::uvec2(80); constexpr glm::uvec2 RenderSize = glm::uvec2(320, 224); constexpr glm::vec2 RenderSizeFloat = glm::vec2(RenderSize); - + constexpr float PlayerWidth = 74.f; + constexpr float PlayerHeight = 84.f; + constexpr cro::FloatRect PlayerBounds((RenderSizeFloat.x - PlayerWidth) / 2.f, 0.f, PlayerWidth, PlayerHeight); constexpr float fogDensity = 5.f; float expFog(float distance, float density) @@ -40,6 +41,12 @@ namespace return fogAmount; } const cro::Colour FogColour = cro::Colour::Teal; + + struct Debug final + { + float maxY = 0.f; + float segmentProgress = 0.f; + }debug; } EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Context context) @@ -60,6 +67,29 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con { if (ImGui::Begin("Player")) { + /*cro::FloatRect textureBounds = m_playerSprite.getComponent().getTextureRect(); + if (ImGui::SliderFloat("Width", &textureBounds.width, 10.f, RenderSizeFloat.x)) + { + textureBounds.left = (RenderSizeFloat.x - textureBounds.width) / 2.f; + m_playerSprite.getComponent().setTextureRect(textureBounds); + m_playerSprite.getComponent().setOrigin(glm::vec2(textureBounds.width / 2.f, 0.f)); + } + if (ImGui::SliderFloat("Height", &textureBounds.height, 10.f, RenderSizeFloat.y)) + { + m_playerSprite.getComponent().setTextureRect(textureBounds); + } + + auto pos = m_playerScene.getActiveCamera().getComponent().getPosition(); + if (ImGui::SliderFloat("Cam height", &pos.y, 1.f, 6.f)) + { + m_playerScene.getActiveCamera().getComponent().setPosition(pos); + }*/ + + ImGui::Text("Max Y %3.3f", debug.maxY); + ImGui::Text("Player Y %3.3f", m_player.position.y); + ImGui::Text("Player Z %3.3f", m_player.position.z); + ImGui::Text("Player Segment Progress %3.3f", debug.segmentProgress); + static const auto Red = ImVec4(1.f, 0.f, 0.f, 1.f); static const auto Green = ImVec4(0.f, 1.f, 0.f, 1.f); if (m_inputFlags.flags & InputFlags::Left) @@ -85,7 +115,7 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::PopStyleColor(); ImGui::Text("Speed %3.3f", m_player.speed); - ImGui::Text("PlayerX %3.3f", m_player.x); + ImGui::Text("PlayerX %3.3f", m_player.position.x); } ImGui::End(); }); @@ -207,7 +237,7 @@ void EndlessDrivingState::loadAssets() void EndlessDrivingState::createPlayer() { - m_playerTexture.create(PlayerSize.x, PlayerSize.y); + m_playerTexture.create(RenderSize.x, RenderSize.y); auto entity = m_playerScene.createEntity(); entity.addComponent(); @@ -222,16 +252,16 @@ void EndlessDrivingState::createPlayer() auto resize = [&](cro::Camera& cam) { cam.viewport = { 0.f, 0.f, 1.f, 1.f }; - cam.setPerspective(cro::Util::Const::degToRad * m_trackCamera.getFOV(), 1.f, 0.1f, 10.f); + cam.setPerspective(cro::Util::Const::degToRad * m_trackCamera.getFOV(), RenderSizeFloat.x/RenderSizeFloat.y, 0.1f, 50.f); }; auto& cam = m_playerScene.getActiveCamera().getComponent(); cam.resizeCallback = resize; resize(cam); - m_playerScene.getActiveCamera().getComponent().setPosition({ -2.3f, 1.9f, 0.f }); + //this has to look straight ahead, as that's what we're supposing in the 2D projection + m_playerScene.getActiveCamera().getComponent().setPosition({ -5.146f, 3.1f, 0.f }); m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::Y_AXIS, -cro::Util::Const::PI / 2.f); - m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::X_AXIS, -0.58f); m_playerScene.getSunlight().getComponent().setRotation(cro::Transform::X_AXIS, -cro::Util::Const::PI / 2.f); } @@ -273,11 +303,12 @@ void EndlessDrivingState::createScene() //player entity = m_gameScene.createEntity(); - entity.addComponent().setPosition(glm::vec3(160.f, 10.f, -0.1f)); - entity.getComponent().setOrigin(glm::vec2(static_cast(PlayerSize.x / 2u), 0.f)); + entity.addComponent().setPosition(glm::vec3(160.f, 0.f, -0.1f)); entity.addComponent(); entity.addComponent(m_playerTexture.getTexture()); - + entity.getComponent().setTextureRect(PlayerBounds); + entity.getComponent().setOrigin(glm::vec2(PlayerBounds.width / 2.f, 0.f)); + m_playerSprite = entity; //road entity = m_gameScene.createEntity(); @@ -358,21 +389,21 @@ void EndlessDrivingState::updatePlayer(float dt) { if (m_inputFlags.flags & InputFlags::Left) { - m_player.x -= dx; + m_player.position.x -= dx; m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + dx); } if (m_inputFlags.flags & InputFlags::Right) { - m_player.x += dx; + m_player.position.x += dx; m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - dx); } } //centrifuge on curves static constexpr float Centrifuge = 0.3f; - const std::size_t segID = static_cast(m_trackCamera.getPosition().z / SegmentLength); - m_player.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; + const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength); + m_player.position.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; //uphill/downhill anim const auto nextID = (segID - 1) % m_road.getSegmentCount(); @@ -398,17 +429,25 @@ void EndlessDrivingState::updatePlayer(float dt) } //is off road - if ((m_player.x < -1.f || m_player.x > 1.f) + if ((m_player.position.x < -1.f || m_player.position.x > 1.f) && (m_player.speed > Player::OffroadMaxSpeed)) { //slow down m_player.speed += Player::OffroadDeceleration * dt; } - m_player.x = std::clamp(m_player.x, -2.f, 2.f); + m_player.position.x = std::clamp(m_player.position.x, -2.f, 2.f); m_player.speed = std::clamp(m_player.speed, 0.f, Player::MaxSpeed); - m_player.z = m_trackCamera.getDepth() + 0.5f; + m_player.position.z = m_trackCamera.getDepth() * m_trackCamera.getPosition().y; + + const float segmentProgress = ((m_trackCamera.getPosition().z + m_player.position.z) - m_road[segID].position.z) / SegmentLength; + debug.segmentProgress = segmentProgress; + m_player.position.y = glm::mix(m_road[segID].position.y, m_road[nextID].position.y, segmentProgress); + + + + //rotate player model with steering //TODO X rot needs to account for the inverse of Y @@ -428,11 +467,11 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.move(glm::vec3(0.f, 0.f, - maxLen)); } - const std::size_t start = static_cast(m_trackCamera.getPosition().z / SegmentLength); + const std::size_t start = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength); float x = 0.f; float dx = 0.f; auto camPos = m_trackCamera.getPosition(); - float maxY = 0.f;// RenderSizeFloat.y; + float maxY = 0.f; std::vector verts; const float halfWidth = RenderSizeFloat.x / 2.f; @@ -450,7 +489,9 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto prevProj = m_trackCamera.getScreenProjection(prev, m_player.x * prev.width, RenderSizeFloat); + auto playerPos = m_player.position; + playerPos.x *= prev.width; + auto prevProj = m_trackCamera.getScreenProjection(prev, playerPos, RenderSizeFloat); //increment @@ -462,17 +503,20 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); } m_trackCamera.setX(camPos.x - x); - auto currProj = m_trackCamera.getScreenProjection(curr, m_player.x * curr.width, RenderSizeFloat); + playerPos = m_player.position; + playerPos.x *= curr.width; + auto currProj = m_trackCamera.getScreenProjection(curr, playerPos, RenderSizeFloat); prev = curr; //cull OOB segments - if (prevProj.z < m_trackCamera.getDepth() - || currProj.y >= maxY) + if ((prev.position.z < m_trackCamera.getPosition().z) + || currProj.y < maxY) { continue; } - maxY = RenderSizeFloat.y - currProj.y; + maxY = currProj.y; + debug.maxY = maxY; //update vertex array float fogAmount = expFog(static_cast(i - start) / DrawDistance, fogDensity); @@ -505,7 +549,7 @@ void EndlessDrivingState::updateRoad(float dt) for (auto& layer : m_background) { layer.textureRect.left += layer.speed * m_road[start].curve * speedRatio; - layer.textureRect.bottom = layer.verticalSpeed * m_road[start].position.y * 0.05f; + layer.textureRect.bottom = layer.verticalSpeed * m_player.position.y * 0.05f; layer.entity.getComponent().setTextureRect(layer.textureRect); } diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 6a4a2eb1e..4431864fc 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -53,6 +53,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient //buffer for player sprite cro::RenderTexture m_playerTexture; cro::Entity m_playerEntity; //3D model + cro::Entity m_playerSprite; cro::Entity m_roadEntity; //texture is fixed size and game is rendered to this @@ -66,8 +67,10 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient struct Player final { - float x = 0.f; //+/- 1 from X centre - float z = 0.f; //rel distance from camera + //float x = 0.f; //+/- 1 from X centre + //float y = 0.f; + //float z = 0.f; //rel distance from camera + glm::vec3 position = glm::vec3(0.f); float speed = 0.f; static inline constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time @@ -83,7 +86,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient float rotationY = 0.f; static constexpr float MaxX = 0.1f; - static constexpr float MaxY = 0.4f; + static constexpr float MaxY = 0.3f; }model; }m_player; diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 94765acfc..520c77801 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -44,7 +44,7 @@ Based on articles: http://www.extentofthejam.com/pseudo/ static inline constexpr float SegmentLength = 250.f; static inline constexpr float RoadWidth = 2500.f; -static inline constexpr std::size_t EnterMin = 30; +static inline constexpr std::size_t EnterMin = 70; static inline constexpr std::size_t EnterMax = 100; static inline constexpr std::size_t HoldMin = 150; static inline constexpr std::size_t HoldMax = 500; @@ -53,7 +53,7 @@ static inline constexpr std::size_t ExitMax = EnterMax; static inline constexpr float CurveMin = -4.f; static inline constexpr float CurveMax = 4.f; -static inline constexpr float HillMin = -30.f; +static inline constexpr float HillMin = 0.f; static inline constexpr float HillMax = 30.f; static inline constexpr std::int32_t DrawDistance = 200; //number of segs diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp index 9128f4488..b896ce3f3 100644 --- a/samples/scratchpad/src/endless/TrackCamera.hpp +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -54,10 +54,11 @@ class TrackCamera final float getFOV() const { return m_fov; } float getDepth() const { return m_depth; } - glm::vec3 getScreenProjection(const TrackSegment& segment, float playerX, glm::vec2 screenSize) + glm::vec3 getScreenProjection(const TrackSegment& segment, glm::vec3 playerPos, glm::vec2 screenSize) { auto translation = segment.position - m_position; - translation.x -= playerX; + translation.x -= playerPos.x; + //translation.y -= playerPos.y; const float scale = (m_depth / translation.z); auto projection = translation * scale; @@ -83,8 +84,8 @@ class TrackCamera final void setZ(float f) { m_position.z = f; } private: - float m_fov = 65.f; - float m_depth = 1.f; + float m_fov = 75.f; + float m_depth = 1.f; //normalised value based on FOV of camera glm::vec3 m_position = glm::vec3(0.f, 1800.f, 300.f); }; \ No newline at end of file From f8fe854f7299a460df7b962677b4dda6653e9549 Mon Sep 17 00:00:00 2001 From: fallahn Date: Fri, 12 Jan 2024 11:49:18 +0000 Subject: [PATCH 11/19] update palette update player animation --- editor/src/WorldStateUI.cpp | 2 +- samples/golf/buildnumber.h | 4 +- samples/golf/src/Colordome-32.hpp | 2 +- samples/golf/src/golf/TrophyState.cpp | 10 ++-- .../scratchpad/src/endless/Colordome-32.hpp | 56 +++++++++++++++++++ .../src/endless/EndlessDrivingState.cpp | 39 +++++++------ .../src/endless/EndlessDrivingState.hpp | 3 +- samples/scratchpad/src/endless/Track.hpp | 7 ++- 8 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 samples/scratchpad/src/endless/Colordome-32.hpp diff --git a/editor/src/WorldStateUI.cpp b/editor/src/WorldStateUI.cpp index 9b1fd078b..0525a8a2a 100644 --- a/editor/src/WorldStateUI.cpp +++ b/editor/src/WorldStateUI.cpp @@ -689,7 +689,7 @@ bool WorldState::imageToArray(const cro::Image& img, const std::string& outpath) if (file.is_open() && file.good()) { file << "#pragma once\n\n#include \n#include \n\n"; - file << "static const std::array Colours =\n{\n"; + file << "static constexpr inline std::array Colours =\n{\n"; for (auto c : colours) { diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 9e6b7f1b0..8578f01b8 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3701 -#define BUILDNUMBER_STR "3701" +#define BUILDNUMBER 3704 +#define BUILDNUMBER_STR "3704" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/Colordome-32.hpp b/samples/golf/src/Colordome-32.hpp index 16e1ec465..4795aa8c0 100644 --- a/samples/golf/src/Colordome-32.hpp +++ b/samples/golf/src/Colordome-32.hpp @@ -6,7 +6,7 @@ namespace CD32 { - static constexpr std::array Colours = + static inline constexpr std::array Colours = { cro::Colour(0xd0b0dff), cro::Colour(0xfff8e1ff), diff --git a/samples/golf/src/golf/TrophyState.cpp b/samples/golf/src/golf/TrophyState.cpp index 764825ae7..c8eab252b 100644 --- a/samples/golf/src/golf/TrophyState.cpp +++ b/samples/golf/src/golf/TrophyState.cpp @@ -502,7 +502,7 @@ void TrophyState::buildScene() backgroundEnt.getComponent().addChild(titleEnt.getComponent()); auto descEnt = m_scene.createEntity(); - descEnt.addComponent().setPosition({ 74.f, 269.f, 0.1f }); + descEnt.addComponent().setPosition({ 74.f, 269.f, 0.2f }); descEnt.addComponent(); descEnt.addComponent(infoFont).setCharacterSize(InfoTextSize); descEnt.getComponent().setFillColour(TextNormalColour); @@ -516,7 +516,7 @@ void TrophyState::buildScene() backgroundEnt.getComponent().addChild(dateEnt.getComponent()); auto iconEnt = m_scene.createEntity(); - iconEnt.addComponent().setPosition({ 32.f, 238.f, 0.1f }); + iconEnt.addComponent().setPosition({ 32.f, 238.f, 0.2f }); iconEnt.getComponent().setScale(glm::vec2(0.5f)); iconEnt.addComponent(); backgroundEnt.getComponent().addChild(iconEnt.getComponent()); @@ -587,7 +587,7 @@ void TrophyState::buildScene() m_trophyEnts[modelIndex].getComponent().active = true; } - + //skip location 0 as it's not a valid achievement m_trophyIndex = ((m_trophyIndex + (AchievementID::Count - 1)) % AchievementID::Count); if (m_trophyIndex == 0) { @@ -609,7 +609,7 @@ void TrophyState::buildScene() m_trophyEnts[modelIndex].getComponent().active = true; } - + //skip location 0 as it's not a valid achievement m_trophyIndex = ((m_trophyIndex + 1) % AchievementID::Count); //there's probably a smart way to do this, but brain. @@ -707,7 +707,7 @@ void TrophyState::buildScene() //displays trophy render texture entity = m_scene.createEntity(); - entity.addComponent().setPosition({ bgBounds.width / 2.f, 138.f, 0.1f }); + entity.addComponent().setPosition({ bgBounds.width / 2.f, 138.f, 0.15f }); entity.addComponent(); entity.addComponent(); bounds = entity.getComponent().getTextureBounds(); diff --git a/samples/scratchpad/src/endless/Colordome-32.hpp b/samples/scratchpad/src/endless/Colordome-32.hpp new file mode 100644 index 000000000..4795aa8c0 --- /dev/null +++ b/samples/scratchpad/src/endless/Colordome-32.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include + +namespace CD32 +{ + static inline constexpr std::array Colours = + { + cro::Colour(0xd0b0dff), + cro::Colour(0xfff8e1ff), + cro::Colour(0xc8b89fff), + cro::Colour(0x987a68ff), + cro::Colour(0x674949ff), + cro::Colour(0x3a3941ff), + cro::Colour(0x6b6f72ff), + cro::Colour(0xadb9b8ff), + cro::Colour(0xadd9b7ff), + cro::Colour(0x6eb39dff), + cro::Colour(0x30555bff), + cro::Colour(0x1a1e2dff), + cro::Colour(0x284e43ff), + cro::Colour(0x467e3eff), + cro::Colour(0x93ab52ff), + cro::Colour(0xf2cf5cff), + cro::Colour(0xec773dff), + cro::Colour(0xb83530ff), + cro::Colour(0x722030ff), + cro::Colour(0x281721ff), + cro::Colour(0x6d2944ff), + cro::Colour(0xc85257ff), + cro::Colour(0xec9983ff), + cro::Colour(0xdbaf77ff), + cro::Colour(0xb77854ff), + cro::Colour(0x833e35ff), + cro::Colour(0x50282fff), + cro::Colour(0x65432fff), + cro::Colour(0x7e6d37ff), + cro::Colour(0x6ebe70ff), + cro::Colour(0xb75834ff), + cro::Colour(0xd55c4dff), + }; + + enum + { + Black, BeigeLight, BeigeMid, BeigeDark, BeigeDarkest, + GreyDark, GreyMid, GreyLight, BlueLight, BlueMid, BlueDark, + BlueDarkest, GreenDark, GreenMid, GreenLight, Yellow, Orange, + Red, RedDark, MauveDark, Mauve, Pink, PinkLight, TanLight, + TanMid, TanDark, TanDarkest, Brown, Olive, Cyan, OrangeDirt, + PinkDirt, + + Count + }; +} \ No newline at end of file diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index b3ca30ac2..1fee0ea82 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -40,7 +41,7 @@ namespace return fogAmount; } - const cro::Colour FogColour = cro::Colour::Teal; + const cro::Colour FogColour = CD32::Colours[CD32::GreenDark]; struct Debug final { @@ -206,7 +207,7 @@ void EndlessDrivingState::render() m_playerScene.render(); m_playerTexture.display(); - m_gameTexture.clear(cro::Colour::Magenta); + m_gameTexture.clear(cro::Colour(std::uint8_t(169), 186, 192)); m_gameScene.render(); m_gameTexture.display(); @@ -243,7 +244,7 @@ void EndlessDrivingState::createPlayer() entity.addComponent(); cro::ModelDefinition md(m_resources); - if (md.loadFromFile("assets/cars/cart.cmt")) + if (md.loadFromFile("assets/golf/models/cart_v2.cmt")) { md.createModel(entity); } @@ -260,16 +261,14 @@ void EndlessDrivingState::createPlayer() resize(cam); //this has to look straight ahead, as that's what we're supposing in the 2D projection - m_playerScene.getActiveCamera().getComponent().setPosition({ -5.146f, 3.1f, 0.f }); - m_playerScene.getActiveCamera().getComponent().rotate(cro::Transform::Y_AXIS, -cro::Util::Const::PI / 2.f); - + m_playerScene.getActiveCamera().getComponent().setPosition({ 0.f, 3.1f, 5.146f }); m_playerScene.getSunlight().getComponent().setRotation(cro::Transform::X_AXIS, -cro::Util::Const::PI / 2.f); } void EndlessDrivingState::createScene() { //background - auto* tex = &m_resources.textures.get("assets/cars/sky.png"); + auto* tex = &m_resources.textures.get("assets/golf/images/skybox/layers/01.png"); tex->setRepeated(true); auto entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.5f)); @@ -279,7 +278,7 @@ void EndlessDrivingState::createScene() m_background[BackgroundLayer::Sky].textureRect = entity.getComponent().getTextureRect(); m_background[BackgroundLayer::Sky].speed = 0.04f; - tex = &m_resources.textures.get("assets/cars/hills.png"); + tex = &m_resources.textures.get("assets/golf/images/skybox/layers/02.png"); tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.4f)); @@ -290,7 +289,7 @@ void EndlessDrivingState::createScene() m_background[BackgroundLayer::Hills].speed = 0.08f; m_background[BackgroundLayer::Hills].verticalSpeed = 0.04f; - tex = &m_resources.textures.get("assets/cars/trees.png"); + tex = &m_resources.textures.get("assets/golf/images/skybox/layers/03.png"); tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.3f)); @@ -298,7 +297,7 @@ void EndlessDrivingState::createScene() entity.addComponent(*tex); m_background[BackgroundLayer::Trees].entity = entity; m_background[BackgroundLayer::Trees].textureRect = entity.getComponent().getTextureRect(); - m_background[BackgroundLayer::Trees].speed = 0.12f; + m_background[BackgroundLayer::Trees].speed = 0.16f; m_background[BackgroundLayer::Trees].verticalSpeed = 0.06f; //player @@ -405,11 +404,7 @@ void EndlessDrivingState::updatePlayer(float dt) const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength); m_player.position.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; - //uphill/downhill anim - const auto nextID = (segID - 1) % m_road.getSegmentCount(); - m_player.model.rotationX = std::clamp((m_road[segID].position.y - m_road[nextID].position.y) * dt, -Player::Model::MaxX, Player::Model::MaxX); - m_player.model.rotationX *= 1.f - (0.1f * speedRatio); - + if ((m_inputFlags.flags & (InputFlags::Up | InputFlags::Down)) == 0) { @@ -443,16 +438,20 @@ void EndlessDrivingState::updatePlayer(float dt) const float segmentProgress = ((m_trackCamera.getPosition().z + m_player.position.z) - m_road[segID].position.z) / SegmentLength; debug.segmentProgress = segmentProgress; - m_player.position.y = glm::mix(m_road[segID].position.y, m_road[nextID].position.y, segmentProgress); + const auto nextID = (segID - 1) % m_road.getSegmentCount(); + m_player.position.y = glm::mix(m_road[segID].position.y, m_road[nextID].position.y, segmentProgress); + glm::vec2 p2(SegmentLength, m_road[nextID].position.y - m_road[segID].position.y); + m_player.model.targetRotationX = std::atan2(-p2.y, p2.x); + m_player.model.rotationX += cro::Util::Maths::shortestRotation(m_player.model.rotationX, m_player.model.targetRotationX) * dt; //rotate player model with steering - //TODO X rot needs to account for the inverse of Y - glm::quat r = glm::toQuat(glm::orientate3(glm::vec3(0.f, /*m_player.model.rotationX*/0.f, m_player.model.rotationY))); - m_playerEntity.getComponent().setRotation(r); + glm::quat r = glm::toQuat(glm::orientate3(glm::vec3(0.f, 0.f, m_player.model.rotationY))); + glm::quat s = glm::toQuat(glm::orientate3(glm::vec3(m_player.model.rotationX, 0.f, 0.f))); + m_playerEntity.getComponent().setRotation(s * r); } void EndlessDrivingState::updateRoad(float dt) @@ -536,7 +535,7 @@ void EndlessDrivingState::updateRoad(float dt) //markings if (curr.roadMarking) { - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 0.02f, currProj.z * 0.02f, cro::Colour::White, verts); + addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 0.02f, currProj.z * 0.02f, CD32::Colours[CD32::BeigeLight], verts); } } diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 4431864fc..6c519e1e1 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -82,11 +82,12 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient struct Model final { + float targetRotationX = 0.f; float rotationX = 0.f; float rotationY = 0.f; static constexpr float MaxX = 0.1f; - static constexpr float MaxY = 0.3f; + static constexpr float MaxY = 0.2f; }model; }m_player; diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 520c77801..6a9725323 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -34,6 +34,7 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #pragma once #include "TrackSegment.hpp" +#include "Colordome-32.hpp" #include #include @@ -74,9 +75,9 @@ class Track final const auto setColour = [&](TrackSegment& seg) { - seg.roadColour = (((start + i) / 3) % 2) ? cro::Colour(0.45f, 0.45f, 0.45f) : cro::Colour(0.4f, 0.4f, 0.4f); - seg.grassColour = (((start + i) / 3) % 2) ? cro::Colour(0.f, 0.65f, 0.f) : cro::Colour(0.f, 0.75f, 0.f); - seg.rumbleColour = (((start + i) / 9) % 2) ? cro::Colour::Red : cro::Colour::White; + seg.roadColour = CD32::Colours[CD32::GreyDark];// (((start + i) / 3) % 2) ? CD32::Colours[CD32::GreyDark] : CD32::Colours[CD32::GreyMid]; + seg.grassColour = CD32::Colours[CD32::GreenMid];// (((start + i) / 3) % 2) ? CD32::Colours[CD32::GreenDark] : CD32::Colours[CD32::GreenMid]; + seg.rumbleColour = (((start + i) / 9) % 2) ? CD32::Colours[CD32::Red] : CD32::Colours[CD32::BeigeLight]; seg.roadMarking = (((start + i) / 6) % 2); }; From 6c7399ba6134b207b9a6723d6868bfe347645bc8 Mon Sep 17 00:00:00 2001 From: fallahn Date: Fri, 12 Jan 2024 15:11:50 +0000 Subject: [PATCH 12/19] initial track side sprite rendering --- samples/scratchpad/scratchpad.vcxproj | 1 + samples/scratchpad/scratchpad.vcxproj.filters | 3 + .../src/endless/EndlessDrivingState.cpp | 157 +++++++++++++++--- .../src/endless/EndlessDrivingState.hpp | 6 + .../scratchpad/src/endless/TrackCamera.hpp | 11 +- .../scratchpad/src/endless/TrackSegment.hpp | 14 ++ .../scratchpad/src/endless/TrackSprite.hpp | 54 ++++++ 7 files changed, 219 insertions(+), 27 deletions(-) create mode 100644 samples/scratchpad/src/endless/TrackSprite.hpp diff --git a/samples/scratchpad/scratchpad.vcxproj b/samples/scratchpad/scratchpad.vcxproj index a7efca71c..341441521 100644 --- a/samples/scratchpad/scratchpad.vcxproj +++ b/samples/scratchpad/scratchpad.vcxproj @@ -374,6 +374,7 @@ + diff --git a/samples/scratchpad/scratchpad.vcxproj.filters b/samples/scratchpad/scratchpad.vcxproj.filters index d06856439..3680d260f 100644 --- a/samples/scratchpad/scratchpad.vcxproj.filters +++ b/samples/scratchpad/scratchpad.vcxproj.filters @@ -443,6 +443,9 @@ Header Files\endless + + Header Files\endless + diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 1fee0ea82..6c531423e 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include #include #include @@ -234,6 +236,27 @@ void EndlessDrivingState::addSystems() void EndlessDrivingState::loadAssets() { + cro::SpriteSheet spriteSheet; + spriteSheet.loadFromFile("assets/golf/sprites/shrubbery_autumn02_low.spt", m_resources.textures); + + const auto parseSprite = + [&](const cro::Sprite& sprite, std::int32_t spriteID) + { + auto bounds = sprite.getTextureBounds(); + m_trackSprites[spriteID].size = { bounds.width, bounds.height }; + m_trackSprites[spriteID].uv = sprite.getTextureRectNormalised(); + }; + + parseSprite(spriteSheet.getSprite("tree01"), TrackSprite::Tree01); + parseSprite(spriteSheet.getSprite("tree03"), TrackSprite::Tree02); + + + auto entity = m_gameScene.createEntity(); + entity.addComponent().setPosition({ 0.f, 0.f, -7.f }); + entity.addComponent().setTexture(spriteSheet.getTexture()); + entity.getComponent().setCullingEnabled(false); + entity.getComponent().setPrimitiveType(GL_TRIANGLES); + m_trackSpriteEntity = entity; } void EndlessDrivingState::createPlayer() @@ -321,14 +344,37 @@ void EndlessDrivingState::createScene() auto segmentCount = cro::Util::Random::value(5, 20); for (auto i = 0; i < segmentCount; ++i) { + const std::size_t first = m_road.getSegmentCount(); + const auto enter = cro::Util::Random::value(EnterMin, EnterMax); const auto hold = cro::Util::Random::value(HoldMin, HoldMax); const auto exit = cro::Util::Random::value(ExitMin, ExitMax); + const std::size_t last = first + enter + hold + exit; + const float curve = cro::Util::Random::value(0, 1) ? cro::Util::Random::value(CurveMin, CurveMax) : 0.f; const float hill = cro::Util::Random::value(0, 1) ? cro::Util::Random::value(HillMin, HillMax) * SegmentLength : 0.f; m_road.addSegment(enter, hold, exit, curve, hill); + + + //add sprites to the new segment + for (auto j = first; j < last; ++j) + { + auto& seg = m_road[j]; + auto count = cro::Util::Random::value(0, 2) == 0 ? 1 : 0; + for (auto k = 0; k < count; ++k) + { + auto spriteID = cro::Util::Random::value(TrackSprite::Tree01, TrackSprite::Tree02); + auto pos = -1.25f - cro::Util::Random::value(0.3f, 0.6f); + if (cro::Util::Random::value(0, 1) == 0) + { + pos *= -1.f; + } + seg.sprites.emplace_back(m_trackSprites[spriteID]).position = pos; + seg.sprites.back().scale *= cro::Util::Random::value(0.9f, 1.1f); + } + } } m_road[m_road.getSegmentCount() - 1].roadColour = cro::Colour::White; m_road[m_road.getSegmentCount() - 1].rumbleColour = cro::Colour::Blue; @@ -401,7 +447,7 @@ void EndlessDrivingState::updatePlayer(float dt) //centrifuge on curves static constexpr float Centrifuge = 0.3f; - const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength); + const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength) % m_road.getSegmentCount(); m_player.position.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; @@ -466,7 +512,7 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.move(glm::vec3(0.f, 0.f, - maxLen)); } - const std::size_t start = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength); + const std::size_t start = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength) - 1; float x = 0.f; float dx = 0.f; auto camPos = m_trackCamera.getPosition(); @@ -478,20 +524,23 @@ void EndlessDrivingState::updateRoad(float dt) const auto trackHeight = m_road[start % m_road.getSegmentCount()].position.y; m_trackCamera.move(glm::vec3(0.f, trackHeight, 0.f)); - auto prev = m_road[(start - 1) % m_road.getSegmentCount()]; - for (auto i = start; i < start + DrawDistance; ++i) - { - const auto& curr = m_road[i % m_road.getSegmentCount()]; + //keep this because we need to reverse the draw order + std::vector spriteSegments; - if (i - 1 >= m_road.getSegmentCount()) - { - m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); - } - m_trackCamera.setX(camPos.x - x); - auto playerPos = m_player.position; - playerPos.x *= prev.width; - auto prevProj = m_trackCamera.getScreenProjection(prev, playerPos, RenderSizeFloat); + auto* prev = &m_road[(start - 1) % m_road.getSegmentCount()]; + + if (start - 1 >= m_road.getSegmentCount()) + { + m_trackCamera.setZ(camPos.z - (m_road.getSegmentCount() * SegmentLength)); + } + auto playerPos = m_player.position; + playerPos.x *= prev->width; + m_trackCamera.updateScreenProjection(*prev, playerPos, RenderSizeFloat); + for (auto i = start; i < start + DrawDistance; ++i) + { + const auto currIndex = i % m_road.getSegmentCount(); + auto& curr = m_road[currIndex]; //increment dx += curr.curve; @@ -504,17 +553,24 @@ void EndlessDrivingState::updateRoad(float dt) m_trackCamera.setX(camPos.x - x); playerPos = m_player.position; playerPos.x *= curr.width; - auto currProj = m_trackCamera.getScreenProjection(curr, playerPos, RenderSizeFloat); + m_trackCamera.updateScreenProjection(curr, playerPos, RenderSizeFloat); + - prev = curr; + //stash the sprites - these might poke out from + //behind a hill so we'll draw them anyway regardless + //of segment culling + if (!curr.sprites.empty()) + { + spriteSegments.push_back(currIndex); + } //cull OOB segments - if ((prev.position.z < m_trackCamera.getPosition().z) - || currProj.y < maxY) + if ((prev->position.z < m_trackCamera.getPosition().z) + || curr.projection.position.y < maxY) { continue; } - maxY = currProj.y; + maxY = curr.projection.position.y; debug.maxY = maxY; //update vertex array @@ -522,32 +578,57 @@ void EndlessDrivingState::updateRoad(float dt) //grass auto colour = glm::mix(curr.grassColour.getVec4(), FogColour.getVec4(), fogAmount); - addRoadQuad(halfWidth, halfWidth, prevProj.y, currProj.y, halfWidth, halfWidth, colour, verts); + addRoadQuad(halfWidth, halfWidth, prev->projection.position.y, curr.projection.position.y, halfWidth, halfWidth, colour, verts); //rumble strip colour = glm::mix(curr.rumbleColour.getVec4(), FogColour.getVec4(), fogAmount); - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 1.1f, currProj.z * 1.1f, curr.rumbleColour, verts); + addRoadQuad(prev->projection.position.x, curr.projection.position.x, + prev->projection.position.y, curr.projection.position.y, + prev->projection.width * 1.1f, curr.projection.width * 1.1f, curr.rumbleColour, verts); //road colour = glm::mix(curr.roadColour.getVec4(), FogColour.getVec4(), fogAmount); - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z, currProj.z, curr.roadColour, verts); + addRoadQuad(prev->projection.position.x, curr.projection.position.x, + prev->projection.position.y, curr.projection.position.y, + prev->projection.width, curr.projection.width, curr.roadColour, verts); //markings if (curr.roadMarking) { - addRoadQuad(prevProj.x, currProj.x, prevProj.y, currProj.y, prevProj.z * 0.02f, currProj.z * 0.02f, CD32::Colours[CD32::BeigeLight], verts); + addRoadQuad(prev->projection.position.x, curr.projection.position.x, + prev->projection.position.y, curr.projection.position.y, + prev->projection.width * 0.02f, curr.projection.width * 0.02f, CD32::Colours[CD32::BeigeLight], verts); } + + //do this LAST!! buh + prev = &curr; } //addRoadQuad(320.f, 320.f, 0.f, 100.f, 320.f, 320.f, cro::Colour::Magenta, verts); m_roadEntity.getComponent().getVertexData().swap(verts); + verts.clear(); + //hmmm what's faster, reversing the vector, or iterating backwards? + for (auto i = spriteSegments.crbegin(); i != spriteSegments.crend(); ++i) + { + const auto idx = *i; + const auto& seg = m_road[idx]; + + for (const auto& sprite : seg.sprites) + { + //TODO use the current maxY value to clip the bottom of sprites + glm::vec2 pos = seg.projection.position; + pos.x += seg.projection.scale * sprite.position * RoadWidth * halfWidth; + addRoadSprite(sprite, pos, seg.projection.scale, verts); + } + } + m_trackSpriteEntity.getComponent().getVertexData().swap(verts); //update the background const float speedRatio = s / Player::MaxSpeed; for (auto& layer : m_background) { - layer.textureRect.left += layer.speed * m_road[start].curve * speedRatio; + layer.textureRect.left += layer.speed * m_road[start % m_road.getSegmentCount()].curve * speedRatio; layer.textureRect.bottom = layer.verticalSpeed * m_player.position.y * 0.05f; layer.entity.getComponent().setTextureRect(layer.textureRect); } @@ -564,4 +645,32 @@ void EndlessDrivingState::addRoadQuad(float x1, float x2, float y1, float y2, fl dst.emplace_back(glm::vec2(x1 + w1, y1), c); dst.emplace_back(glm::vec2(x2 - w2, y2), c); dst.emplace_back(glm::vec2(x2 + w2, y2), c); +} + +void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos, float scale, std::vector& dst) +{ + //TODO clip bottom my maxY and skip completely if top < maxY + + + auto uv = sprite.uv; + scale *= sprite.scale; + + glm::vec2 size = sprite.size * scale * 1000.f; + pos.x -= (size.x / 2.f); + + dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), glm::vec2(uv.left, uv.bottom + uv.height)); + dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom)); + dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height)); + + dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height)); + dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom)); + dst.emplace_back(glm::vec2(pos.x + size.x, pos.y), glm::vec2(uv.left + uv.width, uv.bottom)); + + //dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), cro::Colour::Magenta); + //dst.emplace_back(pos, cro::Colour::Magenta); + //dst.emplace_back(pos + size, cro::Colour::Magenta); + + //dst.emplace_back(pos + size, cro::Colour::Magenta); + //dst.emplace_back(pos, cro::Colour::Magenta); + //dst.emplace_back(glm::vec2(pos.x + size.x, pos.y), cro::Colour::Magenta); } \ No newline at end of file diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 6c519e1e1..beedb5a57 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -4,6 +4,7 @@ #include "../StateIDs.hpp" #include "TrackCamera.hpp" +#include "TrackSprite.hpp" #include "Track.hpp" #include @@ -50,6 +51,10 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient }; std::array m_background = {}; + std::array m_trackSprites = {}; + cro::Entity m_trackSpriteEntity; + + //buffer for player sprite cro::RenderTexture m_playerTexture; cro::Entity m_playerEntity; //3D model @@ -114,4 +119,5 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void updatePlayer(float dt); void updateRoad(float dt); void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); + void addRoadSprite(const TrackSprite&, glm::vec2, float, std::vector&); }; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp index b896ce3f3..c8aad2b46 100644 --- a/samples/scratchpad/src/endless/TrackCamera.hpp +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -54,7 +54,7 @@ class TrackCamera final float getFOV() const { return m_fov; } float getDepth() const { return m_depth; } - glm::vec3 getScreenProjection(const TrackSegment& segment, glm::vec3 playerPos, glm::vec2 screenSize) + /*glm::vec3*/void updateScreenProjection(TrackSegment& segment, glm::vec3 playerPos, glm::vec2 screenSize) { auto translation = segment.position - m_position; translation.x -= playerPos.x; @@ -64,11 +64,16 @@ class TrackCamera final auto projection = translation * scale; projection.z = segment.width * scale; + segment.projection.position.x = (screenSize.x / 2.f) * (1.f + projection.x); + segment.projection.position.y = (screenSize.y / 2.f) * (1.f + projection.y); + segment.projection.width = (screenSize.x / 2.f) * projection.z; + segment.projection.scale = scale; + //scale to the output - return glm::vec3( + /*return glm::vec3( (screenSize.x / 2.f) * (1.f + projection.x), (screenSize.y / 2.f) * (1.f + projection.y), - (screenSize.x / 2.f) * projection.z); + (screenSize.x / 2.f) * projection.z);*/ } void setPosition(glm::vec3 p) { m_position = p; } diff --git a/samples/scratchpad/src/endless/TrackSegment.hpp b/samples/scratchpad/src/endless/TrackSegment.hpp index aded88533..f1be44e92 100644 --- a/samples/scratchpad/src/endless/TrackSegment.hpp +++ b/samples/scratchpad/src/endless/TrackSegment.hpp @@ -33,9 +33,13 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #pragma once +#include "TrackSprite.hpp" + #include #include +#include + struct TrackSegment final { glm::vec3 position = glm::vec3(0.f); @@ -48,6 +52,16 @@ struct TrackSegment final cro::Colour grassColour; bool roadMarking = false; + std::vector sprites; + + //contains the last known screen projection + struct Projection final + { + glm::vec2 position = glm::vec2(0.f); + float width = 0.f; + float scale = 1.f; + }projection; + TrackSegment() = default; TrackSegment(glm::vec3 p, float l, float w, float c) : position(p), length(l), width(w), curve(c) {} diff --git a/samples/scratchpad/src/endless/TrackSprite.hpp b/samples/scratchpad/src/endless/TrackSprite.hpp new file mode 100644 index 000000000..59a2c4f3d --- /dev/null +++ b/samples/scratchpad/src/endless/TrackSprite.hpp @@ -0,0 +1,54 @@ +/*----------------------------------------------------------------------- + +Matt Marchant 2024 +http://trederia.blogspot.com + +crogine application - Zlib license. + +This software is provided 'as-is', without any express or +implied warranty.In no event will the authors be held +liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions : + +1. The origin of this software must not be misrepresented; +you must not claim that you wrote the original software. +If you use this software in a product, an acknowledgment +in the product documentation would be appreciated but +is not required. + +2. Altered source versions must be plainly marked as such, +and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any +source distribution. + + +Based on articles: http://www.extentofthejam.com/pseudo/ + https://codeincomplete.com/articles/javascript-racer/ + +-----------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +struct TrackSprite final +{ + float scale = 1.f; + float position = 0.f; //0 center +/- 1 road >1 <-1 off road + glm::vec2 size = glm::vec2(0.f); + cro::FloatRect uv; + + enum + { + Tree01, + Tree02, + + + Count + }; +}; \ No newline at end of file From f179ac85a1349d48cd6869c687cc316c57cdc1dc Mon Sep 17 00:00:00 2001 From: fallahn Date: Fri, 12 Jan 2024 15:20:50 +0000 Subject: [PATCH 13/19] rescale units to something akin to metres --- .../scratchpad/src/endless/EndlessDrivingState.cpp | 4 ++-- samples/scratchpad/src/endless/Track.hpp | 12 ++++++------ samples/scratchpad/src/endless/TrackCamera.hpp | 10 ++-------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 6c531423e..5977e854f 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -446,7 +446,7 @@ void EndlessDrivingState::updatePlayer(float dt) } //centrifuge on curves - static constexpr float Centrifuge = 0.3f; + static constexpr float Centrifuge = 300.f; const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength) % m_road.getSegmentCount(); m_player.position.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; @@ -655,7 +655,7 @@ void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos auto uv = sprite.uv; scale *= sprite.scale; - glm::vec2 size = sprite.size * scale * 1000.f; + glm::vec2 size = sprite.size * scale;// *1000.f; pos.x -= (size.x / 2.f); dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), glm::vec2(uv.left, uv.bottom + uv.height)); diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 6a9725323..6adf5117c 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -42,8 +42,8 @@ Based on articles: http://www.extentofthejam.com/pseudo/ #include -static inline constexpr float SegmentLength = 250.f; -static inline constexpr float RoadWidth = 2500.f; +static inline constexpr float SegmentLength = 0.25f; +static inline constexpr float RoadWidth = 2.5f; static inline constexpr std::size_t EnterMin = 70; static inline constexpr std::size_t EnterMax = 100; @@ -52,10 +52,10 @@ static inline constexpr std::size_t HoldMax = 500; static inline constexpr std::size_t ExitMin = EnterMin; static inline constexpr std::size_t ExitMax = EnterMax; -static inline constexpr float CurveMin = -4.f; -static inline constexpr float CurveMax = 4.f; -static inline constexpr float HillMin = 0.f; -static inline constexpr float HillMax = 30.f; +static inline constexpr float CurveMin = -0.004f; +static inline constexpr float CurveMax = 0.004f; +static inline constexpr float HillMin = -0.03f; +static inline constexpr float HillMax = 0.03f; static inline constexpr std::int32_t DrawDistance = 200; //number of segs diff --git a/samples/scratchpad/src/endless/TrackCamera.hpp b/samples/scratchpad/src/endless/TrackCamera.hpp index c8aad2b46..914b5ed27 100644 --- a/samples/scratchpad/src/endless/TrackCamera.hpp +++ b/samples/scratchpad/src/endless/TrackCamera.hpp @@ -54,7 +54,7 @@ class TrackCamera final float getFOV() const { return m_fov; } float getDepth() const { return m_depth; } - /*glm::vec3*/void updateScreenProjection(TrackSegment& segment, glm::vec3 playerPos, glm::vec2 screenSize) + void updateScreenProjection(TrackSegment& segment, glm::vec3 playerPos, glm::vec2 screenSize) { auto translation = segment.position - m_position; translation.x -= playerPos.x; @@ -68,12 +68,6 @@ class TrackCamera final segment.projection.position.y = (screenSize.y / 2.f) * (1.f + projection.y); segment.projection.width = (screenSize.x / 2.f) * projection.z; segment.projection.scale = scale; - - //scale to the output - /*return glm::vec3( - (screenSize.x / 2.f) * (1.f + projection.x), - (screenSize.y / 2.f) * (1.f + projection.y), - (screenSize.x / 2.f) * projection.z);*/ } void setPosition(glm::vec3 p) { m_position = p; } @@ -92,5 +86,5 @@ class TrackCamera final float m_fov = 75.f; float m_depth = 1.f; //normalised value based on FOV of camera - glm::vec3 m_position = glm::vec3(0.f, 1800.f, 300.f); + glm::vec3 m_position = glm::vec3(0.f, 1.8f, 0.3f); }; \ No newline at end of file From 491896909e551a8edc3d33cd90cc9db401f3b8d7 Mon Sep 17 00:00:00 2001 From: fallahn Date: Fri, 12 Jan 2024 15:40:53 +0000 Subject: [PATCH 14/19] rescale some vars --- .../src/endless/EndlessDrivingState.cpp | 44 +++++++++++-------- .../src/endless/EndlessDrivingState.hpp | 2 +- samples/scratchpad/src/endless/Track.hpp | 4 +- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 5977e854f..1860e88b2 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -299,7 +299,7 @@ void EndlessDrivingState::createScene() entity.addComponent(*tex); m_background[BackgroundLayer::Sky].entity = entity; m_background[BackgroundLayer::Sky].textureRect = entity.getComponent().getTextureRect(); - m_background[BackgroundLayer::Sky].speed = 0.04f; + m_background[BackgroundLayer::Sky].speed = 40.f; tex = &m_resources.textures.get("assets/golf/images/skybox/layers/02.png"); tex->setRepeated(true); @@ -309,8 +309,8 @@ void EndlessDrivingState::createScene() entity.addComponent(*tex); m_background[BackgroundLayer::Hills].entity = entity; m_background[BackgroundLayer::Hills].textureRect = entity.getComponent().getTextureRect(); - m_background[BackgroundLayer::Hills].speed = 0.08f; - m_background[BackgroundLayer::Hills].verticalSpeed = 0.04f; + m_background[BackgroundLayer::Hills].speed = 80.f; + m_background[BackgroundLayer::Hills].verticalSpeed = 40.f; tex = &m_resources.textures.get("assets/golf/images/skybox/layers/03.png"); tex->setRepeated(true); @@ -320,8 +320,8 @@ void EndlessDrivingState::createScene() entity.addComponent(*tex); m_background[BackgroundLayer::Trees].entity = entity; m_background[BackgroundLayer::Trees].textureRect = entity.getComponent().getTextureRect(); - m_background[BackgroundLayer::Trees].speed = 0.16f; - m_background[BackgroundLayer::Trees].verticalSpeed = 0.06f; + m_background[BackgroundLayer::Trees].speed = 160.f; + m_background[BackgroundLayer::Trees].verticalSpeed = 60.f; //player entity = m_gameScene.createEntity(); @@ -517,6 +517,7 @@ void EndlessDrivingState::updateRoad(float dt) float dx = 0.f; auto camPos = m_trackCamera.getPosition(); float maxY = 0.f; + float clipDepth = 0.f; //anything beyonf this requires clipping std::vector verts; const float halfWidth = RenderSizeFloat.x / 2.f; @@ -571,6 +572,7 @@ void EndlessDrivingState::updateRoad(float dt) continue; } maxY = curr.projection.position.y; + clipDepth = curr.position.z; debug.maxY = maxY; //update vertex array @@ -614,12 +616,13 @@ void EndlessDrivingState::updateRoad(float dt) const auto idx = *i; const auto& seg = m_road[idx]; + const float clipHeight = seg.position.z > clipDepth ? maxY : 0.f; + for (const auto& sprite : seg.sprites) { - //TODO use the current maxY value to clip the bottom of sprites glm::vec2 pos = seg.projection.position; pos.x += seg.projection.scale * sprite.position * RoadWidth * halfWidth; - addRoadSprite(sprite, pos, seg.projection.scale, verts); + addRoadSprite(sprite, pos, seg.projection.scale, clipHeight, verts); } } m_trackSpriteEntity.getComponent().getVertexData().swap(verts); @@ -647,24 +650,29 @@ void EndlessDrivingState::addRoadQuad(float x1, float x2, float y1, float y2, fl dst.emplace_back(glm::vec2(x2 + w2, y2), c); } -void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos, float scale, std::vector& dst) +void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos, float scale, float clip, std::vector& dst) { - //TODO clip bottom my maxY and skip completely if top < maxY - - auto uv = sprite.uv; scale *= sprite.scale; - glm::vec2 size = sprite.size * scale;// *1000.f; + glm::vec2 size = sprite.size * scale; pos.x -= (size.x / 2.f); - dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), glm::vec2(uv.left, uv.bottom + uv.height)); - dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom)); - dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height)); + cro::Colour c = cro::Colour::White; + if (clip > pos.x + size.x) + { + //fully occluded + //return; + c = cro::Colour::Magenta; + } + + dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), glm::vec2(uv.left, uv.bottom + uv.height), c); + dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom), c); + dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height), c); - dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height)); - dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom)); - dst.emplace_back(glm::vec2(pos.x + size.x, pos.y), glm::vec2(uv.left + uv.width, uv.bottom)); + dst.emplace_back(pos + size, glm::vec2(uv.left + uv.width, uv.bottom + uv.height), c); + dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom), c); + dst.emplace_back(glm::vec2(pos.x + size.x, pos.y), glm::vec2(uv.left + uv.width, uv.bottom), c); //dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), cro::Colour::Magenta); //dst.emplace_back(pos, cro::Colour::Magenta); diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index beedb5a57..203b140e2 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -119,5 +119,5 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void updatePlayer(float dt); void updateRoad(float dt); void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); - void addRoadSprite(const TrackSprite&, glm::vec2, float, std::vector&); + void addRoadSprite(const TrackSprite&, glm::vec2, float scale, float clip, std::vector&); }; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 6adf5117c..9af94d316 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -54,8 +54,8 @@ static inline constexpr std::size_t ExitMax = EnterMax; static inline constexpr float CurveMin = -0.004f; static inline constexpr float CurveMax = 0.004f; -static inline constexpr float HillMin = -0.03f; -static inline constexpr float HillMax = 0.03f; +static inline constexpr float HillMin = -30.f; +static inline constexpr float HillMax = 30.f; static inline constexpr std::int32_t DrawDistance = 200; //number of segs From 1962148d31d56eed86306fb3d57034e177bb2b8f Mon Sep 17 00:00:00 2001 From: fallahn Date: Fri, 12 Jan 2024 20:17:54 +0000 Subject: [PATCH 15/19] fix up sprite clipping detection --- samples/golf/buildnumber.h | 4 +- .../src/endless/EndlessDrivingState.cpp | 57 ++++++++++++------- .../src/endless/EndlessDrivingState.hpp | 7 ++- samples/scratchpad/src/endless/Track.hpp | 2 +- .../scratchpad/src/endless/TrackSegment.hpp | 2 + 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 8578f01b8..a1bf214e1 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3704 -#define BUILDNUMBER_STR "3704" +#define BUILDNUMBER 3706 +#define BUILDNUMBER_STR "3706" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 1860e88b2..bfac9f5c2 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -26,10 +26,11 @@ namespace { - constexpr glm::uvec2 RenderSize = glm::uvec2(320, 224); + constexpr std::uint32_t RenderScale = 2; + constexpr glm::uvec2 RenderSize = glm::uvec2(320, 224) * RenderScale; constexpr glm::vec2 RenderSizeFloat = glm::vec2(RenderSize); - constexpr float PlayerWidth = 74.f; - constexpr float PlayerHeight = 84.f; + constexpr float PlayerWidth = 74.f * RenderScale; + constexpr float PlayerHeight = 84.f * RenderScale; constexpr cro::FloatRect PlayerBounds((RenderSizeFloat.x - PlayerWidth) / 2.f, 0.f, PlayerWidth, PlayerHeight); constexpr float fogDensity = 5.f; @@ -237,7 +238,7 @@ void EndlessDrivingState::addSystems() void EndlessDrivingState::loadAssets() { cro::SpriteSheet spriteSheet; - spriteSheet.loadFromFile("assets/golf/sprites/shrubbery_autumn02_low.spt", m_resources.textures); + spriteSheet.loadFromFile("assets/golf/sprites/shrubbery_autumn02.spt", m_resources.textures); const auto parseSprite = [&](const cro::Sprite& sprite, std::int32_t spriteID) @@ -256,6 +257,7 @@ void EndlessDrivingState::loadAssets() entity.addComponent().setTexture(spriteSheet.getTexture()); entity.getComponent().setCullingEnabled(false); entity.getComponent().setPrimitiveType(GL_TRIANGLES); + entity.getComponent().setVertexData({ cro::Vertex2D() }); //there's a crash on nvidia drivers if we don't initialise this with at least 1 vertex... m_trackSpriteEntity = entity; } @@ -290,11 +292,14 @@ void EndlessDrivingState::createPlayer() void EndlessDrivingState::createScene() { + static constexpr float BGScale = static_cast(RenderScale) / 2.f; + //background auto* tex = &m_resources.textures.get("assets/golf/images/skybox/layers/01.png"); tex->setRepeated(true); auto entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.5f)); + entity.getComponent().setScale(glm::vec2(BGScale)); entity.addComponent(); entity.addComponent(*tex); m_background[BackgroundLayer::Sky].entity = entity; @@ -305,6 +310,7 @@ void EndlessDrivingState::createScene() tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.4f)); + entity.getComponent().setScale(glm::vec2(BGScale)); entity.addComponent(); entity.addComponent(*tex); m_background[BackgroundLayer::Hills].entity = entity; @@ -316,6 +322,7 @@ void EndlessDrivingState::createScene() tex->setRepeated(true); entity = m_gameScene.createEntity(); entity.addComponent().setPosition(glm::vec3(0.f, 0.f, -9.3f)); + entity.getComponent().setScale(glm::vec2(BGScale)); entity.addComponent(); entity.addComponent(*tex); m_background[BackgroundLayer::Trees].entity = entity; @@ -325,7 +332,7 @@ void EndlessDrivingState::createScene() //player entity = m_gameScene.createEntity(); - entity.addComponent().setPosition(glm::vec3(160.f, 0.f, -0.1f)); + entity.addComponent().setPosition(glm::vec3(RenderSizeFloat.x / 2.f, 0.f, -0.1f)); entity.addComponent(); entity.addComponent(m_playerTexture.getTexture()); entity.getComponent().setTextureRect(PlayerBounds); @@ -338,6 +345,7 @@ void EndlessDrivingState::createScene() entity.addComponent().setPrimitiveType(GL_TRIANGLES); entity.getComponent().setFacing(cro::Drawable2D::Facing::Back); entity.getComponent().setCullingEnabled(false); //assume we're always visible and skip bounds checking + entity.getComponent().setVertexData({ cro::Vertex2D() }); m_roadEntity = entity; @@ -372,14 +380,13 @@ void EndlessDrivingState::createScene() pos *= -1.f; } seg.sprites.emplace_back(m_trackSprites[spriteID]).position = pos; - seg.sprites.back().scale *= cro::Util::Random::value(0.9f, 1.1f); + seg.sprites.back().scale *= cro::Util::Random::value(0.9f, 1.8f) * RenderScale; } } } m_road[m_road.getSegmentCount() - 1].roadColour = cro::Colour::White; m_road[m_road.getSegmentCount() - 1].rumbleColour = cro::Colour::Blue; - //m_road.addSegment(EnterMin, HoldMin, ExitMin, 0.f, 0.f); auto resize = [](cro::Camera& cam) { @@ -446,9 +453,8 @@ void EndlessDrivingState::updatePlayer(float dt) } //centrifuge on curves - static constexpr float Centrifuge = 300.f; const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength) % m_road.getSegmentCount(); - m_player.position.x -= dx * speedRatio * m_road[segID].curve * Centrifuge; + m_player.position.x -= dx * speedRatio * m_road[segID].curve * Player::Centrifuge; @@ -517,7 +523,6 @@ void EndlessDrivingState::updateRoad(float dt) float dx = 0.f; auto camPos = m_trackCamera.getPosition(); float maxY = 0.f; - float clipDepth = 0.f; //anything beyonf this requires clipping std::vector verts; const float halfWidth = RenderSizeFloat.x / 2.f; @@ -556,6 +561,8 @@ void EndlessDrivingState::updateRoad(float dt) playerPos.x *= curr.width; m_trackCamera.updateScreenProjection(curr, playerPos, RenderSizeFloat); + float fogAmount = expFog(static_cast(i - start) / DrawDistance, fogDensity); + curr.fogAmount = fogAmount; //stash the sprites - these might poke out from //behind a hill so we'll draw them anyway regardless @@ -569,14 +576,14 @@ void EndlessDrivingState::updateRoad(float dt) if ((prev->position.z < m_trackCamera.getPosition().z) || curr.projection.position.y < maxY) { + curr.clipSprites = (curr.projection.position.y < maxY); continue; } maxY = curr.projection.position.y; - clipDepth = curr.position.z; + curr.clipSprites = false; debug.maxY = maxY; //update vertex array - float fogAmount = expFog(static_cast(i - start) / DrawDistance, fogDensity); //grass auto colour = glm::mix(curr.grassColour.getVec4(), FogColour.getVec4(), fogAmount); @@ -606,7 +613,6 @@ void EndlessDrivingState::updateRoad(float dt) //do this LAST!! buh prev = &curr; } - //addRoadQuad(320.f, 320.f, 0.f, 100.f, 320.f, 320.f, cro::Colour::Magenta, verts); m_roadEntity.getComponent().getVertexData().swap(verts); verts.clear(); @@ -616,13 +622,13 @@ void EndlessDrivingState::updateRoad(float dt) const auto idx = *i; const auto& seg = m_road[idx]; - const float clipHeight = seg.position.z > clipDepth ? maxY : 0.f; + const float clipHeight = seg.clipSprites ? maxY : 0.f; for (const auto& sprite : seg.sprites) { glm::vec2 pos = seg.projection.position; pos.x += seg.projection.scale * sprite.position * RoadWidth * halfWidth; - addRoadSprite(sprite, pos, seg.projection.scale, clipHeight, verts); + addRoadSprite(sprite, pos, seg.projection.scale, clipHeight, seg.fogAmount, verts); } } m_trackSpriteEntity.getComponent().getVertexData().swap(verts); @@ -650,7 +656,7 @@ void EndlessDrivingState::addRoadQuad(float x1, float x2, float y1, float y2, fl dst.emplace_back(glm::vec2(x2 + w2, y2), c); } -void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos, float scale, float clip, std::vector& dst) +void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos, float scale, float clip, float fogAmount, std::vector& dst) { auto uv = sprite.uv; scale *= sprite.scale; @@ -658,11 +664,15 @@ void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos glm::vec2 size = sprite.size * scale; pos.x -= (size.x / 2.f); - cro::Colour c = cro::Colour::White; - if (clip > pos.x + size.x) + cro::Colour c = glm::mix(glm::vec4(1.f), FogColour.getVec4(), fogAmount); + if (clip > pos.y + size.y) { //fully occluded - //return; + return; + } + + if (clip) + { c = cro::Colour::Magenta; } @@ -674,6 +684,15 @@ void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos dst.emplace_back(pos, glm::vec2(uv.left, uv.bottom), c); dst.emplace_back(glm::vec2(pos.x + size.x, pos.y), glm::vec2(uv.left + uv.width, uv.bottom), c); + + + + + + + + + //dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), cro::Colour::Magenta); //dst.emplace_back(pos, cro::Colour::Magenta); //dst.emplace_back(pos + size, cro::Colour::Magenta); diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index 203b140e2..e07936535 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -78,12 +78,13 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient glm::vec3 position = glm::vec3(0.f); float speed = 0.f; - static inline constexpr float MaxSpeed = SegmentLength * 60.f; //60 is our frame time - static inline constexpr float Acceleration = MaxSpeed / 5.f; + static inline constexpr float MaxSpeed = SegmentLength * 120.f; //60 is our frame time + static inline constexpr float Acceleration = MaxSpeed / 3.f; static inline constexpr float Braking = -MaxSpeed; static inline constexpr float Deceleration = -Acceleration; static inline constexpr float OffroadDeceleration = -MaxSpeed / 2.f; static inline constexpr float OffroadMaxSpeed = MaxSpeed / 4.f; + static inline constexpr float Centrifuge = 530.f; // "pull" on cornering struct Model final { @@ -119,5 +120,5 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void updatePlayer(float dt); void updateRoad(float dt); void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); - void addRoadSprite(const TrackSprite&, glm::vec2, float scale, float clip, std::vector&); + void addRoadSprite(const TrackSprite&, glm::vec2, float scale, float clip, float fogAmount, std::vector&); }; \ No newline at end of file diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index 9af94d316..b1b1ff0e2 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -57,7 +57,7 @@ static inline constexpr float CurveMax = 0.004f; static inline constexpr float HillMin = -30.f; static inline constexpr float HillMax = 30.f; -static inline constexpr std::int32_t DrawDistance = 200; //number of segs +static inline constexpr std::int32_t DrawDistance = 300; //number of segs class Track final { diff --git a/samples/scratchpad/src/endless/TrackSegment.hpp b/samples/scratchpad/src/endless/TrackSegment.hpp index f1be44e92..e252ccdcc 100644 --- a/samples/scratchpad/src/endless/TrackSegment.hpp +++ b/samples/scratchpad/src/endless/TrackSegment.hpp @@ -51,8 +51,10 @@ struct TrackSegment final cro::Colour rumbleColour; cro::Colour grassColour; bool roadMarking = false; + float fogAmount = 0.f; std::vector sprites; + bool clipSprites = false; //contains the last known screen projection struct Projection final From b485276c0b337f4bd29db48f46ac20ed58366eb5 Mon Sep 17 00:00:00 2001 From: fallahn Date: Sat, 13 Jan 2024 11:52:29 +0000 Subject: [PATCH 16/19] add quick emote buttons to text chat window --- samples/golf/buildnumber.h | 4 +- samples/golf/src/golf/GolfState.cpp | 34 +++++----- samples/golf/src/golf/GolfStateUI.cpp | 6 +- samples/golf/src/golf/MenuState.cpp | 6 +- samples/golf/src/golf/TextChat.cpp | 92 ++++++++++++++++++++++++-- samples/golf/src/golf/TextChat.hpp | 12 +++- samples/plugin_template/CMakeLists.txt | 4 +- 7 files changed, 126 insertions(+), 32 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index a1bf214e1..3e85b99eb 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3706 -#define BUILDNUMBER_STR "3706" +#define BUILDNUMBER 3730 +#define BUILDNUMBER_STR "3730" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/golf/GolfState.cpp b/samples/golf/src/golf/GolfState.cpp index aacfbcc9c..7011df89e 100644 --- a/samples/golf/src/golf/GolfState.cpp +++ b/samples/golf/src/golf/GolfState.cpp @@ -350,13 +350,13 @@ bool GolfState::handleEvent(const cro::Event& evt) case SDLK_ESCAPE: if (m_textChat.isVisible()) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, true); } break; case SDLK_F8: if (evt.key.keysym.mod & KMOD_SHIFT) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, true); } break; } @@ -481,7 +481,7 @@ bool GolfState::handleEvent(const cro::Event& evt) case SDLK_F8: if (evt.key.keysym.mod & KMOD_SHIFT) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, true); } break; case SDLK_F9: @@ -520,14 +520,14 @@ bool GolfState::handleEvent(const cro::Event& evt) case SDLK_F10: m_sharedData.clientConnection.netClient.sendPacket(PacketID::ServerCommand, std::uint16_t(ServerCommand::ChangeWind), net::NetFlag::Reliable); break; - case SDLK_KP_0: - setActiveCamera(CameraID::Idle); - { - /*static bool hidden = false; - m_activeAvatar->model.getComponent().setHidden(!hidden); - hidden = !hidden;*/ - } - break; + //case SDLK_KP_0: //used by emote quick key + // setActiveCamera(CameraID::Idle); + //{ + // /*static bool hidden = false; + // m_activeAvatar->model.getComponent().setHidden(!hidden); + // hidden = !hidden;*/ + //} + // break; case SDLK_KP_1: //setActiveCamera(1); //m_cameras[CameraID::Sky].getComponent().state = CameraFollower::Zoom; @@ -566,7 +566,7 @@ bool GolfState::handleEvent(const cro::Event& evt) msg->level = 19; } break; - case SDLK_KP_7: + /*case SDLK_KP_7: //taken over by emote quick key { auto* msg2 = cro::App::getInstance().getMessageBus().post(MessageID::GolfMessage); msg2->type = GolfEvent::BirdHit; @@ -574,7 +574,7 @@ bool GolfState::handleEvent(const cro::Event& evt) float rot = glm::eulerAngles(m_cameras[m_currentCamera].getComponent().getWorldRotation()).y; msg2->travelDistance = rot; } - break; + break;*/ //used in font smoothing debug GolfGame.cpp /*case SDLK_KP_MULTIPLY: { @@ -678,7 +678,7 @@ bool GolfState::handleEvent(const cro::Event& evt) case SDLK_ESCAPE: if (m_textChat.isVisible()) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, true); break; } [[fallthrough]]; @@ -690,15 +690,19 @@ bool GolfState::handleEvent(const cro::Event& evt) toggleQuitReady(); break; case SDLK_7: + case SDLK_KP_7: m_textChat.quickEmote(TextChat::Applaud); break; case SDLK_8: + case SDLK_KP_8: m_textChat.quickEmote(TextChat::Happy); break; case SDLK_9: + case SDLK_KP_9: m_textChat.quickEmote(TextChat::Laughing); break; case SDLK_0: + case SDLK_KP_0: m_textChat.quickEmote(TextChat::Angry); break; } @@ -736,7 +740,7 @@ bool GolfState::handleEvent(const cro::Event& evt) break; case cro::GameController::ButtonTrackpad: case cro::GameController::PaddleR4: - m_textChat.toggleWindow(true); + m_textChat.toggleWindow(true, true); break; } } diff --git a/samples/golf/src/golf/GolfStateUI.cpp b/samples/golf/src/golf/GolfStateUI.cpp index 5c6406152..3f7b1a759 100644 --- a/samples/golf/src/golf/GolfStateUI.cpp +++ b/samples/golf/src/golf/GolfStateUI.cpp @@ -4785,7 +4785,7 @@ bool GolfState::EmoteWheel::handleEvent(const cro::Event& evt) return true; } - switch (evt.key.keysym.sym) + /*switch (evt.key.keysym.sym) { default: break; case SDLK_7: @@ -4808,7 +4808,7 @@ bool GolfState::EmoteWheel::handleEvent(const cro::Event& evt) cooldown = 6.f; buttonNodes[7].getComponent().active = true; return true; - } + }*/ } } @@ -4883,7 +4883,7 @@ bool GolfState::EmoteWheel::handleEvent(const cro::Event& evt) //consume this so we don't mess with the swing return true; case cro::GameController::ButtonX: - m_textChat.toggleWindow(true); + m_textChat.toggleWindow(true, true); //close emote wheel automatically targetScale = 0.f; return true; diff --git a/samples/golf/src/golf/MenuState.cpp b/samples/golf/src/golf/MenuState.cpp index 52dad1589..c70a80692 100644 --- a/samples/golf/src/golf/MenuState.cpp +++ b/samples/golf/src/golf/MenuState.cpp @@ -655,7 +655,7 @@ bool MenuState::handleEvent(const cro::Event& evt) case SDLK_ESCAPE: if (m_textChat.isVisible()) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, false); } break; /*case SDLK_F8: @@ -806,7 +806,7 @@ bool MenuState::handleEvent(const cro::Event& evt) if ((evt.key.keysym.mod & KMOD_SHIFT) && m_currentMenu == MenuID::Lobby) { - m_textChat.toggleWindow(false); + m_textChat.toggleWindow(false, false); } break; } @@ -872,7 +872,7 @@ bool MenuState::handleEvent(const cro::Event& evt) case cro::GameController::ButtonY: if (m_currentMenu == MenuID::Lobby) { - m_textChat.toggleWindow(true); + m_textChat.toggleWindow(true, false); } break; } diff --git a/samples/golf/src/golf/TextChat.cpp b/samples/golf/src/golf/TextChat.cpp index d18c697c2..2620c68d5 100644 --- a/samples/golf/src/golf/TextChat.cpp +++ b/samples/golf/src/golf/TextChat.cpp @@ -1,6 +1,6 @@ /*----------------------------------------------------------------------- -Matt Marchant 2023 +Matt Marchant 2023 - 2024 http://trederia.blogspot.com Super Video Golf - zlib licence. @@ -48,6 +48,17 @@ source distribution. namespace { + static void showToolTip(const char* desc) + { + if (ImGui::BeginItemTooltip()) + { + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(desc); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + } + const cro::Time ResendTime = cro::seconds(1.5f); const std::array ApplaudStrings = @@ -131,8 +142,36 @@ TextChat::TextChat(cro::Scene& s, SharedStateData& sd) m_scrollToEnd (false), m_focusInput (false), m_screenChatIndex (0), - m_screenChatActiveCount (0) + m_screenChatActiveCount (0), + m_showShortcuts (false) { + //use cro string to construct the utf8 strings + cro::String str(std::uint32_t(0x1F44F)); + + auto utf = str.toUtf8(); + + m_buttonStrings.applaud.resize(utf.size()); + std::memcpy(m_buttonStrings.applaud.data(), utf.data(), utf.size()); + + str.clear(); + str = std::uint32_t(0x1F600); + utf = str.toUtf8(); + m_buttonStrings.happy.resize(utf.size()); + std::memcpy(m_buttonStrings.happy.data(), utf.data(), utf.size()); + + str.clear(); + str = std::uint32_t(0x1F923); + utf = str.toUtf8(); + m_buttonStrings.laughing.resize(utf.size()); + std::memcpy(m_buttonStrings.laughing.data(), utf.data(), utf.size()); + + str.clear(); + str = std::uint32_t(0x1F624); + utf = str.toUtf8(); + m_buttonStrings.angry.resize(utf.size()); + std::memcpy(m_buttonStrings.angry.data(), utf.data(), utf.size()); + + registerWindow([&]() { if (m_visible) @@ -140,11 +179,47 @@ TextChat::TextChat(cro::Scene& s, SharedStateData& sd) //used to detect if we had any input auto buffSize = m_inputBuffer.size(); - ImGui::SetNextWindowSize({ 600.f, 280.f }); - if (ImGui::Begin("Chat Window", &m_visible)) + ImGui::SetNextWindowSize({ 600.f, 340.f }); + if (ImGui::Begin("Chat Window", &m_visible, ImGuiWindowFlags_NoCollapse)) { + if (m_showShortcuts) + { + ImGui::Text("Quick Emotes"); + ImGui::Separator(); + if (ImGui::Button(m_buttonStrings.applaud.data())) + { + quickEmote(TextChat::Applaud); + m_visible = false; + } + showToolTip("Applaud - Shortcut: Number 7"); + ImGui::SameLine(); + if (ImGui::Button(m_buttonStrings.happy.data())) + { + quickEmote(TextChat::Happy); + m_visible = false; + } + showToolTip("Happy - Shortcut: Number 8"); + ImGui::SameLine(); + if (ImGui::Button(m_buttonStrings.laughing.data())) + { + quickEmote(TextChat::Laughing); + m_visible = false; + } + showToolTip("Laughing - Shortcut: Number 9"); + ImGui::SameLine(); + if (ImGui::Button(m_buttonStrings.angry.data())) + { + quickEmote(TextChat::Angry); + m_visible = false; + } + showToolTip("Grumpy - Shortcut: Number 0"); + ImGui::Separator(); + } + const float reserveHeight = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0, -reserveHeight), false); + ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.f,0.f,0.f,0.4f)); + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -reserveHeight), false, ImGuiWindowFlags_AlwaysUseWindowPadding); + ImGui::PopStyleColor(); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); for (const auto& [str, colour] : m_displayBuffer) @@ -187,6 +262,9 @@ TextChat::TextChat(cro::Scene& s, SharedStateData& sd) } m_focusInput = false; + + + //TODO emoji keypad rollout } ImGui::End(); @@ -376,8 +454,10 @@ void TextChat::handlePacket(const net::NetEvent::Packet& pkt) m_scene.getActiveCamera().getComponent().active = true; } -void TextChat::toggleWindow(bool showOSK) +void TextChat::toggleWindow(bool showOSK, bool showQuickEmote) { + m_showShortcuts = showQuickEmote; + #ifdef USE_GNS if (Social::isSteamdeck()) { diff --git a/samples/golf/src/golf/TextChat.hpp b/samples/golf/src/golf/TextChat.hpp index 093a2c4e4..1abe8a152 100644 --- a/samples/golf/src/golf/TextChat.hpp +++ b/samples/golf/src/golf/TextChat.hpp @@ -48,7 +48,7 @@ class TextChat final : public cro::GuiClient void handlePacket(const net::NetEvent::Packet&); - void toggleWindow(bool showOSK); + void toggleWindow(bool showOSK, bool showQuickEmote); bool isVisible() const { return m_visible; } @@ -91,6 +91,16 @@ class TextChat final : public cro::GuiClient std::size_t m_screenChatIndex; std::size_t m_screenChatActiveCount; + bool m_showShortcuts; + struct ButtonStrings final + { + std::vector angry; + std::vector applaud; + std::vector happy; + std::vector laughing; + }m_buttonStrings; + + //raises notifications for client icons cro::Clock m_chatTimer; void beginChat(); diff --git a/samples/plugin_template/CMakeLists.txt b/samples/plugin_template/CMakeLists.txt index 45ca126ba..c96c50ba1 100644 --- a/samples/plugin_template/CMakeLists.txt +++ b/samples/plugin_template/CMakeLists.txt @@ -48,9 +48,9 @@ include_directories( add_subdirectory(include) add_subdirectory(src) -# Add XY_DEBUG on Debug builds +# Add CRO_DEBUG on Debug builds if (CMAKE_BUILD_TYPE MATCHES Debug) - add_definitions(-DXY_DEBUG) + add_definitions(-DCRO_DEBUG) endif() # Create the actual binary (PROJECT_SRC variable is set inside previous steps) From be0f384ab383ae2acb3c0b63c001426ad6e44f64 Mon Sep 17 00:00:00 2001 From: fallahn Date: Sat, 13 Jan 2024 15:52:06 +0000 Subject: [PATCH 17/19] add controller input to vehicle --- .../src/endless/EndlessDrivingState.cpp | 117 ++++++++++++++---- .../src/endless/EndlessDrivingState.hpp | 5 + 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index bfac9f5c2..6a450cfd6 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -50,6 +50,8 @@ namespace { float maxY = 0.f; float segmentProgress = 0.f; + + }debug; } @@ -89,6 +91,10 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con m_playerScene.getActiveCamera().getComponent().setPosition(pos); }*/ + ImGui::ProgressBar(m_inputFlags.brakeMultiplier); + ImGui::ProgressBar(m_inputFlags.accelerateMultiplier); + ImGui::ProgressBar(m_inputFlags.steerMultiplier); + ImGui::Text("Max Y %3.3f", debug.maxY); ImGui::Text("Player Y %3.3f", m_player.position.y); ImGui::Text("Player Z %3.3f", m_player.position.z); @@ -143,40 +149,44 @@ bool EndlessDrivingState::handleEvent(const cro::Event& evt) requestStackClear(); requestStackPush(0); break; + } - //TODO move this to player/input and read keybinds - case SDLK_w: + //TODO compare to keybind + if (evt.key.keysym.sym == SDLK_w) + { m_inputFlags.flags |= InputFlags::Up; - break; - case SDLK_s: + } + if (evt.key.keysym.sym == SDLK_s) + { m_inputFlags.flags |= InputFlags::Down; - break; - case SDLK_a: + } + if (evt.key.keysym.sym == SDLK_a) + { m_inputFlags.flags |= InputFlags::Left; - break; - case SDLK_d: + } + if (evt.key.keysym.sym == SDLK_d) + { m_inputFlags.flags |= InputFlags::Right; - break; } } else if (evt.type == SDL_KEYUP) { - switch (evt.key.keysym.sym) + //TODO compare to keybind + if (evt.key.keysym.sym == SDLK_w) { - default: break; - //TODO move this to player/input and read keybinds - case SDLK_w: m_inputFlags.flags &= ~InputFlags::Up; - break; - case SDLK_s: + } + if (evt.key.keysym.sym == SDLK_s) + { m_inputFlags.flags &= ~InputFlags::Down; - break; - case SDLK_a: + } + if (evt.key.keysym.sym == SDLK_a) + { m_inputFlags.flags &= ~InputFlags::Left; - break; - case SDLK_d: + } + if (evt.key.keysym.sym == SDLK_d) + { m_inputFlags.flags &= ~InputFlags::Right; - break; } } @@ -195,6 +205,7 @@ void EndlessDrivingState::handleMessage(const cro::Message& msg) bool EndlessDrivingState::simulate(float dt) { + updateControllerInput(); updateRoad(dt); updatePlayer(dt); @@ -428,10 +439,60 @@ void EndlessDrivingState::createUI() resize(cam); } +void EndlessDrivingState::updateControllerInput() +{ + m_inputFlags.steerMultiplier = 1.f; + m_inputFlags.accelerateMultiplier = 1.f; + m_inputFlags.brakeMultiplier = 1.f; + + + auto axisPos = cro::GameController::getAxisPosition(0, cro::GameController::TriggerRight); + if (axisPos > cro::GameController::TriggerDeadZone) + { + m_inputFlags.accelerateMultiplier = cro::Util::Easing::easeInCubic(static_cast(axisPos) / cro::GameController::AxisMax); + m_inputFlags.flags |= InputFlags::Up; + } + else + { + //hmm, how to check if the keys aren't being used? + m_inputFlags.flags &= ~InputFlags::Up; + } + + axisPos = cro::GameController::getAxisPosition(0, cro::GameController::TriggerLeft); + if (axisPos > cro::GameController::TriggerDeadZone) + { + m_inputFlags.brakeMultiplier = static_cast(axisPos) / cro::GameController::AxisMax; + m_inputFlags.flags |= InputFlags::Down; + } + else + { + m_inputFlags.flags &= ~InputFlags::Down; + } + + axisPos = cro::GameController::getAxisPosition(0, cro::GameController::AxisLeftX); + if (axisPos > cro::GameController::LeftThumbDeadZone) + { + m_inputFlags.steerMultiplier = cro::Util::Easing::easeInCubic(static_cast(axisPos) / cro::GameController::AxisMax); + m_inputFlags.flags |= InputFlags::Right; + m_inputFlags.flags &= ~InputFlags::Left; + } + else if (axisPos < -cro::GameController::LeftThumbDeadZone) + { + m_inputFlags.steerMultiplier = cro::Util::Easing::easeInCubic(static_cast(axisPos) / -cro::GameController::AxisMax); + m_inputFlags.flags |= InputFlags::Left; + m_inputFlags.flags &= ~InputFlags::Right; + } + else + { + m_inputFlags.flags &= ~(InputFlags::Left | InputFlags::Right); + } +} + void EndlessDrivingState::updatePlayer(float dt) { const float speedRatio = (m_player.speed / Player::MaxSpeed); const float dx = dt * 2.f * speedRatio; + const float dxSteer = dt * 2.f * cro::Util::Easing::easeOutQuad(speedRatio); if ((m_inputFlags.flags & (InputFlags::Left | InputFlags::Right)) == 0) { @@ -441,20 +502,22 @@ void EndlessDrivingState::updatePlayer(float dt) { if (m_inputFlags.flags & InputFlags::Left) { - m_player.position.x -= dx; - m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + dx); + const auto d = dxSteer * m_inputFlags.steerMultiplier; + m_player.position.x -= d; + m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + d); } if (m_inputFlags.flags & InputFlags::Right) { - m_player.position.x += dx; - m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - dx); + const auto d = dxSteer * m_inputFlags.steerMultiplier; + m_player.position.x += d; + m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - d); } } //centrifuge on curves const std::size_t segID = static_cast((m_trackCamera.getPosition().z + m_player.position.z) / SegmentLength) % m_road.getSegmentCount(); - m_player.position.x -= dx * speedRatio * m_road[segID].curve * Player::Centrifuge; + m_player.position.x -= dx * cro::Util::Easing::easeInCubic(speedRatio) * m_road[segID].curve * Player::Centrifuge; @@ -467,11 +530,11 @@ void EndlessDrivingState::updatePlayer(float dt) { if (m_inputFlags.flags & InputFlags::Up) { - m_player.speed += Player::Acceleration * dt; + m_player.speed += Player::Acceleration * dt * m_inputFlags.accelerateMultiplier; } if (m_inputFlags.flags & InputFlags::Down) { - m_player.speed += Player::Braking * dt; + m_player.speed += Player::Braking * dt * m_inputFlags.brakeMultiplier; } } diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index e07936535..b376b2445 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -108,6 +108,10 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient }; std::uint16_t flags = 0; std::uint16_t prevFlags = 0; + + float steerMultiplier = 1.f; + float accelerateMultiplier = 1.f; + float brakeMultiplier = 1.f; }m_inputFlags; @@ -117,6 +121,7 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient void createScene(); void createUI(); + void updateControllerInput(); void updatePlayer(float dt); void updateRoad(float dt); void addRoadQuad(float x1, float x2, float y1, float y2, float w1, float w2, cro::Colour, std::vector&); From a8cb69e37a42eeb7226a88607134110cc20fbc49 Mon Sep 17 00:00:00 2001 From: fallahn Date: Sat, 13 Jan 2024 16:35:43 +0000 Subject: [PATCH 18/19] prevent controller input overriding keyboard input properly clip track side sprites --- .../src/endless/EndlessDrivingState.cpp | 73 +++++++++++++------ .../src/endless/EndlessDrivingState.hpp | 2 + samples/scratchpad/src/endless/Track.hpp | 2 +- .../scratchpad/src/endless/TrackSegment.hpp | 2 +- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.cpp b/samples/scratchpad/src/endless/EndlessDrivingState.cpp index 6a450cfd6..99c3716d4 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.cpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.cpp @@ -95,6 +95,8 @@ EndlessDrivingState::EndlessDrivingState(cro::StateStack& stack, cro::State::Con ImGui::ProgressBar(m_inputFlags.accelerateMultiplier); ImGui::ProgressBar(m_inputFlags.steerMultiplier); + ImGui::Text("Key Count %d", m_inputFlags.keyCount); + ImGui::Text("Max Y %3.3f", debug.maxY); ImGui::Text("Player Y %3.3f", m_player.position.y); ImGui::Text("Player Z %3.3f", m_player.position.z); @@ -151,22 +153,29 @@ bool EndlessDrivingState::handleEvent(const cro::Event& evt) break; } - //TODO compare to keybind - if (evt.key.keysym.sym == SDLK_w) - { - m_inputFlags.flags |= InputFlags::Up; - } - if (evt.key.keysym.sym == SDLK_s) - { - m_inputFlags.flags |= InputFlags::Down; - } - if (evt.key.keysym.sym == SDLK_a) + if (!evt.key.repeat) { - m_inputFlags.flags |= InputFlags::Left; - } - if (evt.key.keysym.sym == SDLK_d) - { - m_inputFlags.flags |= InputFlags::Right; + //TODO compare to keybind + if (evt.key.keysym.sym == SDLK_w) + { + m_inputFlags.flags |= InputFlags::Up; + m_inputFlags.keyCount++; + } + if (evt.key.keysym.sym == SDLK_s) + { + m_inputFlags.flags |= InputFlags::Down; + m_inputFlags.keyCount++; + } + if (evt.key.keysym.sym == SDLK_a) + { + m_inputFlags.flags |= InputFlags::Left; + m_inputFlags.keyCount++; + } + if (evt.key.keysym.sym == SDLK_d) + { + m_inputFlags.flags |= InputFlags::Right; + m_inputFlags.keyCount++; + } } } else if (evt.type == SDL_KEYUP) @@ -175,18 +184,22 @@ bool EndlessDrivingState::handleEvent(const cro::Event& evt) if (evt.key.keysym.sym == SDLK_w) { m_inputFlags.flags &= ~InputFlags::Up; + m_inputFlags.keyCount--; } if (evt.key.keysym.sym == SDLK_s) { m_inputFlags.flags &= ~InputFlags::Down; + m_inputFlags.keyCount--; } if (evt.key.keysym.sym == SDLK_a) { m_inputFlags.flags &= ~InputFlags::Left; + m_inputFlags.keyCount--; } if (evt.key.keysym.sym == SDLK_d) { m_inputFlags.flags &= ~InputFlags::Right; + m_inputFlags.keyCount--; } } @@ -445,6 +458,12 @@ void EndlessDrivingState::updateControllerInput() m_inputFlags.accelerateMultiplier = 1.f; m_inputFlags.brakeMultiplier = 1.f; + if (m_inputFlags.keyCount) + { + //some keys are pressed, don't use controller + return; + } + auto axisPos = cro::GameController::getAxisPosition(0, cro::GameController::TriggerRight); if (axisPos > cro::GameController::TriggerDeadZone) @@ -504,14 +523,14 @@ void EndlessDrivingState::updatePlayer(float dt) { const auto d = dxSteer * m_inputFlags.steerMultiplier; m_player.position.x -= d; - m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + d); + m_player.model.rotationY = std::min(Player::Model::MaxY, m_player.model.rotationY + (dx * m_inputFlags.steerMultiplier)); } if (m_inputFlags.flags & InputFlags::Right) { const auto d = dxSteer * m_inputFlags.steerMultiplier; m_player.position.x += d; - m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - d); + m_player.model.rotationY = std::max(-Player::Model::MaxY, m_player.model.rotationY - (dx * m_inputFlags.steerMultiplier)); } } @@ -639,11 +658,11 @@ void EndlessDrivingState::updateRoad(float dt) if ((prev->position.z < m_trackCamera.getPosition().z) || curr.projection.position.y < maxY) { - curr.clipSprites = (curr.projection.position.y < maxY); + curr.clipHeight = (curr.projection.position.y < maxY) ? maxY : 0.f; continue; } maxY = curr.projection.position.y; - curr.clipSprites = false; + curr.clipHeight = 0.f; debug.maxY = maxY; //update vertex array @@ -685,13 +704,11 @@ void EndlessDrivingState::updateRoad(float dt) const auto idx = *i; const auto& seg = m_road[idx]; - const float clipHeight = seg.clipSprites ? maxY : 0.f; - for (const auto& sprite : seg.sprites) { glm::vec2 pos = seg.projection.position; pos.x += seg.projection.scale * sprite.position * RoadWidth * halfWidth; - addRoadSprite(sprite, pos, seg.projection.scale, clipHeight, seg.fogAmount, verts); + addRoadSprite(sprite, pos, seg.projection.scale, seg.clipHeight, seg.fogAmount, verts); } } m_trackSpriteEntity.getComponent().getVertexData().swap(verts); @@ -736,7 +753,17 @@ void EndlessDrivingState::addRoadSprite(const TrackSprite& sprite, glm::vec2 pos if (clip) { - c = cro::Colour::Magenta; + //c = cro::Colour::Magenta; + + const auto diff = clip - pos.y; + const auto uvOffset = diff / size.y; + const auto uvDiff = uv.height * uvOffset; + + pos.y += diff; + size.y -= diff; + + uv.bottom += uvDiff; + uv.height -= uvDiff; } dst.emplace_back(glm::vec2(pos.x, pos.y + size.y), glm::vec2(uv.left, uv.bottom + uv.height), c); diff --git a/samples/scratchpad/src/endless/EndlessDrivingState.hpp b/samples/scratchpad/src/endless/EndlessDrivingState.hpp index b376b2445..da08793cf 100644 --- a/samples/scratchpad/src/endless/EndlessDrivingState.hpp +++ b/samples/scratchpad/src/endless/EndlessDrivingState.hpp @@ -112,6 +112,8 @@ class EndlessDrivingState final : public cro::State, public cro::GuiClient float steerMultiplier = 1.f; float accelerateMultiplier = 1.f; float brakeMultiplier = 1.f; + + std::int32_t keyCount = 0; //tracks how many keys are pressed and only allows controller to override when 0 }m_inputFlags; diff --git a/samples/scratchpad/src/endless/Track.hpp b/samples/scratchpad/src/endless/Track.hpp index b1b1ff0e2..ca294b543 100644 --- a/samples/scratchpad/src/endless/Track.hpp +++ b/samples/scratchpad/src/endless/Track.hpp @@ -57,7 +57,7 @@ static inline constexpr float CurveMax = 0.004f; static inline constexpr float HillMin = -30.f; static inline constexpr float HillMax = 30.f; -static inline constexpr std::int32_t DrawDistance = 300; //number of segs +static inline constexpr std::int32_t DrawDistance = 500; //number of segs class Track final { diff --git a/samples/scratchpad/src/endless/TrackSegment.hpp b/samples/scratchpad/src/endless/TrackSegment.hpp index e252ccdcc..7b6b53bab 100644 --- a/samples/scratchpad/src/endless/TrackSegment.hpp +++ b/samples/scratchpad/src/endless/TrackSegment.hpp @@ -54,7 +54,7 @@ struct TrackSegment final float fogAmount = 0.f; std::vector sprites; - bool clipSprites = false; + float clipHeight = 0.f; //contains the last known screen projection struct Projection final From 4d88321a17cbe041db5027b6afb8a3027da64d07 Mon Sep 17 00:00:00 2001 From: fallahn Date: Sun, 14 Jan 2024 11:07:46 +0000 Subject: [PATCH 19/19] null terminate button strings refresh options window when toggling putt assist checkbox --- samples/golf/buildnumber.h | 4 ++-- samples/golf/src/golf/OptionsState.cpp | 2 ++ samples/golf/src/golf/TextChat.cpp | 9 ++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/samples/golf/buildnumber.h b/samples/golf/buildnumber.h index 3e85b99eb..999a99741 100644 --- a/samples/golf/buildnumber.h +++ b/samples/golf/buildnumber.h @@ -3,7 +3,7 @@ #ifndef BUILD_NUMBER_H_ #define BUILD_NUMBER_H_ -#define BUILDNUMBER 3730 -#define BUILDNUMBER_STR "3730" +#define BUILDNUMBER 3733 +#define BUILDNUMBER_STR "3733" #endif /* BUILD_NUMBER_H_ */ diff --git a/samples/golf/src/golf/OptionsState.cpp b/samples/golf/src/golf/OptionsState.cpp index b353495db..6b6aa7fa7 100644 --- a/samples/golf/src/golf/OptionsState.cpp +++ b/samples/golf/src/golf/OptionsState.cpp @@ -1935,6 +1935,7 @@ void OptionsState::buildAVMenu(cro::Entity parent, const cro::SpriteSheet& sprit { m_sharedData.showBeacon = !m_sharedData.showBeacon; m_audioEnts[AudioID::Accept].getComponent().play(); + m_scene.getActiveCamera().getComponent().active = true; } }); @@ -2125,6 +2126,7 @@ void OptionsState::buildAVMenu(cro::Entity parent, const cro::SpriteSheet& sprit { m_sharedData.showPuttingPower = !m_sharedData.showPuttingPower; m_audioEnts[AudioID::Accept].getComponent().play(); + m_scene.getActiveCamera().getComponent().active = true; } }); diff --git a/samples/golf/src/golf/TextChat.cpp b/samples/golf/src/golf/TextChat.cpp index 2620c68d5..809bc6358 100644 --- a/samples/golf/src/golf/TextChat.cpp +++ b/samples/golf/src/golf/TextChat.cpp @@ -152,25 +152,28 @@ TextChat::TextChat(cro::Scene& s, SharedStateData& sd) m_buttonStrings.applaud.resize(utf.size()); std::memcpy(m_buttonStrings.applaud.data(), utf.data(), utf.size()); + m_buttonStrings.applaud.push_back(0); str.clear(); str = std::uint32_t(0x1F600); utf = str.toUtf8(); m_buttonStrings.happy.resize(utf.size()); std::memcpy(m_buttonStrings.happy.data(), utf.data(), utf.size()); + m_buttonStrings.happy.push_back(0); str.clear(); str = std::uint32_t(0x1F923); utf = str.toUtf8(); m_buttonStrings.laughing.resize(utf.size()); std::memcpy(m_buttonStrings.laughing.data(), utf.data(), utf.size()); + m_buttonStrings.laughing.push_back(0); str.clear(); str = std::uint32_t(0x1F624); utf = str.toUtf8(); m_buttonStrings.angry.resize(utf.size()); std::memcpy(m_buttonStrings.angry.data(), utf.data(), utf.size()); - + m_buttonStrings.angry.push_back(0); registerWindow([&]() { @@ -184,8 +187,8 @@ TextChat::TextChat(cro::Scene& s, SharedStateData& sd) { if (m_showShortcuts) { - ImGui::Text("Quick Emotes"); - ImGui::Separator(); + ImGui::Text("Quick Emotes: "); + ImGui::SameLine(); if (ImGui::Button(m_buttonStrings.applaud.data())) { quickEmote(TextChat::Applaud);