Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
LeandroSQ committed Feb 6, 2024
1 parent 5ab9302 commit 07b84fc
Show file tree
Hide file tree
Showing 61 changed files with 1,225 additions and 1,351 deletions.
Binary file removed .github/images/Arrow_Down_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Arrow_Left_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Arrow_Right_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Arrow_Up_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Esc_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Mouse_Left_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Mouse_Middle_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Mouse_Right_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Space_Key_Dark.png
Binary file not shown.
Binary file removed .github/images/Z_Key_Dark.png
Binary file not shown.
Binary file removed .github/screenshots/screenshot01.png
Binary file not shown.
Binary file removed .github/screenshots/screenshot02.png
Binary file not shown.
Binary file removed .github/screenshots/screenshot03.png
Binary file not shown.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ jobs:
- name: Copy WASM module (Ubuntu)
if: matrix.target == 'web' && matrix.os == 'ubuntu-latest'
run: |
cp ./build/sandbox.wasm ./src/web
cp ./build/sandbox.js ./src/web
cp ./build/sandbox.html ./src/web
cp ./build/asteroids.wasm ./src/web
cp ./build/asteroids.js ./src/web
cp ./build/asteroids.html ./src/web
- name: Deploy to GitHub Pages (Ubuntu)
if: matrix.target == 'web' && matrix.os == 'ubuntu-latest'
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ lib/*/
imgui.ini
compile_commands.json
.DS_Store
src/web/sandbox.*
src/web/asteroids.*
src/tests
.cache
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.18.0)
set(PROJECT_NAME sandbox)
set(PROJECT_NAME asteroids)

function(dump_info)
message(STATUS "CMAKE_SYSTEM: ${CMAKE_SYSTEM}")
Expand Down
76 changes: 0 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +0,0 @@
# C++ Simple physics engine

Implements a simple physics engine in C++ based on [Verlet integration](https://en.wikipedia.org/wiki/Verlet_integration) and [Verlet constraints](https://en.wikipedia.org/wiki/Verlet_integration#Verlet_constraints).

<center>
<p float="left" align="center">
<img src=".github/screenshots/screenshot01.png" style="width: 48%"/>
<img src=".github/screenshots/screenshot02.png" style="width: 48%"/>
</p>
</center>

<p align="center">
<a href="https://leandrosq.github.io/cpp-physics-sandbox/">Live demo here</a>
</p>

## About

You can check the WEB version [here](https://leandrosq.github.io/cpp-physics-sandbox/). It is a port using WASM generated by Emscripten using WebGL on the browser.

* Restricted only to circles
* Supports gravity
* Supports collisions
* Implements a Quadtree for collision detection
* Supports constraints
* Implements both a circle and a rectangle world constraint
* Supports user interaction
* Dragging
* Spawning
* Explode

## Controls

### Desktop

> <img src=".github/images/Mouse_Left_Key_Dark.png" align="center" height="32"> `Left click` to spawn circles
> <img src=".github/images/Mouse_Right_Key_Dark.png" align="center" height="32"> `Right click` to drag circles
> <img src=".github/images/Mouse_Middle_Key_Dark.png" align="center" height="32"> `Middle click` to explode circles
> <img src=".github/images/Space_Key_Dark.png" align="center" height="32"> `Space bar` to flip the Gravity vector
> <img src=".github/images/Z_Key_Dark.png" align="center" height="32"> `Z` to toggle Gravity ON/OFF
> <img src=".github/images/Arrow_Up_Key_Dark.png" align="center" height="32"> `Up arrow` to increase the Gravity force
> <img src=".github/images/Arrow_Down_Key_Dark.png" align="center" height="32"> `Down arrow` to decrease the Gravity force
> <img src=".github/images/Arrow_Left_Key_Dark.png" align="center" height="32"> `Left arrow` to decrease the Gravity angle
> <img src=".github/images/Arrow_Right_Key_Dark.png" align="center" height="32"> `Right arrow` to increase the Gravity angle
> <img src=".github/images/Esc_Key_Dark.png" align="center" height="32"> `ESC` to exit
<p float="left" align="center">
<span>Other controls included on the GUI can be used with the mouse as demonstrated below.</span>
<img src=".github/screenshots/screenshot03.png" style="width: 48%"/>
</p>

## Project

### Resources

| Name | Description |
| -- | -- |
| [ClangD](https://clangd.llvm.org/) | Language Server for C++ |
| [CMake](https://cmake.org/) | Cross-platform open-source make system |
| [Clang-tidy](https://clang.llvm.org/extra/clang-tidy/) | A clang-based C++ “linter” tool |
| [Clang-format](https://clang.llvm.org/docs/ClangFormat.html) | A tool to format C/C++/Obj-C code |
| [Emscripten](https://emscripten.org/) | Used for the web port, generating the WASM binaries. |
| [Raylib](https://www.raylib.com/) | A simple and easy-to-use library to enjoy videogames programming |
| [Dear ImGui](https://www.github.com/ocornut/imgui) | Bloat-free Immediate Mode Graphical User interface for C++ with minimal dependencies |
| [Dear ImGui Raylib](https:://github.com/RobLoach/raylib-imgui) | Dear ImGui bindings for Raylib |
| [NES CSS](https://nostalgic-css.github.io/NES.css/) | NES.css is NES-style (8bit-like) CSS Framework. |
| Github Actions | Used for CI/CD |
| Github Pages | Used for hosting the web version |
3 changes: 2 additions & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,15 @@ endfunction()

# Dependencies
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(SUPPORT_RPRAND_GENERATOR ON)
include_library(raylib 5.0 https://github.com/raysan5/raylib/archive/refs/tags/VERSION.tar.gz)

set(BUILD_RAYLIB_CPP_EXAMPLES OFF CACHE BOOL "" FORCE)
include_library(raylib_cpp 5.0.1 https://github.com/RobLoach/raylib-cpp/archive/refs/tags/vVERSION.tar.gz)

# include_library(raygui 4.0 https://github.com/raysan5/raygui/archive/refs/tags/VERSION.tar.gz)

include_library(dear_imgui 1.90.1 https://github.com/ocornut/imgui/archive/refs/tags/vVERSION.tar.gz)
include_library(dear_imgui docking https://github.com/ocornut/imgui/archive/refs/heads/VERSION.tar.gz)
include_library(rlimgui main https://github.com/raylib-extras/rlimgui/archive/refs/heads/VERSION.tar.gz)
target_compile_definitions(rlimgui PRIVATE NO_FONT_AWESOME)
target_link_libraries(rlimgui dear_imgui raylib)
Expand Down
2 changes: 1 addition & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cmake --build ./build -j 10
# Check if the previous command succeeded
if [ $? -eq 0 ]; then
echo "Build succeeded"
./build/sandbox
./build/asteroids
else
echo "Build failed"
fi
2 changes: 1 addition & 1 deletion scripts/copy-web-artifacts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

set -e

find ./build -depth 1 -name 'sandbox.*' -print -exec cp {} src/web \;
find ./build -depth 1 -name 'asteroids.*' -print -exec cp {} src/web \;
2 changes: 1 addition & 1 deletion scripts/linter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cmake --build ./build -j 10
# Check if the previous command succeeded
if [ $? -eq 0 ]; then
echo "Build succeeded... running linter!"
cmake --build ./build --target sandbox_lint
cmake --build ./build --target asteroids_lint
else
echo "Build failed"
fi
2 changes: 1 addition & 1 deletion scripts/server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

npx nodemon --watch build/sandbox.* --exec "sh scripts/copy-web-artifacts.sh" &
npx nodemon --watch build/asteroids.* --exec "sh scripts/copy-web-artifacts.sh" &
npx live-server --port=3000 --no-browser ./src/web &

wait
2 changes: 1 addition & 1 deletion scripts/web.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ else
exit 1
fi

cp ./build/web/sandbox.* ./src/web
cp ./build/web/asteroids.* ./src/web
42 changes: 42 additions & 0 deletions src/core/data/dummy-list.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "dummy-list.hpp"
#include "../models/asteroid.hpp"

void DummyList::clear() {
asteroids.clear();
}

bool DummyList::isEmpty() {
return asteroids.empty();
}

uint32_t DummyList::size() {
return asteroids.size();
}

uint16_t DummyList::getCellIndex(raylib::Vector2 position) {
return 0;
}

raylib::Vector2 DummyList::getCellPosition(uint16_t index) {
return raylib::Vector2::Zero();
}

void DummyList::resize(uint16_t rows, uint16_t cols) {
// Do nothing
}

void DummyList::insert(std::shared_ptr<Asteroid> asteroid) {
asteroids.push_back(asteroid);
}

void DummyList::remove(std::shared_ptr<Asteroid> asteroid) {
asteroids.erase(std::remove(asteroids.begin(), asteroids.end(), asteroid), asteroids.end());
}

std::vector<std::shared_ptr<Asteroid>> DummyList::retrieve(raylib::Vector2 position, uint16_t radius) {
return asteroids;
}

std::vector<std::shared_ptr<Asteroid>> DummyList::all() {
return asteroids;
}
26 changes: 26 additions & 0 deletions src/core/data/dummy-list.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "../precomp.hpp"
#include "icontainer.hpp"

class Asteroid;

class DummyList : public IContainer {
private:
std::vector<std::shared_ptr<Asteroid>> asteroids;

public:
DummyList() = default;
~DummyList() = default;

void clear() override;
bool isEmpty() override;
uint32_t size() override;
uint16_t getCellIndex(raylib::Vector2 position) override;
raylib::Vector2 getCellPosition(uint16_t index) override;
void resize(uint16_t rows, uint16_t cols) override;
void insert(std::shared_ptr<Asteroid> asteroid) override;
void remove(std::shared_ptr<Asteroid> asteroid) override;
std::vector<std::shared_ptr<Asteroid>> retrieve(raylib::Vector2 position, uint16_t radius) override;
std::vector<std::shared_ptr<Asteroid>> all() override;
};
19 changes: 19 additions & 0 deletions src/core/data/icontainer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "../precomp.hpp"

class Asteroid;

class IContainer {
public:
virtual void clear() = 0;
virtual bool isEmpty() = 0;
virtual uint32_t size() = 0;
virtual uint16_t getCellIndex(raylib::Vector2 position) = 0;
virtual raylib::Vector2 getCellPosition(uint16_t index) = 0;
virtual void resize(uint16_t rows, uint16_t cols) = 0;
virtual void insert(std::shared_ptr<Asteroid> asteroid) = 0;
virtual void remove(std::shared_ptr<Asteroid> asteroid) = 0;
virtual std::vector<std::shared_ptr<Asteroid>> retrieve(raylib::Vector2 position, uint16_t radius) = 0;
virtual std::vector<std::shared_ptr<Asteroid>> all() = 0;
};
117 changes: 117 additions & 0 deletions src/core/data/spatial-hash-grid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "spatial-hash-grid.hpp"
#include "../settings.hpp"
#include "../models/asteroid.hpp"

void SpatialHashGrid::clear() {
for (auto &cell : cells) {
cell.asteroids.resize(0);
}
count = 0;
}

bool SpatialHashGrid::isEmpty() {
return cells.empty() || count <= 0;
}

uint32_t SpatialHashGrid::size() {
return count;
}

uint16_t SpatialHashGrid::getCellIndex(raylib::Vector2 position) {
uint16_t index = (uint16_t)(position.y / cellSize) * cols + (uint16_t)(position.x / cellSize);
if (index < 0) index = 0;
if (index >= cells.size()) index = cells.size() - 1;
return index;
}

raylib::Vector2 SpatialHashGrid::getCellPosition(uint16_t index) {
return raylib::Vector2((index % cols) * cellSize, ((float)index / cols) * cellSize);
}

void SpatialHashGrid::resize(uint16_t rows, uint16_t cols) {
const auto backup = all();
cells.clear();
count = 0;
cells.resize(rows * cols);

this->rows = rows;
this->cols = cols;

cellSize = std::min(ceilf(HEIGHT / (float)rows), ceilf(WIDTH / (float)cols));

for (auto &asteroid : backup) {
insert(asteroid);
}
}

void SpatialHashGrid::insert(std::shared_ptr<Asteroid> asteroid) {
auto index = getCellIndex(asteroid->position);
asteroid->index = index;
asteroid->color = cells[index].color;
cells[index].asteroids.push_back(asteroid);
count++;
}

void SpatialHashGrid::remove(std::shared_ptr<Asteroid> asteroid) {
auto index = getCellIndex(asteroid->position);
asteroid->index = -1;
cells[index].asteroids.remove(asteroid);
count--;
}

void SpatialHashGrid::update() {
for (auto &cell : cells) {
auto it = cell.asteroids.begin();
while (it != cell.asteroids.end()) {
uint16_t index = getCellIndex(it->get()->position);
if (index != it->get()->index) {
it->get()->index = index;
it->get()->color = cell.color;
cells[index].asteroids.push_back(*it);
it = cells[it->get()->index].asteroids.erase(it);
} else {
it++;
}
}
}
}

std::vector<std::shared_ptr<Asteroid>> SpatialHashGrid::retrieve(raylib::Vector2 position, uint16_t radius) {
// Get the adjacent cells based on the radius
uint16_t startRow = std::max(0, (int)(position.y - radius) / cellSize);
uint16_t endRow = std::min(rows - 1, (int)(position.y + radius) / cellSize);
uint16_t startCol = std::max(0, (int)(position.x - radius) / cellSize);
uint16_t endCol = std::min(cols - 1, (int)(position.x + radius) / cellSize);

std::vector<std::shared_ptr<Asteroid>> result;
for (uint16_t row = startRow; row <= endRow; row++) {
for (uint16_t col = startCol; col <= endCol; col++) {
uint16_t index = row * cols + col;
for (auto &asteroid : cells[index].asteroids) {
if (position.Distance(asteroid->position) <= radius) {
result.push_back(asteroid);
}
}
}
}

return result;
}

std::vector<std::shared_ptr<Asteroid>> SpatialHashGrid::all() {
std::vector<std::shared_ptr<Asteroid>> result;
for (auto &cell : cells) {
result.insert(result.end(), cell.asteroids.begin(), cell.asteroids.end());
}
return result;
}

void SpatialHashGrid::render() {
for (uint16_t row = 0; row < rows; row++) {
for (uint16_t col = 0; col < cols; col++) {
uint16_t index = row * cols + col;
DrawRectangleLines(col * cellSize, row * cellSize, cellSize, cellSize, cells[index].color);
DrawText(TextFormat("%d", index), col * cellSize + 5, row * cellSize + 5, 10, WHITE);
}
}
}
Loading

0 comments on commit 07b84fc

Please sign in to comment.