How to use b2Draw with SDL2? DrawSegment is not called - c++

I expect to see hello in the console:
DebugDrawer.cpp
#include "DebugDrawer.h"
#include <iostream>
DebugDrawer::DebugDrawer()
{
}
void DebugDrawer::DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color)
{
std::cout << "hello" << std::endl;
}
void DebugDrawer::DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { }
void DebugDrawer::DrawPolygon(const b2Vec2 *vertices, int32 vertexCount, const b2Color &color) { }
void DebugDrawer::DrawPoint(const b2Vec2 &p, float size, const b2Color &color) { }
void DebugDrawer::DrawCircle(const b2Vec2 &center, float radius, const b2Color &color) { }
void DebugDrawer::DrawSolidCircle(const b2Vec2 &center, float radius, const b2Vec2 &axis, const b2Color &color) { }
void DebugDrawer::DrawTransform(const b2Transform &xf) { }
I inherited from the b2Draw and overloaded the methods:
DebugDrawer.h
#ifndef DEBUGDRAWER_H
#define DEBUGDRAWER_H
#include "box2d/b2_draw.h"
class DebugDrawer : public b2Draw
{
public:
DebugDrawer();
private:
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawPoint (const b2Vec2 &p, float size, const b2Color &color);
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawCircle(const b2Vec2& center, float radius, const b2Color& color);
void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color);
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
};
#endif // DEBUGDRAWER_H
I created an object with the box shape:
b2PolygonShape shape;
shape.SetAsBox(50.f / WORLD_SCALE, 50.f / WORLD_SCALE);
b2BodyDef bdef;
bdef.type = b2_staticBody;
pBody = pWorld->CreateBody(&bdef);
pBody->CreateFixture(&shape, 2.f);
I set the debug draw in the main.cpp file:
pDebugDrawer = new DebugDrawer();
pWorld->SetDebugDraw(pDebugDrawer);
I set flags:
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
flags += b2Draw::e_jointBit;
flags += b2Draw::e_centerOfMassBit;
flags += b2Draw::e_aabbBit;
flags += b2Draw::e_pairBit;
pDebugDrawer->SetFlags(flags);
I call pWorld.Step() and pWorld->DebugDraw():
pWorld->Step(0.016f, 8, 3);
pWorld->DebugDraw();
main.cpp
#ifdef _WIN32
#include <windows.h>
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif
#define SDL_MAIN_HANDLED
#include <glad/glad.h>
#include <SDL.h>
#include <box2d/box2d.h>
#include <iostream>
#include "DebugDrawer.h"
const float WORLD_SCALE = 30.f;
b2World* pWorld;
DebugDrawer* pDebugDrawer;
b2Body* pBody;
int main()
{
// Initialize the SDL2 library
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
SDL_Log("Failed to initialize the SDL2 library: %s", SDL_GetError());
return 1;
}
// Create a SDL window
const int WIN_WIDTH = 500;
const int WIN_HEIGHT = 500;
SDL_Window* window = SDL_CreateWindow(
"Empty Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WIN_WIDTH, WIN_HEIGHT,
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
// Create a SDL renderer
SDL_Renderer* renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer)
{
SDL_Log("Failed to create a SDL renderer %s", SDL_GetError());
return 1;
}
SDL_GLContext context = SDL_GL_CreateContext(window);
// Initialize the GLAD library
if (!gladLoadGL())
{
SDL_Log("Failed to initialize the GLAD library");
return 1;
}
glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
b2Vec2 gravity(0.f, 9.8f);
pWorld = new b2World(gravity);
pDebugDrawer = new DebugDrawer();
pWorld->SetDebugDraw(pDebugDrawer);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
flags += b2Draw::e_jointBit;
flags += b2Draw::e_centerOfMassBit;
flags += b2Draw::e_aabbBit;
flags += b2Draw::e_pairBit;
pDebugDrawer->SetFlags(flags);
b2PolygonShape shape;
shape.SetAsBox(50.f / WORLD_SCALE, 50.f / WORLD_SCALE);
b2BodyDef bdef;
bdef.type = b2_staticBody;
pBody = pWorld->CreateBody(&bdef);
pBody->CreateFixture(&shape, 2.f);
SDL_Event event;
bool running = true;
SDL_PollEvent(&event);
while (running)
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
running = false;
break;
}
break;
}
glClear(GL_COLOR_BUFFER_BIT);
pWorld->Step(0.016f, 8, 3);
pWorld->DebugDraw();
SDL_GL_SwapWindow(window);
SDL_PollEvent(&event);
}
delete pWorld;
delete pDebugDrawer;
SDL_GL_DeleteContext(context);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

