Pong/Levels/Game.cpp

318 lines
8.7 KiB
C++
Raw Permalink Normal View History

2023-11-11 18:56:55 -08:00
#include "Game.h"
2024-06-29 22:28:46 -07:00
#include <lwe/GameLoop.h>
#include <lwe/RenderWindow.h>
#include <lwe/systems/AudioSystem.h>
#include <lwe/systems/RigidBodySystem.h>
#include <lwe/systems/Portrait2DSystem.h>
#include <lwe/systems/GuiSystem.h>
#include <lwe/coms/AudioSource.h>
#include <lwe/coms/AABB2D.h>
#include <lwe/coms/Circle.h>
#include <lwe/coms/Portrait2D.h>
#include <lwe/gpu/GpuFontAtlas.h>
#include <lwe/gui/LabelGui.h>
#include <ehs/io/audio/Audio.h>
#include <ehs/io/hid/Input.h>
#include <ehs/io/hid/Keyboard.h>
#include <ehs/HRNG.h>
#include <ehs/system/CPU.h>
2023-11-14 00:07:42 -08:00
const float Game::paddleSpeed = 400.0f;
2023-11-16 00:04:12 -08:00
const float Game::ballSpeed = 5000.0f;
2023-11-11 18:56:55 -08:00
Game::~Game()
{
}
Game::Game()
2023-11-16 00:04:12 -08:00
: Level("Game"), plyScore(0), aiScore(0), started(false)
2023-11-11 18:56:55 -08:00
{
}
Game::Game(const Game& lvl)
2023-11-16 00:04:12 -08:00
: Level(lvl), plyScore(lvl.plyScore), aiScore(lvl.aiScore), started(lvl.started)
2023-11-11 18:56:55 -08:00
{
}
Game& Game::operator=(const Game& lvl)
{
if (this == &lvl)
return *this;
Level::operator=(lvl);
2023-11-14 00:07:42 -08:00
plyScore = lvl.plyScore;
aiScore = lvl.aiScore;
2023-11-16 00:04:12 -08:00
started = lvl.started;
2023-11-14 00:07:42 -08:00
2023-11-11 18:56:55 -08:00
return *this;
}
2024-06-29 22:28:46 -07:00
void Game::SetupResources(lwe::GpuInterface *inf)
2023-11-11 18:56:55 -08:00
{
2024-06-29 22:28:46 -07:00
Level::SetupResources(inf);
2023-11-11 18:56:55 -08:00
// Setup Resource Code Here
2024-06-29 22:28:46 -07:00
AddResource(new lwe::GpuMesh(inf, ehs::portraitGui));
2023-11-11 18:56:55 -08:00
2024-06-29 22:28:46 -07:00
AddResource(new ehs::Audio("resources/audio/Wall.wav", ehs::DataType::FLOAT));
AddResource(new ehs::Audio("resources/audio/Paddle.wav", ehs::DataType::FLOAT));
AddResource(new ehs::Audio("resources/audio/Score.wav", ehs::DataType::FLOAT));
2023-11-14 21:33:11 -08:00
2024-06-29 22:28:46 -07:00
constexpr ehs::UInt_8 circleData[] = {255, 255, 255, 255};
lwe::GpuImg* circle = new lwe::GpuImg("Circle", inf, 1, 4, {1, 1}, (ehs::Byte*)circleData, lwe::GpuImgAspect::IMG_ASPECT_COLOR);
2023-11-11 18:56:55 -08:00
AddResource(circle);
}
2024-06-29 22:28:46 -07:00
void Game::Setup(lwe::GpuInterface *inf)
2023-11-11 18:56:55 -08:00
{
2024-06-29 22:28:46 -07:00
Level::Setup(inf);
2023-11-11 18:56:55 -08:00
// Setup Code Here
2024-06-29 22:28:46 -07:00
lwe::GameLoop* gl = GetParent();
2023-11-11 18:56:55 -08:00
lwe::RenderWindow* win = gl->GetWindow();
// Adding Systems Here
2024-07-01 19:39:05 -07:00
AddSystem(new lwe::AudioSystem());
2023-11-11 18:56:55 -08:00
AddSystem(new lwe::Portrait2DSystem());
AddSystem(new lwe::RigidBodySystem());
lwe::GuiSystem* gui = new lwe::GuiSystem();
2024-06-29 22:28:46 -07:00
gui->AddResource(new lwe::GpuFontAtlas("resources/fonts/Arial_48.ehf", win->GetInterface()));
2023-11-11 18:56:55 -08:00
AddSystem(gui);
2024-06-29 22:28:46 -07:00
ehs::Vec2_f scale = win->GetSwapChain()->GetScale();
ehs::Vec2_f center = win->GetSwapChain()->GetScale() / 2;
2023-11-11 18:56:55 -08:00
// Score Gui
2024-06-29 22:28:46 -07:00
lwe::LabelGui* plyScore = new lwe::LabelGui("PlyScore", "Arial_48", "0");
plyScore->SetPosition({20.0f, 20.0f, 0.0f});
2023-11-11 18:56:55 -08:00
gui->AddGui(plyScore);
2024-06-29 22:28:46 -07:00
lwe::LabelGui* aiScore = new lwe::LabelGui("AiScore", "Arial_48", "0");
aiScore->SetPosition({scale.x - 68.0f, 20.0f, 0.0f});
2023-11-11 18:56:55 -08:00
gui->AddGui(aiScore);
// Bounds Entity
2024-06-29 22:28:46 -07:00
lwe::Entity bounds("Bounds");
bounds.SetScale({win->GetSwapChain()->GetScale(), 1.0f});
2023-11-11 18:56:55 -08:00
2023-11-16 00:04:12 -08:00
lwe::AABB2D* collider = new lwe::AABB2D("BoundsCollider", 0.0f, 0.0f);
2023-11-14 00:07:42 -08:00
collider->SetInverted(true);
2023-11-16 00:04:12 -08:00
collider->SetStatic(true);
2024-06-29 22:28:46 -07:00
bounds.AddComponent(collider);
2023-11-11 18:56:55 -08:00
AddEntity(bounds);
// Field Separator Entity
2024-06-29 22:28:46 -07:00
lwe::Entity fieldSep("FieldSeparator");
fieldSep.SetScale({10.0f, scale.y, 1.0f});
fieldSep.SetPos({center.x - 5.0f, 0.0f, 0.0f});
2023-11-11 18:56:55 -08:00
lwe::Portrait2D* fieldSepImg = new lwe::Portrait2D("PaddleImg", "Circle");
fieldSepImg->SetColor({0.75f});
2024-06-29 22:28:46 -07:00
fieldSep.AddComponent(fieldSepImg);
2023-11-11 18:56:55 -08:00
AddEntity(fieldSep);
// Paddle Entity Template
2024-06-29 22:28:46 -07:00
lwe::Entity paddle("Paddle");
paddle.SetScale({20.0f, 200.0f, 1.0f});
2023-11-11 18:56:55 -08:00
2023-11-16 00:04:12 -08:00
lwe::AABB2D* paddleCollider = new lwe::AABB2D("PaddleCollider", 0.0f, 0.0f);
paddleCollider->SetStatic(true);
2024-06-29 22:28:46 -07:00
paddle.AddComponent(paddleCollider);
2023-11-14 00:07:42 -08:00
2023-11-11 18:56:55 -08:00
lwe::Portrait2D* paddleImg = new lwe::Portrait2D("PaddleImg", "Circle");
paddleImg->SetColor({0.75f});
2024-06-29 22:28:46 -07:00
paddle.AddComponent(paddleImg);
2023-11-11 18:56:55 -08:00
AddTemplate(paddle);
// Player's Paddle
lwe::Entity* plyPaddle = CreateEntity("Paddle", "PlyPaddle");
plyPaddle->SetPos({50.0f, center.y - 100.0f, 0.0f});
// Player's Paddle
lwe::Entity* aiPaddle = CreateEntity("Paddle", "AiPaddle");
aiPaddle->SetPos({scale.x - 50.0f, center.y - 100.0f, 0.0f});
// Ball Entity
2024-06-29 22:28:46 -07:00
lwe::Entity ball("Ball");
ball.SetScale({20.0f, 20.0f, 1.0f});
ball.SetPos({center.x - 10.0f, center.y - 10.0f, 0.0f});
2023-11-11 18:56:55 -08:00
2023-11-16 00:04:12 -08:00
lwe::AABB2D* ballCollider = new lwe::AABB2D("BallCollider", 0.5f, 1.1f);
2023-11-14 21:33:11 -08:00
ballCollider->SetCollidedCb([](lwe::RigidBody* a, lwe::RigidBody* b)
{
2024-06-29 22:28:46 -07:00
lwe::Entity* aOwner = (lwe::Entity*)a->GetEntity();
lwe::Entity* bOwner = (lwe::Entity*)b->GetEntity();
2023-11-14 21:33:11 -08:00
2024-06-29 22:28:46 -07:00
static ehs::UInt_64 id = 0;
2023-11-14 21:33:11 -08:00
if (bOwner->GetId() == "Bounds")
{
2024-06-29 22:28:46 -07:00
lwe::AudioSource* audio = new lwe::AudioSource("Audio_" + ehs::Str_8::FromNum(id++),"Wall");
2023-11-14 21:33:11 -08:00
audio->EnableAutoDelete(true);
audio->EnableLoop(false);
audio->Play();
aOwner->AddComponent(audio);
}
else
{
2024-06-29 22:28:46 -07:00
lwe::AudioSource* audio = new lwe::AudioSource("Audio_" + ehs::Str_8::FromNum(id++),"Paddle");
2023-11-14 21:33:11 -08:00
audio->EnableAutoDelete(true);
audio->EnableLoop(false);
audio->Play();
aOwner->AddComponent(audio);
}
});
2024-06-29 22:28:46 -07:00
ball.AddComponent(ballCollider);
2023-11-11 18:56:55 -08:00
lwe::Portrait2D* ballImg = new lwe::Portrait2D("BallImg", "Circle");
ballImg->SetColor({1.0f, 0.0f, 0.0f});
2024-06-29 22:28:46 -07:00
ball.AddComponent(ballImg);
2023-11-11 18:56:55 -08:00
AddEntity(ball);
}
void Game::PostInitialize(lwe::GpuCmdBuffer* cmdBuffer)
{
Level::PostInitialize(cmdBuffer);
// Post Initialization Code Here
}
2024-06-29 22:28:46 -07:00
void Game::OnUpdate(lwe::RenderWindow* win, ehs::Input* input, const float delta)
2023-11-11 18:56:55 -08:00
{
2023-11-30 15:44:01 -08:00
Level::OnUpdate(win, input, delta);
2023-11-11 18:56:55 -08:00
// Update Code Here
2024-06-29 22:28:46 -07:00
const ehs::InputHandler* ih = win->GetInputHandler();
2023-11-11 18:56:55 -08:00
2024-06-29 22:28:46 -07:00
const ehs::Keyboard* keyboard = (ehs::Keyboard*)ih->GetDeviceByType(EHS_HID_KEYBOARD);
2023-11-30 15:44:01 -08:00
if (!keyboard)
return;
2023-11-11 18:56:55 -08:00
2023-11-14 00:07:42 -08:00
lwe::Entity* bounds = GetEntity("Bounds");
lwe::Entity* ball = GetEntity("Ball");
2024-06-29 22:28:46 -07:00
ehs::Vec3_f ballPos = ball->GetPos();
ehs::Vec3_f ballScale = ball->GetScale();
2023-11-14 00:07:42 -08:00
2023-11-16 00:04:12 -08:00
if (ballPos.x <= bounds->GetPos().x + 10.0f)
2023-11-14 00:07:42 -08:00
{
aiScore++;
lwe::GuiSystem* gui = (lwe::GuiSystem*)GetSystem("GuiSystem");
lwe::LabelGui* aiScoreLabel = (lwe::LabelGui*)gui->GetGui("AiScore");
2024-06-29 22:28:46 -07:00
aiScoreLabel->SetText(ehs::Str_8::FromNum(aiScore));
2023-11-14 00:07:42 -08:00
ResetGame(bounds, ball);
}
2023-11-16 00:04:12 -08:00
else if (ballPos.x + ballScale.x >= bounds->GetScale().x - 10.0f)
2023-11-14 00:07:42 -08:00
{
plyScore++;
lwe::GuiSystem* gui = (lwe::GuiSystem*)GetSystem("GuiSystem");
lwe::LabelGui* plyScoreLabel = (lwe::LabelGui*)gui->GetGui("PlyScore");
2024-06-29 22:28:46 -07:00
plyScoreLabel->SetText(ehs::Str_8::FromNum(plyScore));
2023-11-14 00:07:42 -08:00
ResetGame(bounds, ball);
}
2023-11-11 18:56:55 -08:00
lwe::Entity* plyPaddle = GetEntity("PlyPaddle");
2024-06-29 22:28:46 -07:00
if (!started && keyboard->IsTouched(ehs::Keyboard::Space))
2023-11-14 00:07:42 -08:00
{
2024-06-29 22:28:46 -07:00
if (!ehs::CPU::HasRDRND())
2023-11-14 00:07:42 -08:00
return;
2023-11-16 00:04:12 -08:00
lwe::AABB2D* ballCollider = (lwe::AABB2D*)ball->GetComponent("AABB2D");
2023-11-14 00:07:42 -08:00
2024-06-29 22:28:46 -07:00
if (const ehs::UInt_8 result = ehs::HRNG::Generate_s8(0, 4); result == 0)
2023-11-16 00:04:12 -08:00
ballCollider->ApplyForce({ballSpeed, ballSpeed, 0.0f});
2023-11-14 00:07:42 -08:00
else if (result == 1)
2023-11-16 00:04:12 -08:00
ballCollider->ApplyForce({-ballSpeed, ballSpeed, 0.0f});
2023-11-14 00:07:42 -08:00
else if (result == 2)
2023-11-16 00:04:12 -08:00
ballCollider->ApplyForce({ballSpeed, -ballSpeed, 0.0f});
2023-11-14 00:07:42 -08:00
else if (result == 3)
2023-11-16 00:04:12 -08:00
ballCollider->ApplyForce({-ballSpeed, -ballSpeed, 0.0f});
2023-11-14 00:07:42 -08:00
started = true;
}
2024-06-29 22:28:46 -07:00
if (keyboard->IsDown(ehs::Keyboard::W))
2023-11-14 00:07:42 -08:00
{
2024-06-29 22:28:46 -07:00
ehs::Vec3_f newPos = plyPaddle->GetPos() - ehs::Vec3_f(0.0f, paddleSpeed, 0.0f) * delta;
2023-11-14 00:07:42 -08:00
if (newPos.y <= bounds->GetPos().y)
newPos.y = bounds->GetPos().y;
plyPaddle->SetPos(newPos);
}
2023-11-11 18:56:55 -08:00
2024-06-29 22:28:46 -07:00
if (keyboard->IsDown(ehs::Keyboard::S))
2023-11-14 00:07:42 -08:00
{
2024-06-29 22:28:46 -07:00
ehs::Vec3_f newPos = plyPaddle->GetPos() + ehs::Vec3_f(0.0f, paddleSpeed, 0.0f) * delta;
2023-11-14 00:07:42 -08:00
if (newPos.y + plyPaddle->GetScale().y >= bounds->GetScale().y)
newPos.y = bounds->GetScale().y - plyPaddle->GetScale().y;
plyPaddle->SetPos(newPos);
}
lwe::Entity* aiPaddle = GetEntity("AiPaddle");
2024-06-29 22:28:46 -07:00
ehs::Vec3_f aiPaddlePos = aiPaddle->GetPos();
ehs::Vec3_f aiPaddleScale = aiPaddle->GetScale();
2023-11-14 00:07:42 -08:00
if (aiPaddlePos.y + aiPaddleScale.y / 2.0f < ballPos.y + ballScale.y / 2.0f)
{
2024-06-29 22:28:46 -07:00
aiPaddlePos = aiPaddlePos + ehs::Vec3_f(0.0f, paddleSpeed * 2.0f, 0.0f) * delta;
2023-11-14 00:07:42 -08:00
if (aiPaddlePos.y + aiPaddleScale.y / 2.0f > ballPos.y + ballScale.y / 2.0f)
aiPaddlePos.y = ballPos.y + ballScale.y / 2.0f - aiPaddleScale.y / 2.0f;
if (aiPaddlePos.y + aiPaddleScale.y >= bounds->GetScale().y)
aiPaddlePos.y = bounds->GetScale().y - aiPaddleScale.y;
aiPaddle->SetPos(aiPaddlePos);
}
else
{
2024-06-29 22:28:46 -07:00
aiPaddlePos = aiPaddlePos - ehs::Vec3_f(0.0f, paddleSpeed * 2.0f, 0.0f) * delta;
2023-11-14 00:07:42 -08:00
if (aiPaddlePos.y + aiPaddleScale.y / 2.0f < ballPos.y + ballScale.y / 2.0f)
aiPaddlePos.y = ballPos.y + ballScale.y / 2.0f - aiPaddleScale.y / 2.0f;
if (aiPaddlePos.y <= bounds->GetPos().y)
aiPaddlePos.y = bounds->GetPos().y;
aiPaddle->SetPos(aiPaddlePos);
}
2023-11-11 18:56:55 -08:00
}
void Game::PreRender(lwe::GpuCmdBuffer* cmdBuffer)
{
Level::PreRender(cmdBuffer);
// Pre-Render Code Here
2023-11-14 00:07:42 -08:00
}
void Game::ResetGame(const lwe::Entity* bounds, lwe::Entity* ball)
{
2023-11-14 21:33:11 -08:00
lwe::AudioSource* audio = new lwe::AudioSource("Score", "Score");
audio->EnableAutoDelete(true);
audio->EnableLoop(false);
audio->Play();
ball->AddComponent(audio);
2023-11-14 00:07:42 -08:00
ball->SetPos(bounds->GetScale() / 2.0f - ball->GetScale() / 2.0f);
2023-11-16 00:04:12 -08:00
lwe::AABB2D* ballCollider = (lwe::AABB2D*)ball->GetComponent("AABB2D");
ballCollider->ResetVelocity();
2023-11-14 00:07:42 -08:00
started = false;
}