156 lines
3.6 KiB
C++
156 lines
3.6 KiB
C++
//
|
|
// Created by Grant Horner on 11/30/25.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <cassert>
|
|
|
|
#include "raylib.h"
|
|
|
|
struct Player {
|
|
Rectangle rect;
|
|
uint8_t lives;
|
|
float speed;
|
|
float invulnerability_secs;
|
|
double last_hit;
|
|
float tear_speed;
|
|
float tear_range;
|
|
float tear_radius;
|
|
double last_fired;
|
|
double fire_rate;
|
|
|
|
[[nodiscard]] Vector2 center() const noexcept;
|
|
|
|
[[nodiscard]] bool is_invulnerable(double now) const noexcept;
|
|
|
|
void move(Vector2 delta);
|
|
};
|
|
|
|
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;
|
|
float speed;
|
|
uint32_t hp;
|
|
[[nodiscard]] bool alive() const noexcept { return hp != 0; }
|
|
};
|
|
|
|
enum ItemType {
|
|
TEARS_UP,
|
|
TEARS_DOWN,
|
|
RANGE_UP,
|
|
RANGE_DOWN,
|
|
ITEM_TYPE_COUNT
|
|
};
|
|
|
|
template<>
|
|
struct std::formatter<ItemType> : std::formatter<string_view> {
|
|
bool title_case = false;
|
|
|
|
constexpr auto parse(std::format_parse_context &ctx) {
|
|
auto it = ctx.begin();
|
|
if (it == ctx.end()) return it;
|
|
|
|
if (*it == 't') {
|
|
title_case = true;
|
|
++it;
|
|
}
|
|
|
|
return it;
|
|
}
|
|
|
|
auto format(const ItemType &item_type, std::format_context &ctx) const {
|
|
std::string_view item_type_str;
|
|
switch (item_type) {
|
|
case TEARS_UP:
|
|
item_type_str = title_case ? "Tears Up" : "TEARS_UP";
|
|
break;
|
|
case TEARS_DOWN:
|
|
item_type_str = title_case ? "Tears Down" : "TEARS_DOWN";
|
|
break;
|
|
case RANGE_UP:
|
|
item_type_str = title_case ? "Range Up" : "RANGE_UP";
|
|
break;
|
|
case RANGE_DOWN:
|
|
item_type_str = title_case ? "Range Down" : "RANGE_DOWN";
|
|
break;
|
|
case ITEM_TYPE_COUNT:
|
|
item_type_str = title_case ? "Item Type Count" : "ITEM_TYPE_COUNT";
|
|
break;
|
|
}
|
|
return std::formatter<string_view>::format(item_type_str, ctx);;
|
|
}
|
|
};
|
|
|
|
struct Item {
|
|
Vector2 center;
|
|
float radius;
|
|
ItemType type;
|
|
bool active;
|
|
|
|
[[nodiscard]] Color color() const noexcept {
|
|
switch (type) {
|
|
case TEARS_UP:
|
|
return BLUE;
|
|
case TEARS_DOWN:
|
|
return GREEN;
|
|
case RANGE_UP:
|
|
return RED;
|
|
case RANGE_DOWN:
|
|
return ORANGE;
|
|
case ITEM_TYPE_COUNT:
|
|
assert(0 && "ITEM_TYPE_COUNT should not be instantiated.");
|
|
}
|
|
|
|
assert(0 && "Unreachable.");
|
|
}
|
|
};
|
|
|
|
struct Viewport {
|
|
Viewport() = default;
|
|
|
|
Viewport(const float screen_width, const float screen_height)
|
|
: screen_width(screen_width),
|
|
screen_height(screen_height),
|
|
padding(50),
|
|
level_width(screen_width - padding * 2),
|
|
level_height(screen_height - padding * 2),
|
|
level_left(padding),
|
|
level_top(padding),
|
|
level_right(level_width + padding),
|
|
level_bottom(level_height + padding) {
|
|
}
|
|
|
|
Viewport& operator=(const Viewport &other) = default;
|
|
|
|
float screen_width;
|
|
float screen_height;
|
|
|
|
float padding;
|
|
|
|
float level_width;
|
|
float level_height;
|
|
float level_left;
|
|
float level_top;
|
|
float level_right;
|
|
float level_bottom;
|
|
};
|