I should use DrawPolygon to draw segments of colliders when I use boxes to draw borders around game objects. DrawSegment() will be called when an instance of b2EdgeShape is created:
b2EdgeShape edgeShape;
edgeShape.SetOneSided(b2Vec2(0.f, 0.f), b2Vec2(1.f, 0.f),
b2Vec2(2.f, 0.f), b2Vec2(3.f, 0.f));
m_pEdgeBody = m_pWorld->CreateBody(&bdef);
m_pEdgeBody->CreateFixture(&edgeShape, 2.f);

Related

GLFW Mouse drift

I am currently developing a test project for OpenGL to discover its possibilities.
I am experiencing a weird bug with GLFW 4.0 apparently called "mouse drift" (from different github issues). It means that even though my mouse is not moving, the glfw input callback will still be called with small x and y values (generally 1 or -1).
I provided my code here : https://github.com/Lygaen/testgl (not ads or promoting, just giving the link to the full project to help reproduce). I am using a basic GLFW, GLAD and GLM framework.
My goal is to calculate the delta position of the mouse, to have correct camera movement.
Thank you for any help that you could provide !
Here is the code that calculates input :
window.h
#ifndef __WINDOW_H__
#define __WINDOW_H__
#include <string>
#include <glad/gl.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
class Window
{
private:
GLFWwindow *window;
bool correctlyLoaded;
static void resizeCallback(GLFWwindow *, int, int);
public:
Window(const std::string &, int, int);
~Window();
const bool hasCorrectlyLoaded();
const bool shouldClose();
const void pollEvents();
const void exitNextFrame();
};
class Input
{
private:
static char *keyStates;
static bool *mouseStates;
static glm::dvec2 pos;
static glm::dvec2 delta;
static std::vector<int> pressed;
static void keyCallback(GLFWwindow *, int, int, int, int);
static void mouseCallback(GLFWwindow *, double, double);
static void mouseButtonCallback(GLFWwindow *, int, int, int);
public:
static const bool isPressed(int);
static const bool isDown(int);
static const bool isReleased(int);
static const glm::dvec2 getMousePosition();
static const glm::dvec2 getMouseDelta();
static const bool isMouseButtonDown(int);
static const void setCallbacks(GLFWwindow *);
static const void loopClear();
static const void terminate();
};
#endif // __WINDOW_H__
window.cpp
#include "window.h"
#include <spdlog/spdlog.h>
#include <algorithm>
Window::Window(const std::string &title, int width, int height)
{
correctlyLoaded = false;
if (!glfwInit())
{
spdlog::default_logger()->critical("Could not load GLFW");
return;
}
spdlog::default_logger()->info("Loaded GLFW {}", glfwGetVersionString());
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!window)
{
spdlog::default_logger()->critical("Failed to create GLFW window !");
return;
}
glfwMakeContextCurrent(window);
if (!gladLoadGL(glfwGetProcAddress))
{
spdlog::default_logger()->critical("Failed to load OpenGL !");
return;
}
spdlog::default_logger()->info("Loaded OpenGL {}", glfwGetVersionString());
glViewport(0, 0, width, height);
glEnable(GL_MULTISAMPLE);
glfwSetFramebufferSizeCallback(window, Window::resizeCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Input::setCallbacks(window);
correctlyLoaded = true;
}
Window::~Window()
{
glfwTerminate();
}
void Window::resizeCallback(GLFWwindow *, int width, int height)
{
glViewport(0, 0, width, height);
}
const bool Window::hasCorrectlyLoaded()
{
return correctlyLoaded;
}
const bool Window::shouldClose()
{
return glfwWindowShouldClose(window);
}
const void Window::pollEvents()
{
Input::loopClear();
glfwSwapBuffers(window);
glfwPollEvents();
}
const void Window::exitNextFrame()
{
glfwSetWindowShouldClose(window, true);
}
char *Input::keyStates;
bool *Input::mouseStates;
glm::tvec2<double> Input::pos;
glm::tvec2<double> Input::delta;
std::vector<int> Input::pressed;
void Input::keyCallback(GLFWwindow *, int key, int /*scancode*/, int action, int /*mods*/)
{
if (key < 0 || key > GLFW_KEY_LAST)
return;
keyStates[key] = action;
if (action == GLFW_PRESS)
{
pressed.push_back(key);
}
}
void Input::mouseCallback(GLFWwindow *window, double nXPos, double nYPos)
{
glm::dvec2 newPos = {nXPos, nYPos};
delta = newPos - pos;
pos = newPos;
glfwSetCursorPos(window, 0, 0);
}
void Input::mouseButtonCallback(GLFWwindow *window, int button, int action, int /*mods*/)
{
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
return;
mouseStates[button] = action;
}
const bool Input::isPressed(int key)
{
return std::count(pressed.begin(), pressed.end(), key);
}
const bool Input::isDown(int key)
{
return keyStates[key] != GLFW_RELEASE;
}
const bool Input::isReleased(int key)
{
return keyStates[key] == GLFW_RELEASE;
}
const glm::dvec2 Input::getMousePosition()
{
return pos;
}
const glm::dvec2 Input::getMouseDelta()
{
return delta;
}
const bool Input::isMouseButtonDown(int mouseButton)
{
return mouseStates[mouseButton] == GLFW_PRESS;
}
const void Input::setCallbacks(GLFWwindow *window)
{
keyStates = new char[GLFW_KEY_LAST];
mouseStates = new bool[GLFW_MOUSE_BUTTON_LAST];
glfwSetKeyCallback(window, Input::keyCallback);
glfwSetCursorPosCallback(window, Input::mouseCallback);
glfwSetMouseButtonCallback(window, Input::mouseButtonCallback);
}
const void Input::loopClear()
{
pressed.clear();
}
const void Input::terminate()
{
delete[] keyStates;
delete[] mouseStates;
}
main.cpp
#include <iostream>
#include "gui/window.h"
#include "gui/gl/shader.h"
#include <spdlog/spdlog.h>
#include <spdlog/fmt/bin_to_hex.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/scalar_multiplication.hpp>
glm::mat4 fpsView(glm::vec3 cam, float pitch, float yaw)
{
float cosPitch = cos(pitch);
float sinPitch = sin(pitch);
float cosYaw = cos(yaw);
float sinYaw = sin(yaw);
glm::vec3 xaxis = {cosYaw, 0, -sinYaw};
glm::vec3 yaxis = {sinYaw * sinPitch, cosPitch, cosYaw * sinPitch};
glm::vec3 zaxis = {sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw};
// Create a 4x4 view matrix from the right, up, forward and eye position vectors
glm::mat4 viewMatrix = {
glm::vec4(xaxis.x, yaxis.x, zaxis.x, 0),
glm::vec4(xaxis.y, yaxis.y, zaxis.y, 0),
glm::vec4(xaxis.z, yaxis.z, zaxis.z, 0),
glm::vec4(-glm::dot(xaxis, cam), -glm::dot(yaxis, cam), -glm::dot(zaxis, cam), 1)};
return viewMatrix;
}
int main(int, char **)
{
#ifndef NDEBUG
spdlog::set_level(spdlog::level::trace);
#endif
Window window("Test GL", 800, 600);
if (!window.hasCorrectlyLoaded())
{
return 1;
}
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = {
// note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
Shader shader;
unsigned int VAO;
GL(glGenVertexArrays(1, &VAO));
GL(glBindVertexArray(VAO));
unsigned int VBO;
GL(glGenBuffers(1, &VBO));
GL(glBindBuffer(GL_ARRAY_BUFFER, VBO));
GL(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));
unsigned int EBO;
GL(glGenBuffers(1, &EBO));
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW));
GL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0));
GL(glEnableVertexAttribArray(0));
glm::mat4 Projection = glm::perspective(glm::radians(90.0f), (float)800 / (float)600, 0.1f, 100.0f);
glm::vec3 cam{4, 3, 3};
glm::vec2 dir{0, 0};
glm::mat4 Model = glm::mat4(1.0f);
while (!window.shouldClose())
{
GL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));
GL(glClear(GL_COLOR_BUFFER_BIT));
glm::mat4 View = fpsView(cam, dir.y, dir.x);
glm::mat4 mvp = Projection * View * Model;
shader.setUniform("MVP", &mvp);
shader.bind();
GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO));
GL(glBindVertexArray(VAO));
GL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0));
GL(glBindVertexArray(0));
window.pollEvents();
if (Input::isPressed(GLFW_KEY_ESCAPE))
{
window.exitNextFrame();
}
if (Input::isPressed(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else if (Input::isReleased(GLFW_KEY_F6))
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glm::dvec2 d = Input::getMouseDelta();
dir += d * 0.001;
}
spdlog::default_logger()->info("Quitting !");
}

Exception thrown: write access violation. this->**m_buffer** was 0x111011101110112

Im following this (https://www.udemy.com/course/free-learn-c-tutorial-beginners/learn/lecture/1838486#announcements ) tutorial and im stuck.
It seem that windows throws that exception and it cant be handled.
I think I try write something to some wrong place but cant see it.
Heres the line that causes the problem.
m_buffer[(y * SCREEN_WIDTH) + x] = color;
And here is everything else
//====================================main.cpp=======================================
#include<iostream>
#include "Screen.h"
#include<SDL.h>
using namespace std;
int main(int argc, char* argv[]) {
Screen screen;
if (!screen.init()) {
cout << "Error initialising SDL." << endl;
}
while (true) {
// update particles
// draw particles
for (int y = 0; y < Screen::SCREEN_HEIGHT; y++) {
for (int x = 0; x < Screen::SCREEN_WIDTH; x++ ){
screen.setPixel(x, y, 128, 0, 255);
}
}
//Draw the screen
screen.update();
// see for messages/events
if (!screen.processEvents()) {
break;
}
}
screen.close();
return 0;
}
//==========================================================================================
screen.h
#ifndef SCREEN_H_
#define SCREEN_H_
#include<SDL.h>
#include<iostream>
class Screen
{
public:
const static int SCREEN_WIDTH = 800;
const static int SCREEN_HEIGHT = 600;
private:
SDL_Window* m_window;
SDL_Renderer* m_renderer;
SDL_Texture* m_texture;
Uint32* m_buffer;
public:
Screen();
bool init();
void update();
void setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue);
bool processEvents();
void close();
};
#endif // !SCREEN_H_
//=======================screen.cpp======================================================
#include "Screen.h"
Screen::Screen() : m_window(NULL), m_renderer(NULL), m_texture(NULL), m_buffer(NULL)
{
}
bool Screen::init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
m_window = SDL_CreateWindow("Particle Fire Explosion",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); //-----------------SDL_WINDOW_HIDDEN SDL_WINDOW_SHOWN
if (m_window == 0) {
SDL_Quit();
return false;
}
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC);
m_texture = SDL_CreateTexture(m_renderer,
SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, SCREEN_WIDTH, SCREEN_HEIGHT);
if (m_renderer == NULL) {
SDL_DestroyWindow(m_window);
SDL_Quit();
return false;
}
if (m_texture == NULL) {
SDL_DestroyWindow(m_window);
SDL_DestroyRenderer(m_renderer);
SDL_Quit();
return false;
}
Uint32* buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];
memset(buffer, 0xFF, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(Uint32));
return true;
}
bool Screen::processEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
{
return false;
}
}
return true;
}
void Screen::setPixel(int x, int y, Uint8 red, Uint8 green, Uint8 blue) {
Uint32 color = 0;
color += red;
color <<= 8;
color += green;
color <<= 8;
color += blue;
color <<= 8;
color += 0xFF;
m_buffer[(y * SCREEN_WIDTH) + x] = color;
}
void Screen::update() {
SDL_UpdateTexture(m_texture, NULL, m_buffer, SCREEN_WIDTH * sizeof(Uint32));
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
void Screen::close() {
delete[] m_buffer;
SDL_DestroyRenderer(m_renderer);
SDL_DestroyTexture(m_texture);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
//==========================================================================================
Maybe someone can see what is the broblem?
Your Screen::init() method never sets m_buffer, so when setPixel() tries to dereference it, it is dereferencing a NULL pointer, which invokes undefined behavior.
this line is wrong
Uint32* buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];
you mean
m_buffer = new Uint32[SCREEN_WIDTH * SCREEN_HEIGHT];

Static Function using static variable error (illegal reference)

Ive been working in glfw c++ and want to get input from the mouse wheel by using the glfwSetScrollCallback() and I put it in a window class that I created because it requires a glfw window. I created a scroll_callback function that adjusts the fov for the camera that I initialize in a camera class. The glfwSetScrollCallback() uses that static void of my scroll_callback function in my camera class. However, I cant seem how to initialize a the fov variable in my camera.h and use it in the static void in my camera.cpp. I tried changing it to a static public variable because I need to call it in my main class but it didnt work. Any thoughts thank you!!!
camera.h
#pragma once
#include <GL\glew.h>
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <GLFW\glfw3.h>
class Camera
{
public:
Camera();
Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed);
void keyControl(bool* keys, GLfloat deltaTime);
void mouseControl(GLfloat xChange, GLfloat yChange);
static float fov;
glm::mat4 calculateViewMatrix();
~Camera();
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
private:
glm::vec3 position;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 worldUp;
GLfloat yaw;
GLfloat pitch;
GLfloat moveSpeed;
GLfloat turnSpeed;
void update();
};
Camera.cpp
#include "Camera.h"
#include <iostream>
Camera::Camera() {}
Camera::Camera(glm::vec3 startPosition, glm::vec3 startUp, GLfloat startYaw, GLfloat startPitch, GLfloat startMoveSpeed, GLfloat startTurnSpeed)
{
position = startPosition;
worldUp = startUp;
yaw = startYaw;
pitch = startPitch;
front = glm::vec3(0.0f, 0.0f, -1.0f);
moveSpeed = startMoveSpeed;
turnSpeed = startTurnSpeed;
update();
}
void Camera::keyControl(bool* keys, GLfloat deltaTime)
{
GLfloat velocity = moveSpeed * deltaTime;
if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP])
{
position += front * velocity;
}
if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN])
{
position -= front * velocity;
}
if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT])
{
position -= right * velocity;
}
if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT])
{
position += right * velocity;
}
}
void Camera::mouseControl(GLfloat xChange, GLfloat yChange)
{
xChange *= turnSpeed;
yChange *= turnSpeed;
yaw += xChange;
pitch += yChange;
if (pitch > 89.0f)
{
pitch = 89.0f;
}
if (pitch < -89.0f)
{
pitch = -89.0f;
}
update();
}
void Camera::scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov > 1.0f && fov < 45.0f)
fov -= yoffset;
else if (fov <= 1.0f)
fov = 1.0f;
else if (fov >= 45.0f)
fov = 45.0f;
}
glm::mat4 Camera::calculateViewMatrix()
{
return glm::lookAt(position, position + front, up);
}
void Camera::update()
{
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
front = glm::normalize(front);
right = glm::normalize(glm::cross(front, worldUp));
up = glm::normalize(glm::cross(right, front));
}
Camera::~Camera()
{
}
window.cpp
#include "Window.h"
#include "Camera.h"
#include <iostream>
Window::Window()
{
width = 800;
height = 800;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
Window::Window(GLint windowWidth, GLint windowHeight)
{
width = windowWidth;
height = windowHeight;
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
}
int Window::Initialise()
{
if (!glfwInit())
{
printf("Error Initialising GLFW");
glfwTerminate();
return 1;
}
// Setup GLFW Windows Properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Core Profile
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Allow forward compatiblity
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Create the window
mainWindow = glfwCreateWindow(width, height, "Test Window", NULL, NULL);
if (!mainWindow)
{
printf("Error creating GLFW window!");
glfwTerminate();
return 1;
}
// Get buffer size information
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
// Set the current context
glfwMakeContextCurrent(mainWindow);
// Handle Key + Mouse Input
createCallbacks();
glfwSetScrollCallback(mainWindow, Camera::scroll_callback);
glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Allow modern extension access
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if (error != GLEW_OK)
{
printf("Error: %s", glewGetErrorString(error));
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
glEnable(GL_DEPTH_TEST);
// Create Viewport
glViewport(0, 0, bufferWidth, bufferHeight);
glfwSetWindowUserPointer(mainWindow, this);
}
void Window::createCallbacks()
{
glfwSetKeyCallback(mainWindow, handleKeys);
glfwSetCursorPosCallback(mainWindow, handleMouse);
}
GLfloat Window::getXChange()
{
GLfloat theChange = xChange;
xChange = 0.0f;
return theChange;
}
GLfloat Window::getYChange()
{
GLfloat theChange = yChange;
yChange = 0.0f;
return theChange;
}
void Window::handleKeys(GLFWwindow* window, int key, int code, int action, int mode)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS)
{
theWindow->keys[key] = true;
}
else if (action == GLFW_RELEASE)
{
theWindow->keys[key] = false;
}
}
}
void Window::handleMouse(GLFWwindow* window, double xPos, double yPos)
{
Window* theWindow = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (theWindow->mouseFirstMoved)
{
theWindow->lastX = xPos;
theWindow->lastY = yPos;
theWindow->mouseFirstMoved = false;
}
theWindow->xChange = xPos - theWindow->lastX;
theWindow->yChange = theWindow->lastY - yPos;
theWindow->lastX = xPos;
theWindow->lastY = yPos;
}
Window::~Window()
{
glfwDestroyWindow(mainWindow);
glfwTerminate();
}

