Hi,
I want to try to make snake game in opengl, but I’m stucked where I have to detect if the head is in the same place with the fruit.I don’t know how to get the them position.Here is my code:
#include <iostream>
//GLEW
#define GLEW_STATIC
#include<glew.h>
//GLFW
#include <glfw3.h>
#include <SOIL.h>
#include "Shader.h"
// GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Functions prototype
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void generateCube();
void checkMovement();
GLfloat sensitivity = 0.3f;
// Window Dimensions
const GLuint screenWidth = 1000, screenHeight = 800;
bool keys[1024];
GLfloat xoffset = 0.0f;
GLfloat yoffset = 0.0f;
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
bool up = true;
bool left = false;
bool right = false;
bool down = false;
int main()
{
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
// GLFW init
glfwInit();
// Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a GLFWWindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "Snake OpenGL", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
}
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
glewInit();
// Initialize GLEW to setup the OpenGL Function pointers
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
int width, height;
glfwGetFramebufferSize(window, &width, &height);
// Define the viewport dimensions
glViewport(0, 0, screenWidth, screenHeight);
Shader headShader("headShader.vs", "headShader.frag");
Shader groundShader("headShader.vs", "groundShader.frag");
Shader fruitShader("headShader.vs", "fruitShader.frag");
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f
};
GLuint indices[] = {
0, 1, 3,
1, 2, 3
};
GLuint headTexture, groundTexture;
GLuint VBO, HEAD, EBO, GROUND, FRUIT;
glGenVertexArrays(1, &HEAD);
glGenVertexArrays(1, &GROUND);
glGenVertexArrays(1, &FRUIT);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// HEAD VAO
glBindVertexArray(HEAD);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Set the vertex attrib pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Set the texture attrib pointers
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Head texture========================================
glGenTextures(1, &headTexture);
glBindTexture(GL_TEXTURE_2D, headTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int imgWidth, imgHeight;
unsigned char* image = SOIL_load_image("images/metal.png", &imgWidth, &imgHeight, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
//GROUND VAO============================================================
glBindVertexArray(GROUND);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Set the vertex attrib pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Set the texture attrib pointers
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Ground texture==================================================
glGenTextures(1, &groundTexture);
glBindTexture(GL_TEXTURE_2D, groundTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
image = SOIL_load_image("images/ground.jpg", &imgWidth, &imgHeight, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
// FRUIT VAO
glBindVertexArray(FRUIT);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Set the vertex attrib pointers
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
// Game Loop
while (!glfwWindowShouldClose(window))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
//Check if any events have been activated(key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
// Render
// Clear the color buffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Ground SHADER PROGRAM
groundShader.Use();
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f));
GLint modelLoc = glGetUniformLocation(headShader.Program, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glBindTexture(GL_TEXTURE_2D, groundTexture);
glUniform1i(glGetUniformLocation(groundShader.Program, "groundTexture"), 0);
glBindVertexArray(GROUND);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//FRUIT SHADER PROGRAM
fruitShader.Use();
model = glm::mat4();
model = glm::translate(model, glm::vec3((GLfloat)(rand() % 1), (GLfloat)(rand() % 1), 0.0f));
model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(FRUIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//HEAD SHADER PROGRAM
headShader.Use();
// MODEL MATRIX
model = glm::mat4();
model = glm::translate(model, glm::vec3(xoffset, yoffset, -1.0f));
//model = glm::rotate(model, glm::radians(-50.0f), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.1, 0.1, 0.1));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
checkMovement();
glBindTexture(GL_TEXTURE_2D, headTexture);
glUniform1i(glGetUniformLocation(headShader.Program, "ourTexture"), 0);
glBindVertexArray(HEAD);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &HEAD);
glDeleteVertexArrays(1, &GROUND);
glDeleteVertexArrays(1, &FRUIT);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();
return 0;
}
void key_callback(GLFWwindow *window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
/* if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
keys[key] = true;
else if (action == GLFW_RELEASE)
keys[key] = false;
}
*/
if (key == GLFW_KEY_W && action == GLFW_PRESS)
{
up = true;
down = false;
left = false;
right = false;
}
if (key == GLFW_KEY_S && action == GLFW_PRESS)
{
up = false;
down = true;
left = false;
right = false;
}
if (key == GLFW_KEY_D && action == GLFW_PRESS)
{
up = false;
down = false;
left = false;
right = true;
}
if (key == GLFW_KEY_A && action == GLFW_PRESS)
{
up = false;
down = false;
left = true;
right = false;
}
}
void checkMovement()
{
if (up)
{
yoffset += sensitivity * deltaTime;
}
if (down)
{
yoffset -= sensitivity * deltaTime;
}
if (right)
{
xoffset += sensitivity * deltaTime;
}
if (left)
{
xoffset -= sensitivity * deltaTime;
}
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
}
It is possible to take the positions from the vertex shader and calculate them in the game loop ?Or if you can give me some suggestions.
P.S: I know the code is ugly but I’m a beginner.
Thank you!