I get this error
undefined reference to `InputHandler::InputHandler()' on line 22
I am working on a InputHandler Class in SDL
InputHandler.h
/*
* InputHandler.h
*
* Created on: 16 apr. 2014
* Author: JAN
*/
#ifndef INPUTHANDLER_H_
#define INPUTHANDLER_H_
#include "SDL2/SDL.h"
#include "Vector2D.h"
class InputHandler
{
public:
static InputHandler* Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new InputHandler();
}
return s_pInstance;
}
void reset();
// update and clean the input handler
void update();
void clean();
// keyboard events
bool isKeyDown(SDL_Scancode key) const;
// joystick events
int getAxisX(int joy, int stick) const;
int getAxisY(int joy, int stick) const;
bool getButtonState(int joy, int buttonNumber) const;
// mouse events
bool getMouseButtonState(int buttonNumber) const;
Vector2D* getMousePosition() const;
private:
InputHandler();
~InputHandler();
InputHandler(const InputHandler&);
InputHandler& operator=(const InputHandler&);
// private functions to handle different event types
// handle keyboard events
void onKeyDown();
void onKeyUp();
// handle mouse events
void onMouseMove(SDL_Event& event);
void onMouseButtonDown(SDL_Event& event);
void onMouseButtonUp(SDL_Event& event);
// handle joysticks events
void onJoystickAxisMove(SDL_Event& event);
void onJoystickButtonDown(SDL_Event& event);
void onJoystickButtonUp(SDL_Event& event);
// member variables
// keyboard specific
const Uint8* m_keystates;
// singleton
static InputHandler* s_pInstance;
};
typedef InputHandler TheInputHandler;
#endif
InputHandler.cpp
/*
* InputHandler.cpp
*
* Created on: 16 apr. 2014
* Author: JAN
*/
#include "InputHandler.h"
#include "Game.h"
InputHandler* InputHandler::s_pInstance = 0;
bool InputHandler::isKeyDown(SDL_Scancode key) const
{
if(m_keystates != 0)
{
if(m_keystates[key] == 1)
{
return true;
}
else
{
return false;
}
}
return false;
}
void InputHandler::update()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
onKeyDown();
break;
case SDL_KEYUP:
onKeyUp();
break;
default:
break;
}
}
}
void InputHandler::onKeyDown()
{
m_keystates = SDL_GetKeyboardState(0);
}
void InputHandler::onKeyUp()
{
m_keystates = SDL_GetKeyboardState(0);
}
I am new to programming in c++ and working with SDL. So it's probably a stupid error but if someone can explain me that would be great! Kinda stuck on this right now don't know what i am doing wrong
You haven't defined the default constructor anywhere.
Add it to the cpp file.
You seem to be missing quite a few other members, too.
In class InputHandler your constructor must be like this: InputHandler(){}
Related
I'm trying to create a game. I have a class GameObjects that many classes will inherit from. The class GameObject has a draw method that takes the window address to the display. Why does the sprite show up without the texture when displayed like this?
This is the texture, more of a placeholder. I was able to load it in other files directly creating the sprite and drawing it.
Here is my main.cpp
#include <iostream>
#include "Game.h"
int main()
{
//window setup
Game game;
//Initialize game
game.start();
return 0;
}
Here is my Game.h
#pragma once
#include "GameObject.h"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
class Game
{
private:
//window variables
int w_width;
int w_height;
sf::RenderWindow window;
sf::Event ev;
bool isRunning;
std::vector<GameObject> o_vector;
void initVariables();
void initWindow();
void initObjects();
void drawObjects();
public:
void start();
void run();
void input();
void update();
void render();
};
And Game.cpp
#include "Game.h"
#include "GameObject.h"
void Game::start()
{
this->initVariables();
this->initWindow();
this->initObjects();
this->run();
}
//Initializations
void Game::initVariables()
{
isRunning = true;
//window variables
w_width = 1280;
w_height = 720;
}
void Game::drawObjects()
{
for (int o_count = 0; o_count < o_vector.size(); o_count++)
{
o_vector.at(o_count).draw(window);
}
}
void Game::initWindow()
{
//window creation
window.create(sf::VideoMode(w_width, w_height), "The Dungeon Crawler", sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize);
}
void Game::initObjects()
{
GameObject baseObject;
o_vector.push_back(baseObject);
}
void Game::run()
{
while (isRunning)
{
input();
update();
render();
}
}
void Game::input()
{
while (window.pollEvent(ev))
{
switch (ev.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
switch (ev.key.code)
{
case sf::Keyboard::Escape:
window.close();
break;
case sf::Keyboard::A:
break;
}
}
}
}
void Game::update()
{
}
void Game::render()
{
window.clear(sf::Color(0, 0, 128));
drawObjects();
window.display();
}
Here is GameObject.h
#pragma once
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
class GameObject
{
private:
std::string name;
std::vector<int> o_position;
std::vector<int> o_size;
std::string t_path;
sf::Sprite o_sprite;
sf::Texture o_texture;
void initVariables();
public:
//Constructors & Destructors
GameObject();
~GameObject();
//Getters
std::vector<int> getPos();
std::vector<int> getSize();
sf::Sprite getSprite();
//Setters
void setPos(std::vector<int>pos_in);
void setSize(std::vector<int> size_in);
//Graphics
void draw(sf::RenderWindow &displayWindow);
};
And GameObject.cpp
#include "GameObject.h"
GameObject::GameObject()
{
initVariables();
}
GameObject::~GameObject()
{
}
void GameObject::initVariables()
{
o_position = { 0,0 };
o_size = { 64,64 };
t_path = "Resources/EmptySquare.png";
if (!o_texture.loadFromFile(t_path))
{
std::cout << "Failed to load" << std::endl;
return;
}
o_sprite.setTexture(o_texture);
}
std::vector<int> GameObject::getPos()
{
return o_position;
}
std::vector<int> GameObject::getSize()
{
return o_size;
}
sf::Sprite GameObject::getSprite()
{
return o_sprite;
}
void GameObject::setPos(std::vector<int> pos_in)
{
o_position = pos_in;
}
void GameObject::setSize(std::vector<int> size_in)
{
o_size = size_in;
}
void GameObject::draw(sf::RenderWindow &displayWindow)
{
displayWindow.draw(o_sprite);
}
Thank you for any help!
the problem is this line in Game::initObjects()
GameObject baseObject;
o_vector.push_back(baseObject);
you creata a copy of GameObject.
so it will make a copy of o_sprite.
the o_sprite copies the texture pointer.
after this function ends, the texture pointer is no longer valid.
sf::Sprite has the member const Texture* m_texture; and when calling sf::Sprite::setTexture(const Texture& texture) this member m_texture will in fact point to the texture. That texture will be destructed after initObjects() ends, and your element at position 0 will have a o_sprite.m_texture that points to this destructed object. SFML/Sprite.hpp
you could define the correct operator=(GameObject) that implements the correct sprite copy - or in this case simply say:
void Game::initObjects()
{
o_vector.resize(1);
}
resize will call the constructor of GameObject and you will have no copies and therefore dangling pointers.
Another way would be for you to allocate game object on the heap and store a pointer to it in the vector. This way you will avoid the cost of copying.
To make these changes, declare baseObject as private member of Game class and in initObjects method allocate it on the heap.
class Game
{
private:
GameObject *baseObject;
std::vector<GameObject *> o_vector;
};
void Game::initObjects()
{
baseObject = new GameObject;
o_vector.push_back(baseObject);
}
void Game::drawObjects()
{
for (int o_count = 0; o_count < o_vector.size(); o_count++)
{
o_vector.at(o_count)->draw(window); // use -> operator to call draw
}
}
PS: Instead of raw pointer, you can also use C++11 smart pointer.
I am trying to storesf::RectangleShape's into thestd::vectorand then draw each of them into thesf::RenderWindow.
Single rectangle shape is representing 1x1 tetromino and i would like to store it into the vector each time it reaches the bottom of the window. Then I would like to reset the position of the current tetromino to the default position.
I think I'm not even to able store it correctly. Each time the tetromino reaches the bottom it gives me this error message:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Bellow please find my current code. I just started working on it and already got stuck.
Definitions.h
#pragma once
// Point structure
struct Point
{
int dim_x;
int dim_y;
};
// Field Dimensions
const int fieldRows = 10;
const int fieldColumns = 9;
const int pointSize = 50.f;
// For checkingEdges funntion within the Tetrnomino.h
enum Edge
{
leftEdge,
rightEdge,
noneEdge
};
Game.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Definitions.h"
#include "Tetromino.h"
class Game
{
public:
Game();
~Game();
// Game starter
void run();
// Accessors
bool running();
private:
// Updating and rendering the game window
void update();
void render();
// Initialization
void initVariables();
void initWindow();
void initBacgroundMusic();
// Polling
void pollEvents();
// Window logic stuff
sf::RenderWindow* _window;
sf::Event _event;
void drawStack();
// Bacground Music
sf::Music _ost;
// Tetromino + Its logic
Tetromino _T;
sf::Time delayTime = sf::milliseconds(300);
sf::Clock clock;
};
Tetromino.h
#pragma once
#include <SFML/Graphics.hpp>
#include <vector>
#include "Definitions.h"
class Tetromino
{
public:
Tetromino();
~Tetromino();
// Initialization
void initTetromino();
// Tetromonino logic
void moveTetromino();
Edge checkEdges();
// Getters & Setters
sf::RectangleShape getTetromino();
sf::RectangleShape getStackPart(int part);
int getStackSize();
void setTetromino(sf::RectangleShape &t);
private:
// The current tetromino
sf::RectangleShape _tetromino;
std::vector<sf::RectangleShape> _stack;
};
Game.cpp
#include "Game.h"
//-----Consturcotrs and Destructors-----//
Game::Game()
{
//Basic Initialization
_T.initTetromino();
initVariables();
}
Game::~Game()
{
delete _window;
}
//-----Private Functions-----//
void Game::run()
{
update();
render();
}
bool Game::running()
{
return _window->isOpen();
}
void Game::update()
{
sf::Time elapsed = clock.getElapsedTime();
pollEvents();
if (elapsed >= delayTime)
{
_T.moveTetromino();
clock.restart();
}
}
void Game::render()
{
_window->clear(sf::Color::White);
_window->draw(_T.getTetromino());
drawStack();
_window->display();
}
void Game::initVariables()
{
_window = nullptr;
initWindow();
initBacgroundMusic();
}
void Game::initWindow()
{
_window = new sf::RenderWindow(sf::VideoMode(fieldColumns * pointSize, fieldRows * pointSize), "Tetris v0.2", sf::Style::Default);
_window->setVerticalSyncEnabled(true);
_window->setFramerateLimit(60);
}
void Game::initBacgroundMusic()
{
_ost.openFromFile("../QT_SFML_Tetris/Music.ogg");
_ost.play();
_ost.setLoop(true);
_ost.setVolume(50.f);
}
void Game::pollEvents()
{
while (_window->pollEvent(_event))
{
if (_event.type == sf::Event::Closed) {_window->close();}
if (_event.type == sf::Event::KeyPressed)
{
if (_event.key.code == sf::Keyboard::Escape){_window->close();}
if (_event.key.code == sf::Keyboard::Left && _T.checkEdges() != leftEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x - pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Right && _T.checkEdges() != rightEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x + pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Down)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x, t.getPosition().y+ pointSize);
_T.setTetromino(t);
render();
}
}
}
}
**void Game::drawStack()**
{
for (unsigned int i = _T.getStackSize(); i > 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}
main.cpp
#include <Game.h>
int main()
{
Game game;
while (game.running())
{
game.run();
}
return 0;
}
Tetromino.cpp
#include "Tetromino.h"
//-----Consturcotrs and Destructors-----//
Tetromino::Tetromino()
{
}
Tetromino::~Tetromino()
{
}
//-----Public Functions-----//
void Tetromino::initTetromino()
{
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
_tetromino.setSize(sf::Vector2f(pointSize, pointSize));
_tetromino.setFillColor(sf::Color::Red);
}
void Tetromino::moveTetromino()
{
_tetromino.move(0.f, pointSize);
if (_tetromino.getPosition().y > fieldRows * pointSize - pointSize)
{
_stack.push_back(_tetromino);
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
}
}
Edge Tetromino::checkEdges()
{
if (_tetromino.getPosition().x == 0)
{
return leftEdge;
}
else if (_tetromino.getPosition().x == (fieldColumns * pointSize) - pointSize)
{
return rightEdge;
}
else return noneEdge;
}
sf::RectangleShape Tetromino::getTetromino()
{
return _tetromino;
}
sf::RectangleShape Tetromino::getStackPart(int part)
{
return _stack[part];
}
int Tetromino::getStackSize()
{
return _stack.size();
}
void Tetromino::setTetromino(sf::RectangleShape &t)
{
_tetromino = t;
}
I think the main issue could be within this line:
_stack.push_back(_tetromino);
In the drawStack() method you try to iterate backwards.
There is a reverse iterator doing this for you.
you have an off-by one error in your index calculation, which works only with an empty vector (exactly to prevent these errors you should use the iterator!)
You may want to read about iterators in C++ here is a small example.
According to your code it will look like (note that you need also a getStack()-method in Tetromino.hpp, returning the reference of the vector):
void Game::drawStack()
{
for (auto it = _T.getStack().rbegin(); it != _T.getStack().rend(); it++)
{
_window->draw(*it);
}
}
If you want to keep the index, I this is a fix:
void Game::drawStack()
{
for (int i = _T.getStackSize()-1; i >= 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}
For my game, I want to use PhysFs to extract music files that are in a zip file
I created a custom class MusicStream that inherits from sf::InputStream that I use as an sf::Music's stream.
This is my basic program:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "musicstream.h"
#include "physfs.h"
int main() {
PHYSFS_init(0);
PHYSFS_addToSearchPath("data.zip", 0);
std::string musicFile = "music.ogg";
if (PHYSFS_exists(musicFile.c_str()) == 0) {
PHYSFS_deinit();
return EXIT_FAILURE;
}
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::Music myMusic;
MusicStream myStream(musicFile.c_str());
if (!myStream.getError()) {
myMusic.openFromStream(myStream);
myMusic.play();
}
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) window.close();
}
}
myMusic.stop();
PHYSFS_deinit();
return 0;
}
This works flawlessly, except for one thing:
When I close the window and the program exits, I'm getting a runtime error R6025 pure virtual function call and the program crashes.
So apparently a pure virtual function is called (sf::InputStream's dtor??), but I implemented all of sf::InputStream's functions and it doesn't make sense to me.
Also, I'm not really sure if the code is relevant but in case it is, this is the custom class:
musicstream.h
#ifndef MUSIC_STREAM_H_INCLUDED
#define MUSIC_STREAM_H_INCLUDED
#include <SFML/System.hpp>
#include "physfs.h"
class MusicStream : public sf::InputStream {
public:
MusicStream();
MusicStream(const char *fileName);
virtual ~MusicStream() override;
sf::Int64 read(void *data, sf::Int64) override;
sf::Int64 seek(sf::Int64 position) override;
sf::Int64 tell() override;
sf::Int64 getSize() override;
bool getError() const;
private:
PHYSFS_File *file_;
bool error_;
};
#endif
musicstream.cpp
#include "musicstream.h"
MusicStream::MusicStream() :
error_(true)
{
}
MusicStream::MusicStream(const char *filename) :
error_(false)
{
file_ = PHYSFS_openRead(filename);
if (file_ == nullptr) {
error_ = true;
}
}
MusicStream::~MusicStream() {
if (error_) { return; }
PHYSFS_close(file_);
}
sf::Int64 MusicStream::read(void *data, sf::Int64 size) {
if (error_) { return 0; }
sf::Int64 fileRead = PHYSFS_read(file_, data, 1, size);
if (fileRead == -1) {
return 0;
}
return fileRead;
}
sf::Int64 MusicStream::seek(sf::Int64 position) {
if (error_) { return -1; }
if (PHYSFS_seek(file_, position) == 0) {
return -1;
}
return position;
}
sf::Int64 MusicStream::tell() {
if (error_) { return -1; }
sf::Int64 position = PHYSFS_tell(file_);
return position;
}
sf::Int64 MusicStream::getSize() {
if (error_) { return -1; }
sf::Int64 size = PHYSFS_fileLength(file_);
return size;
}
bool MusicStream::getError() const {
return error_;
}
The problem were these two lines:
sf::Music myMusic;
MusicStream myStream(musicFile.c_str());
I swapped them and got rid of the error. It's because music is played in its own thread. It tried reading from the stream after it was destroyed. Now the music is destroyed before the stream is.
I'm trying to move the layout up when the keyboard is presented cause it hides my input textfield
but my app crash from line HASH_FIND_PTR(_targets, &tmp, element); from this class
void ActionManager::addAction(Action *action, Node *target, bool paused)
{
CCASSERT(action != nullptr, "");
CCASSERT(target != nullptr, "");
tHashElement *element = nullptr;
// we should convert it to Ref*, because we save it as Ref*
Ref *tmp = target;
HASH_FIND_PTR(_targets, &tmp, element); //error
if (! element)
{
element = (tHashElement*)calloc(sizeof(*element), 1);
element->paused = paused;
target->retain();
element->target = target;
HASH_ADD_PTR(_targets, target, element);
}
actionAllocWithHashElement(element);
CCASSERT(! ccArrayContainsObject(element->actions, action), "");
ccArrayAppendObject(element->actions, action);
action->startWithTarget(target);
}
I'm using cocos2d-x 3.2
i have debug and it's crashing after this line m_pLayout->runAction(moveBy);
anyone please give me some advice how can i solve it thanks
My LoginScene.h
#include "cocos2d.h"
#include "cocos-ext.h"
#include "CocosGUI.h"
USING_NS_CC;
USING_NS_CC_EXT;
using namespace ui;
class LoginScene : public Scene
{
public:
LoginScene(bool pPortrait=false);
~LoginScene();
virtual void onEnter();
virtual void onExit();
void onLogin(Ref* pSender, Widget::TouchEventType type);
void onRegister(Ref* pSender, Widget::TouchEventType type);
void TextFieldEvent(Ref* pSender,TextField::EventType type);
protected:
Layout* m_pLayout;
Layer* m_pUILayer;
};
and LoginScene.cpp
#include "LoginScene.h"
#include "cocostudio/CCSSceneReader.h"
#include "cocostudio/CCSGUIReader.h"
#include "cocostudio/CCActionManagerEx.h"
#include <sqlite3.h>
LoginScene::LoginScene(bool pPortrait):m_pLayout(NULL),m_pUILayer(NULL)
{
Scene::init();
}
LoginScene::~LoginScene()
{
}
void LoginScene::onEnter()
{
Scene::onEnter();
m_pUILayer=Layer::create();
m_pUILayer->scheduleUpdate();
addChild(m_pUILayer);
//register root from json
m_pLayout=dynamic_cast<Layout*>(cocostudio::GUIReader::getInstance()->widgetFromJsonFile("LoginScene/LoginScene.json"));
m_pUILayer->addChild(m_pLayout);
//button initialize
Button *btnLogin=static_cast<Button*>(Helper::seekWidgetByName(m_pLayout, "btnLogin"));
btnLogin->addTouchEventListener(CC_CALLBACK_2(LoginScene::onLogin, this));
Button *btnRegister=static_cast<Button*>(Helper::seekWidgetByName(m_pLayout, "btnRegister"));
btnRegister->addTouchEventListener(CC_CALLBACK_2(LoginScene::onRegister, this));
//textfield initialize
TextField *txtUsername=static_cast<TextField*>(Helper::seekWidgetByName(m_pLayout, "txtUsername"));
txtUsername->addEventListenerTextField(m_pLayout, textfieldeventselector(LoginScene::TextFieldEvent));
TextField *txtPassword=static_cast<TextField*>(Helper::seekWidgetByName(m_pLayout, "txtPassword"));
txtPassword->addEventListenerTextField(m_pLayout, textfieldeventselector(LoginScene::TextFieldEvent));
}
void LoginScene::onExit()
{
m_pUILayer->removeFromParent();
cocostudio::GUIReader::destroyInstance();
cocostudio::ActionManagerEx::destroyInstance();
cocostudio::SceneReader::destroyInstance();
Scene::onExit();
}
void LoginScene::onLogin(Ref* pSender, Widget::TouchEventType type)
{
if(type==Widget::TouchEventType::ENDED)
{
CCLOG("abc");
}
}
void LoginScene::onRegister(Ref* pSender, Widget::TouchEventType type)
{
if (type==Widget::TouchEventType::ENDED)
{
CCLOG("abc");
}
}
void LoginScene::TextFieldEvent(Ref* pSender,TextField::EventType type)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
switch (type)
{
case TextField::EventType::ATTACH_WITH_IME:
{
TextField* txtUsername=dynamic_cast<TextField*>(pSender);
MoveBy* moveBy=MoveBy::create(0.5f, Vec2(0,txtUsername->getContentSize().height*2.5));
m_pLayout->runAction(moveBy);
}
break;
case TextField::EventType::DETACH_WITH_IME:
{
TextField* txtUsername=dynamic_cast<TextField*>(pSender);
MoveBy* moveBy=MoveBy::create(0.1f, Vec2(0,-txtUsername->getContentSize().height*2.5));
m_pLayout->runAction(moveBy);
}
break;
default:
break;
}
#endif
}
When I try to call OnLoop I get error that it doesn't recognise it.
///Ins_App.h
#ifndef INS_APP_H
#define INS_APP_H
#include <SDL/SDL.h>
class Ins_App
{
private:
/* Variables */
bool Running;
SDL_Surface* Surf_Display;
public:
/* inMain */
Ins_App();
int OnExecute();
public:
/* Other */
bool OnInit();
void OnEvent(SDL_Event* Event);
void OnLoop();
void OnRender();
void OnCleanup();
protected:
};
#endif // INS_APP_H
///Ins_App.cpp
#include "Ins_App.h"
Ins_App::Ins_App()
{
Running = true;
Surf_Display = NULL;
}
int Ins_App::OnExecute(){
if(OnInit() == false){
return -1;
}
SDL_Event Event;
while(Running){
while(SDL_PollEvent(&Event)){
OnEvent(&Event);
}
OnLoop();
OnRender();
}
return 0;
}
int main(int argc, char* argv[]){
Ins_App iApp;
return iApp.OnExecute();
}
///OnLoop.cpp
#include "Ins_App.h"
void OnLoop(){
}
And here is the error:
obj\Debug\src\Ins_App.o:C:\Users\Al\Documents\Ins
\src\Ins_App.cpp|19|undefined reference to `Ins_App::OnLoop()'|
What am I doing wrong?
You didn't define your member:
void OnLoop(){
}
should be
void Ins_App::OnLoop(){
}
You're basically just defining a free function named OnLoop, not your member.