Initial Commit

This commit is contained in:
2025-01-02 00:15:37 -05:00
commit b9afc57e6e
29 changed files with 1826 additions and 0 deletions

27
src/Engine/Animation.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include "Engine/Animation.h"
#include "jlog/Logger.hpp"
float Animation::GetMsBetweenFrames() const {
return ms_between_frames;
}
void Animation::SetMsBetweenFrames(float new_ms_between_frames) {
ms_between_frames = new_ms_between_frames;
}
std::string Animation::GetName() const {
return name;
}
const JGL::Texture* Animation::GetTexture(float animation_time) const {
if (textures.empty())
jlog::Fatal("Getting an animation frame but the animation is empty?");
animation_time = std::max(0.0f, std::min(animation_time, 1.0f));
float animation_ms = ms_between_frames * textures.size();
float animation_length_ms = animation_time * animation_ms;
auto frame_index = (size_t) std::floor(animation_length_ms / ms_between_frames);
frame_index = std::min(frame_index, textures.size() - 1);
return &textures[frame_index];
}

View File

View File

@@ -0,0 +1,88 @@
#include "J3ML/J3ML.hpp"
#include "Engine/Entity/Entity.h"
#include "Engine/Globals.h"
using namespace J3ML;
void Entity::MoveX(float speed) {
position.x = position.x + (speed * Globals::Window->GetDeltaTime());
}
void Entity::MoveY(float speed) {
position.y = position.y + (speed * Globals::DeltaTime());
}
void Entity::MoveForward(float speed) {
position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(face_angle);
position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(face_angle);
}
void Entity::MoveBackward(float speed) {
speed = -speed;
position.x = position.x + (speed * Globals::DeltaTime()) * Math::Cos(face_angle);
position.y = position.y + (speed * Globals::DeltaTime()) * Math::Sin(face_angle);
}
void Entity::MoveLeft(float speed) {
position.x = position.x + (speed * Globals::DeltaTime()) * -Math::Sin(face_angle);
position.y = position.y + (speed * Globals::DeltaTime()) * Math::Cos(face_angle);
}
void Entity::MoveRight(float speed) {
position.x = position.x + (speed * Globals::DeltaTime()) * Math::Sin(face_angle);
position.y = position.y + (speed * Globals::DeltaTime()) * -Math::Cos(face_angle);
}
void Entity::SetRotation(float new_face_angle) {
face_angle = new_face_angle;
if (face_angle < 0)
face_angle = fmod(face_angle + Math::Pi * 2, Math::Pi * 2);
else if (face_angle >= 2 * M_PI)
face_angle = fmod(face_angle, Math::Pi * 2);
}
void Entity::Rotate(float speed) {
SetRotation(face_angle + speed * Globals::DeltaTime());
}
float Entity::GetRotation() const {
return face_angle;
}
Vector2 Entity::GetPosition() const {
return position;
}
bool Entity::AppendChild(Entity* entity) {
bool success = false;
if (!Globals::CurrentScene->EntityListContains(entity))
children.push_back(entity), success = true;
return success;
}
Entity::~Entity() {
for (auto* e : children)
delete e;
children = {};
}
void Entity::UpdateChildren() {
for (auto& e : children) {
e->Update();
if (!e->children.empty())
e->UpdateChildren();
}
}
void Entity::DestroyChild(Entity* entity) {
auto it = std::find(children.begin(), children.end(), entity);
if (it != children.end())
delete *it, children.erase(it);
}
void Entity::RemoveChild(Entity* entity) {
auto it = std::find(children.begin(), children.end(), entity);
if (it != children.end())
children.erase(it);
}

View File

@@ -0,0 +1 @@

