Various Works.

This commit is contained in:
2025-06-17 21:17:13 -05:00
parent 10a8a846da
commit e4ef5c8f6a
11 changed files with 168 additions and 119 deletions

View File

@@ -78,6 +78,8 @@ target_link_libraries(Editor2D PUBLIC Event J3ML jlog ReWindow JGL JUI mcolor jj
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/assets)
# TODO: Reorganize lib files into LevelAPI, EditorApp, TestGame.
add_executable(Editor2DApp main.cpp app.rc)
target_link_libraries(Editor2DApp PUBLIC Editor2D)

View File

@@ -143,6 +143,7 @@ protected:
tile.quad = quads[i];
tile.name = std::format("tile_{}", i);
tile.metadata = json::value();
tile.collides = true;
tiles.emplace(tiles.begin() + i, tile);
}
}

View File

@@ -3,9 +3,16 @@
namespace TestGame {
class GameEntity : public Entity
{
public:
float gravity = 9.8f;
float mass = 12.f;
float air_resistance = 8.f;
float friction = 0.001f;
float acceleration = 1200;
GameEntity(const Vector2& spawn_pos) {
pos = spawn_pos;

View File

@@ -1,3 +1,15 @@
#pragma once
#include <JUI/Widgets/Window.hpp>
namespace TestGame {
class PhysicsTweaker : public JUI::Window {
public:
PhysicsTweaker() : JUI::Window() {
}
protected:
private:
};
}

View File

@@ -1,54 +1,20 @@
#pragma once
#include "GameEntity.hpp"
#include <JGL/JGL.h>
namespace TestGame {
class Player : public GameEntity
{
public:
Player(const Vector2& spawn_pos) : GameEntity(spawn_pos) {
bbox = {16, 24};
}
inline static JGL::Texture* sprite = nullptr;
Player(const Vector2& spawn_pos);
~Player() {
~Player();
}
void Update(float elapsed) override;
void Update(float elapsed) override {
// Update current position to our next_position, which was computed on the last frame.
// This means we can collision solve our next_pos in between calls to entity->Update();
pos = next_pos;
velocity.x *= 1 - (elapsed * air_resistance);
//velocity.y *= 1 - (elapsed * air_resistance);
//if (on_ground)
//velocity.x *= friction;
velocity.y += (elapsed*gravity*mass);
next_pos += velocity * elapsed;
if (Math::Abs(velocity.y) > 2)
on_ground = false;
if (InputService::IsKeyDown(Keys::A))
velocity.x -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::D))
velocity.x += acceleration * elapsed;
if (InputService::IsKeyDown(Keys::W))
velocity.y -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::S))
velocity.y += acceleration * elapsed;
}
void Draw() override {
J2D::FillRect(Colors::Blue, pos, bbox);
J2D::DrawPartialSprite(player_tex, pos, {0,0}, bbox);
}
void Draw() override;
};
}

View File

@@ -5,6 +5,9 @@
#include "JUI/Widgets/Scene.hpp"
#include "ReWindow/types/Window.h"
#include <JUI/Widgets/Slider.hpp>
#include <JUI/Base/TextBase.hpp>
namespace TestGame
{
constexpr int GL_MAJOR = 2;
@@ -14,6 +17,39 @@ namespace TestGame
constexpr int START_APP_HEIGHT = 768;
static const std::string START_APP_TITLE = "Redacted Software 2D Level Editor - Map Testing Game";
// Implemented in next version of JUI.
class LabeledSlider : public JUI::Slider, public JUI::TextBase {
public:
LabeledSlider() : Slider(), TextBase() {
}
explicit LabeledSlider(Widget* parent) : LabeledSlider()
{
this->Parent(parent);
}
void Draw() override {
Slider::Draw();
auto abs_pos = this->GetAbsolutePosition();
auto abs_size = this->GetAbsoluteSize();
auto pos_pad = GetAbsolutePaddingTopLeft();
auto size_pad = GetAbsolutePaddingBottomRight();
TextBase::Draw(abs_pos + pos_pad, abs_size - size_pad);
}
void Update(float elapsed) override {
Slider::Update(elapsed);
TextBase::Update(elapsed);
}
protected:
private:
};
class TestGameAppWindow : public ReWindow::OpenGLWindow
{
public:
@@ -58,16 +94,12 @@ namespace TestGame
void DrawLayer(const Layer* layer) const;
void ApplyOriginTransformation() {
glTranslatef(GetWidth() / 2.f, GetHeight() / 2.f, 0);
}
/// Translates the coordinate-space origin {0,0} to be at the center of the screen.
void ApplyOriginTransformation();
void ApplyCameraTransformation() {
ApplyOriginTransformation();
glRotatef(camera.rotation.current, 0, 0, 1);
glScalef(camera.scale.current, camera.scale.current, 1);
glTranslatef(-camera.translation.current.x, -camera.translation.current.y, 0);
}
/// Applies the camera's rotation, scale, and translation to the coordinate system.
/// This is performed after translating the origin to the center of the screen.
void ApplyCameraTransformation();
void DrawLevel(const Level* level) const
{
@@ -77,6 +109,7 @@ namespace TestGame
}
}
/// Draw objects with the camera projection, as if they are in world-space.
void DrawWorldSpace() {
if (!data_ready) return; // Don't try to draw the level if not loaded.
@@ -159,4 +192,5 @@ namespace TestGame
#pragma endregion
};
}

