I'm trying to create a state engine in my game for the different screens. id start screen, maybe a file chooser in the future, overworld map, menu screen, etc. But when I forward declare the class it says there are no constructors.
GameState.h:
#pragma once
class GameState
{
public:
virtual ~GameState() {}
virtual void Update() {}
virtual void HandleEvents() {}
virtual void Draw(Graphics& gfx) {}
GameState* getCurrentState()
{
return currentState;
}
void ChangeState(GameState* state)
{
currentState = state;
}
protected:
SDL_Renderer* renderer;
GameState* currentState;
};
GameStates.h
#pragma once
#include "GameState.h"
#include "Texture.h"
#include "Keyboard.h"
class TitleGameState;
class IntroGameState : public GameState
{
public:
IntroGameState(SDL_Renderer* renderer, KeyboardClient& kbd)
:
kbd(kbd)
{
background = new Texture("red.png", renderer);
this->renderer = renderer;
}
~IntroGameState() {}
void HandleEvents()
{
while (!kbd.KeyEmpty())
{
KeyEvent e = kbd.ReadKey();
switch (e.GetCode())
{
case SDLK_RETURN:
if (e.IsPress())
{
currentState = new TitleGameState(renderer, kbd);
}
break;
}
}
}
void Logic() {}
void Draw(Graphics& gfx)
{
background->Draw(0, 0, gfx);
}
private:
Texture* background;
KeyboardClient& kbd;
};
class TitleGameState : public GameState
{
public:
TitleGameState(SDL_Renderer* renderer, KeyboardClient& kbd)
:
kbd(kbd)
{
background = new Texture("blue.png", renderer);
}
~TitleGameState() {}
void HandleEvents()
{
while (!kbd.KeyEmpty())
{
KeyEvent e = kbd.ReadKey();
switch (e.GetCode())
{
case SDLK_RETURN:
if (e.IsPress())
{
printf("OK");
}
break;
}
}
}
void Logic() {}
void Draw(Graphics&gfx)
{
background->Draw(0, 0, gfx);
}
private:
Texture* background;
KeyboardClient& kbd;
};
I define the class right afterwards, and I know I can just move it above IntroGameState, however when I implement the menu game state, it will go back and forth between the menu state and the overworld state. How can I get around this?
Compiler Error:
error C2514: 'TitleGameState' : class has no constructors
File: gamestates.h
Line: 28
Line 28 is this line of code:
currentState = new TitleGameState(renderer, kbd);
The error on the line currentState = new TitleGameState(renderer, kbd); is because the compiler has yet to see the constructor for the class. It doesn't know how to compile this code.
If you forward declare the class class TitleGameState; all you can declare is pretty much a pointer TitleGameState*.
To compile the code you have, you need to define the class before using. Note: defining the class does not mean defining all the methods as well. A class definition consists of the method and member declarations.
class TitleGameState : public GameState
{
public:
TitleGameState(SDL_Renderer*, KeyboardClient&);
~TitleGameState();
void HandleEvents();
// ...
};
class IntroGameState : public GameState
{
// ...
}
After the definition of the classes, you can then define the member functions;
/*inline*/ void TitleGameState::HandleEvents()
// inline is needed if the method is defined in a header file
// to help avoid linker errors
{
// ...
}
Related
I am writing an Arduino program where LEDs and a bunch of other electronics are controlled by different buttons. To simplify the code, I am using the Observer Mode:
class Observer observes EventThrowers, who performs check() every frame and notifies Observers if necessary. The code definition for Observer and EventThrower looks like this:
class Observer {
public:
virtual void handleEvent(int label, bool state) = 0; // Virtual method called by EventThrowers.
};
class EventThrower {
private:
std::vector<Observer *> observer_list;
protected:
void notifyObservers(int label, bool state) {
for (Observer *observer : observer_list) {
observer->handleEvent(label, state);
}
}
public:
virtual void check() = 0; // Virtual method used in loop() for frame checking.
void addObserver(Observer *_observer) {
this->observer_list.push_back(_observer);
}
};
And my LEDCtrl class (an Observer) and ButtonClick class (an EventThrower) definitions are:
class LEDCtrl : public Observer {
public:
// properties
LEDCtrl(int _led_pin) { ... } // constructor
void handleEvent(int label, bool state) { ... } // overridden handleEvent method
private:
void toggleLight(bool new_status) { ... } // assistant method
};
class ButtonClick : public EventThrower {
public:
// properties
ButtonClick(int _button_pin, int _default, int _label) { ... } // constructor
void check() { ... } // overridden check() that is called every frame to check the status of the button and choose to notify Observers or not
};
My initialization of a LEDCtrl-ButtonClick instance pair looks like:
ButtonClick *buttonClick1 = new ButtonClick(BUTTON1, 0, 0);
LEDCtrl *ledCtrl1 = new LEDCtrl(LED1);
buttonClick1->addObserver(ledCtrl1);
However, the above code throws this compile error:
error: 'buttonClick1' does not name a type
buttonClick1->addObserver(ledCtrl1);
^~~~~~~~~~~~
How can I fix this?
As the title says I have the following "base" class that user can extend:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start();
virtual void EventHandler(SDL_Event event);
virtual void Update();
virtual void Draw();
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
My problem is I can't know what name, the user, choose for his classes so how I can call a known method (like Start or EventHandler) from my main class inside an unknown class?
An example of a class that is unknown to me but well-known to the user can be:
class SomeFunnyRandomName : public BaseScene
{
public:
void Start();
void Eventhandler(SDL_Event event);
void Update();
void Draw();
};
So form the main class I need to call Start() inside "SomeFunnyRandomName" without:
SomeFunnyRandomName sfrn = new SomeFunnyRandomName();
If you can include the code it will be very helpful (but not required).
You take a reference or pointer to BaseScene, and call the methods on that. The caller passes an instance of their derived class.
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene & scene) : scene(scene) {}
void doStuff() { scene.Start(); scene.Update(); }
/*... etc*/
};
int main() {
SomeFunnyRandomName scene;
UsesScene usesScene(scene);
usesScene.doStuff();
}
I am trying to pass a pointer to memeber of class(Dialog::handler) from its method(in scope of Dialog::render) to some outer method(Button::OnClick).
Here is a small example:
class Button
{
public:
void OnClick(void (*handler)())
{
handler();
}
};
class Dialog
{
public:
void handler()
{
//do stuff
}
void render()
{
auto button = new Button;
//Source of problem
button->OnClick(this->*handler);
}
};
But compiler shows error:
non-standard syntax; use '&' to create a pointer to member
Also I triend other combinations, like:
this->handler.
&this.handler.
this.*handler.
etc
But obviously they failed.
You could use std::function and pass it a lambda in which you've caught this of the object you'd like to call back:
#include <functional>
#include <iostream>
class Button {
public:
void OnClick(std::function<void()> handler) {
handler();
}
};
class Dialog {
public:
void handler() {
std::cout << "Dialog::handler\n";
}
void render() {
auto button = new Button;
// a lambda catching "this" Dialog.
button->OnClick([this] { this->handler(); });
delete button; // you didn't delete your button
}
};
int main() {
Dialog d;
d.render();
}
But it looks like you should probably inherit from a common base class that has a virtual void handler() so you can pass object pointers/references around instead. A rough idea:
#include <iostream>
class VisualBase {
public:
virtual void handler() = 0;
virtual ~VisualBase() = 0;
};
VisualBase::~VisualBase() {}
class Button : public VisualBase {
public:
void handler() override {}
void OnClick(VisualBase* caller) {
caller->handler();
}
};
class Dialog : public VisualBase {
public:
void handler() override {
std::cout << "Dialog::handler\n";
}
void render() {
Button button;
button.OnClick(this);
}
};
int main() {
Dialog d;
d.render();
}
I have a small piece of Arduino code that gives me compilation error:
error: no matching function for call to 'PushButton::PushButton(int, LeftButtonEvent*)
In its own header file I have two classes:
class Event
{
public:
virtual void handle() {
}
};
class PushButton
{
public:
PushButton(int pinButton, Event *event);
uint8_t read();
private:
uint8_t _buttonState;
Event _event;
};
And the source file for classes:
PushButton::PushButton(int pinButton, Event *event)
{
// implementation
}
uint8_t PushButton::read() {
// implementation
return _buttonState;
}
In the main ino sketch header file I have defined a new class that extends Event class:
class LeftButtonEvent : public Event {
public:
virtual void handle();
};
And in the sketch source file I provide the implementation for the handle method and use it:
void LeftButtonEvent::handle() {
log("Is working!!!!!");
}
LeftButtonEvent leftButtonEvent;
PushButton leftButton;
void setup() {
leftButton = PushButton(PIN_LEFT_BUTTON, &leftButtonEvent);
}
I was expecting the constructor for PushButton to accept a LeftButtonEvent type because it extends Event class, but it looks like it doesn't like it.
Am I missing something?
As there is only incomplete code and I couldn't test it directly, there is example how it's possible to get it work (it's all in one sketch, Arduino IDE 1.6.12, C++11):
class Event {
public:
virtual void handle() = 0;
};
class EventLeft : public Event {
public:
virtual void handle() {
Serial.println("EventLeft");
}
} leftEvent;
class EventRight : public Event {
public:
virtual void handle() {
Serial.println("EventRight");
}
} rightEvent;
class PushButton {
public:
PushButton(int8_t _pin, Event * _event) : pin(_pin), state(true), event(_event) {
pinMode(pin, INPUT_PULLUP);
}
void check() {
if (! digitalRead(pin)) { // inverted logic
if (state) event->handle();
state = false;
} else {
state = true;
}
}
private:
int8_t pin;
bool state;
Event * event;
};
PushButton buttons[] = {
{4, &leftEvent},
{5, &rightEvent}
};
void setup() {
Serial.begin(115200);
}
void loop() {
delay(10);
for (PushButton & button : buttons) button.check();
//// if the range based for loop above doesn't work, you have to use old school one:
// for (uint8_t i = 0; i < 2; ++i) buttons[i].check();
}
So it is my understanding that to make a class abstract in c++ you have to create one, just one, pure virtual method in that class. In my code i create an abstract GameObject class, which is inherited by my Player class, but the problem is i get errors in my Player.cpp saying error LNK2001: unresolved extrenal symbol "public:virtual void__thiscall GameObject::Load(void)" (?Load#GameObject##UAEXXZ) for every method except the initialise, and this gets fixed when i set them all = 0, im just wondering why
// Abstract class to provide derived classes with common attributes
#include <SDL.h>
#include "AnimationManager.h"
#include "Debug.h"
#include "InputHandler.h"
class GameObject
{
public:
virtual void Initialise() = 0;
virtual void Load();
virtual void HandleEvents();
virtual void Update();
virtual void Draw();
Vector2D* position;
int currantFrame;
SDL_Renderer* renderer;
float speed;
bool alive;
};
#include "GameObject.h"
class Player : public GameObject
{
public:
virtual void Initialise();
virtual void Load();
virtual void HandleEvents();
virtual void Update();
virtual void Draw();
Player(SDL_Renderer* r);
~Player();
};
#include "Player.h"
Player::Player(SDL_Renderer* r)
{
renderer = r;
}
Player::~Player()
{
}
void Player::Initialise()
{
position = new Vector2D(10, 10);
currantFrame = 0;
}
void Player::Load()
{
TheAnimationManager::Instance()->load("Assets/circle.png", "player", renderer);
}
void Player::HandleEvents()
{
SDL_Event event;
if (SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_a:
DEBUG_MSG("A Pressed");
position->m_x -= 10;
break;
case SDLK_d:
DEBUG_MSG("D Pressed");
position->m_x += 10;
break;
}
break;
}
}
}
void Player::Update()
{
Vector2D* p = TheInputHandler::Instance()->GetMousePosition();
DEBUG_MSG(p->GetY());
DEBUG_MSG(p->GetX());
currantFrame = int(((SDL_GetTicks() / 100) % 4));
}
void Player::Draw()
{
TheAnimationManager::Instance()->Animate("player", (int)position->GetX(), (int)position->GetY(), 90, 82, 0, currantFrame, renderer, SDL_FLIP_NONE);
}
Every virtual method which might be called through a base class pointer that isn't pure virtual needs to have an implementation.
You seem to have a backwards idea of how abstract/virtual works. You don't choose to make a class abstract, why would you? You choose to make a member function pure virtual, because there is no sensible implementation for it. Then, as a consequence of having a pure virtual function, the class becomes abstract.
The class becoming abstract does not mean that every one of its functions suddenly becomes pure virtual.
Your error is a linker error. The linker was looking for the implementation of the GameObject::Load function, which you didn't provide. If you mark the function as pure virtual, the linker won't look for an implementation.
Some compilers require that for each signature the virtual keyword would specified only once, in the base class. Try this:
class GameObject
{
public:
virtual void Initialise() = 0;
virtual void Load() = 0;
virtual void HandleEvents() = 0;
virtual void Update() = 0;
virtual void Draw() = 0;
...
};
class Player : public GameObject
{
public:
void Initialise();
void Load();
void HandleEvents();
void Update();
void Draw();
...
};
if you don't need the public GameObject::Initialise method be pure virtual, at least give it an empty body, like this
class GameObject
{
public:
void Initialise() {}
...
};
Another conjecture: do you have, by any chance, any instantiations of GameObject in your code? Do you have something like this:
GameObject go;
or something like this:
void foo( GameObject go );
or something like this:
GameObject bar();
or something like this:
vector<GameObject> all_my_objects;