Added maze class that handles parsing of the map and rendering of the floor, walls and objectives.

Detects and counts the number of objectives encountered. The number is printed on exit.
This commit is contained in:
trotFunky 2019-11-04 03:04:57 +01:00
parent 888e8bd7f5
commit 24ff555e88
13 changed files with 31453 additions and 41 deletions

View file

@ -21,7 +21,10 @@ find_package(GLUT REQUIRED)
add_executable(game add_executable(game
src/main.cpp src/main.cpp
src/MovementManager.h src/MovementManager.h
src/MovementManager.cpp src/TileTypes.h) src/MovementManager.cpp
src/TileTypes.h
src/Maze.cpp
src/Maze.h)
target_include_directories(game PRIVATE target_include_directories(game PRIVATE
${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}

View file

@ -2,9 +2,14 @@
This very small project is the final part of my OpenGL course. It uses my custom engine. This very small project is the final part of my OpenGL course. It uses my custom engine.
Code quality is quite poor on this project as it has been rushed.
## Building ## Building
### Dependencies ### Dependencies
- OpenGL - OpenGL
- Glut - Glut
- My custom engine (Submodule of the project) - My custom engine (Submodule of the project)
## Sources
- `ground.tga` from [Sergiu Matei](https://www.artstation.com/artwork/LWYvk).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

BIN
resources/Outside.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 MiB

BIN
resources/ground.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

31149
resources/raptor.off Normal file

File diff suppressed because it is too large Load diff

BIN
resources/raptor.tga Normal file

Binary file not shown.

BIN
resources/wall.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

201
src/Maze.cpp Normal file
View file

@ -0,0 +1,201 @@
//
// Created by trotfunky on 04/11/2019.
//
#include "Maze.h"
Maze::Maze(const std::string& maze_map, unsigned int scaling_factor, const Texture& floor_texture,
const Texture& wall_texture, const Texture& outside_texture, Model3D& objective) :
scaling_factor(scaling_factor),
floor(floor_texture),
wall(wall_texture),
out(outside_texture),
objective(objective)
{
map.load_rgb_tga(maze_map);
corner_pos = map.width * this->scaling_factor;
for (unsigned int x = 0; x < map.width; x++)
for (unsigned int y = 0; y < map.height; y++)
{
unsigned int data_index = (x*map.height + y)*(map.color_bits/8);
Vec3i colour_data{
map.image_data[data_index],
map.image_data[data_index+1],
map.image_data[data_index+2]};
if (colour_data == Tiles::objective)
{
objective_positions.emplace_back(x,objective_altitude,y);
}
else if (colour_data == Tiles::wall)
{
wall_positions.emplace_back(x,wall_height,y);
}
else if (colour_data == Tiles::end)
{
outside_position = Vec3d{static_cast<double>(x),
wall_height,
static_cast<double>(y)};
}
}
}
void Maze::draw()
{
// Draw ground
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glBindTexture(GL_TEXTURE_2D,floor.opengl_id[0]);
// Deactivate interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glColor4f(1.0f, 1.0f, 1.0f,1.00);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3i(0,0,0);
glTexCoord2d(50,0);
glVertex3i(0,0,corner_pos);
glTexCoord2d(50,50);
glVertex3i(corner_pos,0,corner_pos);
glTexCoord2d(0,50);
glVertex3i(corner_pos,0,0);
glEnd();
// Draw walls
glBindTexture(GL_TEXTURE_2D,wall.opengl_id[0]);
// Deactivate interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glColor4f(1.0f, 1.0f, 1.0f,1.00);
glBegin(GL_QUADS);
for (const Vec3d& wall_tile: wall_positions)
{
// TODO : Factor with another for
glTexCoord2d(0,1);
glVertex3f(wall_tile.x*scaling_factor,0,wall_tile.z*scaling_factor);
glTexCoord2d(0,0);
glVertex3f(wall_tile.x*scaling_factor,wall_height,wall_tile.z*scaling_factor);
glTexCoord2d(1,0);
glVertex3f((wall_tile.x+1)*scaling_factor,wall_height,wall_tile.z*scaling_factor);
glTexCoord2d(1,1);
glVertex3f((wall_tile.x+1)*scaling_factor,0,wall_tile.z*scaling_factor);
glTexCoord2d(0,1);
glVertex3f(wall_tile.x*scaling_factor,0,wall_tile.z*scaling_factor);
glTexCoord2d(0,0);
glVertex3f(wall_tile.x*scaling_factor,wall_height,wall_tile.z*scaling_factor);
glTexCoord2d(1,0);
glVertex3f(wall_tile.x*scaling_factor,wall_height,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(1,1);
glVertex3f(wall_tile.x*scaling_factor,0,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(0,1);
glVertex3f((wall_tile.x+1)*scaling_factor,0,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(0,0);
glVertex3f((wall_tile.x+1)*scaling_factor,wall_height,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(1,0);
glVertex3f(wall_tile.x*scaling_factor,wall_height,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(1,1);
glVertex3f(wall_tile.x*scaling_factor,0,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(0,1);
glVertex3f((wall_tile.x+1)*scaling_factor,0,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(0,0);
glVertex3f((wall_tile.x+1)*scaling_factor,wall_height,(wall_tile.z+1)*scaling_factor);
glTexCoord2d(1,0);
glVertex3f((wall_tile.x+1)*scaling_factor,wall_height,wall_tile.z*scaling_factor);
glTexCoord2d(1,1);
glVertex3f((wall_tile.x+1)*scaling_factor,0,wall_tile.z*scaling_factor);
}
glEnd();
for (const Vec3d& objective_pos: objective_positions)
{
glPushMatrix();
glTranslatef((objective_pos.x+0.5)*scaling_factor,objective_pos.y,(objective_pos.z+0.5)*scaling_factor);
objective.draw_model();
glPopMatrix();
}
// Draw outside
glBindTexture(GL_TEXTURE_2D,out.opengl_id[0]);
// Deactivate interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glColor4f(1.0f, 1.0f, 1.0f,1.00);
glBegin(GL_QUADS);
glTexCoord2d(0,1);
glVertex3f(outside_position.x*scaling_factor,0,outside_position.z*scaling_factor);
glTexCoord2d(0,0);
glVertex3f(outside_position.x*scaling_factor,wall_height,outside_position.z*scaling_factor);
glTexCoord2d(1,0);
glVertex3f((outside_position.x+1)*scaling_factor,wall_height,outside_position.z*scaling_factor);
glTexCoord2d(1,1);
glVertex3f((outside_position.x+1)*scaling_factor,0,outside_position.z*scaling_factor);
glTexCoord2d(0,1);
glVertex3f(outside_position.x*scaling_factor,0,outside_position.z*scaling_factor);
glTexCoord2d(0,0);
glVertex3f(outside_position.x*scaling_factor,wall_height,outside_position.z*scaling_factor);
glTexCoord2d(1,0);
glVertex3f(outside_position.x*scaling_factor,wall_height,(outside_position.z+1)*scaling_factor);
glTexCoord2d(1,1);
glVertex3f(outside_position.x*scaling_factor,0,(outside_position.z+1)*scaling_factor);
glTexCoord2d(0,1);
glVertex3f((outside_position.x+1)*scaling_factor,0,(outside_position.z+1)*scaling_factor);
glTexCoord2d(0,0);
glVertex3f((outside_position.x+1)*scaling_factor,wall_height,(outside_position.z+1)*scaling_factor);
glTexCoord2d(1,0);
glVertex3f(outside_position.x*scaling_factor,wall_height,(outside_position.z+1)*scaling_factor);
glTexCoord2d(1,1);
glVertex3f(outside_position.x*scaling_factor,0,(outside_position.z+1)*scaling_factor);
glTexCoord2d(0,1);
glVertex3f((outside_position.x+1)*scaling_factor,0,(outside_position.z+1)*scaling_factor);
glTexCoord2d(0,0);
glVertex3f((outside_position.x+1)*scaling_factor,wall_height,(outside_position.z+1)*scaling_factor);
glTexCoord2d(1,0);
glVertex3f((outside_position.x+1)*scaling_factor,wall_height,outside_position.z*scaling_factor);
glTexCoord2d(1,1);
glVertex3f((outside_position.x+1)*scaling_factor,0,outside_position.z*scaling_factor);
glEnd();
}
bool Maze::remove_objective(const Vec2i& position)
{
Vec3d objective{static_cast<double>(position.x),
objective_altitude,
static_cast<double>(position.y)};
for (auto it = objective_positions.begin();it!=objective_positions.end();++it)
{
if (objective == *it)
{
objective_positions.erase(it);
return true;
}
}
return false;
}

47
src/Maze.h Normal file
View file

@ -0,0 +1,47 @@
//
// Created by trotfunky on 04/11/2019.
//
#ifndef LABYRINTHE_MAZE_H
#define LABYRINTHE_MAZE_H
#include <string>
#include <vector>
#include <DataHandling/Texture.h>
#include <DataHandling/Model3D.h>
#include "TileTypes.h"
class Maze {
public:
Maze(const std::string& maze_map, unsigned int scaling_factor, const Texture& floor_texture,
const Texture& wall_texture, const Texture& outside_texture, Model3D& objective);
void draw();
bool remove_objective(const Vec2i& position);
unsigned int scaling_factor;
Texture map;
private:
const Texture& floor;
const Texture& wall;
const Texture& out;
Model3D& objective;
const double objective_altitude = 0;
const double wall_height = 2;
unsigned corner_pos;
Vec3d outside_position;
std::vector<Vec3d> objective_positions;
// FIXME : Draw only border walls...
std::vector<Vec3d> wall_positions;
void preapre_display_list();
};
#endif //LABYRINTHE_MAZE_H

View file

@ -38,7 +38,7 @@ void constrained_translation(const Vec3d& translation, Camera& camera, const Tex
camera.local_translate({0,0,translation.z}); camera.local_translate({0,0,translation.z});
} }
if (current_map_colour(camera.get_eyepos(), map, pixel_scale) == wall) if (current_map_colour(camera.get_eyepos(), map, pixel_scale) == Tiles::wall)
{ {
// If we are going into a wall, revert // If we are going into a wall, revert
camera.set_position(original_position); camera.set_position(original_position);

View file

@ -7,9 +7,12 @@
#include "Math/Vectors.h" #include "Math/Vectors.h"
namespace Tiles
{
static const Vec3i path{255,255,255}; static const Vec3i path{255,255,255};
static const Vec3i wall{0,0,0}; static const Vec3i wall{0,0,0};
static const Vec3i end{0,255,0}; static const Vec3i end{0,255,0};
static const Vec3i objective{0,0,255}; static const Vec3i objective{0,0,255};
}
#endif //LABYRINTHE_TILETYPES_H #endif //LABYRINTHE_TILETYPES_H

View file

@ -6,9 +6,19 @@
#include "DataHandling/Texture.h" #include "DataHandling/Texture.h"
#include "MovementManager.h" #include "MovementManager.h"
#include "TileTypes.h" #include "TileTypes.h"
#include "Maze.h"
static Texture map; static int score = 0;
static constexpr float horizontal_speed = 0.05;
static Texture ground;
static Texture wall;
static Texture out;
static Texture raptor;
static Model3D raptor_model;
static Maze* maze;
static constexpr float horizontal_speed = 0.15;
static constexpr int units_per_pixel = 2; static constexpr int units_per_pixel = 2;
static constexpr int map_side = 32; static constexpr int map_side = 32;
static constexpr int corner_pos = (map_side*units_per_pixel); static constexpr int corner_pos = (map_side*units_per_pixel);
@ -23,7 +33,6 @@ void manage_inputs()
Vec3d translation{0,0,0}; Vec3d translation{0,0,0};
// TODO : camera_translate function in MovementManager that handles both the correct translation and rollback.
if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT)) if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT))
{ {
translation.z += horizontal_speed; translation.z += horizontal_speed;
@ -42,15 +51,24 @@ void manage_inputs()
translation.x -= horizontal_speed; translation.x -= horizontal_speed;
} }
constrained_translation(translation,OGLE::camera,map,units_per_pixel); constrained_translation(translation,OGLE::camera,maze->map,units_per_pixel);
Vec3i map_colour = current_map_colour(OGLE::camera.get_eyepos(), map, units_per_pixel); Vec3i map_colour = current_map_colour(OGLE::camera.get_eyepos(),maze->map, units_per_pixel);
if (map_colour == end) if (map_colour == Tiles::end)
{ {
std::cout << "Success !" << std::endl; std::cout << "Success !" << std::endl;
std::cout << "You managed to collect " << score << " raptors!" << std::endl;
glutDestroyWindow(glutGetWindow()); glutDestroyWindow(glutGetWindow());
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
else if(map_colour == Tiles::objective)
{
if (maze->remove_objective({static_cast<int>(OGLE::camera.get_eyepos().x/maze->scaling_factor),
static_cast<int>(OGLE::camera.get_eyepos().z/maze->scaling_factor)}))
{
score += 1;
}
}
Vec2i mouse_delta = InputStatus::get_mouse_delta(true); Vec2i mouse_delta = InputStatus::get_mouse_delta(true);
if (mouse_delta.x != 0 || mouse_delta.y != 0) if (mouse_delta.x != 0 || mouse_delta.y != 0)
@ -65,43 +83,29 @@ void display()
{ {
manage_inputs(); manage_inputs();
glEnable(GL_ALPHA_TEST); maze->draw();
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glBindTexture(GL_TEXTURE_2D,map.opengl_id[0]);
// Deactivate interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glColor4f(1.0f, 1.0f, 1.0f,1.00);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex3i(0,0,0);
glTexCoord2d(1,0);
glVertex3i(0,0,corner_pos);
glTexCoord2d(1,1);
glVertex3i(corner_pos,0,corner_pos);
glTexCoord2d(0,1);
glVertex3i(corner_pos,0,0);
glEnd();
glDisable(GL_ALPHA_TEST);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
OGLE::setup(argc,argv,display,"The Labyrinth !"); OGLE::setup(argc,argv,display,"The Labyrinth !");
map.load_rgb_tga("resources/Map.tga"); ground.load_rgb_tga("resources/ground.tga");
wall.load_rgb_tga("resources/wall.tga");
out.load_rgb_tga("resources/Outside.tga");
raptor.load_rgb_tga("resources/raptor.tga");
raptor_model.load_ascii_off_file("resources/raptor.off");
raptor_model.assign_texture(raptor);
raptor_model.set_scaling(0.0025,0.0025,0.0025);
raptor_model.set_rotation(-90,1,0,0);
OGLE::camera.set_position({corner_pos/2,1,corner_pos/2}); OGLE::camera.set_position({corner_pos/2,1,corner_pos/2});
maze = new Maze("resources/Map.tga", 2, ground, wall, out, raptor_model);
// Fill colour is sky blue.
glClearColor(0.53,0.81,0.75,1);
glutMainLoop(); glutMainLoop();
return 0; return 0;
} }