Add gravity well and physics
parent
5abb201ed3
commit
78c07da39f
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
@ -41,8 +43,23 @@ struct GravityWellComponent : public Component {
|
||||||
float mass = 150000.0f;
|
float mass = 150000.0f;
|
||||||
float minDist = 30.0f;
|
float minDist = 30.0f;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
float followLerp = 12.0f;
|
||||||
void Setup() override {}
|
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 {}
|
void Cleanup() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -50,7 +67,40 @@ struct GravityReceiverComponent : public Component {
|
||||||
Entity *well = nullptr;
|
Entity *well = nullptr;
|
||||||
bool inVoid = false;
|
bool inVoid = false;
|
||||||
void Setup() override {}
|
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 {}
|
void Cleanup() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,13 @@ std::shared_ptr<Entity> CreateProbe() {
|
||||||
transform.x = 96.0f;
|
transform.x = 96.0f;
|
||||||
transform.y = 230.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>();
|
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<ColliderComponent>();
|
||||||
e->AddComponent<TrailComponent>();
|
e->AddComponent<TrailComponent>();
|
||||||
e->AddComponent<ProjectionComponent>();
|
e->AddComponent<ProjectionComponent>();
|
||||||
|
|
@ -25,8 +26,15 @@ std::shared_ptr<Entity> CreateProbe() {
|
||||||
|
|
||||||
std::shared_ptr<Entity> CreateGravityWell() {
|
std::shared_ptr<Entity> CreateGravityWell() {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
e->AddComponent<TransformComponent>();
|
auto &transform = e->AddComponent<TransformComponent>();
|
||||||
e->AddComponent<GravityWellComponent>();
|
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>();
|
e->AddComponent<RenderComponent>();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +44,8 @@ std::shared_ptr<Entity> CreateStar(float x, float y) {
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
t.x = x;
|
t.x = x;
|
||||||
t.y = y;
|
t.y = y;
|
||||||
e->AddComponent<ScrollableComponent>();
|
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||||
|
scrollable.worldX = x;
|
||||||
e->AddComponent<ColliderComponent>();
|
e->AddComponent<ColliderComponent>();
|
||||||
e->AddComponent<CollectibleComponent>();
|
e->AddComponent<CollectibleComponent>();
|
||||||
e->AddComponent<RenderComponent>();
|
e->AddComponent<RenderComponent>();
|
||||||
|
|
@ -48,7 +57,8 @@ std::shared_ptr<Entity> CreateAsteroid(float x, float y) {
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
t.x = x;
|
t.x = x;
|
||||||
t.y = y;
|
t.y = y;
|
||||||
e->AddComponent<ScrollableComponent>();
|
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||||
|
scrollable.worldX = x;
|
||||||
e->AddComponent<ColliderComponent>();
|
e->AddComponent<ColliderComponent>();
|
||||||
e->AddComponent<RenderComponent>();
|
e->AddComponent<RenderComponent>();
|
||||||
return e;
|
return e;
|
||||||
|
|
@ -58,9 +68,11 @@ std::shared_ptr<Entity> CreateNullZone(float x, float width) {
|
||||||
auto e = std::make_shared<Entity>();
|
auto e = std::make_shared<Entity>();
|
||||||
auto &t = e->AddComponent<TransformComponent>();
|
auto &t = e->AddComponent<TransformComponent>();
|
||||||
t.x = x;
|
t.x = x;
|
||||||
(void)width;
|
auto &scrollable = e->AddComponent<ScrollableComponent>();
|
||||||
e->AddComponent<ScrollableComponent>();
|
scrollable.worldX = x;
|
||||||
e->AddComponent<NullZoneComponent>();
|
|
||||||
|
auto &nullZone = e->AddComponent<NullZoneComponent>();
|
||||||
|
nullZone.width = width;
|
||||||
e->AddComponent<RenderComponent>();
|
e->AddComponent<RenderComponent>();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,50 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Components.hpp"
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
void UpdateAllSystems(std::vector<std::shared_ptr<Entity>> &entities, float deltaTime) {
|
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) {
|
for (auto &entity : entities) {
|
||||||
if (!entity) {
|
if (entity == worldEntity || entity == wellEntity || !entity) {
|
||||||
continue;
|
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);
|
entity->Update(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
as6/main.cpp
31
as6/main.cpp
|
|
@ -17,6 +17,9 @@ int main() {
|
||||||
entities.push_back(CreateWorld());
|
entities.push_back(CreateWorld());
|
||||||
entities.push_back(CreateGravityWell());
|
entities.push_back(CreateGravityWell());
|
||||||
entities.push_back(CreateProbe());
|
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());
|
entities.push_back(CreateHUD());
|
||||||
|
|
||||||
while (!window.ShouldClose()) {
|
while (!window.ShouldClose()) {
|
||||||
|
|
@ -25,7 +28,12 @@ int main() {
|
||||||
UpdateAllSystems(entities, dt);
|
UpdateAllSystems(entities, dt);
|
||||||
|
|
||||||
auto worldScroll = entities[0]->GetComponent<ScrollComponent>();
|
auto worldScroll = entities[0]->GetComponent<ScrollComponent>();
|
||||||
|
auto wellTransform = entities[1]->GetComponent<TransformComponent>();
|
||||||
auto probeTransform = entities[2]->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.BeginDrawing();
|
||||||
window.ClearBackground(raylib::Color(11, 15, 26, 255));
|
window.ClearBackground(raylib::Color(11, 15, 26, 255));
|
||||||
|
|
@ -47,6 +55,29 @@ int main() {
|
||||||
raylib::Color(235, 215, 125, 255));
|
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();
|
window.EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue