Compare commits
19 Commits
ReWindow-I
...
main
Author | SHA1 | Date | |
---|---|---|---|
f96a846202 | |||
442b397290 | |||
9f8224462b | |||
166bf96928 | |||
cf1518a61b | |||
583315193d | |||
29c32f6d9a | |||
4f6080a962 | |||
ffb989cd19 | |||
f204dc5898 | |||
9b06da8ee1 | |||
28a2d42369 | |||
0be005a877 | |||
27dd9b3639 | |||
07c970749f | |||
ca55970ed9 | |||
|
9f4b8987c0 | ||
|
a3d67ef18a | ||
|
01f2acca60 |
@@ -28,20 +28,39 @@ include(cmake/CPM.cmake)
|
||||
# You specify the release name to target against. See the link below for releases:
|
||||
# https://git.redacted.cc/Redacted/ReWindow/releases
|
||||
|
||||
CPMAddPackage(
|
||||
NAME mcolor
|
||||
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-5.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ReWindow
|
||||
URL URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-31.zip
|
||||
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-32.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME JGL
|
||||
URL https://git.redacted.cc/josh/JGL/archive/Prerelease-47.zip
|
||||
)
|
||||
|
||||
add_executable(ReWalkerApp main.cpp)
|
||||
|
||||
target_include_directories(ReWalkerApp PUBLIC ${ReWindow_SOURCE_DIR}/include ${J3ML_SOURCE_DIR}/include)
|
||||
target_include_directories(ReWalkerApp PUBLIC
|
||||
${ReWindow_SOURCE_DIR}/include
|
||||
${J3ML_SOURCE_DIR}/include
|
||||
${mcolor_SOURCE_DIR}/include
|
||||
${JGL_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(ReWalkerApp PUBLIC J3ML ReWindowLibrary)
|
||||
target_link_libraries(ReWalkerApp PUBLIC J3ML ReWindow mcolor JGL)
|
||||
|
||||
# simple window test
|
||||
add_executable(TestWindowApp test.cpp)
|
||||
|
||||
target_include_directories(TestWindowApp PUBLIC ${ReWindow_SOURCE_DIR}/include ${J3ML_SOURCE_DIR}/include)
|
||||
target_include_directories(TestWindowApp PUBLIC
|
||||
${ReWindow_SOURCE_DIR}/include
|
||||
${J3ML_SOURCE_DIR}/include
|
||||
${mcolor_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(TestWindowApp PUBLIC J3ML ReWindowLibrary)
|
||||
target_link_libraries(TestWindowApp PUBLIC J3ML ReWindow)
|
39
README.md
39
README.md
@@ -1,9 +1,44 @@
|
||||
# ReWalker
|
||||
ReWalker is a simple random walker program that uses ReWindow to handle windowing and mouse operations.
|
||||
|
||||
This is a simple random walker that has a little twist that if the user clicks the mouse over the window it "blows" the walker away from the mouse pointer.
|
||||
This is a simple random walker that has a little twist that if the user clicks the mouse over the window it "blows" the walker away from the mouse pointer. Pressing the space bar will reset the walker back to the centre of the screen and pressing the esc key will close the application.
|
||||
|
||||
The user can user the number 1, 2, 3, 4 and 5 keys to change the force at which the walker is blown away from the mouse pointer. 1 is lowest force and 5 is highest.
|
||||
|
||||
There are now 4 red impervious obstacles to bump into.
|
||||
|
||||
test.cpp builds to TestWindowApp as a test to help me understand how ReWindow works.
|
||||
|
||||
main.cpp builds to ReWalkerApp which is the main random walker program.
|
||||
|
||||
Thanks to Bill, Josh and Maxine for sorting the correct ReWindow Integration.
|
||||
|
||||
## Run ReWalker
|
||||
|
||||
|
||||
Install dependencies
|
||||
|
||||
```bash
|
||||
Rocky/Fedora/RHEL: dnf install cmake make gcc-g++ libX11 libX11-devel mesa-libGL-devel
|
||||
Pop_OS!/Ubuntu/Debian: apt-get install cmake make gcc g++ libx11-6 libx11-dev libgl-dev libxrandr-dev libvulkan-dev
|
||||
```
|
||||
|
||||
Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://git.redacted.cc/rich/ReWalker.git
|
||||
```
|
||||
|
||||
Build
|
||||
|
||||
```bash
|
||||
cd ReWalker && mkdir build && cd build && cmake .. && make
|
||||
```
|
||||
|
||||
Run it
|
||||
|
||||
```bash
|
||||
./ReWalkerApp
|
||||
```
|
||||
## Thanks
|
||||
|
||||
Thanks to Bill, Josh and Maxine for sorting the correct ReWindow Integration, and other things.
|
227
main.cpp
227
main.cpp
@@ -1,53 +1,224 @@
|
||||
// ReWalker
|
||||
// A random walker that moves around the screen
|
||||
// Written using Redacted ReWindow https://git.redacted.cc/Redacted/ReWindow
|
||||
// A random walker that moves around the screen with a fading trail, mouse interaction, and a status bar.
|
||||
// There are now obsticalse you cant walk through
|
||||
// Updated to use the latest ReWindow API and JGL rendering.
|
||||
// Written by Rich
|
||||
// With help from (and thanks to) from Maxine, Josh and Bill
|
||||
// With help from (and thanks to) from Maxine, Josh, and Bill.
|
||||
|
||||
#include <rewindow/types/window.h>
|
||||
#include <rewindow/logger/logger.h>
|
||||
#include <GL/gl.h>
|
||||
#include <ReWindow/types/Window.h>
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <JGL/JGL.h>
|
||||
#include <Color4.hpp>
|
||||
#include <memory>
|
||||
|
||||
// define window size and dot size (dot size should be odd)
|
||||
|
||||
// Define window size and dot size
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
#define DOT_SIZE 5
|
||||
#define OBSTACLE_SIZE 50
|
||||
|
||||
struct Walker {
|
||||
float x, y;
|
||||
#define STATUS_BAR_HEIGHT 30 // Height of the status bar at the bottom
|
||||
|
||||
Walker() : x(WIDTH / 2.0f), y(HEIGHT / 2.0f) {}
|
||||
#define FADE_SPEED 0.05f
|
||||
constexpr unsigned int TRAIL_LENGTH = 20;
|
||||
|
||||
void step() {
|
||||
float angle = static_cast<float>(rand()) / RAND_MAX * 360.0f;
|
||||
angle = angle * M_PI / 180.0f;
|
||||
float dx = std::cos(angle);
|
||||
float dy = std::sin(angle);
|
||||
// Enable debug mode
|
||||
#define DEBUG 1
|
||||
|
||||
x = std::clamp(x + dx, 0.0f, static_cast<float>(WIDTH - 1));
|
||||
y = std::clamp(y + dy, 0.0f, static_cast<float>(HEIGHT - 1));
|
||||
/**
|
||||
* @brief Represents an obstacle that the walker cannot pass through.
|
||||
*/
|
||||
struct Obstacle {
|
||||
Vector2 position; // Top-left corner of the obstacle
|
||||
|
||||
Obstacle(float x, float y) : position(x, y) {}
|
||||
|
||||
/**
|
||||
* @brief Checks if a given position is inside the obstacle.
|
||||
*/
|
||||
bool isColliding(const Vector2& pos) const {
|
||||
return pos.x >= position.x && pos.x <= position.x + OBSTACLE_SIZE &&
|
||||
pos.y >= position.y && pos.y <= position.y + OBSTACLE_SIZE;
|
||||
}
|
||||
};
|
||||
|
||||
class RandomWalkerWindow : public ReWindow::RWindow {
|
||||
/**
|
||||
* @brief Represents the walker that moves randomly.
|
||||
*/
|
||||
struct Walker {
|
||||
Vector2 position;
|
||||
Vector2 lastValidPosition;
|
||||
|
||||
Walker() : position(WIDTH / 2.0f, (HEIGHT - STATUS_BAR_HEIGHT) / 2.0f),
|
||||
lastValidPosition(position) {}
|
||||
|
||||
/**
|
||||
* @brief Moves the walker in a random direction.
|
||||
*/
|
||||
void step(const std::vector<Obstacle>& obstacles) {
|
||||
float angle = static_cast<float>(rand()) / RAND_MAX * 360.0f;
|
||||
angle = Math::Radians(angle);
|
||||
float dx = std::cos(angle);
|
||||
float dy = std::sin(angle);
|
||||
|
||||
// Store last valid position
|
||||
lastValidPosition = position;
|
||||
|
||||
// Update position
|
||||
position.x = std::clamp(position.x + dx, 0.0f, static_cast<float>(WIDTH - 1));
|
||||
position.y = std::clamp(position.y + dy, 0.0f, static_cast<float>(HEIGHT - STATUS_BAR_HEIGHT - 1));
|
||||
|
||||
// Check for collisions
|
||||
for (const auto& obstacle : obstacles) {
|
||||
if (obstacle.isColliding(position)) {
|
||||
position = lastValidPosition; // Revert movement if collision occurs
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pushes the walker away from the mouse pointer.
|
||||
*/
|
||||
void pushAway(float mouseX, float mouseY, float force, const std::vector<Obstacle>& obstacles) {
|
||||
float deltaX = position.x - mouseX;
|
||||
float deltaY = position.y - mouseY;
|
||||
|
||||
float distance = std::sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
if (distance > 0.0f) {
|
||||
float unitX = deltaX / distance;
|
||||
float unitY = deltaY / distance;
|
||||
|
||||
lastValidPosition = position;
|
||||
|
||||
position.x = std::clamp(position.x + unitX * force, 0.0f, static_cast<float>(WIDTH - 1));
|
||||
position.y = std::clamp(position.y + unitY * force, 0.0f, static_cast<float>(HEIGHT - STATUS_BAR_HEIGHT - 1));
|
||||
|
||||
// Prevent moving into obstacles
|
||||
for (const auto& obstacle : obstacles) {
|
||||
if (obstacle.isColliding(position)) {
|
||||
position = lastValidPosition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the walker to the center of the screen.
|
||||
*/
|
||||
void resetPosition() {
|
||||
position = Vector2(WIDTH / 2.0f, (HEIGHT - STATUS_BAR_HEIGHT) / 2.0f);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Custom ReWindow window class that manages the walker simulation.
|
||||
*/
|
||||
class RandomWalkerWindow : public ReWindow::OpenGLWindow {
|
||||
public:
|
||||
RandomWalkerWindow(const std::string& title, int width, int height)
|
||||
: ReWindow::RWindow(title, width, height) {}
|
||||
: ReWindow::OpenGLWindow(title, width, height, 2, 1),
|
||||
walker(std::make_unique<Walker>()),
|
||||
pushForce(3.0f)
|
||||
{
|
||||
// Define four obstacles
|
||||
obstacles.emplace_back(200, 150);
|
||||
obstacles.emplace_back(500, 150);
|
||||
obstacles.emplace_back(200, 400);
|
||||
obstacles.emplace_back(500, 400);
|
||||
}
|
||||
|
||||
void OnOpen() override {
|
||||
if (!JGL::Init({WIDTH, HEIGHT}, 0, 0))
|
||||
exit(0);
|
||||
|
||||
this->render_target = new RenderTarget({WIDTH, HEIGHT}, Colors::White);
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Clear with white
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
GLSwapBuffers();
|
||||
handleMouseInput();
|
||||
handleKeyboardInput();
|
||||
|
||||
// Move walker
|
||||
walker->step(obstacles);
|
||||
|
||||
JGL::Update({WIDTH, HEIGHT});
|
||||
J2D::Begin(render_target, true);
|
||||
fadeTrail();
|
||||
drawTrail();
|
||||
drawObstacles();
|
||||
plotWalker();
|
||||
J2D::End();
|
||||
|
||||
J2D::Begin(nullptr, true);
|
||||
J2D::DrawRenderTarget(render_target, {0, 0});
|
||||
J2D::End();
|
||||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Walker> walker;
|
||||
std::vector<Obstacle> obstacles;
|
||||
std::vector<std::pair<Vector2, float>> trailBuffer{};
|
||||
RenderTarget* render_target = nullptr;
|
||||
|
||||
float pushForce;
|
||||
|
||||
void handleMouseInput() {
|
||||
auto mousePos = GetMouseCoordinates();
|
||||
if (IsMouseButtonDown(MouseButtons::Left)) {
|
||||
walker->pushAway(mousePos.x, mousePos.y, pushForce, obstacles);
|
||||
}
|
||||
}
|
||||
|
||||
void handleKeyboardInput() {
|
||||
if (IsKeyDown(Keys::Space)) {
|
||||
walker->resetPosition();
|
||||
}
|
||||
if (IsKeyDown(Keys::Escape)) {
|
||||
Close();
|
||||
}
|
||||
if (IsKeyDown(Keys::One)) pushForce = 1.0f;
|
||||
if (IsKeyDown(Keys::Two)) pushForce = 2.0f;
|
||||
if (IsKeyDown(Keys::Three)) pushForce = 3.0f;
|
||||
if (IsKeyDown(Keys::Four)) pushForce = 4.0f;
|
||||
if (IsKeyDown(Keys::Five)) pushForce = 5.0f;
|
||||
}
|
||||
|
||||
void fadeTrail() {
|
||||
for (auto& trailPoint : trailBuffer)
|
||||
trailPoint.second = std::max(trailPoint.second - FADE_SPEED, 0.0f);
|
||||
trailBuffer.emplace_back(walker->position, 1.0f);
|
||||
if (trailBuffer.size() > TRAIL_LENGTH)
|
||||
trailBuffer.erase(trailBuffer.begin());
|
||||
}
|
||||
|
||||
void drawTrail() {
|
||||
for (const auto& trailPoint : trailBuffer)
|
||||
J2D::DrawPoint({0, 0, 0, (uint8_t)(trailPoint.second * 255.0f)}, trailPoint.first, DOT_SIZE);
|
||||
}
|
||||
|
||||
void plotWalker() {
|
||||
J2D::DrawPoint(Colors::Black, walker->position, DOT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draws the four red obstacles.
|
||||
*/
|
||||
void drawObstacles() {
|
||||
for (const auto& obstacle : obstacles) {
|
||||
J2D::FillRect(Colors::Red, obstacle.position, {OBSTACLE_SIZE, OBSTACLE_SIZE});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
std::unique_ptr<RandomWalkerWindow> window =
|
||||
std::make_unique<RandomWalkerWindow>("Random Walker with ReWindow", WIDTH, HEIGHT);
|
||||
|
||||
window->SetRenderer(RenderingAPI::OPENGL);
|
||||
window->Open();
|
||||
auto window = std::make_unique<RandomWalkerWindow>("Random Walker with Obstacles", WIDTH, HEIGHT);
|
||||
if (!window->Open())
|
||||
return -1;
|
||||
|
||||
while (!window->IsClosing()) {
|
||||
window->ManagedRefresh();
|
||||
|
20
test.cpp
20
test.cpp
@@ -1,32 +1,30 @@
|
||||
// simple test program to open a window with
|
||||
// a blue background.
|
||||
|
||||
#include <rewindow/types/window.h>
|
||||
#include <rewindow/logger/logger.h>
|
||||
#include <ReWindow/types/Window.h>
|
||||
#include <ReWindow/Logger.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 600
|
||||
|
||||
|
||||
class RandomWalkerWindow : public ReWindow::RWindow {
|
||||
class RandomWalkerWindow : public ReWindow::OpenGLWindow {
|
||||
public:
|
||||
RandomWalkerWindow(const std::string& title, int width, int height)
|
||||
: ReWindow::RWindow(title, width, height) {}
|
||||
: ReWindow::OpenGLWindow(title, width, height, 2, 1) {}
|
||||
|
||||
void OnRefresh(float elapsed) override {
|
||||
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // Clear with blue
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
GLSwapBuffers();
|
||||
//glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // Clear with blue
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
SwapBuffers();
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
std::unique_ptr<RandomWalkerWindow> window =
|
||||
std::make_unique<RandomWalkerWindow>("Random Walker with ReWindow", WIDTH, HEIGHT);
|
||||
|
||||
window->SetRenderer(RenderingAPI::OPENGL);
|
||||
std::unique_ptr<RandomWalkerWindow> window =
|
||||
std::make_unique<RandomWalkerWindow>("Random Walker with ReWindow", WIDTH, HEIGHT);
|
||||
window->Open();
|
||||
|
||||
while (!window->IsClosing()) {
|
||||
|
Reference in New Issue
Block a user