Commit 9ab1b141 authored by Jonas Johan Solsvik's avatar Jonas Johan Solsvik 🎮
Browse files

Start on collision impl with cool comments

parent 244e11f3
......@@ -5,184 +5,252 @@
struct Thing
{
sf::Vector2f velocity{0, 0};
sf::RectangleShape shape{};
sf::Vector2f velocity{0, 0};
sf::RectangleShape shape{};
};
using ThingVector = std::vector<Thing>;
using ThingIDVector = std::vector<uint>;
auto eventsUpdate(
sf::RenderWindow &window,
sf::View &camera) -> void;
sf::RenderWindow &window,
sf::View &camera) -> void;
auto physicsUpdate(
ThingVector &things,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void;
ThingVector &things,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void;
auto physicsUpdate(
ThingVector &things,
const sf::Time deltaTime,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void;
ThingVector &things,
const sf::Time deltaTime,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void;
auto physicsTestCollision(
Thing &thing,
Thing &otherThing) -> void;
Thing &thing,
Thing &otherThing,
const float dt) -> void;
auto animationUpdate(
ThingVector &things,
const sf::Time deltaTime) -> void;
ThingVector &things,
const sf::Time deltaTime) -> void;
auto renderUpdate(
sf::RenderWindow &window,
const ThingVector &things) -> void;
sf::RenderWindow &window,
const ThingVector &things) -> void;
auto main() -> int
{
// # Create the main window and camera
const int WIDTH = 600;
const int HEIGHT = 600;
const int FRAMERATE_LIMIT = 90;
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Double trouble");
window.setFramerateLimit(FRAMERATE_LIMIT);
sf::View camera(sf::FloatRect(0, 0, WIDTH, HEIGHT));
camera.setCenter(0, -200);
camera.setSize(WIDTH, HEIGHT);
window.setView(camera);
ThingVector things;
const ThingIDVector dynamicThings = {0, 1};
const ThingIDVector staticThings = {2};
{
// # Create players
const auto PLAYER_SIZE = sf::Vector2f{50.0f, 50.0f};
const auto PLAYER_ORIGIN = sf::Vector2f{PLAYER_SIZE.x / 2.0f, PLAYER_SIZE.y / 2.0f};
Thing player1{};
player1.shape.setFillColor(sf::Color::Red);
player1.shape.setSize(PLAYER_SIZE);
player1.shape.setOrigin(PLAYER_ORIGIN);
player1.shape.setPosition(sf::Vector2f{-100, -25});
things.emplace_back(player1);
Thing player2{};
player2.shape.setFillColor(sf::Color::Blue);
player2.shape.setSize(PLAYER_SIZE);
player2.shape.setOrigin(PLAYER_ORIGIN);
player2.shape.setPosition(sf::Vector2f{100, -25});
things.emplace_back(player2);
// # Create ground
Thing ground{};
ground.shape.setSize(sf::Vector2f{4000, 20});
ground.shape.setPosition(-2000, 0);
ground.shape.setFillColor(sf::Color::White);
things.emplace_back(ground);
}
sf::Clock clock; // starts the clock
while (window.isOpen())
{
const auto deltaTime = clock.getElapsedTime();
clock.restart();
eventsUpdate(window, camera);
physicsUpdate(things, deltaTime, dynamicThings, staticThings);
animationUpdate(things, deltaTime);
renderUpdate(window, things);
}
return 0;
// # Create the main window and camera
const int WIDTH = 600;
const int HEIGHT = 600;
const int FRAMERATE_LIMIT = 90;
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Double trouble");
window.setFramerateLimit(FRAMERATE_LIMIT);
sf::View camera(sf::FloatRect(0, 0, WIDTH, HEIGHT));
camera.setCenter(0, -200);
camera.setSize(WIDTH, HEIGHT);
window.setView(camera);
ThingVector things;
const ThingIDVector dynamicThings = {0, 1};
const ThingIDVector staticThings = {2};
{
// # Create players
const auto PLAYER_SIZE = sf::Vector2f{50.0f, 50.0f};
const auto PLAYER_ORIGIN = sf::Vector2f{PLAYER_SIZE.x / 2.0f, PLAYER_SIZE.y / 2.0f};
Thing player1{};
player1.shape.setFillColor(sf::Color::Red);
player1.shape.setSize(PLAYER_SIZE);
player1.shape.setOrigin(PLAYER_ORIGIN);
player1.shape.setPosition(sf::Vector2f{-100, -25});
things.emplace_back(player1);
Thing player2{};
player2.shape.setFillColor(sf::Color::Blue);
player2.shape.setSize(PLAYER_SIZE);
player2.shape.setOrigin(PLAYER_ORIGIN);
player2.shape.setPosition(sf::Vector2f{100, -25});
things.emplace_back(player2);
// # Create ground
Thing ground{};
ground.shape.setSize(sf::Vector2f{4000, 20});
ground.shape.setPosition(-2000, 0);
ground.shape.setFillColor(sf::Color::White);
things.emplace_back(ground);
}
sf::Clock clock; // starts the clock
while (window.isOpen())
{
const auto deltaTime = clock.getElapsedTime();
clock.restart();
eventsUpdate(window, camera);
physicsUpdate(things, deltaTime, dynamicThings, staticThings);
animationUpdate(things, deltaTime);
renderUpdate(window, things);
}
return 0;
}
auto eventsUpdate(
sf::RenderWindow &window,
sf::View &camera) -> void
sf::RenderWindow &window,
sf::View &camera) -> void
{
// # Process events
sf::Event event;
while (window.pollEvent(event))
{
// ## Close window on exit
if (event.type == sf::Event::Closed ||
event.type == sf::Event::KeyPressed &&
event.key.code == sf::Keyboard::Escape)
{
window.close();
}
if (event.type == sf::Event::Resized)
{
sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
camera.setSize(event.size.width, event.size.height);
window.setView(camera);
}
}
// # Process events
sf::Event event;
while (window.pollEvent(event))
{
// ## Close window on exit
if (event.type == sf::Event::Closed ||
event.type == sf::Event::KeyPressed &&
event.key.code == sf::Keyboard::Escape)
{
window.close();
}
if (event.type == sf::Event::Resized)
{
sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
camera.setSize(event.size.width, event.size.height);
window.setView(camera);
}
}
}
auto physicsUpdate(
ThingVector &things,
const sf::Time deltaTime,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void
ThingVector &things,
const sf::Time deltaTime,
const ThingIDVector &dynamicThings,
const ThingIDVector &staticThings) -> void
{
const auto GRAVITY = sf::Vector2f{0, 10.0f * 30};
const auto dt = deltaTime.asSeconds();
for (const auto dynamicThingID : dynamicThings)
{
auto &dynamicThing = things[dynamicThingID];
// Add gravity to velocity
{
dynamicThing.velocity += GRAVITY * dt;
}
for (const auto otherDynamicThingID : dynamicThings)
{
if (dynamicThingID == otherDynamicThingID)
{
continue;
}
physicsTestCollision(dynamicThing, things[otherDynamicThingID]);
}
for (const auto staticThing : staticThings)
{
physicsTestCollision(dynamicThing, things[staticThing]);
}
}
const auto DRAG_COEFFISIENT = 0.1f;
const auto GRAVITY = 10.0f * 30;
const auto MAX_Y = 10.0f * 30;
const auto dt = deltaTime.asSeconds();
for (const auto dynamicThingID : dynamicThings)
{
auto &dynamicThing = things[dynamicThingID];
// Add gravity to velocity
{
dynamicThing.velocity.y = std::min(dynamicThing.velocity.y + GRAVITY * dt, MAX_Y);
dynamicThing.velocity *= 1.0f - DRAG_COEFFISIENT * dt;
}
for (const auto otherDynamicThingID : dynamicThings)
{
if (dynamicThingID == otherDynamicThingID)
{
continue;
}
physicsTestCollision(dynamicThing, things[otherDynamicThingID], dt);
}
for (const auto staticThing : staticThings)
{
physicsTestCollision(dynamicThing, things[staticThing], dt);
}
}
}
auto physicsTestCollision(
Thing &thing,
Thing &otherThing) -> void
Thing &collidingThing,
Thing &impactThing,
const float dt) -> void
{
const auto pos = collidingThing.shape.getPosition();
const auto dtPos = pos + collidingThing.velocity * dt;
const auto halfSize = collidingThing.shape.getSize() / 2.0f;
/**
* Get the four corners of the colliding rectangle
*
* [topLeft] -------------- [topRight] |--------------
* | | -->>> |
* | | |
* | | |
* | collider | -->>> | impacter
* | | |
* | | |
* | | -->>> |
* [botLeft] -------------- [botRight] |--------------
*
*/
const auto topLeft = sf::Vector2f{pos.x - halfSize.x, pos.y - halfSize.y};
const auto topRight = sf::Vector2f{pos.x + halfSize.x, pos.y - halfSize.y};
const auto bottomLeft = sf::Vector2f{pos.x - halfSize.x, pos.y + halfSize.y};
const auto bottomRight = sf::Vector2f{pos.x + halfSize.x, pos.y + halfSize.y};
/**
* Extrapolate where the colliding rectangle will be after dt
*
* -----------|
* |
* | [dtTopLeft] --------------- [dtTopRight]
* | | | -->>>
* collider |--- | |
* | \ | |
* | \-->> | collider | -->>>
* | | |
* | | |
* -----------| | | -->>>
* [dtBotLeft] ---------------- [dtBotRight]
*/
const auto dtTopLeft = sf::Vector2f{dtPos.x - halfSize.x, dtPos.y - halfSize.y};
const auto dtTopRight = sf::Vector2f{dtPos.x + halfSize.x, dtPos.y - halfSize.y};
const auto dtBottomLeft = sf::Vector2f{dtPos.x - halfSize.x, dtPos.y + halfSize.y};
const auto dtBottomRight = sf::Vector2f{dtPos.x + halfSize.x, dtPos.y + halfSize.y};
/**
* Get the four corners of the impact rectangle
*
* -----| [impTopLeft] -------------- [impTopRight]
* | -->>> | |
* | | |
* | | |
* | -->>> | impacter |
* | | |
* | | |
* | -->>> | |
* -----| [impBotLeft] --------------- [impBotRight]
*/
const auto impPos = impactThing.shape.getPosition();
const auto impHalfSize = impactThing.shape.getSize() / 2.0f;
const auto impTopLeft = sf::Vector2f{impPos.x - impHalfSize.x, impPos.y - impHalfSize.y};
const auto impTopRight = sf::Vector2f{impPos.x + impHalfSize.x, impPos.y - impHalfSize.y};
const auto impBottomLeft = sf::Vector2f{impPos.x - impHalfSize.x, impPos.y + impHalfSize.y};
const auto impBottomRight = sf::Vector2f{impPos.x + impHalfSize.x, impPos.y + impHalfSize.y};
}
auto animationUpdate(
ThingVector &things,
const sf::Time deltaTime) -> void
ThingVector &things,
const sf::Time deltaTime) -> void
{
for (auto &thing : things)
{
const auto position = thing.shape.getPosition();
const auto velocity = thing.velocity;
const auto dt = deltaTime.asSeconds();
thing.shape.setPosition(
position.x + velocity.x * dt,
position.y + velocity.y * dt);
}
for (auto &thing : things)
{
const auto position = thing.shape.getPosition();
const auto velocity = thing.velocity;
const auto dt = deltaTime.asSeconds();
thing.shape.setPosition(
position.x + velocity.x * dt,
position.y + velocity.y * dt);
}
}
auto renderUpdate(
sf::RenderWindow &window,
const ThingVector &things) -> void
sf::RenderWindow &window,
const ThingVector &things) -> void
{
window.clear();
for (auto &thing : things)
{
window.draw(thing.shape);
}
window.display();
window.clear();
for (auto &thing : things)
{
window.draw(thing.shape);
}
window.display();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment