I am looking for help creating a sprite in a different class and file cocos2d-x. I have used the code from the cocos2d-x website for subclassing a sprite and other posts and It would not work for me. I have followed the sonar systems tutorial for making a separate class for a "bird" sprite ("Player" in my case) and am having trouble with an error when trying to pass the helloworld layer through the Player class constructor that takes a parameter of a layer. the error says: "'Player::Player(const Player &)': cannot convert argument 1 from 'HelloWorld *const ' to 'const Player &' ApocalypseWorld c:\cocosprojects\apocalypseworld\classes\helloworldscene.cpp 39"
here is the code:
Player.h:
#pragma once
#include "cocos2d.h"
class Player
{
public:
Player( cocos2d::Layer* layer );
private:
cocos2d::Sprite *player1;
};
Player.cpp:
#include "Player.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
Player::Player( cocos2d::Layer* layer )
{
player1 = Sprite::create("PlayerHead.png");
player1->setPosition(Point(200, 200));
layer->addChild(player1, 100);
}
HelloWorldScene.h:
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "Player.h"
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
Player* player;
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp:
#include "HelloWorldScene.h"
#include "Player.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
USING_NS_CC;
using namespace cocostudio::timeline;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
auto rootNode = CSLoader::createNode("MainScene.csb");
addChild(rootNode);
player = new Player(this);
return true;
}
i get a little red squigly line under the t in:
player = new Player(this);
at the end of the HelloWorldScene.cpp file
Edited code:
Player.h:
#ifndef __Sample__Player__
#define __Sample__Player__
#include "cocos2d.h"
USING_NS_CC;
class Player : public Node
{
public:
static Player* createPlayer(Layer* layer);
Sprite* head;
};
#endif
Player.cpp:
#include "Player.h"
Player* Player::createPlayer(Layer* layer) {
auto ret = new (std::nothrow) Player;
if(ret && ret->init()) {
ret->autorelease();
ret->head = Sprite::create("PlayerHead.png");
ret->addChild(ret->head);
layer->addChild(ret, 100);
return ret;
}
CC_SAFE_RELEASE(ret);
return nullptr;
}
Then in your scene.h:
#include "Player.h"
And in your scene.cpp:
auto player = Player::createPlayer(this);
addChild(player);
Related
I know that this type of problem has been reported before, but the answers weren't helpful to me. This is the code situation:
// main.cpp
#include <QApplication>
#include "game.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
Game game;
game.show();
return app.exec();
}
// game.h
#ifndef GAME_H
#define GAME_H
#include "scene.h"
class Game {
public:
Game();
void show();
private:
GameScene scene;
};
#endif // GAME_H
// scene.h
#ifndef SCENE_H
#define SCENE_H
#include "GraphicsManager.h"
struct GameScene {
static GraphicsManager<MainWindow> window() { return win; }
private:
static GraphicsManager<MainWindow> win;
};
#endif // SCENE_H
// game.cpp
#include "game.h"
Game::Game() {
scene.window().render();
}
void Game::show() {
qDebug() << "crash test before show";
scene.window().view()->show(); // crashes here
qDebug() << "crash test after show";
}
// GraphicsManager.h
#ifndef GRAPHICSMANAGER_H
#define GRAPHICSMANAGER_H
#include <QGraphicsScene>
#include <QGraphicsView> // inherits QWidget
#include <QGraphicsPixmapItem>
#include <QImage>
#include <QBrush>
template <typename T>
struct GraphicsManager {
void render() { static_cast<T*>(this)->render(); }
QGraphicsScene* scene() { return static_cast<T*>(this)->scene(); }
QGraphicsView* view() { return static_cast<T*>(this)->view(); }
};
struct MainWindow :
GraphicsManager<MainWindow> {
void render() {
m_scene = new QGraphicsScene(0, 0, 800, 800);
m_view = new QGraphicsView(m_scene);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setFixedSize(800, 800);
}
QGraphicsScene* scene() { return m_scene; }
QGraphicsView* view() { return m_view; }
private:
QGraphicsScene* m_scene; // raw pointer is used here, since
QGraphicsView* m_view; // they both inherit QObject,
};
#endif // GRAPHICSMANAGER_H
Now admittedly I am very new to Qt in general, so it's possible that I don't understand some of its mechanics. But as you can see in the minimal code example above, I want to try to use CRTP when it comes to the graphics interface module, and according to my tests, everything works fine until the QWidget::show() method is called in Game::show(). Right after that call the application crashes.
The crash report message does not provide any useful information or hints as to why this happened. Does anyone have an idea of what I have done wrong?
EDIT: This is the compiler message:
11:05:06: Running steps for project test3...
11:05:06: Starting: "C:\CMake\bin\cmake.exe" --build C:/a_Skola/Programmeringsmetodik/space_invaders_testsite/build-test3-Desktop_Qt_6_4_1_MinGW_64_bit-Debug --target all
ninja: no work to do.
11:05:06: The process "C:\CMake\bin\cmake.exe" exited normally.
11:05:06: Elapsed time: 00:00.
I'm trying to code a simple game, where the main.cpp file instantiates the Game class, and the Game class instantiates the Player class. I want the Player class to have access to the Game class' variables, so I guess the best way to do that is to have the Game class pass itself to the Player class:
game.h
#pragma once
#include <raylib.h>
#include "player.h"
class Game
{
public:
Game();
void run();
private:
void update();
void draw();
Player player;
};
game.cpp
#include "game.h"
Game::Game() : player(this, { 0, 0, 0 })
{
}
void Game::run()
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "teste");
SetTargetFPS(60);
while (!WindowShouldClose())
{
update();
draw();
}
CloseWindow();
}
void Game::update()
{
player.update();
}
void Game::draw()
{
BeginDrawing();
ClearBackground(RAYWHITE);
EndDrawing();
}
player.h
#pragma once
#include <raylib.h>
#include "game.h"
class Player
{
public:
Player(Game* game, Vector3 pos);
void update();
void draw();
Game* game;
Vector3 pos;
};
player.cpp
#include "player.h"
Player::Player(Game* game, Vector3 pos)
{
this->game = game;
this->pos = pos;
speed = .1;
}
void Player::update()
{
if (IsKeyDown(KEY_D)) pos.x += 1;
if (IsKeyDown(KEY_A)) pos.x += -1;
if (IsKeyDown(KEY_S)) pos.z += 1;
if (IsKeyDown(KEY_W)) pos.z += -1;
}
void Player::draw()
{
}
The code seems fine to Intellisense, but the compiler just throws a bunch of errors.
I tried passing this as an argument to the Player class constructor, but it didn't work out, as the compiler doesn't accept it.
You have a circular dependency between your header files.
game.h depends on player.h, because the Game::player member is a Player instance, not a Player* pointer or Player& reference, so the complete Player class declaration is needed. This is fine.
However, player.h depends on game.h, but Game hasn't been declared yet (because of the header guard in game.h) when the Player class declaration is compiled.
Since the Player::game member is just a Game* pointer, you can use a forward declaration to break that header dependency, eg:
game.h
#pragma once
//#include <raylib.h> // <-- game.h doesn't use anything from this, so move it to game.cpp
#include "player.h" // <-- needed here because of Game::player
class Game
{
public:
Game();
void run();
private:
void update();
void draw();
Player player;
};
game.cpp
#include "game.h"
#include <raylib.h> // <-- move here
Game::Game() : player(this, { 0, 0, 0 })
{
}
...
player.h
#pragma once
#include <raylib.h> // <-- leave here if it declares Vector3
//#include "game.h" // <-- move to player.cpp
class Game; // <-- use this forward declaration instead
class Player
{
public:
Player(Game* game, Vector3 pos);
void update();
void draw();
Game* game;
Vector3 pos;
};
player.cpp
#include "player.h"
#include "game.h" // <-- move here
Player::Player(Game* game, Vector3 pos)
{
this->game = game;
...
}
...
In short, a header file should #include only the things it actually uses directly. Anything else should be #include'd in the .cpp file instead. But, anything in a header file that is just a pointer or reference can be forward-declared without using an #include. Keep your #includes to a minimum in header files. The compilation process will be cleaner and more efficient because of it.
I am trying to create simple application with gtkmm but I'm having some problem.
Here's how it looks now:
Here's the code to generate it:
MyWindow.h:
#ifndef MYWINDOW_H_
#define MYWINDOW_H_
#include <gtkmm/window.h>
#include <gtkmm/frame.h>
#include "MyDrawingArea.h"
class MyWindow :public Gtk::Window {
public:
MyWindow();
virtual ~MyWindow() {}
private:
MyDrawingArea drawing_area;
};
#endif /* MYWINDOW_H_ */
MyWindow.cpp:
#include "MyWindow.h"
MyWindow::MyWindow() : drawing_area("Drawing area") {
set_title("My app");
set_border_width(10);
add(drawing_area);
drawing_area.draw_stuff_in_area();
show_all_children();
}
MyDrawingArea.h:
#ifndef MYDRAWINGAREA_H_
#define MYDRAWINGAREA_H_
#include <gtkmm/frame.h>
#include <gtkmm/drawingarea.h>
class MyDrawingArea : public Gtk::Frame {
public:
MyDrawingArea(const Glib::ustring& title);
virtual ~MyDrawingArea() {}
void draw_stuff_in_area();
private:
Gtk::DrawingArea area;
};
#endif /* MYDRAWINGAREA_H_ */
MyDrawingArea.cpp:
#include "MyDrawingArea.h"
#include <iostream>
#include <gtkmm/window.h>
MyDrawingArea::MyDrawingArea(const Glib::ustring& title) : Gtk::Frame(title) {
set_border_width(20);
add(area);
area.set_size_request(300, 250);
}
void MyDrawingArea::draw_stuff_in_area() {
Cairo::RefPtr<Cairo::Context> cr = area.get_window()->create_cairo_context(); // program crashes here!
// draw stuff with 'cr' here...
}
As the comment suggests, the program crashes when I try to create a Cairo::Context, though I don't think the Cairo::Context creation is the problem: Every dereferencing to the object returned by my_area.get_window() crashes the program!
Anyone know what's causing the problem?
Hi did you check the return value of area.get_window() because documentation says
Returns the widget’s window if it is realized, 0 otherwise.
OK so i have a few problems.
1. I need to be able to register the childclass when its created with game for broadcasting.
2. I need to be able to call the child class's method from an array of GameObject Pointers.
3. I need it to be the actual classes, not just copys of them.
In the file systemvars.h i have my global methods and some variables.
#pragma once
//=================================
// include guard
#ifndef _SYSTEMVARS_H_
#define _SYSTEMVARS_H_
//=================================
// forward declared dependencies
class Game;
//=================================
// included dependencies
#include <iostream>
using namespace std;
//global enums
const enum CLASSTYPE{CLASSTYPE_NULL,CLASSTYPE_PLAYER,CLASSTYPE_DUNGION,CLASSTYPE_ENTITY,CLASSTYPE_MAP,CLASSTYPE_MENU};
//Global methods
void setGameRefrence(Game*);
Game* getGameRefrence();
systemvars.cpp: definitions
#include "SystemVars.h"
static Game* curentgame;
void setGameRefrence(Game* mygame)
{
curentgame = mygame;
}
Game* getGameRefrence()
{
return curentgame;
}
In my Game.h: a holder for gameobjects
#pragma once
//=================================
// include guard
#ifndef _GAME_H_
#define _GAME_H_
//=================================
// forward declared dependencies
class GameObject;
//class Player;
//=================================
// included dependencies
#include "SystemVars.h"
#include "GameObject.h"
//#include "Player.h"
#include <iostream>
using namespace std;
//=================================
// the actual class
class Game
{
public:
Game(void);
void registerGameObject(GameObject*);
void unregisterGameObject(GameObject*);
void sendMessageToAllObjects(string message,CLASSTYPE recipeint);
~Game(void);
private:
GameObject *gameobjects2[1000];
int numberofobject;
};
#endif
the game.cpp gameclass definition
#include "Game.h"
//#include "Player.h"
Game::Game(void)
{
setGameRefrence(this);
//logHelperMessage(INFO,1,"Registerd game");
numberofobject = 0;
}
void Game::registerGameObject(GameObject* newobj)
{
//logHelperMessage(INFO,1,"Registerd");
newobj->setId(numberofobject);
gameobjects2[numberofobject] = newobj;
numberofobject++;
//gameobjects.push_back(newobj);
}
void Game::unregisterGameObject(GameObject* objtodie)
{
//logHelperMessage(INFO,1,"Unregister");
for(int i = objtodie->getId();i < numberofobject - 1;i++)
{
gameobjects2[i] = gameobjects2[i+1];
gameobjects2[i]->setId(i);
}
gameobjects2[numberofobject-1] = nullptr;
numberofobject--;
}
void Game::sendMessageToAllObjects(string message,CLASSTYPE recipeint)
{
for(int i = 0; i < numberofobject;i++)
{
cout << "Sent the message from game");
//((Player *)gameobjects2[i])->sendMessage(message);
//static_cast<Player*>(gameobjects2[i])->sendMessage(message);
}
}
Game::~Game(void)
{
}
Gameobject.h: the parent of my inner game classes.
#pragma once
//=================================
// include guard
#ifndef _GAMEOBJECT_H_
#define _GAMEOBJECT_H_
//=================================
// forward declared dependencies
enum CLASSTYPE;
//=================================
// included dependencies
#include <iostream>
#include "SystemVars.h"
using namespace std;
//=================================
// the actual class
class GameObject
{
public:
GameObject();
GameObject(CLASSTYPE mytype);
~GameObject(void);
virtual void sendMessage(string data);
virtual CLASSTYPE getMyClassType();
virtual void setMyClassType(CLASSTYPE newrecip);
void setId(int val);
int getId();
protected:
CLASSTYPE _MYCURRENTCLASSTYPE;
int myid;
};
#endif
Gameobject.cpp
#include "GameObject.h"
GameObject::GameObject() : _MYCURRENTCLASSTYPE(CLASSTYPE_NULL)
{
//do not register
}
GameObject::GameObject(CLASSTYPE mytype): _MYCURRENTCLASSTYPE(mytype)
{
//register this object into the gameobject list.
getGameRefrence()->registerGameObject(this);
}
GameObject::~GameObject(void)
{
getGameRefrence()->unregisterGameObject(this);
}
void GameObject::sendMessage(string data)
{
//logHelperMessage(INFO,1,"Recived te message in GameObject");
cout << "Recived te message in GameObject";
}
CLASSTYPE GameObject::getMyClassType()
{
return _MYCURRENTCLASSTYPE;
}
void GameObject::setMyClassType(CLASSTYPE newrecip)
{
}
void GameObject::setId(int val)
{
myid = val;
}
int GameObject::getId()
{
return myid;
}
Player.h:
pragma once
//=================================
// include guard
#ifndef _PLAYER_H_
#define _PLAYER_H_
//=================================
// forward declared dependencies
//=================================
// included dependencies
#include "SystemVars.h"
#include "GameObject.h"
//=================================
// the actual class
class Player : public GameObject
{
public:
Player();
void sendMessage(string data) override;
void test();
}
Player.cpp:
Player::Player() : GameObject(CLASSTYPE_PLAYER)
{
}
void Player::sendMessage(string data)
{
//logHelperMessage(INFO,1,"Recived the message in Player");
cout << "Recived the message in Player";
//logHelperMessage(INFO,1,data.c_str());
cout << data;
}
void Player::test()
{
cout << "Sent message";
getGameRefrence()->sendMessageToAllObjects("Test",CLASSTYPE_PLAYER);
}
main.cpp
#pragma once
#include "SystemVars.cpp"
#include "Player.h"
#include "Game.h"
Game mygame;
int main(int argc, char **argv)
{
setGameRefrence(&mygame);
Player newplayer = Player();
newplayer.test();
}
Now that that is all out of the way.
The expected output is:
Sent message
Sent message from game
Recived message in Player
but insted i get:
Sent message
Sent message from game
Recived message in Gameobject
Im pretty sure i have a sliceing problem, but im not sure what to do about it, or where it is.
So, any ideas gents?
ALso, i tried to cut back the classes a bit so im not posting 2000~ lines of code. So if anyhting missing let me know.
About a dozen classes inherit from gameobject. and i need them all to talk to eachother in one way or another.
Just by having CLASSTYPE_PLAYER, etc. makes me concerned that you're trying to subvert/reinvent C++ OOP. You already have the concept of 'class' in the language, why re-invent it? Forgive me if I'm wrong. Aside from this, I suggest you look up publisher-subscriber frameworks to do the kind of thing you're after, or implement your own. I'm sure somebody will answer your C++ issue more directly.
Edit: tone of first comment.
I had a problem with an illegal access error and I have removed the default constructor from Player.h as I deduced that the problem was due to it. The problem I am having now is that the Level.cpp wanted a default constructor so I edited the Level.h file as shown. That problem was resolved but now I am not being able to return a pointer to the player. The error 'illegal operation on bound member function' is being shown. Any ideas please? I'm a beginner in C++ and any help would be appreciated.
Player.h:
#ifndef _TAG_PLAYER
#define _TAG_PLAYER
#pragma once
#include "Tile.h"
#include "Point.h"
class CGame;
class CPlayer : public CTile
{
public:
CPlayer(Point pos, CGame* game);
~CPlayer();
char getDisplay() ;
virtual bool canMove(const Direction direction, Point p) ;
virtual void move(const Direction direction, Point p);
bool CheckForHome() ;
};
#endif _TAG_PLAYER
Player.cpp:
#include "Box.h"
#include "Level.h"
#include "Tile.h"
CPlayer::CPlayer(Point pos, CGame* game)
{
this->game=game;
Point p;
p.x=0;
p.y=0;
setPosition(p);
}
CPlayer::~CPlayer()
{
}
bool CPlayer::CheckForHome() {
Point p = getPosition();
bool OnHomeTile;
if(game->getLevel()->getTiles()[p.y][ p.x] == GOAL)
{
OnHomeTile = true;
} else {
OnHomeTile = false;
}
return OnHomeTile;
}
char CPlayer::getDisplay()
{
if (CheckForHome())
{
return SOKOBANONGOAL_CHAR;
}
else
{
return PLAYER_CHAR;
}
}
Level.h:
#pragma once
#include "Point.h"
#include "Tile.h"
#include "Player.h"
#include "Box.h"
#include <list>
#include <string>
class CGame;
class CLevel
{
private:
list<CBox> boxes;
TileType tiles[GRID_HEIGHT][GRID_WIDTH];
CPlayer player(Point p, CGame* game); -> new declaration
//CPlayer player; -> old declaration
protected:
CGame* game;
public:
CLevel();
~CLevel();
CPlayer* getPlayer();
list<CBox>* getBoxes();
TileType (*getTiles())[GRID_WIDTH];
};
Constructor of Level.cpp
CLevel::CLevel()
{
this->game=game;
Point p;
p.x=0;
p.y=0;
player(p,game);
memset(tiles, GROUND, sizeof(TileType)*GRID_HEIGHT*GRID_WIDTH);
}
The function with the error in Level.cpp:
CPlayer* CLevel::getPlayer()
{
return &player;
}
Currently you've declared player as a member function not a member variable, which is why you're getting the weird error message. You can't mix the declaration and the initialisation of member variables like this.
You declaration should just be
CPlayer player;
But your CLevel constructor needs to initialise it, for example like:
CLevel() : player(Point(0, 0), game) { }
The problem with that though is that currently CLevel doesn't have a game to initialise the player with. Perhaps you could pass the game to the constructor of CLevel?
I think you need to read up on constructors and initialisation of members a bit more.