Fixes for rendering and add maze parser
This commit is contained in:
@@ -1,2 +1,6 @@
|
|||||||
# snowland-game
|
# snowland-game
|
||||||
My experiments with go, sdl and opengl.
|
This is a continuation of my [goland-game](https://github.com/five-hundred-eleven/goland-game) project.
|
||||||
|
|
||||||
|
While the previous project was implemented in go, for this project I was not able to get the go bindings for OpenGL working, and so I went with C++.
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void main()
|
|||||||
float specularStrength = 0.5;
|
float specularStrength = 0.5;
|
||||||
vec3 viewDir = normDist;
|
vec3 viewDir = normDist;
|
||||||
vec3 reflectDir = reflect(-lightDir, norm);
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 8);
|
||||||
vec3 specular = specularStrength * spec * lightColor;
|
vec3 specular = specularStrength * spec * lightColor;
|
||||||
|
|
||||||
float dist = distance(viewPos, FragPos);
|
float dist = distance(viewPos, FragPos);
|
||||||
|
|||||||
145
mazeparser.py
Normal file
145
mazeparser.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import matplotlib.image as mpimage
|
||||||
|
|
||||||
|
img = mpimage.imread("/home/cowley/Pictures/maze.png")
|
||||||
|
rows = len(img)
|
||||||
|
cols = len(img[0])
|
||||||
|
|
||||||
|
|
||||||
|
def isfilled(val):
|
||||||
|
return all(x > 0.2 for x in val)
|
||||||
|
|
||||||
|
|
||||||
|
def getval(img, x, y):
|
||||||
|
if y < 0 or y >= len(img):
|
||||||
|
return False
|
||||||
|
if x < 0 or x >= len(img[y]):
|
||||||
|
return False
|
||||||
|
return isfilled(img[y][x])
|
||||||
|
|
||||||
|
|
||||||
|
segments = []
|
||||||
|
for iy in range(-1, rows + 1):
|
||||||
|
seg_start = None
|
||||||
|
for ix in range(-1, cols + 1):
|
||||||
|
if getval(img, ix, iy) and not getval(img, ix, iy - 1):
|
||||||
|
if seg_start is None:
|
||||||
|
seg_start = (ix - 0.5, iy - 0.5)
|
||||||
|
else:
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix - 0.5, iy - 0.5), (0.0, 0.0, 1.0)))
|
||||||
|
seg_start = None
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (cols - 0.5, iy - 0.5), (0.0, 0.0, 1.0)))
|
||||||
|
|
||||||
|
|
||||||
|
for iy in range(-1, rows + 1):
|
||||||
|
seg_start = None
|
||||||
|
for ix in range(-1, cols + 1):
|
||||||
|
if getval(img, ix, iy) and not getval(img, ix, iy + 1):
|
||||||
|
if seg_start is None:
|
||||||
|
seg_start = (ix - 0.5, iy + 0.5)
|
||||||
|
else:
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix - 0.5, iy + 0.5), (0.0, 0.0, -1.0)))
|
||||||
|
seg_start = None
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (cols - 0.5, iy + 0.5), (0.0, 0.0, -1.0)))
|
||||||
|
|
||||||
|
for ix in range(-1, cols + 1):
|
||||||
|
seg_start = None
|
||||||
|
for iy in range(-1, rows + 1):
|
||||||
|
if getval(img, ix, iy) and not getval(img, ix - 1, iy):
|
||||||
|
if seg_start is None:
|
||||||
|
seg_start = (ix - 0.5, iy - 0.5)
|
||||||
|
else:
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix - 0.5, iy - 0.5), (-1.0, 0.0, 0.0)))
|
||||||
|
seg_start = None
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix - 0.5, rows - 0.5), (-1.0, 0.0, 0.0)))
|
||||||
|
|
||||||
|
for ix in range(-1, cols + 1):
|
||||||
|
seg_start = None
|
||||||
|
for iy in range(-1, rows + 1):
|
||||||
|
if getval(img, ix, iy) and not getval(img, ix + 1, iy):
|
||||||
|
if seg_start is None:
|
||||||
|
seg_start = (ix + 0.5, iy - 0.5)
|
||||||
|
else:
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix + 0.5, iy - 0.5), (1.0, 0.0, 0.0)))
|
||||||
|
seg_start = None
|
||||||
|
if seg_start is not None:
|
||||||
|
segments.append((seg_start, (ix + 0.5, rows - 0.5), (1.0, 0.0, 0.0)))
|
||||||
|
|
||||||
|
print(segments[:10])
|
||||||
|
|
||||||
|
res = {}
|
||||||
|
res["players"] = []
|
||||||
|
player = {
|
||||||
|
"y": 2.5,
|
||||||
|
"x": 845.0,
|
||||||
|
"z": -5.0,
|
||||||
|
"yaw": 270.0,
|
||||||
|
}
|
||||||
|
res["players"].append(player)
|
||||||
|
res["surfaces"] = []
|
||||||
|
for segment in segments:
|
||||||
|
p1 = {"x": segment[0][0], "z": -segment[0][1], "y": 0.0}
|
||||||
|
p2 = {
|
||||||
|
"x": segment[1][0],
|
||||||
|
"z": -segment[1][1],
|
||||||
|
"y": 0.0,
|
||||||
|
}
|
||||||
|
p3 = {
|
||||||
|
"x": segment[1][0],
|
||||||
|
"z": -segment[1][1],
|
||||||
|
"y": 5.0,
|
||||||
|
}
|
||||||
|
p4 = {
|
||||||
|
"x": segment[0][0],
|
||||||
|
"z": -segment[0][1],
|
||||||
|
"y": 5.0,
|
||||||
|
}
|
||||||
|
surface = [p1, p2, p3, p4, segment[2]]
|
||||||
|
res["surfaces"].append(surface)
|
||||||
|
|
||||||
|
xmin = 0.0
|
||||||
|
xmax = 0.0
|
||||||
|
zmin = 0.0
|
||||||
|
zmax = 0.0
|
||||||
|
|
||||||
|
with open("maze.txt", "w") as f:
|
||||||
|
f.write(f"{player['x']} {player['y']} {player['z']} {player['yaw']}\n")
|
||||||
|
f.write(f"{len(res['surfaces'])}\n")
|
||||||
|
for segment in res["surfaces"]:
|
||||||
|
for point in segment[:4]:
|
||||||
|
if point["x"] < xmin:
|
||||||
|
xmin = point["x"]
|
||||||
|
if point["x"] > xmax:
|
||||||
|
xmax = point["x"]
|
||||||
|
if point["z"] < zmin:
|
||||||
|
zmin = point["z"]
|
||||||
|
if point["z"] > zmax:
|
||||||
|
zmax = point["x"]
|
||||||
|
point = segment[0]
|
||||||
|
norm = f"{segment[4][0]} {segment[4][1]} {segment[4][2]}"
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
point = segment[1]
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
point = segment[2]
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
point = segment[3]
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
point = segment[2]
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
point = segment[0]
|
||||||
|
f.write(f"{point['x']} {point['y']} {point['z']} {norm}\n")
|
||||||
|
f.write("\n")
|
||||||
|
f.write(f"{xmin} 0.0 {zmin} 0.0 1.0 0.0\n")
|
||||||
|
f.write(f"{xmax} 0.0 {zmin} 0.0 1.0 0.0\n")
|
||||||
|
f.write(f"{xmin} 0.0 {zmax} 0.0 1.0 0.0\n")
|
||||||
|
f.write(f"{xmax} 0.0 {zmax} 0.0 1.0 0.0\n")
|
||||||
|
f.write(f"{xmin} 0.0 {zmax} 0.0 1.0 0.0\n")
|
||||||
|
f.write(f"{xmax} 0.0 {zmin} 0.0 1.0 0.0\n")
|
||||||
77
snowland.cpp
77
snowland.cpp
@@ -22,8 +22,8 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
|||||||
void processInput(GLFWwindow *window);
|
void processInput(GLFWwindow *window);
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
const unsigned int WINDOWWIDTH = 1280;
|
const unsigned int WINDOWWIDTH = 1600;
|
||||||
const unsigned int WINDOWHEIGHT = 720;
|
const unsigned int WINDOWHEIGHT = 900;
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
glm::vec3 player_pos = glm::vec3(0.0f, 0.0f, 3.0f);
|
glm::vec3 player_pos = glm::vec3(0.0f, 0.0f, 3.0f);
|
||||||
@@ -31,7 +31,7 @@ glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f);
|
|||||||
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
|
glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
bool first_mouse = true;
|
bool first_mouse = true;
|
||||||
float yaw = -90.0f;
|
float yaw = 0.0f;
|
||||||
float pitch = 0.0f;
|
float pitch = 0.0f;
|
||||||
float lastX = WINDOWWIDTH / 2.0;
|
float lastX = WINDOWWIDTH / 2.0;
|
||||||
float lastY = WINDOWHEIGHT / 2.0;
|
float lastY = WINDOWHEIGHT / 2.0;
|
||||||
@@ -49,6 +49,7 @@ const char *modelC = "model";
|
|||||||
const char *viewposC = "viewPos";
|
const char *viewposC = "viewPos";
|
||||||
const char *lightcolorC = "lightColor";
|
const char *lightcolorC = "lightColor";
|
||||||
const char *objectcolorC = "objectColor";
|
const char *objectcolorC = "objectColor";
|
||||||
|
const char *lightstrengthC = "lightStrength";
|
||||||
|
|
||||||
int num_walls;
|
int num_walls;
|
||||||
float *wall_vertices;
|
float *wall_vertices;
|
||||||
@@ -74,7 +75,7 @@ glm::vec3 checkIntersection(glm::vec3 movement) {
|
|||||||
glm::vec3 vec_start, vec_stop, p1, p2, p3, res;
|
glm::vec3 vec_start, vec_stop, p1, p2, p3, res;
|
||||||
int gotX = 0, gotZ = 0;
|
int gotX = 0, gotZ = 0;
|
||||||
vec_start = player_pos;
|
vec_start = player_pos;
|
||||||
vec_stop = vec_start + movement * 10.0f;
|
vec_stop = vec_start + movement * 20.0f;
|
||||||
res.x = movement.x;
|
res.x = movement.x;
|
||||||
res.y = movement.y;
|
res.y = movement.y;
|
||||||
res.z = movement.z;
|
res.z = movement.z;
|
||||||
@@ -119,7 +120,7 @@ int main()
|
|||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(WINDOWWIDTH, WINDOWHEIGHT, "LearnOpenGL", NULL, NULL);
|
GLFWwindow* window = glfwCreateWindow(WINDOWWIDTH, WINDOWHEIGHT, "Snowland!", NULL, NULL);
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
{
|
{
|
||||||
printf("Failed to create GLFW window.\n");
|
printf("Failed to create GLFW window.\n");
|
||||||
@@ -198,15 +199,28 @@ int main()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int program = glCreateProgram();
|
int wall_program = glCreateProgram();
|
||||||
glAttachShader(program, vertex_shader);
|
glAttachShader(wall_program, vertex_shader);
|
||||||
glAttachShader(program, fragment_shader);
|
glAttachShader(wall_program, fragment_shader);
|
||||||
glLinkProgram(program);
|
glLinkProgram(wall_program);
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
glGetProgramiv(wall_program, GL_LINK_STATUS, &success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
char infoLog[1024];
|
char infoLog[1024];
|
||||||
glGetProgramInfoLog(program, 1024, NULL, infoLog);
|
glGetProgramInfoLog(wall_program, 1024, NULL, infoLog);
|
||||||
printf("Shader program link error: %s\n", infoLog);
|
printf("Shader wall_program link error: %s\n", infoLog);
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int floor_program = glCreateProgram();
|
||||||
|
glAttachShader(floor_program, vertex_shader);
|
||||||
|
glAttachShader(floor_program, fragment_shader);
|
||||||
|
glLinkProgram(floor_program);
|
||||||
|
glGetProgramiv(floor_program, GL_LINK_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
char infoLog[1024];
|
||||||
|
glGetProgramInfoLog(floor_program, 1024, NULL, infoLog);
|
||||||
|
printf("Shader floor_program link error: %s\n", infoLog);
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -221,9 +235,8 @@ int main()
|
|||||||
fscanf(fp, "%f %f %f %f\n", &player_pos.x, &player_pos.y, &player_pos.z, &yaw);
|
fscanf(fp, "%f %f %f %f\n", &player_pos.x, &player_pos.y, &player_pos.z, &yaw);
|
||||||
fscanf(fp, "%d\n", &num_walls);
|
fscanf(fp, "%d\n", &num_walls);
|
||||||
// num surfaces * 6 (vertices per point) * 6 (floats per point)
|
// num surfaces * 6 (vertices per point) * 6 (floats per point)
|
||||||
// add 1 for floor
|
int num_wall_vertices = num_walls * 6 * 6;
|
||||||
int num_walls = (num_walls) * 6 * 6;
|
wall_vertices = (float *)calloc(sizeof(float), num_wall_vertices);
|
||||||
wall_vertices = (float *)calloc(sizeof(float), num_walls * 6 * 6);
|
|
||||||
// read walls
|
// read walls
|
||||||
for (int i = 0; i < num_walls; i++) {
|
for (int i = 0; i < num_walls; i++) {
|
||||||
for (int j = 0; j < 6; j++) {
|
for (int j = 0; j < 6; j++) {
|
||||||
@@ -266,7 +279,7 @@ int main()
|
|||||||
glBindVertexArray(wallsVAO);
|
glBindVertexArray(wallsVAO);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, wallsVBO);
|
glBindBuffer(GL_ARRAY_BUFFER, wallsVBO);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_walls, wall_vertices, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_wall_vertices, wall_vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
// position attribute
|
// position attribute
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
|
||||||
@@ -314,30 +327,40 @@ int main()
|
|||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
glUseProgram(program);
|
glUseProgram(wall_program);
|
||||||
|
|
||||||
glm::mat4 projection = glm::perspective(glm::radians(fov), (float)WINDOWWIDTH / (float)WINDOWHEIGHT, 0.1f, 256.0f);
|
glm::mat4 projection = glm::perspective(glm::radians(fov), (float)WINDOWWIDTH / (float)WINDOWHEIGHT, 0.1f, 256.0f);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(program, projectionC), 1, GL_FALSE, &projection[0][0]);
|
glUniformMatrix4fv(glGetUniformLocation(wall_program, projectionC), 1, GL_FALSE, &projection[0][0]);
|
||||||
|
|
||||||
glm::mat4 view = glm::lookAt(player_pos, player_pos + camera_front, camera_up);
|
glm::mat4 view = glm::lookAt(player_pos, player_pos + camera_front, camera_up);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(program, viewC), 1, GL_FALSE, &view[0][0]);
|
glUniformMatrix4fv(glGetUniformLocation(wall_program, viewC), 1, GL_FALSE, &view[0][0]);
|
||||||
|
|
||||||
glm::vec3 wall_color = glm::vec3(0.5f, 0.5f, 0.5f);
|
glm::vec3 wall_color = glm::vec3(0.61f, 0.6f, 0.59f);
|
||||||
glUniform3fv(glGetUniformLocation(program, objectcolorC), 1, &wall_color[0]);
|
glUniform3fv(glGetUniformLocation(wall_program, objectcolorC), 1, &wall_color[0]);
|
||||||
|
|
||||||
glm::vec3 light_color = glm::vec3(1.0f, 1.0f, 1.0f);
|
glm::vec3 light_color = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
glUniform3fv(glGetUniformLocation(program, lightcolorC), 1, &light_color[0]);
|
glUniform3fv(glGetUniformLocation(wall_program, lightcolorC), 1, &light_color[0]);
|
||||||
|
|
||||||
glUniform3fv(glGetUniformLocation(program, viewposC), 1, &player_pos[0]);
|
glUniform3fv(glGetUniformLocation(wall_program, viewposC), 1, &player_pos[0]);
|
||||||
|
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(program, modelC), 1, GL_FALSE, &model[0][0]);
|
glUniformMatrix4fv(glGetUniformLocation(wall_program, modelC), 1, GL_FALSE, &model[0][0]);
|
||||||
|
|
||||||
glBindVertexArray(wallsVAO);
|
glBindVertexArray(wallsVAO);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, num_walls);
|
glDrawArrays(GL_TRIANGLES, 0, num_wall_vertices);
|
||||||
|
|
||||||
glm::vec3 floor_color = glm::vec3(0.0f, 0.0f, 0.0f);
|
glUseProgram(floor_program);
|
||||||
glUniform3fv(glGetUniformLocation(program, objectcolorC), 1, &floor_color[0]);
|
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(floor_program, projectionC), 1, GL_FALSE, &projection[0][0]);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(floor_program, viewC), 1, GL_FALSE, &view[0][0]);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(floor_program, modelC), 1, GL_FALSE, &model[0][0]);
|
||||||
|
glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &player_pos[0]);
|
||||||
|
|
||||||
|
glm::vec3 floor_color = glm::vec3(0.11f, 0.1f, 0.09f);
|
||||||
|
glUniform3fv(glGetUniformLocation(floor_program, objectcolorC), 1, &floor_color[0]);
|
||||||
|
|
||||||
|
glm::vec3 floor_light_color = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
glUniform3fv(glGetUniformLocation(floor_program, lightcolorC), 1, &floor_light_color[0]);
|
||||||
|
|
||||||
glBindVertexArray(floorVAO);
|
glBindVertexArray(floorVAO);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6 * 6 * 1);
|
glDrawArrays(GL_TRIANGLES, 0, 6 * 6 * 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user