Refactoring testgame code.
This commit is contained in:
@@ -35,48 +35,10 @@ class Entity
|
||||
json::value metadata;
|
||||
#pragma endregion
|
||||
Entity();
|
||||
Entity(const json::value& json)
|
||||
{
|
||||
Deserialize(json);
|
||||
}
|
||||
Entity(const json::value& json);
|
||||
|
||||
|
||||
json::value Serialize() const
|
||||
{
|
||||
json::object data;
|
||||
data["name"] = this->name;
|
||||
data["type"] = this->type;
|
||||
data["x"] = this->x;
|
||||
data["y"] = this->y;
|
||||
data["width"] = this->width;
|
||||
data["height"] = this->height;
|
||||
data["rotation"] = this->rotation;
|
||||
data["flip-h"] = this->flip_h;
|
||||
data["flip-v"] = this->flip_v;
|
||||
data["z-index"] = (float)this->z_index;
|
||||
data["color"] = JsonConversions::deparse_color_to_hex(overlay_color);
|
||||
data["metadata"] = this->metadata;
|
||||
return data;
|
||||
}
|
||||
|
||||
void Deserialize(const json::value& json)
|
||||
{
|
||||
name = json["name"].as_string();
|
||||
type = json["type"].as_string();
|
||||
x = json["x"].number.value();
|
||||
y = json["y"].number.value();
|
||||
width = json["width"].number.value_or(0);
|
||||
height = json["height"].number.value_or(0);
|
||||
rotation = json["rotation"].number.value_or(0);
|
||||
//flip_h = json["flip-h"].boolean.value();
|
||||
//flip_v = json["flip-v"].boolean.value();
|
||||
z_index = json["z-index"].number.value();
|
||||
// TODO: sscanf is bad!!!
|
||||
//overlay_color = JsonConversions::parse_color(json["color"]);
|
||||
metadata = json["metadata"];
|
||||
|
||||
|
||||
}
|
||||
|
||||
json::value Serialize() const;
|
||||
|
||||
void Deserialize(const json::value& json);
|
||||
};
|
7
include/TestGame/Crate.hpp
Normal file
7
include/TestGame/Crate.hpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace TestGame {
|
||||
class Crate : public GameEntity {
|
||||
|
||||
};
|
||||
}
|
26
include/TestGame/GameEntity.hpp
Normal file
26
include/TestGame/GameEntity.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "Data/Entity.hpp"
|
||||
|
||||
|
||||
namespace TestGame {
|
||||
class GameEntity : public Entity
|
||||
{
|
||||
public:
|
||||
|
||||
GameEntity(const Vector2& spawn_pos) {
|
||||
pos = spawn_pos;
|
||||
next_pos = spawn_pos;
|
||||
}
|
||||
|
||||
virtual void Update(float elapsed) = 0;
|
||||
|
||||
virtual void Draw() = 0;
|
||||
|
||||
Vector2 pos;
|
||||
Vector2 next_pos;
|
||||
Vector2 bbox;
|
||||
Vector2 velocity;
|
||||
bool noclip = false;
|
||||
bool on_ground = true;
|
||||
};
|
||||
}
|
3
include/TestGame/PhysicsTweaker.hpp
Normal file
3
include/TestGame/PhysicsTweaker.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
|
54
include/TestGame/Player.hpp
Normal file
54
include/TestGame/Player.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "GameEntity.hpp"
|
||||
|
||||
|
||||
namespace TestGame {
|
||||
class Player : public GameEntity
|
||||
{
|
||||
public:
|
||||
Player(const Vector2& spawn_pos) : GameEntity(spawn_pos) {
|
||||
bbox = {16, 24};
|
||||
}
|
||||
|
||||
~Player() {
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
162
include/TestGame/TestGameApp.hpp
Normal file
162
include/TestGame/TestGameApp.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "GameEntity.hpp"
|
||||
#include "Player.hpp"
|
||||
#include "App/EditorCamera.hpp"
|
||||
#include "Data/Level.hpp"
|
||||
#include "JUI/Widgets/Scene.hpp"
|
||||
#include "ReWindow/types/Window.h"
|
||||
|
||||
namespace TestGame
|
||||
{
|
||||
constexpr int GL_MAJOR = 2;
|
||||
constexpr int GL_MINOR = 1;
|
||||
|
||||
constexpr int START_APP_WIDTH = 1024;
|
||||
constexpr int START_APP_HEIGHT = 768;
|
||||
static const std::string START_APP_TITLE = "Redacted Software 2D Level Editor - Map Testing Game";
|
||||
|
||||
class TestGameAppWindow : public ReWindow::OpenGLWindow
|
||||
{
|
||||
public:
|
||||
EditorCamera camera;
|
||||
Level* loaded_level = nullptr;
|
||||
Tileset* loaded_tileset = nullptr;
|
||||
JGL::Texture* loaded_tilesheet = nullptr;
|
||||
|
||||
JUI::Scene* scene = nullptr;
|
||||
|
||||
|
||||
Player* player = nullptr;
|
||||
|
||||
bool data_ready = false;
|
||||
|
||||
std::vector<GameEntity*> entities;
|
||||
|
||||
TestGameAppWindow();
|
||||
|
||||
~TestGameAppWindow() override;
|
||||
|
||||
|
||||
/// Initializes and styles all the JUI widgets used by the application.
|
||||
/// This function is called from Load().
|
||||
void CreateUI();
|
||||
|
||||
/// Load all resources.
|
||||
/// This is called after the application window is initially opened, and the OpenGL context is created.
|
||||
/// But is always called before the first pass of the gameloop (Update, Draw, Step, etc).
|
||||
void Load();
|
||||
|
||||
bool Open() override;
|
||||
|
||||
/// Performs collision testing and response between entities and tiles.
|
||||
void CollisionSolve(float elapsed);
|
||||
|
||||
void CameraUpdate(float elapsed);
|
||||
|
||||
void Update(float elapsed);
|
||||
|
||||
|
||||
void DrawLayer(const Layer* layer) const;
|
||||
|
||||
|
||||
void ApplyOriginTransformation() {
|
||||
glTranslatef(GetWidth() / 2.f, GetHeight() / 2.f, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void DrawLevel(const Level* level) const
|
||||
{
|
||||
for (const auto* layer : level->layers)
|
||||
{
|
||||
DrawLayer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawWorldSpace() {
|
||||
|
||||
if (!data_ready) return; // Don't try to draw the level if not loaded.
|
||||
|
||||
DrawLevel(loaded_level);
|
||||
|
||||
for (auto* entity : entities) {
|
||||
entity->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void Render() {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
J2D::Begin();
|
||||
{
|
||||
glPushMatrix();
|
||||
{
|
||||
ApplyCameraTransformation();
|
||||
DrawWorldSpace();
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
J2D::End();
|
||||
|
||||
scene->Draw();
|
||||
|
||||
}
|
||||
|
||||
#pragma region ReWindow Overrides
|
||||
void OnRefresh(float elapsed) override
|
||||
{
|
||||
Update(elapsed);
|
||||
Render();
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
enum JUI::MouseButton ToJUIEnum(const MouseButton& btn) {
|
||||
if (btn == MouseButtons::Left) return JUI::MouseButton::Left;
|
||||
if (btn == MouseButtons::Middle) return JUI::MouseButton::Middle;
|
||||
if (btn == MouseButtons::Right) return JUI::MouseButton::Right;
|
||||
|
||||
// Default condition.
|
||||
return JUI::MouseButton::Left;
|
||||
}
|
||||
|
||||
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &e) override {
|
||||
auto btn = ToJUIEnum(e.Button);
|
||||
|
||||
if (scene->ObserveMouseInput(btn, true)) return;
|
||||
}
|
||||
|
||||
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &e) override {
|
||||
auto btn = ToJUIEnum(e.Button);
|
||||
if (scene->ObserveMouseInput(btn, false)) return;
|
||||
}
|
||||
|
||||
void OnMouseMove(const ReWindow::MouseMoveEvent &e) override {
|
||||
Vector2 mposv2(e.Position.x, e.Position.y);
|
||||
if (scene->ObserveMouseMovement(mposv2)) return;
|
||||
}
|
||||
|
||||
void OnKeyDown(const ReWindow::KeyDownEvent &e) override {
|
||||
if (scene->ObserveKeyInput(e.key, true)) return;
|
||||
}
|
||||
|
||||
void OnKeyUp(const ReWindow::KeyUpEvent &e) override {
|
||||
if (scene->ObserveKeyInput(e.key, false)) return;
|
||||
}
|
||||
|
||||
void OnFocusGain(const ReWindow::RWindowEvent &e) override {
|
||||
focused = true;
|
||||
}
|
||||
|
||||
void OnFocusLost(const ReWindow::RWindowEvent &e) override {
|
||||
focused = false;
|
||||
}
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
}
|
Reference in New Issue
Block a user