From 6694d4ece984d82b7d42cc3d429cd4ec9632f450 Mon Sep 17 00:00:00 2001 From: Grant Horner Date: Sun, 30 Nov 2025 12:08:35 -0500 Subject: [PATCH] initial commit --- .gitignore | 1 + CMakeLists.txt | 21 +++++ main.cpp | 207 +++++++++++++++++++++++++++++++++++++++++++++++++ types.h | 39 ++++++++++ 4 files changed, 268 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 types.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2643aae --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 4.0) +project(isaac__) + +set(CMAKE_CXX_STANDARD 23) + +include(FetchContent) + +FetchContent_Declare( + raylib + GIT_REPOSITORY "https://github.com/raysan5/raylib.git" + GIT_TAG "5.5" + GIT_PROGRESS TRUE + GIT_SHALLOW true +) + +FetchContent_MakeAvailable(raylib) + +add_executable(isaac__ main.cpp + types.h) +target_link_libraries(${PROJECT_NAME} PUBLIC raylib) +target_include_directories(${PROJECT_NAME} PUBLIC ${raylib_public_headers}) \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..4fe780f --- /dev/null +++ b/main.cpp @@ -0,0 +1,207 @@ +#include +#include +#include + +#include "types.h" + +auto screen_width = 800; +auto screen_height = 600; +Rectangle walls[] = { + {.x = 100, .y = 100, .width = 5, .height = 100} +}; + +Player player; +auto player_speed = 5.0f; + +Tear tears[100] = {}; +float tear_speed = 10; +float tear_range = 500; +float tear_radius = 10.0f; +double last_fired = 0; +double fire_rate = .5; + +Enemy enemies[100] = {}; + +Vector2 Player::center() const noexcept { + return {.x = this->x + this->width / 2, .y = this->y + this->height / 2}; +} + +void Player::move(const float delta_x, const float delta_y) { + auto x = std::min( + std::max(this->x + delta_x, 0.0f), + static_cast(screen_width) - this->width); + + auto y = std::min( + std::max(this->y + delta_y, 0.0f), + static_cast(screen_height) - this->height); + + bool collided = false; + const Rectangle next_position = { + .x = x, + .y = y, + .width = this->width, + .height = this->height + }; + + for (const auto wall: walls) { + if (CheckCollisionRecs(wall, next_position)) { + collided = true; + break; + } + } + + if (collided) { + } else { + this->x = x; + this->y = y; + } +} + +struct EnemySpawner { + std::mutex m; + std::condition_variable cv; + std::atomic running; + std::atomic paused; + std::thread timer; + long long rate_secs; + + explicit EnemySpawner(const long long rate_secs) + : rate_secs(rate_secs) { + } + + void start() { + running.store(true); + timer = std::thread([&] { + while (running.load()) { + const auto start = std::chrono::steady_clock::now(); + + if (!paused.load()) { + std::print("Running at {}\n", start.time_since_epoch().count()); + } + + auto next = start + std::chrono::seconds(rate_secs); + std::unique_lock lock{m}; + cv.wait_until(lock, next, [&] { return !running.load(); }); + } + }); + } + + ~EnemySpawner() { + running.store(false); + cv.notify_all(); + timer.join(); + } +}; + +void spawn_tear(const Vector2 center, const Direction direction) { + for (auto &[tear_center, tear_direction, tear_active, starting_center]: tears) { + if (!tear_active) { + tear_center = center; + tear_direction = direction; + tear_active = true; + starting_center = center; + break; + } + } +} + +void update_tears() { + for (auto &[center, direction, active, starting_center]: tears) { + if (active) { + for (const auto wall: walls) { + if (CheckCollisionCircleRec(center, tear_radius, wall)) { + active = false; + break; + } + } + switch (direction) { + case UP: + center.y -= tear_speed; + break; + case DOWN: + center.y += tear_speed; + break; + case LEFT: + center.x -= tear_speed; + break; + case RIGHT: + center.x += tear_speed; + break; + } + + if (tear_range < Vector2Distance(center, starting_center)) { + active = false; + } + } + } +} + +int main() { + InitWindow(800, 600, "Isaac++"); + SetTargetFPS(60); + + EnemySpawner spawner{10}; + spawner.start(); + player.x = 10; + player.y = 10; + player.width = 50; + player.height = 50; + + while (!WindowShouldClose()) { + if (IsWindowResized()) { + screen_height = GetScreenHeight(); + screen_width = GetScreenWidth(); + } + + float delta_x = 0; + float delta_y = 0; + + if (IsKeyDown(KEY_W)) delta_y -= player_speed; + if (IsKeyDown(KEY_S)) delta_y += player_speed; + if (IsKeyDown(KEY_A)) delta_x -= player_speed; + if (IsKeyDown(KEY_D)) delta_x += player_speed; + player.move(delta_x, delta_y); + + + std::optional tear_direction; + if (IsKeyDown(KEY_LEFT)) { + tear_direction = LEFT; + } + if (IsKeyDown(KEY_UP)) { + tear_direction = UP; + } + if (IsKeyDown(KEY_RIGHT)) { + tear_direction = RIGHT; + } + if (IsKeyDown(KEY_DOWN)) { + tear_direction = DOWN; + } + + if (const auto now = GetTime(); last_fired + fire_rate < now && tear_direction.has_value()) { + last_fired = now; + spawn_tear(player.center(), tear_direction.value()); + } + + update_tears(); + + + BeginDrawing(); + ClearBackground(RAYWHITE); + DrawText("Hello", 100, 100, 20, RED); + DrawRectangleRec(player, BLUE); + + for (const auto wall: walls) { + DrawRectangleRec(wall, GREEN); + } + + for (const auto tear: tears) { + if (tear.active) { + DrawCircle(static_cast(tear.center.x), static_cast(tear.center.y), tear_radius, SKYBLUE); + } + } + + EndDrawing(); + } + CloseWindow(); + return 0; +} diff --git a/types.h b/types.h new file mode 100644 index 0000000..f2788d9 --- /dev/null +++ b/types.h @@ -0,0 +1,39 @@ +// +// Created by Grant Horner on 11/30/25. +// + +#pragma once + +#include "raymath.h" +#include "raylib.h" + +struct Player : Rectangle { + [[nodiscard]] Vector2 center() const noexcept; + + void move(float delta_x, float delta_y); +}; + +enum Direction { + UP, DOWN, LEFT, RIGHT +}; + +struct Tear { + Tear() noexcept = default; + + Tear(const Vector2 center, const Direction direction) noexcept + : center(center), direction(direction), + active(true), + starting_center(center) { + }; + Vector2 center; + Direction direction; + bool active; + Vector2 starting_center; +}; + +struct Enemy { + Vector2 center; + float radius; + Vector2 moving; + bool alive; +};