-OBJS = main.o stb_image.o helpers.o tiny_obj_loader.o baseclass.o old_objects.o geometric_objects.o hud.o door.o vehicle.o
-CXXFLAGS = -g -Wall
+OBJS = main.o stb_image.o helpers.o tiny_obj_loader.o baseclass.o old_objects.o geometric_objects.o hud.o door.o vehicle.o maze.o
+CXXFLAGS = -g -Wall -std=c++20
LDFLAGS = -lGL -lglfw -lGLEW -pthread -g
# For FreeBSD (doesn't seem to hurt anything on Linux)
./a.out
${OBJS} : game.h
-main.o : projectiles.h activation_area.h turret.h tile_floor.h old_objects.h moving_platform.h geometric_objects.h hud.h door.h vehicle.h
+main.o : projectiles.h activation_area.h turret.h tile_floor.h old_objects.h moving_platform.h geometric_objects.h hud.h door.h vehicle.h maze.h
float randvel(float speed);
void init_helpers();
void free_helpers();
+glm::vec3 get_look_at_point();
+ssize_t is_empty(glm::vec3 position, float distance = 0.2f);
class gameobject {
public:
#include "hud.h"
EXTERN hud main_hud;
-
}
void rollsphere::roll_to(size_t index, glm::vec3 new_location, float speed){
+ data_mutex.lock();
speeds[index] = speed;
new_locations[index] = new_location;
new_locations[index].y = locations[index].y;
float angular_velocity = speed / radii[index];
glm::vec3 axis = glm::cross(new_locations[index] - locations[index], glm::vec3(0, 1, 0));
- main_hud.lprintf(0, "Angular Velocity: %f, axis %f, %f, %f\n", angular_velocity, axis.x, axis.y, axis.z);
rotation_matrices[index] = glm::rotate(glm::mat4(1.0f), -angular_velocity, axis);
+ data_mutex.unlock();
}
void rollsphere::move(int elapsed_time){
+ data_mutex.lock();
for(size_t i = 0; i < locations.size(); i++){
if(speeds[i] > 0.0001){
glm::vec3 direction = glm::normalize(new_locations[i] - locations[i]);
locations[i] += speeds[i] * direction;
ups[i] = rotation_matrices[i] * ups[i];
forwards[i] = rotation_matrices[i] * forwards[i];
- if(glm::length(new_locations[i] - locations[i]) < 0.01)
+ if(glm::length(new_locations[i] - locations[i]) < speeds[i])
speeds[i] = 0.0f;
}
}
+ data_mutex.unlock();
}
void rollsphere::addsphere(glm::vec3 location, float radius, glm::vec3 up, glm::vec3 forward){
free(general_buffer);
}
+glm::vec3 get_look_at_point(){
+ glm::vec3 look_at_point = player_position;
+ look_at_point.x += cosf(player_elevation) * sinf(player_heading);
+ look_at_point.y += sinf(player_elevation);
+ look_at_point.z += cosf(player_elevation) * cosf(player_heading);
+ return look_at_point;
+}
+
float randvel(float speed){
long min = -100;
long max = 100;
in vec2 in_texcoord;
uniform mat4 vp;
out vec2 frag_texcoord;
-out vec4 gl_Position;
void main(void) {
gl_Position = vp * models[gl_InstanceID] * vec4(in_vertex, 1.0);
#include "geometric_objects.h"
#include "door.h"
#include "vehicle.h"
+#include "maze.h"
std::mutex grand_mutex;
projectile ice_balls;
wall_block spawned_blocks("cube.obj", "projectile.jpg", glm::vec3(2, 2, 2));
fragment brick_fragments;
+maze_solver round_maze_solver;
class target : public loaded_object, public block_object {
public:
};
-ssize_t is_empty(glm::vec3 position, float distance = 0.2f){
+ssize_t is_empty(glm::vec3 position, float distance){
for(gameobject* o : objects) {
ssize_t collide_index = o->collision_index(position, distance);
if(collide_index != -1)
return false;
}
return true;
-
}
void fire(bool burst = false){
player_platform = 0;
}
}
+ if(GLFW_KEY_V == key && 0 == action)
+ round_maze_solver.launch(-100);
}
int shutdown_engine = 0;
test_sphere.addsphere(glm::vec3(-30, 10, 530), 20);
objects.push_back(&test_sphere);
+ maze test_maze;
+ test_maze.start_location = glm::vec3(0, -100, 600);
+ test_maze.load_from_file("maze_map");
+ objects.push_back(&test_maze);
+ objects.push_back(&round_maze_solver);
+
/* Initialize game objects */
for(gameobject* o : objects){
if(o->init()){
/* Where are we? A: player_position
* What are we looking at?
*/
- glm::vec3 look_at_point = player_position;
- look_at_point.x += cosf(player_elevation) * sinf(player_heading);
- look_at_point.y += sinf(player_elevation);
- look_at_point.z += cosf(player_elevation) * cosf(player_heading);
+
+ glm::vec3 look_at_point = get_look_at_point();
glm::mat4 view = glm::lookAt(player_position, look_at_point, glm::vec3(0, 1, 0));
glm::mat4 projection = glm::perspective(45.0f, width / height, 0.1f, 10000.0f);
glm::mat4 vp = projection * view;
--- /dev/null
+#include "game.h"
+#include "maze.h"
+
+bool maze::load_from_file(const char* filename){
+ FILE *infile = fopen(filename, "r");
+ if(!infile){
+ printf(RED("Maze file %s could not be opened").c_str(), filename);
+ return false;
+ }
+ char *line;
+ size_t linesize = 0;
+ ssize_t readlen;
+ glm::vec3 place = start_location;
+ while(0 < (readlen = getline(&line, &linesize, infile))){
+ for(char *c = line; *c && (*c == '#' || *c == ' '); c++) {
+ if(*c == '#')
+ locations.push_back(place);
+ place.x += 8;
+ }
+ place.x = start_location.x;
+ place.z += 8;
+ }
+ fclose(infile);
+ return true;
+}
+
+void maze_solver::launch(float maze_height){
+ glm::vec3 lap = get_look_at_point();
+ data_mutex.lock();
+ sphere::addsphere(lap, 3.5);
+ float height_change = player_position.y - maze_height;
+ lap -= player_position;
+ lap *= height_change / lap.y;
+ lap = player_position - lap;
+ lap = glm::vec3(8.0f * roundf(lap.x / 8.0f), maze_height, 8.0f * roundf(lap.z / 8.0f));
+ new_locations.push_back(lap);
+ main_hud.lprintf(0, "Solver sent to: %f, %f, %f", lap.x, lap.y, lap.z);
+ speeds.push_back(0.1f);
+ rotation_matrices.push_back(glm::mat4(1.0f));
+ visiteds.push_back(std::set<intpoint>());
+ stacks.push_back(std::vector<intpoint>());
+ data_mutex.unlock();
+}
+
+void maze_solver::move(int elapsed_time) {
+ for(size_t i = 0; i < locations.size(); i++){
+ bool found_next = false;
+ if(speeds[i] < 0.001){
+ for(auto &n : intpoint(locations[i]).neighbors()){
+ if(!is_empty(n.vec3(), 0.0f))
+ continue;
+ if(visiteds[i].contains(n))
+ continue;
+ visiteds[i].insert(n);
+ stacks[i].push_back(n);
+ found_next = true;
+ roll_to(i, n.vec3(), solve_speed);
+ main_hud.lprintf(0, "Going to %d, %d, %d", n.x, n.y, n.z);
+ break; // We found somewhere new to go!
+ }
+ if(!found_next){ // Backtrack
+ if(stacks[i].size()){
+ roll_to(i, stacks[i].back().vec3(), solve_speed);
+ main_hud.lprintf(0, "Backtrack to %f, %f, %f", new_locations[i].x, new_locations[i].y, new_locations[i].z);
+ stacks[i].pop_back();
+ } else { // We can't backtrack, because the stack is empty
+ visiteds[i].clear(); // Maybe just start over?
+ }
+ }
+ }
+ }
+ rollsphere::move(elapsed_time);
+}
--- /dev/null
+#pragma once
+
+#include "geometric_objects.h"
+#include<set>
+
+class maze : public wall_block {
+public:
+ glm::vec3 start_location;
+ maze() : wall_block("cube.obj", "brick_2.png", glm::vec3(4, 4, 4)) {
+ scale = 4.0f;
+ }
+
+ bool load_from_file(const char* filename);
+};
+
+class maze_solver : public rollsphere {
+ struct intpoint {
+ int x, y, z;
+ intpoint(glm::vec3 p) {
+ x = roundf(p.x);
+ y = roundf(p.y);
+ z = roundf(p.z);
+ }
+ intpoint(int nx, int ny, int nz) : x(nx), y(ny), z(nz) {}
+ bool operator== (const intpoint &other) const {
+ return other.x == x && other.y == y && other.z == z;
+ }
+ bool operator<(const intpoint &other) const {
+ return (x << 20) + (y << 10) + z < (other.x << 20) + (other.y << 10) + other.z;
+ }
+ std::vector<intpoint> neighbors(){
+ std::vector<intpoint> retval;
+ retval.push_back(intpoint(x - 8, y, z));
+ retval.push_back(intpoint(x + 8, y, z));
+ retval.push_back(intpoint(x, y, z - 8));
+ retval.push_back(intpoint(x, y, z + 8));
+ return retval;
+ }
+ glm::vec3 vec3(){
+ return glm::vec3(x, y, z);
+ }
+ };
+public:
+ float solve_speed = 0.01f;
+ std::vector<std::set<intpoint>> visiteds;
+ std::vector<std::vector<intpoint>> stacks;
+ void launch(float maze_height);
+ void move(int elapsed_time) override;
+};
--- /dev/null
+######### ##########
+# # # ##
+# # #### # # ## ##
+# ## # # #
+# ################
+# # ## ##
+##### #### # # #
+# ### # # ## #
+##### ### # #
+# # ######### # ##
+# ### # #
+# # ############
+####### # # ## #
+# # # #
+#### #### ##########
+## ### ### #
+# ####### # #
+# ## ### ## #
+# # #
+####################