Compare commits

..

3 commits

Author SHA1 Message Date
648548693d Cleaned static variables now part of the maze 2019-11-04 04:00:56 +01:00
24ff555e88 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.
2019-11-04 03:05:37 +01:00
888e8bd7f5 Added a function to manage movement inside the maze.
Added goal and objective to the test maze.
2019-11-04 00:12:43 +01:00
14 changed files with 31498 additions and 60 deletions

View file

@ -21,7 +21,10 @@ find_package(GLUT REQUIRED)
add_executable(game
src/main.cpp
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
${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.
Code quality is quite poor on this project as it has been rushed.
## Building
### Dependencies
- OpenGL
- Glut
- 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

Before After
Before After

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

@ -4,7 +4,7 @@
#include "MovementManager.h"
Vec3i current_map_colour(const Vec3d& world_pos, const Texture& texture, const int& pixel_scale)
Vec3i current_map_colour(const Vec3d& world_pos, const Texture& texture, const unsigned int& pixel_scale)
{
Vec2i map_pos{static_cast<int>(world_pos.x/pixel_scale),
static_cast<int>(world_pos.z/pixel_scale)};
@ -15,3 +15,32 @@ Vec3i current_map_colour(const Vec3d& world_pos, const Texture& texture, const i
texture.image_data[data_index+1],
texture.image_data[data_index+2]};
}
void constrained_translation(const Vec3d& translation, Camera& camera, const Texture& map, const unsigned int& pixel_scale)
{
Vec3d original_position = camera.get_eyepos();
Vec3d forward_direction = camera.get_gaze();
forward_direction.y = 0;
forward_direction.normalize();
// Forward and up movements are global, disconnects with viewing pitch.
if (translation.x != 0 || translation.y != 0)
{
forward_direction = forward_direction * translation.x;
forward_direction.y = translation.y;
camera.translate(forward_direction);
}
// Strafing movement is relative local.
if (translation.z != 0)
{
camera.local_translate({0,0,translation.z});
}
if (current_map_colour(camera.get_eyepos(), map, pixel_scale) == Tiles::wall)
{
// If we are going into a wall, revert
camera.set_position(original_position);
}
}

View file

@ -7,9 +7,15 @@
#include <Math/Vectors.h>
#include <DataHandling/Texture.h>
#include <Camera.h>
#include "TileTypes.h"
/// Returns the colour of the pixel corresponding to the current world position, assuming the map starts at (0,0).
Vec3i current_map_colour(const Vec3d& world_pos, const Texture& texture, const int& pixel_scale);
Vec3i current_map_colour(const Vec3d& world_pos, const Texture& texture, const unsigned int& pixel_scale);
/// Translates the camera inside the maze and check for collisions
/// \param translation Translation that will be executed in the horizontal plane, x forward, z strafe.
void constrained_translation(const Vec3d& translation, Camera& camera, const Texture& map, const unsigned int& pixel_scale);
#endif //LABYRINTHE_MOVEMENTMANAGER_H

View file

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

View file

@ -2,16 +2,22 @@
// Created by trotFunky on 03/11/2019.
//
#include "Engine.h"
#include <Engine.h>
#include "DataHandling/Texture.h"
#include "MovementManager.h"
#include "TileTypes.h"
#include "Maze.h"
static Texture map;
static constexpr float horizontal_speed = 0.025;
static constexpr int units_per_pixel = 2;
static constexpr int map_side = 32;
static constexpr int corner_pos = (map_side*units_per_pixel);
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 int score = 0;
void manage_inputs()
{
@ -21,43 +27,44 @@ void manage_inputs()
exit(EXIT_SUCCESS);
}
Vec3d horizontal_movement = OGLE::camera.get_gaze();
horizontal_movement.y = 0;
horizontal_movement.normalize();
Vec3d translation{0,0,0};
Vec3d previous_camera_position = OGLE::camera.get_eyepos();
// TODO : camera_translate function in MovementManager that handles both the correct translation and rollback.
if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT))
{
OGLE::camera.local_translate({0, 0, horizontal_speed});
translation.z += horizontal_speed;
}
if (InputStatus::is_special_key_pressed(GLUT_KEY_LEFT))
{
OGLE::camera.local_translate({0, 0, -horizontal_speed});
translation.z -= horizontal_speed;
}
if (InputStatus::is_special_key_pressed(GLUT_KEY_UP))
{
OGLE::camera.translate(horizontal_movement * horizontal_speed);
translation.x += horizontal_speed;
}
if (InputStatus::is_special_key_pressed(GLUT_KEY_DOWN))
{
OGLE::camera.translate(horizontal_movement * -horizontal_speed);
translation.x -= horizontal_speed;
}
Vec3i map_colour = current_map_colour(OGLE::camera.get_eyepos(), map, units_per_pixel);
if (map_colour == wall)
{
// If we are going into a wall, revert
OGLE::camera.set_position(previous_camera_position);
}
else if (map_colour == end)
constrained_translation(translation,OGLE::camera,maze->map,maze->scaling_factor);
Vec3i map_colour = current_map_colour(OGLE::camera.get_eyepos(),maze->map, maze->scaling_factor);
if (map_colour == Tiles::end)
{
std::cout << "Success !" << std::endl;
std::cout << "You managed to collect " << score << " raptors!" << std::endl;
glutDestroyWindow(glutGetWindow());
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);
if (mouse_delta.x != 0 || mouse_delta.y != 0)
@ -72,42 +79,30 @@ void display()
{
manage_inputs();
glEnable(GL_ALPHA_TEST);
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);
maze->draw();
}
int main(int argc, char** argv)
{
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});
maze = new Maze("resources/Map.tga", 2, ground, wall, out, raptor_model);
OGLE::camera.set_position({static_cast<double>(maze->map.width*maze->scaling_factor/2.0),
1,
static_cast<double>(maze->map.width*maze->scaling_factor/2.0)});
// Fill colour is sky blue.
glClearColor(0.53,0.81,0.75,1);
glutMainLoop();
return 0;