Get object position

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. :smiley:
Thank you!

separate the 3 main steps in the main loop:

  1. processing input (key input, mouse input, etc)
  2. update the scene (advance snake, check if food / wall collides with snake)
  3. processing output (draw graphics)

each step can be done in a separate class, they only have to share the (struct) scene / world

Hey John,

Thank you for your reply.I studied opengl from that website.The problem is that I still don’t want to complicate with separeteing the code because I don’t have the experience for this yet.The owner of the website (Joey) adviced me to do the things how I can and in time to modify it.So all I asked for is just to know how I can get the 2 positions of the objects.

I don’t know if this helps, but the last column (or is it the last row) in the object’s model/world matrix is it’s position as a 4D vector. You can throw away the w value.

Sorry BBeck1, I don’t understand what do you mean.:slight_smile:
Maybe you can show me in the code.

See this discussion but it’s easier because you have to invert the camera matrix. You don’t even have to do that for an object’s matrix. You just grab the fourth column (numbering from 0) and you’re done.

Great, thank you very much BBeck1. I think I know how to do it. :smiley:

So, I thought I understood what BBeck1 said, but I didn’t. Anyway I tried to find another way and this is what I did, but it doesn’t work.


#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 checkMovement();
void checkCollision(GLfloat xoffset, GLfloat yoffset, GLfloat &xfruitPos, GLfloat &yfruitPos);

// Window Dimensions
const GLuint screenWidth = 1000, screenHeight = 800;

bool keys[1024];


GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;



bool up = true;
bool left = false;
bool right = false;
bool down = false;

glm::vec3 cameraPos(0.0f, 0.0f, 6.0f);

GLfloat sensitivity = 0.0001f;
GLfloat xoffset = 0.0f;
GLfloat yoffset = 0.0f;
GLfloat xfruitPos = 0.0002f;
GLfloat yfruitPos = 0.0002f;

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;
		glm::mat4 view;
		glm::mat4 proj;

		view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
		proj = glm::perspective(45.0f, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
		model = glm::translate(model, glm::vec3(0.0f, 0.0f, 3.0f));
		model = glm::scale(model, glm::vec3(4.0f, 4.0f, 4.0f));
		GLint modelLoc = glGetUniformLocation(headShader.Program, "model");
		GLint viewLoc = glGetUniformLocation(headShader.Program, "view");
		GLint projLoc = glGetUniformLocation(headShader.Program, "projection");
		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));

		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(xfruitPos, yfruitPos, 0.0f));
		model = glm::scale(model, glm::vec3(0.25f, 0.25f, 0.25f));
		modelLoc = glGetUniformLocation(headShader.Program, "model");
		viewLoc = glGetUniformLocation(headShader.Program, "view");
		projLoc = glGetUniformLocation(headShader.Program, "projection");
		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
	
		

		glBindVertexArray(FRUIT);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		glBindVertexArray(0);

		checkCollision(xoffset, yoffset, xfruitPos, yfruitPos);
		//HEAD SHADER PROGRAM
		headShader.Use();

		// MODEL MATRIX
		model = glm::mat4();
		model = glm::translate(model, glm::vec3(xoffset, yoffset, 0.0f));
		model = glm::scale(model, glm::vec3(0.25f, 0.25f, 0.25f));
		modelLoc = glGetUniformLocation(headShader.Program, "model");
		viewLoc = glGetUniformLocation(headShader.Program, "view");
		projLoc = glGetUniformLocation(headShader.Program, "projection");
		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));

		glBindTexture(GL_TEXTURE_2D, headTexture);
		glUniform1i(glGetUniformLocation(headShader.Program, "ourTexture"), 0);
		glBindVertexArray(HEAD);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		glBindVertexArray(0);

		checkMovement();


		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;
		if (yoffset == 1.0f)
		{
			std::cout << "DONE" << std::endl;
		}
	}
	if (down)
	{
		yoffset -= sensitivity;
		if (yoffset == 1.0f)
		{
			std::cout << "DONE" << std::endl;
		}
	}
	if (right)
	{
		xoffset += sensitivity;
		if (xoffset == 1.0f)
		{
			std::cout << "DONE" << std::endl;
		}
	}
	if (left)
	{
		xoffset -= sensitivity;
		if (xoffset == 1.0f)
		{
			std::cout << "DONE" << std::endl;
		}
	}
	std::cout << std::endl;
}

void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	
}

