This commit is contained in:
2026-11-08 07:45:01 -05:00
commit 36e093f84c
1109 changed files with 254529 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
#ifndef CHARACTER_MIND_CLASS
#define CHARACTER_MIND_CLASS
#include <random>
#include <vector>
#include <glm/glm.hpp>
#include "CharacterAction.h"
class Character;
class Camera;
// Decides what a character does, as actions. A character without a mind does nothing.
// AI goes here later, as another kind of mind.
class CharacterMind {
public:
virtual ~CharacterMind() = default;
// Called once a frame, adds whatever the character should do this frame
virtual void ProduceActions(const Character& character, std::vector<CharacterAction>& actions) = 0;
};
// The player: WASD, relative to where the camera faces, shift tapped to dash or held to sprint, space to jump, left click to attack and the number keys for abilities,
// aimed at whatever's under the crosshair. Looking around doesn't turn the
// character, it faces where it walks, but it swings the way the camera looks.
class KeyboardMind : public CharacterMind {
public:
explicit KeyboardMind(const Camera& camera) : camera(camera) {}
// Off while the keys are busy with something else, like typing in the console
bool enabled = true;
// Off while the mouse is busy with something else, like clicking on menus
bool mouseEnabled = true;
void ProduceActions(const Character& character, std::vector<CharacterAction>& actions) override;
private:
const Camera& camera;
bool prevAttackDown = false;
bool prevJumpDown = false;
bool prevShiftDown = false;
double shiftPressedAt = 0.0; // glfwGetTime when shift went down
float dashTapTime = 0.2f; // real seconds shift can be held and still count as a tap, longer is a sprint
bool prevAbilityDown[9] = {};
};
// An enemy with a rifle. It keeps its distance from its target, strafing side to side and facing them, shoots
// whenever it gets a moment and steps in to stab when they get close. Shots go where they were when it started
// aiming, so moving dodges them.
class RiflemanMind : public CharacterMind {
public:
RiflemanMind(const Character* target, float arenaHalfSize) : target(target), arenaHalfSize(arenaHalfSize) {}
const Character* target; // who it's after, nullptr just stands there
float arenaHalfSize; // how far the ground goes from the middle each way, so it doesn't back off the edge
float closest = 6.0f; // meters it backs off inside of
float farthest = 12.0f; // and closes in outside of
float stabReach = 1.6f; // meters it stabs from
float rushDistance = 3.5f; // they're this close and its stab is ready, it goes in for it
float shotWaitMin = 0.8f; // real seconds it waits between shots, picked at random between these
float shotWaitMax = 1.8f;
float sweepMin = 2.2f; // meters it sweeps from, its step carrying it the rest of the way
float sweepMax = 4.5f;
float sprintDistance = 18.0f; // farther than this it sprints to catch up
float dodgeChance = 0.5f; // of dashing aside when it sees a shot coming
float dashWaitMin = 2.0f; // real seconds between dashes, picked at random between these
float dashWaitMax = 4.5f;
void ProduceActions(const Character& character, std::vector<CharacterAction>& actions) override;
private:
std::mt19937 rng{ std::random_device{}() };
double lastTime = -1.0;
float shotWait = 1.0f;
float dashWait = 1.0f;
unsigned int seenUse = 0; // the last of their ability uses it decided whether to dodge
float strafeWait = 0.0f; // until it picks which way to strafe again
float strafeSign = 1.0f;
glm::vec3 aim = glm::vec3(0.0f, 0.0f, 1.0f); // where the ability it's in was aimed
};
#endif