I am trying to create by own game engine where each basic is a GameObject which will consist of an update function and other notifiers.
Here is my code so far:
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "AssetManager.hpp"
class GameObject : public sf::Drawable, public sf::Transformable
{
public:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
target.draw(*this, states);
};
};
class Sprite : public GameObject, public sf::Sprite {
public:
Sprite(AssetManager assetManager, std::string assetName) : sf::Sprite(){
setTexture(assetManager.getTextureNamed(assetName));
}
};
int main(int argc, char const** argv)
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
AssetManager assetManager = AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
assetManager.loadTextureWithName("tank", "tank.png", sf::Vector2f(16,16));
Sprite tank = Sprite(assetManager, "tank");
while(window.isOpen()){
window.clear();
window.draw(tank);
window.display();
}
return EXIT_SUCCESS;
}
Please note, the asset manager simply stores textures in memory and returns it when needed with a given size.
The problem is on the line: window.draw(tank);, I am getting the error
Ambiguous conversion from derived class 'const Sprite' to base class 'const sf::Drawable':
Why is this as I have implemented the draw function in the GameObject class and how can I fix it?
Your Sprite class inherits from GameObject which inherits from sf::Drawable. Your class also inherits from sf::Sprite which also inherits from sf::Drawable. Now your Sprite class has 2 inherited sf::Drawable subobjects and the compiler can't choose.
To fix this, either rethink your design or inherit virtually.
To solve this issue, I dod not have to use private inheritance as some suggested, I just needed my base class (GameObject) to inherit nothing. My Sprite class would then inherit sf::Sprite like so:
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "AssetManager.hpp"
class GameObject{
public:
virtual void update(){}
};
class Sprite : public GameObject, public sf::Sprite {
public:
Sprite(AssetManager* assetManager, std::string assetName) : sf::Sprite(assetManager->getTextureNamed(assetName)){
}
};
class Tank: public Sprite{
public:
Tank(AssetManager* assetManager) : Sprite(assetManager, "tank"){
setScale(3, 3);
};
virtual void update(){
move(1,0);
}
};
int main(int argc, char const** argv)
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
AssetManager* assetManager = new AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
assetManager->loadTextureWithName("tank", "tank.png", sf::Vector2f(16,16));
Tank tank = Tank(assetManager);
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed){
window.close();
}
}
tank.update();
window.clear();
window.draw(tank);
window.display();
}
return EXIT_SUCCESS;
}
Related
In SFML I wanted to have a sprite but with other functions and variables so i decided to create a class that inherits the sprite class like this:
1. Player.hpp
#pragma once
#include <stdio.h>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
class Player : sf::Sprite{
public:
void setup();
void input();
private:
int direction;
void moveRight();
void moveLeft();
sf::Texture textures[8];
};
2(WIP). Player.cpp
void Player::setup(){
direction = 0;
textures[0].loadFromFile("images/player_right_still.png");
textures[1].loadFromFile("images/player_right_jump.png");
textures[2].loadFromFile("images/player_right_walk1.png");
textures[3].loadFromFile("images/player_right_walk2.png");
textures[4].loadFromFile("images/player_left_still.png");
textures[5].loadFromFile("images/player_left_jump.png");
textures[6].loadFromFile("images/player_left_walk1.png");
setTexture(textures[0]);
}
void Player::input(){
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Keyboard::isKeyPressed(sf::Keyboard::D)){
moveRight();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::A)){
moveLeft();
}
}
void Player::moveRight(){
}
void Player::moveLeft(){
}
game.cpp (picture because SO is being weird on me)
But when I compile it I get this error:
game.cpp: In function ‘int main()’:
game.cpp:23:27: error: ‘sf::Drawable’ is an inaccessible base of ‘Player’
window.draw(player);
class Player : sf::Sprite means that inheritance is private, that is code using instances of Player class won't be able to cast it to Sprite or access methods inherited from Sprite class. You should change inheritance to public:
class Player: public sf::Sprite
I just started writing a simple game in SFML 2.0.
I created class AABB with inheritance two class from SFML to write in class draw() method.
But i get all the time this error:
\main.cpp|14|error: cannot declare variable 'block' to be of abstract type 'AABB'|
code:
#include <SFML/Graphics.hpp>
#include <vector>
#include <iostream>
#include "headers/system.h"
#include "headers/AABB.h"
using namespace std;
int main()
{
sf::RectangleShape shape(sf::Vector2f(50,50));
AABB block (shape);
System sys;
if(!sys.create())
{
cout << "Critical error! Did you modified ini files?";
return EXIT_FAILURE;
}
sf::RenderWindow * WindowApp = sys.getHandle();
while (WindowApp->isOpen())
{
sf::Event event;
while (WindowApp->pollEvent(event))
{
if (event.type == sf::Event::Closed)
WindowApp->close();
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
WindowApp->close();
}
WindowApp->draw(block);
WindowApp->clear();
WindowApp->display();
}
return EXIT_SUCCESS;
}
AABB.h:
#include <SFML\Graphics.hpp>
#include <SFML\System.hpp>
#include <SFML\Audio.hpp>
#include <SFML\Network.hpp>
using namespace std;
class AABB : public sf::Drawable, public sf::Transformable
{
public:
AABB(sf::Vector2f pos, sf::Vector2f size) :
m_pos(pos),
m_size(size) {}
AABB(sf::RectangleShape shape) :
m_sprite(shape)
{}
private:
virtual void draw(sf::RenderTarget& target) const ;
private:
sf::Vector2f m_size;
sf::Vector2f m_pos;
sf::RectangleShape m_sprite;
};
AABB.cpp
#include "../headers/AABB.h"
using namespace std;
void AABB::draw(sf::RenderTarget& target) const
{
target.draw(m_sprite);
}
system class is not important here i think :D
BTW when I remove inheritance from class app compile without errors. What i suppose to do ? Please help me :)
Your class AABB inherits sf::Drawable, which is an abstract class, and AABB does not override all pure virtual functions of it -- which would be necessary to make AABB a concrete class and to have objects of it. I suspect that this is the result of a typo. Where you write
virtual void draw(sf::RenderTarget& target) const ;
in AABB.h, it should be
virtual void draw(sf::RenderTarget& target, sf::RenderStates) const ;
because the latter is the signature of sf::Drawable's pure virtual function, as is described in the SFML documentation. You will have to change the definition of this function in AABB.cpp as well, naturally.
I'm having a problem with circular dependencies, I suppose this is a design flaw from introducing the Game class in the wrong way.
Game.h:
#pragma once
#include <SFML\Graphics.hpp>
#include "GameScreen.h"
#include "TitleScreen.h"
class Game
{
protected:
sf::RenderWindow window;
GameScreen* CurrentGameScreen;
TitleScreen Title;
public:
Game(void);
~Game(void);
sf::RenderWindow getWindow(void);
void Run();
void Close();
};
GameScreen.h:
#pragma once
#include "Game.h"
class GameScreen
{
public:
GameScreen(void);
~GameScreen(void);
virtual void LoadAllResources() {};
virtual void DrawScreen(Game* game) {};
virtual void Update(Game* game) {};
};
TitleScreen.h:
#pragma once
#include <SFML\Graphics.hpp>
#include "GameScreen.h"
class TitleScreen : public virtual GameScreen
{
private:
sf::Texture title_screen;
sf::Sprite titleScreen;
sf::Font font;
sf::Text menuExit;
public:
TitleScreen(void);
~TitleScreen(void);
void LoadAllResources();
void DrawScreen(Game* game);
void Update(Game* game);
};
Then there's the main file:
#include "Game.h"
int main()
{
Game game;
game.Run();
//sf::RenderWindow window(sf::VideoMode(800, 600), "Test");
//GameScreen* currentScreen;
//TitleScreen titleScreen;
//currentScreen = &titleScreen;
//while (window.isOpen())
//{
// currentScreen->Update(&window);
// currentScreen->DrawScreen(&window);
//}
return 0;
}
GameScreen.h and TitleScreen.h raise a handful of C2061. From what I understand these are caused by circular dependencies between Game.h and Gamescreen.h.
TitleScreen.h is giving me error C2504: 'GameScreen' : base class undefined.
Game.h: on lines 12 and 13, give C2143: syntax error : missing ';' before '*', although I'm not sure where this is coming from and my IDE is not giving me any syntax errors.
If I remove the #include statement from GameScreen.h and substitute it with a forward declaration class Game; (which I guess breaks the circular dependency?) most of the above is solved, but TitleScreen.cpp throws a set of C2027, C2227 and C2228 (undefined type, left of -> and left of .) every time I try to access a Game object. IntelliSense points out that a pointer to an incomplete class is not allowed.
I got it working before introducing the Game class - DrawScreen() and Update() would take as argument a pointer to window (sf::RenderWindow* window). There's part of the old code left in main.cpp.
In the GameScreen.h you should declare the Game class instead of including its whole header file, so this:
class Game;
instead of:
#include "Game.h"
class Game {
private:
string title;
bool running;
State currentState;
public:
sf::RenderWindow window;
void setup();
void run();
};
I have a variable called currentState. This is State:
#ifndef STATE_HPP
#define STATE_HPP
using namespace std;
class State {
private:
public:
void start();
void update();
void render();
};
#endif
And then I have a class called PlayState, which inherits State:
#ifndef PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <SFML/Graphics.hpp>
#include "Game.hpp"
#include "State.hpp"
using namespace std;
class PlayState : public State {
private:
sf::CircleShape shape;
Game game;
public:
PlayState();
void start();
void update();
void render();
};
#endif
On my Game.cpp, I am creating currentState, by doing:
currentState = PlayState();
The problem is, though, that it's not working. currentState.update() is state.update(). It seems that I am not overriding the State methods when I create PlayState.
Here's PlayState.cpp:
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <stdio.h>
#include "PlayState.hpp"
PlayState::PlayState() {
printf("heyyy\n");
}
void PlayState::start() {
shape.setRadius(100.f);
shape.setOrigin(20.0f, 20.0f);
shape.setFillColor(sf::Color::Green);
}
void PlayState::update() {
sf::Event event;
while (game.window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
game.window.close();
//running = false;
}
}
printf("here\n");
}
void PlayState::render() {
printf("here\n");
game.window.clear();
game.window.draw(shape);
game.window.display();
}
Any ideas about how I can 'override' those methods? Thank you.
EDIT
I had to make State.cpp functions virtual so that they can be overriden.
I also had to define State *currentState as a pointer and create PlayState with "currentState = new PlayState();".
Also, now I access .update and .draw with ->update() and ->draw().
Two problems. As #McAden said, the functions in State that are to be overridden in PlayState need to be marked virtual. The other problem is that the data member currentState in Game has type State. When you assign an object of type PlayState to it, it gets the State part of the PlayState object, but not the derived parts. This is called "slicing". To prevent it, make currentState a pointer to State, and when you create that PlayState object, assign its address to the Game object's currentState.
What you're looking for is the concept of virtual functions.
Wikipedia entry
State needs:
virtual void update();
PlayState needs:
void update();
You need to make your function's with the virtual modifier ie.
virtual void Update();
When calling currentState->Update() this will call the topmost overridden function, if you desire to call any of the parent classes functions inside of the classes methods simply specify ie. State::Update(); when calling the function.
I have a class called "Game", with prototypes functions "Update" and "Draw" but they're not defined. It's up to the object inheriting the "Game" object to override them. Is this possible?
Contents of "Game.h"
class Game // does it have to abstract/virtual?
{
public:
//General stuff for all games here
}
void Update(Game *game) = 0; // or make it virtual in someway
Contents of "MyGame.h"
#include "Game.h"
class MyGame : public Game
{
public:
// General stuff for my game
}
void Update(MyGame *game);
// Contents of "MyGame.cpp"
#include "MyGame.h"
void Update(MyGame *game) // does it have to be overriden/overloaded?
{
}
// Contents of "GameManager.h"
#include "Game.h"
class GameManager
{
public:
Game *game;
}
void Update(GameManager *manager);
// Contents of "GameManager.cpp"
#include "Game.h"
void Update(GameManager *manager)
{
Update(manager->game);
}
The key is the last method:
Why can't GameManager call MyGame Update() method when GameManager's Game object = MyGame and not Game?
Define Draw and Update as virtual methods in the base class Game.
class Game
{
public:
virtual void Draw() {};
};
class MyGame : public Game
{
public:
virtual void Draw() {}
};
void callDraw(Game* game)
{
game->Draw();
}
//...
Game* game = new MyGame;
callDraw(game);
The last call will call the method in MyGame although it's called on a Game pointer.