View File

@@ -855,21 +855,11 @@ void EditorApp::Draw()
int hovered_tile_id = GetTile(cell);
if (hovered_tile_id > 0) {
if (hovered_tile_id > -1) {
Tile hovered_tile = loaded_tileset->tiles[hovered_tile_id];
J2D::DrawString(Colors::White, std::format("Hovered Tile: {}", hovered_tile.name), 16, 64, 16);
}
glPopMatrix();
auto maus = GetMouseCoordinates();

View File

@@ -1,5 +1,15 @@
#include <Data/Entity.hpp>
Entity::Entity():
x(0), y(0),
width(0), height(0),
rotation(0),
flip_h(0), flip_v(0),
z_index(0),
overlay_color() {
}
Entity::Entity(const json::value &json) {
Deserialize(json);
}

48
src/TestGame/Player.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include <ReWindow/InputService.h>
#include <TestGame/Player.hpp>
#include <JGL/JGL.h>
TestGame::Player::Player(const Vector2 &spawn_pos): GameEntity(spawn_pos) {
bbox = {16, 24};
}
TestGame::Player::~Player() {
}
void TestGame::Player::Update(float elapsed) {
// Update current position to our next_position, which was computed on the last frame.
// This means we can collision solve our next_pos in between calls to entity->Update();
pos = next_pos;
velocity.x *= 1 - (elapsed * air_resistance);
//velocity.y *= 1 - (elapsed * air_resistance);
//if (on_ground)
//velocity.x *= friction;
velocity.y += (elapsed*gravity*mass);
next_pos += velocity * elapsed;
if (Math::Abs(velocity.y) > 2)
on_ground = false;
if (InputService::IsKeyDown(Keys::A))
velocity.x -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::D))
velocity.x += acceleration * elapsed;
if (InputService::IsKeyDown(Keys::W))
velocity.y -= acceleration * elapsed;
if (InputService::IsKeyDown(Keys::S))
velocity.y += acceleration * elapsed;
}
void TestGame::Player::Draw() {
J2D::FillRect(Colors::Blue, pos, bbox);
J2D::DrawPartialSprite(sprite, pos, {0,0}, bbox);
}

View File