32
src/Engine/GameWindow.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include "Engine/GameWindow.h"
#include "Engine/Globals.h"
#include "Engine/Entity/Camera.h"
#include "JGL/JGL.h"
void DemoGameWindow::InitGL() {
if (!JGL::Init(GetSize(), 0, 0))
exit(-1);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
void DemoGameWindow::Display() {
JGL::Update(GetSize());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// These are checked separately so that if Update() changes the scene we don't crash.
if (Globals::CurrentScene)
Globals::CurrentScene->Update();
if (Globals::CurrentScene)
Globals::CurrentScene->Render();
DemoGameWindow::GLSwapBuffers();
}
void DemoGameWindow::OnRefresh(float elapsed) {
Display();
}

View File

@@ -0,0 +1,52 @@
#include "Engine/Level/Fixed.h"
bool Fixed::Collidable() const {
return collidable;
}
Vector2i Fixed::GetPosition() const {
return position;
}
AABB2D Fixed::GetBounds() const {
auto maximum = Vector2(position.x + texture->GetDimensions().x, position.y + texture->GetDimensions().y);
return { Vector2(position), maximum };
}
bool Fixed::Enabled() const {
return enabled;
}
void Fixed::Enable() {
enabled = true;
}
void Fixed::Disable() {
enabled = false;
}
Fixed::~Fixed() {
delete texture;
}
void Fixed::GenerateCollision() {
if (!Collidable() || !Enabled() || !texture)
return;
std::vector<Vector2i> result{};
auto pixel_data = texture->GetPixelData();
for (int y = 0; y < texture->GetDimensions().y; y++)
for (int x = 0; x < texture->GetDimensions().x; x++)
if (pixel_data[y * texture->GetDimensions().x + x].A() != 0)
result.emplace_back((int) x + position.x, (int) y + position.y);
collision = result;
}
std::vector<Vector2i> Fixed::GetCollision() {
return collision;
}
const Texture* Fixed::GetTexture() {
return texture;
}

View File

@@ -0,0 +1,86 @@
#include "Engine/Level/Scene.h"
bool Scene::EntityListContains(const Entity* entity) const {
for (auto* e : EntityList)
if (e == entity)
return true;
return false;
}
bool Scene::FixedListContains(const Fixed* fixed) const {
for (auto* f : FixedList)
if (f == fixed)
return true;
return false;
}
size_t Scene::FixedCount() const {
return FixedList.size();
}
size_t Scene::EntityCount() const {
return EntityList.size();
}
void Scene::Update() {
for (auto& e : EntityList)
e->Update();
}
void Scene::Render() {
for (auto& f : FixedList)
if (f->Enabled())
f->Render();
// TODO Render order. In this system it's not possible for child entities to be rendered before the parent.
for (auto& e : EntityList)
if (auto* r = dynamic_cast<Renderable*>(e))
r->Render();
if (HeadsUpDisplay)
HeadsUpDisplay->Render();
}
Scene::~Scene() {
for (auto* f : FixedList)
delete f;
for (auto* e : EntityList)
delete e;
}
void Scene::AppendEntity(Entity* entity) {
if (!EntityListContains(entity))
EntityList.push_back(entity);
}
void Scene::AppendFixed(Fixed* fixed) {
if (!FixedListContains(fixed))
FixedList.push_back(fixed);
}
void Scene::DestroyEntity(Entity *entity) {
auto it = std::find(EntityList.begin(), EntityList.end(), entity);
if (it != EntityList.end())
delete *it, EntityList.erase(it);
}
void Scene::DestroyFixed(Fixed* fixed) {
auto it = std::find(FixedList.begin(), FixedList.end(), fixed);
if (it != FixedList.end())
delete *it, FixedList.erase(it);
}
void Scene::RemoveEntity(Entity* entity) {
auto it = std::find(EntityList.begin(), EntityList.end(), entity);
if (it != EntityList.end())
EntityList.erase(it);
}
void Scene::RemoveFixed(Fixed* fixed) {
auto it = std::find(FixedList.begin(), FixedList.end(), fixed);
if (it != FixedList.end())
FixedList.erase(it);
}

View File

@@ -0,0 +1,11 @@
#include <Game/Scene/DemoGameScene.h>
#include <Game/Entity/DemoGameHud.h>
#include <Game/Entity/Box.h>
void DemoGameScene::Init() {
auto* hud = new DemoGameHud();
auto* b = new Box({0, 0});
HeadsUpDisplay = hud;
AppendEntity(b);
}

18
src/Game/Entities/Box.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include <Game/Entity/Box.h>
void Box::Render() {
J2D::Begin(nullptr, true);
J2D::FillRect(Colors::Red, Vector2(position), {20, 20});
J2D::End();
}
void Box::Update() {
if (Globals::Window->IsKeyDown(Keys::W))
MoveY(-500);
if (Globals::Window->IsKeyDown(Keys::S))
MoveY(500);
if (Globals::Window->IsKeyDown(Keys::A))
MoveX(-500);
if (Globals::Window->IsKeyDown(Keys::D))
MoveX(500);
}

View File

@@ -0,0 +1,9 @@
#include <Game/Entity/DemoGameHud.h>
#include <Engine/Globals.h>
void DemoGameHud::Render() {
float framerate = Globals::Window->GetRefreshRate();
J2D::Begin(nullptr, true);
J2D::DrawString(Colors::Whites::Ivory, "Framerate: " + std::to_string((int) framerate), 0, 0, 1, 16);
J2D::End();
}

38
src/Game/Splash.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "Game/Scene/Splash.h"
#include "Engine/Globals.h"
#include "Game/Scene/DemoGameScene.h"
void DemoGameSplash::Init() {
RedactedSoftware = new JGL::Texture("assets/sprites/Re3D.png");
}
void DemoGameSplash::Update() {
angle += (elapsed * 4) * Globals::DeltaTime();
elapsed += Globals::DeltaTime();
// Pretend we're actually loading something idk.
if (elapsed >= 2.75) {
auto* dgs = new DemoGameScene();
Globals::ChangeScene(dgs);
}
}
void DemoGameSplash::Render() {
auto text_length = JGL::Fonts::Jupiteroid.MeasureString("Loading ....", 24);
std::string text = "Loading";
int dots = static_cast<int>(floor(elapsed / 0.35)) % 4;
for (int i = 0; i < dots; ++i)
text += ".";
J2D::Begin(nullptr, true);
J2D::DrawSprite(RedactedSoftware, {Globals::Window->GetSize().x - RedactedSoftware->GetDimensions().x, Globals::Window->GetSize().y - RedactedSoftware->GetDimensions().y}, angle, {0.5, 0.5});
J2D::DrawString(Colors::Whites::Ivory, text, (Globals::Window->GetSize().x - text_length.x) - RedactedSoftware->GetDimensions().x , Globals::Window->GetSize().y - text_length.y * 1.125, 1, 24);
J2D::End();
}
DemoGameSplash::~DemoGameSplash() {
delete RedactedSoftware;
}