C++ Redefinition of Default Argument: Parameter 1 (Vector2D)

Im constantly getting a redefinition of default argument parameter 1 error and its preventing from building the project successfully to test code as I include it. Im relatively new to C++ and this form of building a game, having multiple header and cpp files referencing eachother.
Texture2D.cpp:
#include <iostream>
#include <SDL_image.h>
#include <string>
#include "Texture2D.h"
#include "Constants.h"
#include "Commons.h"
using namespace::std;
Texture2D::Texture2D(SDL_Renderer* renderer)
{
SDL_Renderer* mRenderer = NULL;
SDL_Texture* mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
Texture2D::~Texture2D()
{
Free();
mRenderer = NULL;
}
bool Texture2D::LoadFromFile(string path)
{
//remove the memory used for a previous texture
Free();
SDL_Texture* mTexture = NULL;
//load the image
SDL_Surface* pSurface = IMG_Load(path.c_str());
mWidth = pSurface->w;
mHeight = pSurface->h;
if (pSurface != NULL)
{
mTexture = SDL_CreateTextureFromSurface(mRenderer, pSurface);
if (mTexture == NULL)
{
cout << "Unable to create texture from surface. Error: " << SDL_GetError() << endl;
}
//Color key the image - The color to be transparent
SDL_SetColorKey(pSurface, SDL_TRUE, SDL_MapRGB(pSurface->format, 0, 0xFF, 0xFF));
SDL_FreeSurface(pSurface);
return mTexture;
}
else
{
cout << "Unable to create texture from surface. Error: " << IMG_GetError() << endl;
}
}
void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f)
{
//clear the screen
SDL_SetRenderDrawColor(mRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(mRenderer);
//set where to render the texture
SDL_Rect renderLocation = { 0, 0, mWidth, mHeight };
//render to screen
SDL_RenderCopyEx(mRenderer, mTexture, NULL, &renderLocation, 0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(mRenderer);
}
void Texture2D::Free()
{
if (mTexture != NULL)
{
SDL_DestroyTexture(mTexture);
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
Texture2D.h:
#pragma once
#ifndef _TEXTURE2D_H
#define _TEXTURE2D_H
#include <SDL.h>
#include <SDL_image.h>
#include <map>
#include <string>
#include "Commons.h"
class Texture2D
{
public:
Texture2D(SDL_Renderer* renderer);
~Texture2D();
bool LoadFromFile(std::string path);
void Free();
void Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f);
int GetWidth() { return mWidth; }
int GetHeight() { return mHeight; }
private:
SDL_Renderer* mRenderer;
SDL_Texture* mTexture;
int mWidth;
int mHeight;
};
#endif //_TEXTURE2D_H
Commons.h:
#pragma once
#ifndef _COMMONS_H
#define _COMMONS_H
struct Vector2D
{
Vector2D()
{
x = 0.0f;
y = 0.0f;
}
float x;
float y;
};
struct InitialVector2D
{
InitialVector2D()
{
initialx = 0.0f;
initialy = 0.0f;
}
float initialx;
float initialy;
};
enum SCREENS
{
SCREEN_INTRO = 0,
SCREEN_MENU,
SCREEN_LEVEL1,
SCREEN_LEVEL2,
SCREEN_GAMEOVER,
SCREEN_HIGHSCORES
};
#endif //_COMMONS_H
When giving a default parameter, you should only add the default in the header declaration. So, changing:
void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f)
to:
void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle)
should fix the error.
Simply remove the default specification here: void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f) As the compiler tells you, that was already given in the function declaration. – πάντα ῥεῖ 47 mins ago

SDL 2.0 C++: Polymorphism Vectors, my objects are not loading different images

So I'm basically following a book called SDL Game Development by Shaun Mitchell.
I'm current on page 58, where it tells us how to implement polymorphism.
So far what I have down are:
- Create the main code where we do all our rendering updating etc. (Game.cpp and Game.h)
- Create a Texture manager as a singleton (TextureManager.h and TextureManager.cpp)
- Create a GameObject (GameObject.h and GameObject.cpp)
- Create a Player that inherits GameObject (Player.h and Player.cpp)
So my GameObject class basically has 3 methods: load, draw and update.
Load basically loads an image, and I use my TextureManager to do so.
Draw draws it and update just changes it positions and current frame.
I pass the name of the image which is basically the directory, the renderer and the textureID from the Game class where I call them.
Essentially the problem is that I pass in two different directories into a GameObject
and a Player, but it only loads up the last directory I pass in. As in both GameObject and Player becomes the same image.
So I think the problem lies in Game class, Player class or GameObject class.
I create the objects in Game class, and push them in vector at Game.cpp in init function
Where it says
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);
GameObject.h
#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H
#include <string>
#include <iostream>
#include "SDL_image.h"
#include "TextureManager.h"
class GameObject
{
public:
virtual bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
virtual void draw(SDL_Renderer* pRenderer);
virtual void update();
virtual void clean();
protected:
std::string m_textureID;
int m_currentFrame;
int m_currentRow;
int m_x;
int m_y;
int m_width;
int m_height;
};
#endif // GAMEOBJECT_H
GameObject.cpp
#include "GameObject.h"
bool GameObject::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
m_textureID = textureID;
m_currentRow = 1;
m_currentFrame = 1;
if(!TextureManager::Instance()->load(name, textureID, pRenderer))
{
return false;
}
return true;
}
void GameObject::draw(SDL_Renderer* pRenderer)
{
TextureManager::Instance()->drawFrame(m_textureID, m_x, m_y,m_width, m_height, m_currentRow, m_currentFrame, pRenderer);
}
void GameObject::update()
{
m_x += 1;
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
}
void GameObject::clean()
{
}
In my Player class, I do the same thing except I use the methods that are already made in GameObject
Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "GameObject.h"
class Player : public GameObject
{
public:
bool load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer);
void draw(SDL_Renderer* pRenderer);
void update();
void clean();
};
#endif // PLAYER_H
Player.cpp
#include "Player.h"
bool Player::load(int x, int y, int width, int height, std::string name, std::string textureID, SDL_Renderer* pRenderer)
{
if(!GameObject::load(x, y, width, height, name, textureID, pRenderer))
{
return false;
}
return true;
}
void Player::draw(SDL_Renderer* pRenderer)
{
GameObject::draw(pRenderer);
}
void Player::update()
{
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
m_x -= 1;
}
void Player::clean()
{
}
This is the part where the images doesn't load the same thing happens in Game.cpp
So I basically created a vector that holds GameObjects, it told me to use it so that I could just for loop through it whenever I want to draw objects
Game.h
#ifndef GAME_H
#define GAME_H
#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <vector>
#include "TextureManager.h"
#include "Player.h"
class Game
{
public:
Game() {}
~Game() {}
bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
void render();
void update();
void handleEvents();
void clean();
// a function to access the private running variable
bool running() { return m_bRunning; }
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
int m_currentFrame;
bool m_bRunning;
GameObject* m_go;
GameObject* m_player;
std::vector<GameObject*> m_gameObjects;
};
#endif
Game.cpp
#include "Game.h"
typedef TextureManager TheTextureManager; // Singleton TextureManager
Game* g_game = 0; // Game Object
bool Game::init(const char* title, int xpos, int ypos, int width,int height, int flags)
{
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
std::cout << "SDL init success\n";
// init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos,width, height, flags);
if(m_pWindow != 0) // window init success
{
std::cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) // renderer init success
{
std::cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
}
else
{
std::cout << "renderer init fail\n";
return false; // renderer init fail
}
}
else
{
std::cout << "window init fail\n";
return false; // window init fail
}
}
else
{
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_go = new GameObject();
m_player = new Player();
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate",m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate",m_pRenderer);
m_gameObjects.push_back(m_go);
m_gameObjects.push_back(m_player);
m_bRunning = true; // everything inited successfully, start the main loop
return true;
}
void Game::render()
{
SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
//m_go.draw(m_pRenderer);
//m_player.draw(m_pRenderer);
for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw(m_pRenderer);
}
SDL_RenderPresent(m_pRenderer); // draw to the screen
}
void Game::clean()
{
std::cout << "cleaning game\n";
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}
void Game::handleEvents()
{
SDL_Event event;
if(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
void Game::update()
{
//m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
//m_go.update();
//m_player.update();
for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
}
int main(int argc, char* argv[])
{
g_game = new Game();
g_game->init("Chapter 1", 100, 100, 640, 480, 0);
while(g_game->running())
{
g_game->render();
g_game->handleEvents();
g_game->update();
SDL_Delay(10); // add the delay
}
g_game->clean();
return 0;
}
As you can see at the end of the init function, I have m_go load up simba, and m_player load up download. Even though they move in different directions (GameObject moves to the right and Player moves to the left as you can see in the classes in update method).
My program only loads download for both.
I'm not sure if the TextureManager class is related but I'll post it anyway
TextureManager.h
#ifndef TEXTUREMANAGER_H
#define TEXTUREMANAGER_H
#include <SDL.h>
#include <SDL_image.h>
#include <string.h>
#include <iostream>
#include <map>
class TextureManager
{
public:
bool load(std::string fileName,std::string id,SDL_Renderer* pRenderer);
void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
std::map <std::string, SDL_Texture*> m_textureMap;
static TextureManager* Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new TextureManager();
return s_pInstance;
}
return s_pInstance;
}
//typedef TextureManager TheTextureManager;
protected:
private:
TextureManager(){}
static TextureManager* s_pInstance;
};
#endif // TEXTUREMANAGER_H
TextureManager.cpp
#include "TextureManager.h"
TextureManager* TextureManager::s_pInstance = 0;
bool TextureManager::load(std::string fileName, std::string id, SDL_Renderer* pRenderer)
{
SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
if(pTempSurface == 0)
{
return false;
}
SDL_Texture* pTexture =
SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
// everything went ok, add the texture to our list
if(pTexture != 0)
{
m_textureMap[id] = pTexture;
return true;
}
// reaching here means something went wrong
return false;
}
void TextureManager::draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
&destRect, 0, 0, flip);
}
void TextureManager::drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = width * currentFrame;
srcRect.y = height * (currentRow - 1);
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect,
&destRect, 0, 0, flip);
}
You are using "animate" more than once for the textureID - this needs to be unique
Your Code:
m_go->load(100, 100, 96, 60, "assets/simba.bmp", "animate", m_pRenderer);
m_player->load(300, 300, 96, 60, "assets/download.bmp", "animate", m_pRenderer)
What happens is the texture is loaded but it overwrites the existing texture which has the "animate" key in the map. Make them unique and this should resolve your issue.