Add gravity well and physics
parent
5abb201ed3
commit
78c07da39f
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "Entity.hpp"
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
|
|
@ -41,8 +43,23 @@ struct GravityWellComponent : public Component {
|
|||
float mass = 150000.0f;
|
||||
float minDist = 30.0f;
|
||||
bool active = false;
|
||||
float followLerp = 12.0f;
|
||||
void Setup() override {}
|
||||
void Update(float) override {}
|
||||
void Update(float dt) override {
|
||||
auto transform = entity->GetComponent<TransformComponent>();
|
||||
if (!transform) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use buffered input
|
||||
active = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
|
||||
|
||||
const Vector2 mouse = GetMousePosition();
|
||||
auto &t = transform->get();
|
||||
const float blend = std::clamp(followLerp * dt, 0.0f, 1.0f);
|
||||
t.x += (mouse.x - t.x) * blend;
|
||||
t.y += (mouse.y - t.y) * blend;
|
||||
}
|
||||
void Cleanup() override {}
|
||||
};
|
||||
|
||||
|
|
@ -50,7 +67,40 @@ struct GravityReceiverComponent : public Component {
|
|||
Entity *well = nullptr;
|
||||
bool inVoid = false;
|
||||
void Setup() override {}
|
||||
void Update(float) override {}
|
||||
void Update(float dt) override {
|
||||
(void)inVoid;
|
||||
|
||||
if (!well) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto myTransform = entity->GetComponent<TransformComponent>();
|
||||
auto physics = entity->GetComponent<PhysicsComponent>();
|
||||
auto wellTransform = well->GetComponent<TransformComponent>();
|
||||
auto wellGravity = well->GetComponent<GravityWellComponent>();
|
||||
if (!myTransform || !physics || !wellTransform || !wellGravity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wellGravity->get().active) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float dx = wellTransform->get().x - myTransform->get().x;
|
||||
const float dy = wellTransform->get().y - myTransform->get().y;
|
||||
const float dist = std::sqrt(dx * dx + dy * dy);
|
||||
if (dist <= 0.0001f) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float clampedDist = std::max(dist, wellGravity->get().minDist);
|
||||
const float force = wellGravity->get().mass / (clampedDist * clampedDist);
|
||||
const float nx = dx / dist;
|
||||
const float ny = dy / dist;
|
||||
|
||||
physics->get().vx += nx * force * dt;
|
||||
physics->get().vy += ny * force * dt;
|
||||
}
|
||||
void Cleanup() override {}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@ std::shared_ptr<Entity> CreateProbe() {
|
|||
transform.x = 96.0f;
|
||||
transform.y = 230.0f;
|
||||
|
||||
auto &physics = e->AddComponent<PhysicsComponent>();
|
||||
physics.vx = 165.0f;
|
||||
physics.vy = 0.0f;
|
||||
physics.speedCap = 420.0f;
|
||||
|
||||
e->AddComponent<GravityReceiverComponent>();
|
||||
|
||||
auto &physics = e->AddComponent<PhysicsComponent>();
|
||||
physics.vx = 108.0f;
|
||||
physics.vy = 0.0f;
|
||||
physics.speedCap = 8192.0f;
|
||||
|
||||
e->AddComponent<ColliderComponent>();
|
||||
e->AddComponent<TrailComponent>();
|
||||
e->AddComponent<ProjectionComponent>();
|
||||
|
|
@ -25,8 +26,15 @@ std::shared_ptr<Entity> CreateProbe() {
|
|||
|
||||
std::shared_ptr<Entity> CreateGravityWell() {
|
||||
auto e = std::make_shared<Entity>();
|
||||
e->AddComponent<TransformComponent>();
|
||||
e->AddComponent<GravityWellComponent>();
|
||||
auto &transform = e->AddComponent<TransformComponent>();
|
||||
transform.x = 96.0f;
|
||||
transform.y = 230.0f;
|
||||
|
||||
auto &well = e->AddComponent<GravityWellComponent>();
|
||||
well.mass = (float)(1 << 22);
|
||||
well.minDist = 28.0f;
|
||||
well.followLerp = 12.0f;
|
||||
|
||||
e->AddComponent<RenderComponent>();
|
||||
return e;
|
||||
}
|
||||
|
|
@ -36,7 +44,8 @@ std::shared_ptr<Entity> CreateStar(float x, float y) {
|
|||
auto &t = e->AddComponent<TransformComponent>();
|
||||
t.x = x;
|
||||
t.y = y;
|
||||
e->AddComponent<ScrollableComponent>();
|
||||
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||
scrollable.worldX = x;
|
||||
e->AddComponent<ColliderComponent>();
|
||||
e->AddComponent<CollectibleComponent>();
|
||||
e->AddComponent<RenderComponent>();
|
||||
|
|
@ -48,7 +57,8 @@ std::shared_ptr<Entity> CreateAsteroid(float x, float y) {
|
|||
auto &t = e->AddComponent<TransformComponent>();
|
||||
t.x = x;
|
||||
t.y = y;
|
||||
e->AddComponent<ScrollableComponent>();
|
||||
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||
scrollable.worldX = x;
|
||||
e->AddComponent<ColliderComponent>();
|
||||
e->AddComponent<RenderComponent>();
|
||||
return e;
|
||||
|
|
@ -58,9 +68,11 @@ std::shared_ptr<Entity> CreateNullZone(float x, float width) {
|
|||
auto e = std::make_shared<Entity>();
|
||||
auto &t = e->AddComponent<TransformComponent>();
|
||||
t.x = x;
|
||||
(void)width;
|
||||
e->AddComponent<ScrollableComponent>();
|
||||
e->AddComponent<NullZoneComponent>();
|
||||
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||
scrollable.worldX = x;
|
||||
|
||||
auto &nullZone = e->AddComponent<NullZoneComponent>();
|
||||
nullZone.width = width;
|
||||
e->AddComponent<RenderComponent>();
|
||||
return e;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "Components.hpp"
|
||||
#include "Entity.hpp"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
void UpdateAllSystems(std::vector<std::shared_ptr<Entity>> &entities, float deltaTime) {
|
||||
std::shared_ptr<Entity> worldEntity;
|
||||
std::shared_ptr<Entity> wellEntity;
|
||||
float scrollX = 0.0f;
|
||||
|
||||
if (!entities.empty()) {
|
||||
worldEntity = entities[0];
|
||||
}
|
||||
if (entities.size() > 1) {
|
||||
wellEntity = entities[1];
|
||||
}
|
||||
|
||||
if (worldEntity) {
|
||||
worldEntity->Update(deltaTime);
|
||||
auto scroll = worldEntity->GetComponent<ScrollComponent>();
|
||||
if (scroll) {
|
||||
scrollX = scroll->get().scrollX;
|
||||
}
|
||||
}
|
||||
|
||||
if (wellEntity) {
|
||||
wellEntity->Update(deltaTime);
|
||||
}
|
||||
|
||||
for (auto &entity : entities) {
|
||||
if (!entity) {
|
||||
if (entity == worldEntity || entity == wellEntity || !entity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto receiver = entity->GetComponent<GravityReceiverComponent>();
|
||||
if (receiver) {
|
||||
receiver->get().well = wellEntity.get();
|
||||
}
|
||||
|
||||
auto transform = entity->GetComponent<TransformComponent>();
|
||||
auto scrollable = entity->GetComponent<ScrollableComponent>();
|
||||
if (transform && scrollable) {
|
||||
transform->get().x = scrollable->get().worldX - scrollX;
|
||||
}
|
||||
|
||||
entity->Update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
as6/main.cpp
31
as6/main.cpp
|
|
@ -17,6 +17,9 @@ int main() {
|
|||
entities.push_back(CreateWorld());
|
||||
entities.push_back(CreateGravityWell());
|
||||
entities.push_back(CreateProbe());
|
||||
entities.push_back(CreateStar(900.0f, 120.0f));
|
||||
entities.push_back(CreateAsteroid(1100.0f, 330.0f));
|
||||
entities.push_back(CreateNullZone(1280.0f, 70.0f));
|
||||
entities.push_back(CreateHUD());
|
||||
|
||||
while (!window.ShouldClose()) {
|
||||
|
|
@ -25,7 +28,12 @@ int main() {
|
|||
UpdateAllSystems(entities, dt);
|
||||
|
||||
auto worldScroll = entities[0]->GetComponent<ScrollComponent>();
|
||||
auto wellTransform = entities[1]->GetComponent<TransformComponent>();
|
||||
auto probeTransform = entities[2]->GetComponent<TransformComponent>();
|
||||
auto starTransform = entities[3]->GetComponent<TransformComponent>();
|
||||
auto asteroidTransform = entities[4]->GetComponent<TransformComponent>();
|
||||
auto nullTransform = entities[5]->GetComponent<TransformComponent>();
|
||||
auto nullZone = entities[5]->GetComponent<NullZoneComponent>();
|
||||
|
||||
window.BeginDrawing();
|
||||
window.ClearBackground(raylib::Color(11, 15, 26, 255));
|
||||
|
|
@ -47,6 +55,29 @@ int main() {
|
|||
raylib::Color(235, 215, 125, 255));
|
||||
}
|
||||
|
||||
if (wellTransform) {
|
||||
const auto &well = wellTransform->get();
|
||||
::DrawCircleLines(static_cast<int>(well.x), static_cast<int>(well.y), 18.0f,
|
||||
raylib::Color(86, 197, 255, 255));
|
||||
}
|
||||
|
||||
if (starTransform) {
|
||||
const auto &star = starTransform->get();
|
||||
::DrawCircleV({star.x, star.y}, 6.0f, raylib::Color(255, 223, 86, 255));
|
||||
}
|
||||
|
||||
if (asteroidTransform) {
|
||||
const auto &asteroid = asteroidTransform->get();
|
||||
::DrawCircleV({asteroid.x, asteroid.y}, 13.0f, raylib::Color(116, 126, 142, 255));
|
||||
}
|
||||
|
||||
if (nullTransform && nullZone) {
|
||||
const auto &zone = nullTransform->get();
|
||||
const int width = static_cast<int>(nullZone->get().width);
|
||||
::DrawRectangle(static_cast<int>(zone.x), 0, width, GetScreenHeight(),
|
||||
raylib::Color(96, 64, 146, 80));
|
||||
}
|
||||
|
||||
window.EndDrawing();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue