I'm getting an error that says:
SZ_GameItem - No appropriate default constructor available.
Here's parts of the codes:
main.cpp:
#include <iostream>
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
using namespace std;
#include "SZ_timer.h"
SZ_Timer aTimer;
const int DELTA_TIME = 10;
bool done = false;
#include "SZ_Player.h"
SZ_Player examplePlayer;
#include "SZ_GameItem.h"
SZ_GameItem exampleItem;
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0);
// Creates the game window
SDL_Window* game_window = SDL_CreateWindow("Rise", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
// Creates the game render to draw on the game window.
SDL_Renderer* game_renderer = SDL_CreateRenderer(game_window, 0, 0);
// Game Loop
examplePlayer.Init();
while (!done)
{
aTimer.resetTicksTimer();
examplePlayer.Update();
examplePlayer.Input();
exampleItem.Update();
SDL_SetRenderDrawColor(game_renderer, 0, 0, 20, SDL_ALPHA_OPAQUE);
SDL_RenderClear(game_renderer);
examplePlayer.Render(game_renderer);
exampleItem.Render(game_renderer);
SDL_RenderPresent(game_renderer);
// If less time has passed than allocated block, wait difference
if (aTimer.getTicks() < DELTA_TIME)
{
SDL_Delay(DELTA_TIME - aTimer.getTicks());
}
}
SDL_Quit();
// Exits program
return 0;
}
SZ_GameItem.cpp:
#include "SZ_GameItem.h"
SZ_GameItem::SZ_GameItem(int eX, int eY, int eW, int eH)
{
x = eX;
y = eY;
height = eH;
width = eW;
rect.x = x;
rect.y = y;
rect.h = height;
rect.w = width;
velocity.x = 1;
velocity.y = 0;
}
SZ_GameItem::~SZ_GameItem()
{
}
void SZ_GameItem::Input()
{
}
void SZ_GameItem::Update()
{
rect.x = x;
rect.y = y;
rect.h = height;
rect.w = width;
x = x + velocity.x;
y = y + velocity.y;
}
void SZ_GameItem::Render(SDL_Renderer* pRenderer)
{
SDL_SetRenderDrawColor(pRenderer, 255, 255, 255, 255);
SDL_RenderDrawRect(pRenderer, &rect);
}
SZ_GameItem.h:
#ifndef aGameItem
#define aGameItem
#include <iostream>
#include "SDL.h"
#include "SZ_Vector2D.h"
class SZ_GameItem
{
public:
SZ_GameItem(int x, int y, int w, int h);
~SZ_GameItem();
void Update();
void Input();
void Render(SDL_Renderer* aRenderer);
SZ_Vector2D velocity;
int x, y, height, width;
private:
SDL_Rect rect;
};
#endif
When you write this line:
SZ_GameItem exampleItem;
you actually declare and initialize a variable of type SZ_GameItem. And in this case, it implicitly initializes the variable using the default constructor (that is, which takes no argument), but you haven't provided one. A default constructor can be implicitly defined in some cases, but as you provided a user-defined constructor, with signature SZ_GameItem(int x, int y, int w, int h), the default constructor is not implicitly defined.
What needs be done is to either initialize this variable yourself using the constructor your provided, or provide a default constructor.
Related
I have a Game class that through its constructor initializes the window and the SDL renderer. I understand from what I read so far (not much) that there should only be one renderer for each window.
Then I have a Player class where through the constructor I want to load a texture with an image, for which I need the renderer, therefore, I put the renderer as the constructor parameter and in this way I am forced to pass from the constructor from Game the renderer to the Player constructor (since it instantiated the Player class in The Game class).
The fact is that the renderer is passed before being created, and I don't know if there is another way to invoke the constructor of the Player from Game, since it forces me to put it that way. I leave the code for you to see:
Game class:
#pragma once
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "player.hpp"
//#include "helpers.hpp"
using namespace std;
#define WINDOW_WIDHT 640
#define WINDOW_HEIGTH 480
class Game
{
public:
Game();
~Game();
void loop();
void update() {}
void input();
void render();
void draw() {}
private:
SDL_Window *window;
SDL_Renderer *renderer = nullptr;
SDL_Event event;
SDL_Texture *gTexture;
bool running;
Player player;
};
Game::Game() : player(renderer)
{
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
//inicializa la carga de pngs
int imgFlags = IMG_INIT_PNG;
if (!IMG_Init(imgFlags) & imgFlags)
{
cout << "No se puede inicializar SDL_Img" << endl;
}
running = true;
loop();
}
Game::~Game()
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
void Game::loop()
{
while (running)
{
input();
render();
update();
}
}
void Game::render()
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_Rect rect;
rect.x = rect.y = 0;
rect.w = WINDOW_WIDHT;
rect.h = WINDOW_HEIGTH;
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
void Game::input()
{
while (SDL_PollEvent(&event) > 0)
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
}
Clase Player:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
//#include "helpers.hpp"
using namespace std;
class Player
{
public:
Player(SDL_Renderer *renderer);
~Player() = default;
const SDL_Rect getDest() { return dest; }
const SDL_Rect getSrc() { return src; }
void setDest(int x, int y, int w, int h);
void setSrc(int x, int y, int w, int h);
SDL_Texture *loadTexture(std::string path, SDL_Renderer *renderer);
private:
SDL_Rect dest;
SDL_Rect src;
};
Player::Player(SDL_Renderer *renderer){
loadTexture("mario.png", renderer);
/* setSrc(48, 48, 48, 48);
setDest(100, 100, 48, 48);
SDL_Rect playerRectSrc = getSrc();
SDL_Rect playerRectDest = getDest(); */
}
void Player::setDest(int x, int y, int w, int h){
dest.x = x;
dest.y = y;
dest.w = w;
dest.h = h;
}
void Player::setSrc(int x, int y, int w, int h){
src.x = x;
src.y = y;
src.w = w;
src.h = h;
}
SDL_Texture* Player::loadTexture(std::string path, SDL_Renderer *renderer)
{
SDL_Texture *newTexture = NULL;
SDL_Surface *loadedSurface = IMG_Load(path.c_str());
if (loadedSurface == NULL)
{
cout << "No se pudo cargar la imagen" << endl;
}
else
{
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == NULL)
{
cout << "No se pudo generar la textura para player" << endl;
}
SDL_FreeSurface(loadedSurface);
}
return newTexture;
}
The question is how to call the Player constructor after the renderer has been created? The only thing I can think of is not to create the texture through the constructor, but through a function, but it wouldn't be the right thing to do, right? that's what the constructor is for
The only thing I can think of is not to create the texture through the constructor, but through a function, but it wouldn't be the right thing to do, right? that's what the constructor is for
Right. However, SDL is a C library so it doesn't use C++ RAII, which is responsible for construction/destruction. First, we call constructors in the member initializer list (: foo{}, bar{foo}), which provides us with fully constructed member objects. Then, we do whatever we want in the constructor body ({ use(foo); }). However, in your case the constructor body ({ SDL_CreateWindowAndRenderer(...); } ) is needed before member initialization (: player{renderer}).
The question is how to call the Player constructor after the renderer has been created?
Construct all that SDL_ stuff before constructing the Player:
class RenderWindow {
SDL_Window* window;
SDL_Renderer* renderer;
public:
RenderWindow() {
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
}
// an easy double-free protection, you can use anything else
RenderWindow(RenderWindow&&) = delete;
~RenderWindow() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
// lvalue-only to forbid dangling like RenderWindow{}.raw_renderer()
auto raw_renderer() & { return renderer; }
};
Now, your Player and Game can be implemented in a natural RAII construct-then-use way:
class Player {
public:
Player(SDL_Renderer*); // TODO implement
};
class Game {
// note the declaration order: construction goes from top to bottom
RenderWindow render_window;
Player player;
public:
// SDL_* happens in render_window{},
// so player{render_window.raw_renderer()} gets an initialized SDL_Renderer
Game(): /*render_window{},*/ player{render_window.raw_renderer()} {}
};
I'm using SDL library for my homework at university, the program run smoothly at first but then I created a class using SDL as member like this:
#pragma once
#include <SDL.h>
#include <string>
#include <SDL_image.h>
#include <cstring>
using namespace std;
class Anh
{
public:
SDL_Surface * SURFACE;
SDL_Texture * TEXTURE;
SDL_Rect RECT;
void ganAnh(string a, SDL_Renderer *renderer);
void setRect(int a, int b, int c, int d);
};
and Object.cpp
#include "Object.h"
void Anh::ganAnh(string a, SDL_Renderer * renderer)
{
SURFACE = IMG_Load(a.c_str);
TEXTURE = SDL_CreateTextureFromSurface(renderer, SURFACE);
}
void Anh::setRect(int a, int b, int c, int d)
{
RECT.x = a;
RECT.y = b;
RECT.w = c;
RECT.h = d;
}
This is the declaration of variable in Source.cpp before main:
Anh Image;
Anh Bar;
But when I used this class members in my function
void LoadBar(SDL_Renderer *renderer, string a)
{
SDL_RenderCopy(renderer, Image.TEXTURE, NULL, &Image.RECT);
Bar.RECT.x = (720 - Bar.RECT.w * a.length()) / 2;
for (int i = 0; i < a.length(); i++)
{
SDL_RenderCopy(renderer, Bar.TEXTURE, NULL, &Bar.RECT);
Bar.RECT.x += 50;
if (i == a.length() - 1) Bar.RECT.x = (720 - Bar.RECT.w * a.length()) / 2;
}
}
It reported C2228 left of '.TEXTURE' must have class/struct/union and
C2660 'SDL_RenderCopy': function does not take 2 arguments
Every time I access class member I got that error. Please help me!
I don't see an instantiation for Bar in your function LoadBar.
For Example:
Anh * Bar = new Anh();
Edit:
Ok, the declaration seems to be not the problem.
But, did you have looked here?
https://msdn.microsoft.com/en-gb/library/3y365xw6.aspx
-> So, if you have not declared another Image or Bar variable the access to your member is not correct.
When I run this it just shows a black screen, and if i Put SDL_GetError() at the end it prints a blank line.....
Any ideas on how to fix this?
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
class character {
public: SDL_Rect src, cur;
public: SDL_Texture *image;
void setSrc(int x, int y, int w, int h) {
src.x = x;
src.y = y;
src.w = w;
src.h = h;
}
void setCur(int x, int y, int w, int h) {
src.x = x;
src.y = y;
src.w = w;
src.h = h;
}
};
int main(int argc, char* argv[]) {
bool in = true;
character p1, p2, ball;
SDL_Window *window = 0;
SDL_Renderer *renderer = 0;
SDL_Surface *screen, *imageLoader;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Pong",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, 0);
p1.setSrc(0, 0, 100, 500);
p1.setCur(0, 0, 100, 500);
imageLoader = IMG_Load("/home/donaldo/Documents/Games/Images/player.bmp");
p1.image = SDL_CreateTextureFromSurface(renderer, imageLoader);
SDL_RenderCopy(renderer, p1.image, &p1.src, &p1.cur);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
return 0;
}
You have a typo in your setCur() function. I assume you want to be setting the cur rectangle, not src again.
Also, not related but it's good practice to free the surface and texture you allocated when you're done with them.
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.
I am trying to write my own rasterizer using only gldrawpixels() (and glfw).
I can't use opengl 3 or 4 stuff, because my laptop only has intelgraphics.
I want to keep my code cross-platform so no windows.h. I can't use pixeltoaster, because it does not build on mingw.
When i run my program it crashes why? I don't know which function causes the error.
Here is my code:
My main.cpp:
#include "main.h"
GLFWwindow* window;
unsigned int x ,y,size;
float* pixeldata;
// init
bool init()
{
bool init_val;
if(!glfwInit() )
{
std::cout << "GLFW failed to initialize \n";
init_val = false;
glfwTerminate();
return init_val;
}
init_val = true;
return init_val;
}
//creat window and allocate memory for pixelbuffer
int createwindow(int width, int height, char* window_name, int fullscreen)
{
x = width;
y = height;
size = x*y;
pixeldata = new float[size*3];
std::cout << size;
if (fullscreen == 1)
{
window = glfwCreateWindow( width, height, window_name ,glfwGetPrimaryMonitor(),NULL );
}
else
{
window = glfwCreateWindow( width, height, window_name ,NULL,NULL );
}
if(!window)
{
std::cout << "failed to open window! \n";
glfwTerminate();
return -1;
}
else
{
glfwMakeContextCurrent(window);
}
}
//places pixel on screen, doesn't work properly
void setpixel(unsigned int xloc,unsigned int yloc)
{
unsigned int pixloc;
pixloc = xloc * yloc;
if(pixloc > size)
{
std::cout << "TOO FAR!";
glfwWindowShouldClose(window);
glfwTerminate();
}
else
{
pixeldata[pixloc*3] = 10;
}
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(x, y, GL_RGB, GL_FLOAT, pixeldata);
}
int main()
{
init();
createwindow(760, 360,"window", 0);
drawline(10,10, 380,180);
while (!glfwWindowShouldClose(window))
{
render();
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
}
My main.h:
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
//GL libs
#include <GL/glfw.h>
#include <GLM/glm.hpp>
// STD libs
#include <iostream>
#include <string>
#include <fstream>
#include <thread>
#include <cmath>
//shared functions
//main.cpp
void setpixel(unsigned int xloc, unsigned int yloc);
//draw.cpp
void drawline( unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1 );
my draw.cpp:
#include "main.h"
//does not work, should draw a line
void drawline( unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1 )
{
int dx = x1 - x0;
int dy = y1 - y0;
int a = dy/dx;
int x2 = x0, y2 = y0;
int b = (a*x2) - y2;
b *= -1;
for (int i = x0; x0 <= x1; i++)
{
y2 = a*x2 + b;
setpixel(i,y2);
}
}
I forgot to tell, this is a hobby project.
It looks like the problem may be in setpixel():
void setpixel(unsigned int xloc,unsigned int yloc)
{
unsigned int pixloc;
pixloc = xloc * yloc; // <- this is wrong
if(pixloc > size)
{
std::cout << "TOO FAR!";
glfwWindowShouldClose(window);
glfwTerminate();
}
else
{
pixeldata[pixloc*3] = 10; // <- and this is wrong
}
}
The first wrong line needs to be:
pixloc = (yloc * bytesPerRow) + (xloc * bytesPerPixel);
where bytesPerRow is width * bytesPerPixel in this case and bytesPerPixel is 3
The second wrong line can then just be:
pixeldata [ pixloc ] = 10;
All that said, you shouldn't write your own line drawing routine. You should just use OpenGL's line drawing capabilities (GL_LINES).