Player's position is reset when close to ghosts
This commit is contained in:
46
CLAUDE.md
Normal file
46
CLAUDE.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
- **Build the game**: `make`
|
||||||
|
- **Clean build artifacts**: `make clean`
|
||||||
|
- **Run the game**: `./ghostland`
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
This is a C++ OpenGL 3D game called "ghostland-game" - a continuation of a previous Go-based project. The player navigates a maze-like environment while being pursued by ghosts.
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
- **ghostland.cpp**: Main game loop, OpenGL setup, window management, and input handling
|
||||||
|
- **Player**: First-person camera system with mouse look, movement physics (including jumping), and flashlight mechanics
|
||||||
|
- **Ghost**: Enemy entities that move autonomously within defined boundaries and face the player
|
||||||
|
- **Shader system**: OpenGL shader loading and uniform management for different rendering passes
|
||||||
|
- **Text rendering**: FreeType-based text rendering system for UI elements like FPS display
|
||||||
|
- **Collision detection**: Ray-triangle intersection testing for wall collisions
|
||||||
|
|
||||||
|
### Key Systems
|
||||||
|
|
||||||
|
- **Maze loading**: The `maze.txt` file contains vertex data for walls parsed at runtime
|
||||||
|
- **Lighting**: Dynamic lighting system with player-controlled flashlight that responds to mouse movement
|
||||||
|
- **Rendering pipeline**: Separate shaders for different object types (walls, ghosts, text, trails)
|
||||||
|
- **Physics**: Simple gravity-based jumping with collision detection against maze geometry
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
- OpenGL 3.3+ with GLAD loader
|
||||||
|
- GLFW for window management and input
|
||||||
|
- GLM for math operations
|
||||||
|
- FreeType for text rendering
|
||||||
|
- stb_image for texture loading
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
- Header files (.h) define class interfaces
|
||||||
|
- Implementation files (.cpp) contain the logic
|
||||||
|
- Shader files (.glsl) define rendering programs
|
||||||
|
- Object files (.o) are generated during build
|
||||||
|
- `maze.txt` contains level geometry data
|
||||||
|
- `fonts/` contains TrueType fonts for text rendering
|
||||||
7
Makefile
7
Makefile
@@ -3,8 +3,8 @@ CFLAGS := -std=c++17 -O3
|
|||||||
LDFLAGS := -ldl -lglfw
|
LDFLAGS := -ldl -lglfw
|
||||||
INCLUDES := -I/usr/include/freetype2/ -I/usr/include/libpng16
|
INCLUDES := -I/usr/include/freetype2/ -I/usr/include/libpng16
|
||||||
|
|
||||||
ghostland: glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o text.o
|
ghostland: glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o text.o config.o
|
||||||
$(CC) -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o text.o /usr/lib/x86_64-linux-gnu/libfreetype.so $(LDFLAGS) $(CFLAGS)
|
$(CC) -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o shader.o ghost.o text.o config.o /usr/lib/x86_64-linux-gnu/libfreetype.so $(LDFLAGS) $(CFLAGS)
|
||||||
|
|
||||||
glad.o: glad.c
|
glad.o: glad.c
|
||||||
$(CC) -c -o glad.o glad.c $(CFLAGS)
|
$(CC) -c -o glad.o glad.c $(CFLAGS)
|
||||||
@@ -30,5 +30,8 @@ ghost.o: ghost.cpp ghost.h
|
|||||||
text.o: text.cpp text.h
|
text.o: text.cpp text.h
|
||||||
$(CC) -c -o text.o text.cpp $(CFLAGS) $(INCLUDES)
|
$(CC) -c -o text.o text.cpp $(CFLAGS) $(INCLUDES)
|
||||||
|
|
||||||
|
config.o: config.cpp config.h
|
||||||
|
$(CC) -c -o config.o config.cpp $(CFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o ghostland
|
rm -f *.o ghostland
|
||||||
|
|||||||
103
config.cpp
Normal file
103
config.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
std::map<std::string, std::string> Config::values;
|
||||||
|
|
||||||
|
bool Config::loadFromFile(const std::string& filename) {
|
||||||
|
std::ifstream file(filename);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cout << "Warning: Could not open config file: " << filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
std::string key, value;
|
||||||
|
if (parseJsonValue(line, key, value)) {
|
||||||
|
values[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
std::cout << "Loaded " << values.size() << " config values from " << filename << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Config::getFloat(const std::string& key, float defaultValue) {
|
||||||
|
auto it = values.find(key);
|
||||||
|
if (it != values.end()) {
|
||||||
|
try {
|
||||||
|
return std::stof(it->second);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cout << "Warning: Invalid float value for key '" << key << "': " << it->second << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::getInt(const std::string& key, int defaultValue) {
|
||||||
|
auto it = values.find(key);
|
||||||
|
if (it != values.end()) {
|
||||||
|
try {
|
||||||
|
return std::stoi(it->second);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cout << "Warning: Invalid int value for key '" << key << "': " << it->second << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Config::getString(const std::string& key, const std::string& defaultValue) {
|
||||||
|
auto it = values.find(key);
|
||||||
|
if (it != values.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Config::trim(const std::string& str) {
|
||||||
|
size_t start = str.find_first_not_of(" \t\r\n");
|
||||||
|
if (start == std::string::npos) return "";
|
||||||
|
size_t end = str.find_last_not_of(" \t\r\n");
|
||||||
|
return str.substr(start, end - start + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Config::parseJsonValue(const std::string& line, std::string& key, std::string& value) {
|
||||||
|
std::string trimmed = trim(line);
|
||||||
|
|
||||||
|
// Skip empty lines, comments, and structural characters
|
||||||
|
if (trimmed.empty() || trimmed[0] == '{' || trimmed[0] == '}' || trimmed[0] == '/' || trimmed[0] == '*') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for key-value pair: "key": value
|
||||||
|
size_t colonPos = trimmed.find(':');
|
||||||
|
if (colonPos == std::string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract key (remove quotes and whitespace)
|
||||||
|
std::string rawKey = trim(trimmed.substr(0, colonPos));
|
||||||
|
if (rawKey.length() >= 2 && rawKey[0] == '"' && rawKey[rawKey.length()-1] == '"') {
|
||||||
|
key = rawKey.substr(1, rawKey.length()-2);
|
||||||
|
} else {
|
||||||
|
key = rawKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract value (remove quotes, whitespace, and trailing comma)
|
||||||
|
std::string rawValue = trim(trimmed.substr(colonPos + 1));
|
||||||
|
if (!rawValue.empty() && rawValue.back() == ',') {
|
||||||
|
rawValue.pop_back();
|
||||||
|
rawValue = trim(rawValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawValue.length() >= 2 && rawValue[0] == '"' && rawValue[rawValue.length()-1] == '"') {
|
||||||
|
value = rawValue.substr(1, rawValue.length()-2);
|
||||||
|
} else {
|
||||||
|
value = rawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !key.empty();
|
||||||
|
}
|
||||||
20
config.h
Normal file
20
config.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public:
|
||||||
|
static bool loadFromFile(const std::string& filename);
|
||||||
|
static float getFloat(const std::string& key, float defaultValue);
|
||||||
|
static int getInt(const std::string& key, int defaultValue);
|
||||||
|
static std::string getString(const std::string& key, const std::string& defaultValue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::map<std::string, std::string> values;
|
||||||
|
static std::string trim(const std::string& str);
|
||||||
|
static bool parseJsonValue(const std::string& line, std::string& key, std::string& value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
12
ghost.cpp
12
ghost.cpp
@@ -111,3 +111,15 @@ float rand_float(float rmin, float rmax) {
|
|||||||
glm::vec3 Ghost::get_pos() const {
|
glm::vec3 Ghost::get_pos() const {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ghost::reverse_direction_from_position(glm::vec3 target_pos) {
|
||||||
|
// Calculate direction from target_pos to ghost position
|
||||||
|
glm::vec3 direction = pos - target_pos;
|
||||||
|
// Set yawr to point directly away from target_pos
|
||||||
|
yawr = atan2(direction.x, direction.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ghost::regenerate_position() {
|
||||||
|
pos.x = rand_float(xmin, xmax);
|
||||||
|
pos.z = rand_float(zmin, zmax);
|
||||||
|
}
|
||||||
|
|||||||
2
ghost.h
2
ghost.h
@@ -9,6 +9,8 @@ class Ghost {
|
|||||||
void apply_movement(float curr_time, float timed);
|
void apply_movement(float curr_time, float timed);
|
||||||
glm::mat4 get_model(glm::vec3 &camera_pos);
|
glm::mat4 get_model(glm::vec3 &camera_pos);
|
||||||
glm::vec3 get_pos() const;
|
glm::vec3 get_pos() const;
|
||||||
|
void reverse_direction_from_position(glm::vec3 target_pos);
|
||||||
|
void regenerate_position();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int ghost_id;
|
int ghost_id;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "ghost.h"
|
#include "ghost.h"
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
@@ -38,7 +39,7 @@ bool first_frame = false;
|
|||||||
float timed = 0.0f;
|
float timed = 0.0f;
|
||||||
float last_frame = 0.0f;
|
float last_frame = 0.0f;
|
||||||
|
|
||||||
float camera_speed = 10.0f;
|
float camera_speed = 20.0f;
|
||||||
|
|
||||||
const char *projectionC = "projection";
|
const char *projectionC = "projection";
|
||||||
const char *viewC = "view";
|
const char *viewC = "view";
|
||||||
@@ -59,12 +60,18 @@ const char *specularC = "light.specular";
|
|||||||
int num_walls;
|
int num_walls;
|
||||||
float *wall_vertices;
|
float *wall_vertices;
|
||||||
|
|
||||||
int trailmax = 1800;
|
int trailmax = 500;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
int success;
|
int success;
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
|
glm::vec3 start_position;
|
||||||
|
float start_yaw;
|
||||||
|
|
||||||
|
// Load configuration
|
||||||
|
Config::loadFromFile("ghostland.json");
|
||||||
|
camera_speed = Config::getFloat("camera_speed", camera_speed);
|
||||||
|
|
||||||
FILE *fp = fopen("maze.txt", "r");
|
FILE *fp = fopen("maze.txt", "r");
|
||||||
float yaw;
|
float yaw;
|
||||||
@@ -72,6 +79,8 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("1st fscanf failed.\n");
|
printf("1st fscanf failed.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
start_position = position;
|
||||||
|
start_yaw = yaw;
|
||||||
player = new Player(position, yaw);
|
player = new Player(position, yaw);
|
||||||
if (fscanf(fp, "%d\n", &num_walls) == EOF) {
|
if (fscanf(fp, "%d\n", &num_walls) == EOF) {
|
||||||
printf("2nd fscanf failed.\n");
|
printf("2nd fscanf failed.\n");
|
||||||
@@ -151,8 +160,11 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
WINDOWWIDTH = monitor_mode->width;
|
WINDOWWIDTH = monitor_mode->width;
|
||||||
WINDOWHEIGHT = monitor_mode->height;
|
WINDOWHEIGHT = monitor_mode->height;
|
||||||
|
//WINDOWWIDTH = 1280;
|
||||||
|
//WINDOWHEIGHT = 960;
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(WINDOWWIDTH, WINDOWHEIGHT, "Ghostland!", monitor, NULL);
|
GLFWwindow* window = glfwCreateWindow(WINDOWWIDTH, WINDOWHEIGHT, "Ghostland!", monitor, NULL);
|
||||||
|
//GLFWwindow* window = glfwCreateWindow(WINDOWWIDTH, WINDOWHEIGHT, "Ghostland!", NULL, NULL);
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
{
|
{
|
||||||
printf("Failed to create GLFW window.\n");
|
printf("Failed to create GLFW window.\n");
|
||||||
@@ -340,7 +352,14 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
std::vector<Ghost *> ghosts;
|
std::vector<Ghost *> ghosts;
|
||||||
for (int i = 0; i < 800; i++) {
|
for (int i = 0; i < 800; i++) {
|
||||||
ghosts.push_back(new Ghost(xmin_wall, xmax_wall, zmin_wall, zmax_wall));
|
Ghost *ghost = new Ghost(xmin_wall, xmax_wall, zmin_wall, zmax_wall);
|
||||||
|
|
||||||
|
// Ensure ghost is not within 30.0 units of start_position
|
||||||
|
while (glm::length(ghost->get_pos() - start_position) <= 30.0f) {
|
||||||
|
ghost->regenerate_position();
|
||||||
|
}
|
||||||
|
|
||||||
|
ghosts.push_back(ghost);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->mouse_callback(window, WINDOWWIDTH/2, WINDOWHEIGHT);
|
player->mouse_callback(window, WINDOWWIDTH/2, WINDOWHEIGHT);
|
||||||
@@ -409,6 +428,37 @@ int main(int argc, char *argv[]) {
|
|||||||
glm::vec3 light_front = player->get_light_front();
|
glm::vec3 light_front = player->get_light_front();
|
||||||
//printf("light_pos: (%f, %f, %f)\n", light_front.x, light_front.y, light_front.z);
|
//printf("light_pos: (%f, %f, %f)\n", light_front.x, light_front.y, light_front.z);
|
||||||
|
|
||||||
|
// Sort ghosts by distance to player for optimization
|
||||||
|
glm::vec3 player_pos = player->get_pos();
|
||||||
|
struct {
|
||||||
|
bool operator()(const Ghost *a, const Ghost *b) const {
|
||||||
|
glm::vec3 a_diff, b_diff;
|
||||||
|
a_diff = player->get_pos() - a->get_pos();
|
||||||
|
b_diff = player->get_pos() - b->get_pos();
|
||||||
|
float a_dist, b_dist;
|
||||||
|
a_dist = glm::length(a_diff);
|
||||||
|
b_dist = glm::length(b_diff);
|
||||||
|
return a_dist < b_dist;
|
||||||
|
}
|
||||||
|
} ghost_compare;
|
||||||
|
std::partial_sort(ghosts.begin(), ghosts.begin() + ghosts.size() / 5, ghosts.end(), ghost_compare);
|
||||||
|
|
||||||
|
// Calculate nearest ghost distance (first ghost is now closest)
|
||||||
|
float nearest_ghost_distance = glm::length(ghosts[0]->get_pos() - player_pos);
|
||||||
|
|
||||||
|
// Interpolate flashlight color based on nearest ghost distance
|
||||||
|
// At 30.0+ units: (0.61, 0.60, 0.59) - normal color
|
||||||
|
// At 10.0 units: (0.99, 0.60, 0.59) - red shift
|
||||||
|
float color_factor = 1.0f;
|
||||||
|
if (nearest_ghost_distance < 30.0f) {
|
||||||
|
color_factor = (nearest_ghost_distance - 10.0f) / (30.0f - 10.0f);
|
||||||
|
color_factor = glm::clamp(color_factor, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 normal_color = glm::vec3(0.61f, 0.60f, 0.59f);
|
||||||
|
glm::vec3 danger_color = glm::vec3(0.99f, 0.60f, 0.59f);
|
||||||
|
diffuse = glm::mix(danger_color, normal_color, color_factor);
|
||||||
|
|
||||||
// fragment requirements
|
// fragment requirements
|
||||||
set_uniform(wall_program, viewposC, camera_pos);
|
set_uniform(wall_program, viewposC, camera_pos);
|
||||||
set_uniform(wall_program, shininessC, wall_shininess);
|
set_uniform(wall_program, shininessC, wall_shininess);
|
||||||
@@ -468,22 +518,24 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
set_uniform(ghost_program, projectionC, projection);
|
set_uniform(ghost_program, projectionC, projection);
|
||||||
set_uniform(ghost_program, viewC, view);
|
set_uniform(ghost_program, viewC, view);
|
||||||
|
|
||||||
struct {
|
|
||||||
bool operator()(const Ghost *a, const Ghost *b) const {
|
|
||||||
glm::vec3 a_diff, b_diff;
|
|
||||||
a_diff = player->get_pos() - a->get_pos();
|
|
||||||
b_diff = player->get_pos() - b->get_pos();
|
|
||||||
float a_dist2, b_dist2;
|
|
||||||
a_dist2 = a_diff.x * a_diff.x + a_diff.y * a_diff.y + a_diff.z * a_diff.z;
|
|
||||||
b_dist2 = b_diff.x * b_diff.x + b_diff.y * b_diff.y + b_diff.z * b_diff.z;
|
|
||||||
return a_dist2 < b_dist2;
|
|
||||||
}
|
|
||||||
} ghost_compare;
|
|
||||||
std::partial_sort(ghosts.begin(), ghosts.begin() + ghosts.size() / 5, ghosts.end(), ghost_compare);
|
|
||||||
for (int i = ghosts.size()/5; i >= 0; i--) {
|
for (int i = ghosts.size()/5; i >= 0; i--) {
|
||||||
glm::mat4 ghost_model = ghosts[i]->get_model(camera_pos);
|
glm::mat4 ghost_model = ghosts[i]->get_model(camera_pos);
|
||||||
ghosts[i]->apply_movement(current_frame, timed);
|
ghosts[i]->apply_movement(current_frame, timed);
|
||||||
|
|
||||||
|
// Check if ghost is within 10.0 units of player
|
||||||
|
glm::vec3 ghost_pos = ghosts[i]->get_pos();
|
||||||
|
glm::vec3 player_pos = player->get_pos();
|
||||||
|
float distance = glm::length(ghost_pos - player_pos);
|
||||||
|
if (distance <= 10.0f) {
|
||||||
|
player->reset_position(start_position, start_yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if ghost is within 30.0 units of start_position
|
||||||
|
float start_distance = glm::length(ghost_pos - start_position);
|
||||||
|
if (start_distance <= 30.0f) {
|
||||||
|
ghosts[i]->reverse_direction_from_position(start_position);
|
||||||
|
}
|
||||||
|
|
||||||
set_uniform(ghost_program, modelC, ghost_model);
|
set_uniform(ghost_program, modelC, ghost_model);
|
||||||
glBindVertexArray(ghostVAO);
|
glBindVertexArray(ghostVAO);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, (3 + 3 + 2) * 6);
|
glDrawArrays(GL_TRIANGLES, 0, (3 + 3 + 2) * 6);
|
||||||
|
|||||||
3
ghostland.json
Normal file
3
ghostland.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"camera_speed": 30.0
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
OpenGL loader generated by glad 0.1.36 on Sat Oct 7 18:46:55 2023.
|
OpenGL loader generated by glad 0.1.36 on Sun Apr 7 15:29:39 2024.
|
||||||
|
|
||||||
Language/Generator: C/C++
|
Language/Generator: C/C++
|
||||||
Specification: gl
|
Specification: gl
|
||||||
|
|||||||
2
maze.txt
2
maze.txt
@@ -1,4 +1,4 @@
|
|||||||
845.0 2.5 -5.0 -128.0
|
845.0 2.5 -5.0 0.0
|
||||||
6498
|
6498
|
||||||
-0.5 0.0 0.5 0.0 0.0 1.0
|
-0.5 0.0 0.5 0.0 0.0 1.0
|
||||||
959.5 0.0 0.5 0.0 0.0 1.0
|
959.5 0.0 0.5 0.0 0.0 1.0
|
||||||
|
|||||||
@@ -250,6 +250,12 @@ void Player::apply_movement(float timed) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::reset_position(glm::vec3 startpos, float startyaw) {
|
||||||
|
position = startpos;
|
||||||
|
yaw = startyaw;
|
||||||
|
velocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Player::get_normal_from_index(int ix) {
|
glm::vec3 Player::get_normal_from_index(int ix) {
|
||||||
return glm::vec3(
|
return glm::vec3(
|
||||||
wall_vertices[ix * 6 * 6 + 3],
|
wall_vertices[ix * 6 * 6 + 3],
|
||||||
|
|||||||
1
player.h
1
player.h
@@ -40,6 +40,7 @@ class Player {
|
|||||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
bool is_in_air();
|
bool is_in_air();
|
||||||
void apply_movement(float timed);
|
void apply_movement(float timed);
|
||||||
|
void reset_position(glm::vec3 startpos, float startyaw);
|
||||||
|
|
||||||
bool operator()(const Ghost &a, const Ghost &b) const;
|
bool operator()(const Ghost &a, const Ghost &b) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user