Hello. I’m a game design student and I’m a little bit desperate to get this code working, since I’ve tried getting help from my fellow classmates, with no luck and I’m getting out of time.
Well, I’m supposed to make a very simple Space Invaders game using OpenGL and Visual Studio, in C++.
My main problem is: I have to draw at least 3 elements on screen, but only one is being rendered.
This is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <string.h>
#include <time.h>
#define GL_LOG_FILE "gl.log"
#include <iostream>
#include "gl_utils.h"
//#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
int g_gl_width = 640;
int g_gl_height = 480;
GLFWwindow *g_window = NULL;
int Pos = 10;
float x;
int distanceToPlayer = 0;
int enemyPos = 1;
int enemyDir = 1;
int enemyVel = 60;
int shot = 3;
int points = 0;
int enemyMovement = 0;
bool goDown = false;
glm::mat4 transform(1.0);
glm::mat4 transform2(1.0);
glm::mat4 transform3(1.0);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
static bool gWireframe = 0;
if (key == GLFW_KEY_LEFT && action == GLFW_PRESS)
{
if (Pos > 1)
{
transform = glm::translate(transform, glm::vec3(-0.1, 0.0, 0.0f));
Pos--;
}
}
else if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS)
{
if (Pos < 19)
{
transform = glm::translate(transform, glm::vec3(0.1, 0.0, 0.0f));
Pos++;
}
}
if ((key == GLFW_KEY_SPACE) && action == GLFW_PRESS)
{
shot = 9;
if (Pos == enemyPos)
{
glm::mat4 aux(1.0f);
transform3 = glm::translate(aux, glm::vec3(-0.9f, 0.9f, 0.0f));
enemyPos = 1;
enemyDir = 1;
distanceToPlayer = 0;
goDown = false;
if (enemyVel > 5)
enemyVel -= 5;
else
{
enemyVel--;
}
points += 1;
cout << "Pontos: " << points << endl;
}
}
else { shot = 3; }
}
int main() {
restart_gl_log();
// all the GLFW and GLEW start-up code is moved to here in gl_utils.cpp
start_gl("Space Invaders");
// tell GL to only draw onto a pixel if the shape is closer to the viewer
//glEnable( GL_DEPTH_TEST ); // enable depth-testing
//glDepthFunc( GL_LESS ); // depth-testing interprets a smaller value as "closer"
char vertex_shader[1024 * 256];
char fragment_shader[1024 * 256];
parse_file_into_str("test_vs.glsl", vertex_shader, 1024 * 256);
parse_file_into_str("test_fs.glsl", fragment_shader, 1024 * 256);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
const GLchar *p = (const GLchar *)vertex_shader;
glShaderSource(vs, 1, &p, NULL);
glCompileShader(vs);
// check for compile errors
int params = -1;
glGetShaderiv(vs, GL_COMPILE_STATUS, ¶ms);
if (GL_TRUE != params) {
fprintf(stderr, "ERROR: GL shader index %i did not compile
", vs);
print_shader_info_log(vs);
return 1; // or exit or something
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
p = (const GLchar *)fragment_shader;
glShaderSource(fs, 1, &p, NULL);
glCompileShader(fs);
// check for compile errors
glGetShaderiv(fs, GL_COMPILE_STATUS, ¶ms);
if (GL_TRUE != params) {
fprintf(stderr, "ERROR: GL shader index %i did not compile
", fs);
print_shader_info_log(fs);
return 1; // or exit or something
}
GLuint shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme);
glGetProgramiv(shader_programme, GL_LINK_STATUS, ¶ms);
if (GL_TRUE != params) {
fprintf(stderr, "ERROR: could not link shader programme GL index %i
",
shader_programme);
print_programme_info_log(shader_programme);
return false;
}
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------JOGADOR------------------------------------
float vertices2[] = {
// positions // colors // texture coords
0.08f, 0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // top right
0.08f, -0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // bottom right
-0.08f, -0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.08f, 0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // top left
};
unsigned int indices2[] = {
0, 1, 3, // first triangle
1, 2, 3, // second triangle
};
unsigned int VBO2, VAO2, EBO2;
glGenVertexArrays(1, &VAO2);
glGenBuffers(1, &VBO2);
glGenBuffers(1, &EBO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
////////////////////////////////////////////////////////INIMIGOS///////////////////////////////////////////////////////////
float vertices_Inimigos[] = {
// positions // colors // texture coords
0.08f, 0.08f, 0.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f, // top right
0.08f, -0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // bottom right
-0.08f, -0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.08f, 0.08f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // top left
};
unsigned int indices_Inimigos[] = {
0, 1, 3, // first triangle
1, 2, 3, // second triangle
};
unsigned int VBO1, VAO1, EBO1;
glGenVertexArrays(1, &VAO1);
glGenBuffers(1, &VBO1);
glGenBuffers(1, &EBO1);
glBindVertexArray(VAO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_Inimigos), vertices_Inimigos, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_Inimigos), indices_Inimigos, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// -----------------------TIRO-------------------------------------------
float vertices3[] = {
// positions // colors // texture coords
0.05f, 0.05f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // top right
0.05f, -0.05f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, // bottom right
-0.05f, -0.05f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.05f, 0.05f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // top left
};
unsigned int indices3[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO3, VAO3, EBO3;
glGenVertexArrays(1, &VAO3);
glGenBuffers(1, &VBO3);
glGenBuffers(1, &EBO3);
glBindVertexArray(VAO3);
glBindBuffer(GL_ARRAY_BUFFER, VBO3);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO3);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices3), indices3, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
// load and create a texture
// -------------------------
unsigned int texture1, texture2, texture3;
glUseProgram(shader_programme);
glUniform1i(glGetUniformLocation(shader_programme, "texture1"), 1);
glUniform1i(glGetUniformLocation(shader_programme, "texture2"), 2);
glUniform1i(glGetUniformLocation(shader_programme, "texture3"), 3);
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int width, height, nrChannels;
//stbi_set_flip_vertically_on_load(true);
unsigned char *data = stbi_load("Nave.jpg", &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
// texture 2
// ---------
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
data = stbi_load("Alien.jpg", &width, &height, &nrChannels, 0);
if (data)
{
// note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
// texture 3
// ---------
glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
data = stbi_load("Shot.jpg", &width, &height, &nrChannels, 0);
if (data)
{
// note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
glEnable(GL_CULL_FACE); // cull face
glCullFace(GL_BACK); // cull back face
glFrontFace(GL_CW); // GL_CCW for counter clock-wise
transform = glm::translate(transform, glm::vec3(0.0, -0.85, 0.0f));
transform2 = glm::translate(transform2, glm::vec3(-0.9f, 0.9f, 0.0f));
while (!glfwWindowShouldClose(g_window)) {
// wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSetKeyCallback(g_window, key_callback);
unsigned int transformLoc = glGetUniformLocation(shader_programme, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
glUseProgram(shader_programme);
// bind textures on corresponding texture units and render
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture2);
glBindVertexArray(VAO1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
glBindVertexArray(VAO2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texture3);
glBindVertexArray(VAO3);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
enemyMovement++;
if (enemyMovement >= enemyVel) {
if (goDown == false)
transform2 = glm::translate(transform2, glm::vec3(0.1f*enemyDir, 0.0f, 0.0f));
else {
transform2 = glm::translate(transform2, glm::vec3(0.0f, -0.1f, 0.0f));
distanceToPlayer++;
cout << "Distância: " << distanceToPlayer << endl;
goDown = false;
//17 dies
}
enemyPos += enemyDir;
if ((enemyPos == 19 || enemyPos == 0) && goDown == false) {
enemyDir = -enemyDir;
goDown = true;
}
enemyMovement = 0;
}
glViewport(0, 0, g_gl_width, g_gl_height);
glfwPollEvents();
if (GLFW_PRESS == glfwGetKey(g_window, GLFW_KEY_ESCAPE)) {
glfwSetWindowShouldClose(g_window, 1);
}
// put the stuff we've been drawing onto the display
if (distanceToPlayer == 17) {
glfwSetWindowShouldClose(g_window, 1);
}
glfwSwapBuffers(g_window);
}
// close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
You see, the objects with textures for Alien.jpg and Shot.jpg are not appearing on screen. Only the Player with the Nave.jpg texture is being rendered.