void checkCollision(GLfloat xoffset, GLfloat yoffset, GLfloat &xfruitPos, GLfloat &yfruitPos)
{
	if ((xoffset == xfruitPos) && (yoffset == yfruitPos))
	{
		xfruitPos++;
		std::cout << "fruitPos.X: " << xfruitPos << std::endl;
		yfruitPos++;
		std::cout << "fruitPos.Y: " << yfruitPos << std::endl;
		std::cout << std::endl;
	}
}

If I give the initial positions to fruit and snake the same, and I calculate if they are equal, is generating the fruit in another position(so it works).But when I move with the snake on fruit’s new position it doesn’t work anymore.Where I am wrong ? It’s because the floating values or … ?
I would be very happy if somebody can help me.
Thank you!

I’m saying it should be:

Position = (glm::vec3) model[3];

where Position is a position in 3D space as a 3D vector.

It looks like you may be doing 2D drawing quads. That could in theory throw things slightly off. For example, you might actually use a z depth between -1 and 1 for layering rather than actual 3D depth.

It looks like your code changed pretty significantly between the first and last post. Specifically, I don’t see where you were using a view or projection matrix in your first post.

If you are trying to do 2D, you should probably be using an orthographic projection matrix rather than a perspective projection matrix.

Also, with modern OGL, it seems to me that you are better off learning 3D game programming before attempting 2D game programming. Having some sort of 2D library may make starting with 2D much more simple, but raw modern OGL, I think makes learning 2D more difficult than learning 3D. That’s because 2D in modern OGL (or DirectX) is actually done in 3D and if you don’t understand how to do 3D programming you will be doing it without understanding it while attempting to do 2D.

You need to get comfortable with vertex buffers, index buffers, and especially with working with matrices including the view, projection, and model matrices of the models.

And I’m not that good at answering 2D questions, because I never really did 2D. I mean I’ve done a few programs here and there and even started in 2D many many years ago when I first started programming as a kid. But I’ve never done anything in 2D with OGL. In fact, I don’t think I ever did anything in DirectX in 2D either. I think the last 2D I did other than Unity was in XNA. And XNA has a built in sprite class where it obfuscates the fact that you are actually drawing in 3D with the 2D sprites.

I used to think you had to learn 2D before learning 3D. But as soon as I figured out how to do 3D, I immediately abandoned 2D and never looked back. So, the reality is that I never spent much time doing 2D and what little I did was long before I got into OGL, DX, or XNA. And it’s never caused me a problem except when trying to answer questions about how 2D game programmers do things.

Anyway, without the view and projection matrices, you are working in Normalized Device Coordinates which are a bit funky in my opinion. With that the center of the screen becomes 0,0 and the right side of the screen is 100% represented by 1 and the left side of the screen is -100% represented by -1. So, that could have factored into the problem originally.

And in 2D, I would not be opposed to keeping the position of the object as a duple outside of the matrix, such as keeping it in a vec2. And then you could build the matrix each frame from that value and know what the position is. It’s probably not the way I would prefer to see it done, but if it helps you get started, I say go for it. Just don’t do that in 3D. When you really get to working in 3D, storing the position and orientation outside of the object’s model matrix is a huge “no no” as a general rule. It will certainly produce gimbal lock. But on a 2D plane, there is no such thing as gimbal lock. So, it’s only a 3D problem.

Thank you for your reply.

In the first post I didn’t use projection and view matrices, but I’ve changed my mind because I thought this would be more easy.
I tried also to use orthographic projection but, I don’t know why it doesn’t display anything(I’ve changed also the multiplication in vertex shader).
I don’t know what else shall I do, but I don’t wanna quit making the game. :smiley:

Hi,

Me again. :smiley:
So, because I didn’t listen to you guys and I wanted to do the things how I thought there were more easy for me:p, I finally managed to make it work.So I’m posting here so other people can know where was my problem.
The problem was because of the floating variables(the debugger helped me a lot).So I’ve changed the code:


if ((xoffset == xfruitPos) && (yoffset == yfruitPos))

to:


if ((GLint)(xoffset) == (GLint)(xfruitPos) && (GLint)(yoffset) == (GLint)(yfruitPos))

Now I have to make a few changes, maybe to sensitivity to multiply by deltaTime etc. and after to randomly position the fruit and grow the bloody snake.:smiley:
Anyway, thank you very much guys for your support.:slight_smile:
Good luck at coding!