@@ -1,6 +1,9 @@
#include <TestGame/TestGameApp.hpp>
#include "JUI/Widgets/FpsGraph.hpp"
#include <JUI/Widgets/ListLayout.hpp>
#include "SimpleAABBSolver.hpp"
TestGame::TestGameAppWindow::TestGameAppWindow():
@@ -15,6 +18,7 @@ TestGame::TestGameAppWindow::~TestGameAppWindow() {
}
void TestGame::TestGameAppWindow::CreateUI() {
using namespace JUI::UDimLiterals;
scene = new JUI::Scene();
@@ -29,6 +33,8 @@ void TestGame::TestGameAppWindow::CreateUI() {
auto* phys_params_slider_window = new JUI::Window(scene);
phys_params_slider_window->Size({300_px, 100_px});
phys_params_slider_window->Position({95_percent - 300_px, 95_percent-200_px});
phys_params_slider_window->Title("Physics Parameters");
auto* layout = new JUI::VerticalListLayout(phys_params_slider_window->Content());
@@ -38,23 +44,23 @@ void TestGame::TestGameAppWindow::CreateUI() {
grav_slider->Minimum(0); grav_slider->Maximum(1); grav_slider->Interval(1.f/10000.f);
grav_slider->CurrentValue(0.098f);
grav_slider->TextColor(Colors::Black);
grav_slider->Content(std::format("Gravity: {}", gravity));
grav_slider->Content("Gravity: 9.82");
grav_slider->ValueChanged += [&, grav_slider](float value) mutable {
gravity = value * 100.f;
grav_slider->Content(std::format("Gravity: {}", Math::Round(gravity, 3)));
player->gravity = value * 100.f;
grav_slider->Content(std::format("Gravity: {}", Math::Round(player->gravity, 3)));
};
auto* air_resist_slider = new LabeledSlider(layout);
air_resist_slider->Size({100_percent, 20_px});
air_resist_slider->Minimum(0); grav_slider->Maximum(1); air_resist_slider->Interval(1.f/10000.f);
air_resist_slider->CurrentValue(0.12f);
air_resist_slider->Content(std::format("Air Resistance: {}", gravity));
air_resist_slider->Content(std::format("Air Resistance: {}", 8));
air_resist_slider->TextColor(Colors::Black);
air_resist_slider->ValueChanged += [&, air_resist_slider](float value) mutable {
air_resistance = value * 100.f;
air_resist_slider->Content(std::format("Air Resistance: {}", Math::Floor(air_resistance)));
player->air_resistance = value * 100.f;
air_resist_slider->Content(std::format("Air Resistance: {}", Math::Floor(player->air_resistance)));
};
@@ -63,11 +69,11 @@ void TestGame::TestGameAppWindow::CreateUI() {
mass_slider->Minimum(0); mass_slider->Maximum(1); mass_slider->Interval(1/10000.f);
mass_slider->CurrentValue(0.08f);
mass_slider->TextColor(Colors::Black);
mass_slider->Content(std::format("Player Mass: {}", gravity));
mass_slider->Content(std::format("Player Mass: {}", 12));
mass_slider->ValueChanged += [&, mass_slider](float value) mutable {
mass = value * 100.f;
mass_slider->Content(std::format("Player Mass: {}", mass));
player->mass = value * 100.f;
mass_slider->Content(std::format("Player Mass: {}", player->mass));
};
auto* accel_slider = new LabeledSlider(layout);
@@ -75,21 +81,20 @@ void TestGame::TestGameAppWindow::CreateUI() {
accel_slider->Minimum(0); accel_slider->Maximum(1); accel_slider->Interval(1/10000.f);
accel_slider->CurrentValue(0.12f);
accel_slider->TextColor(Colors::Black);
accel_slider->Content(std::format("Player Accel: {}", acceleration));
accel_slider->Content(std::format("Player Accel: {}", 1200));
accel_slider->ValueChanged += [&, accel_slider](float value) mutable {
acceleration = value * 10000.f;
accel_slider->Content(std::format("Player Accel: {}", acceleration));
player->acceleration = value * 10000.f;
accel_slider->Content(std::format("Player Accel: {}", player->acceleration));
};
}
void TestGame::TestGameAppWindow::Load() {
Player::sprite = new JGL::Texture("assets/player.png", FilteringMode::NEAREST);
CreateUI();
player_tex = new JGL::Texture("assets/player.png", FilteringMode::NEAREST);
// TODO: More sophisticated order-of-operations is required.
@@ -182,6 +187,9 @@ void TestGame::TestGameAppWindow::CollisionSolve(float elapsed) {
if (cell < 0) continue; // Empty cell.
// Non-colliding tile.
if (!loaded_tileset->tiles[cell].collides) continue;
coll_tests++;
auto cell_aabb = AABB2D(Vector2(cell_topleft), cell_bbox);
@@ -280,3 +288,14 @@ void TestGame::TestGameAppWindow::DrawLayer(const Layer *layer) const {
}
}
}
void TestGame::TestGameAppWindow::ApplyOriginTransformation() {
glTranslatef(GetWidth() / 2.f, GetHeight() / 2.f, 0);
}
void TestGame::TestGameAppWindow::ApplyCameraTransformation() {
ApplyOriginTransformation();
glRotatef(camera.rotation.current, 0, 0, 1);
glScalef(camera.scale.current, camera.scale.current, 1);
glTranslatef(-camera.translation.current.x, -camera.translation.current.y, 0);
}

View File

@@ -12,47 +12,7 @@
#include "JUI/Widgets/ListLayout.hpp"
#include "JUI/Widgets/Slider.hpp"
float gravity = 9.8f;
float mass = 12.f;
float air_resistance = 8.f;
float friction = 0.001f;
float acceleration = 1200;
JGL::Texture* player_tex;
// Implemented in next version of JUI.
class LabeledSlider : public JUI::Slider, public JUI::TextBase {
public:
LabeledSlider() : Slider(), TextBase() {
}
explicit LabeledSlider(Widget* parent) : LabeledSlider()
{
this->Parent(parent);
}
void Draw() override {
Slider::Draw();
auto abs_pos = this->GetAbsolutePosition();
auto abs_size = this->GetAbsoluteSize();
auto pos_pad = GetAbsolutePaddingTopLeft();
auto size_pad = GetAbsolutePaddingBottomRight();
TextBase::Draw(abs_pos + pos_pad, abs_size - size_pad);
}
void Update(float elapsed) override {
Slider::Update(elapsed);
TextBase::Update(elapsed);
}
protected:
private:
};
#include <TestGame/TestGameApp.hpp>
@@ -61,7 +21,7 @@ int main()
{
ReWindow::Logger::Debug.EnableConsole(false);
TestGameAppWindow* app = new TestGameAppWindow();
TestGame::TestGameAppWindow* app = new TestGame::TestGameAppWindow();
bool success = app->Open();