Cocos2DX --> Layer Instantiates Scene? - c++

Reading books and topics on Cocos2dx everyone seems to be teaching it like so:
Create a class that inherits from CCLayer
Within that CCLayer class, instantiate a Static SCENE
Add layout to scene
Metaphorically, it is like the Egg creates its Parent. This seems backwards, non-intuitive. Why not just do this:
Create a class that inherits from CCScene (call it GameScene)
Create another class that inherits from CCLayer (call it GameLayer)
The GameScene class is a singleton (has a singleton member: static GameScene* scene)
Instantiate the GameLayer class within the GameScene class
The GameLayer class will have the usual suspects: UPDATE, INIT, etc. and the GameScene class with have INIT and it's static self-referencing member.
While this may seem like more work, it really isn't and logically makes more sense, furthermore, it affords the developer a place, to place SCENE specific logic, and LAYER specific logic.
Are there any issues doing it this way? Why are so many teaching it backwards?
EXAMPLE:
# GameScene
#ifndef __GameScene__
#define __GameScene__
#include "cocos2d.h"
using namespace cocos2d;
class GameScene : public cocos2d::CCScene
{
public:
~GameScene();
virtual bool init();
static GameScene* scene();
CREATE_FUNC(GameScene);
};
#endif /* defined(__GameScene__) */
#include "GameScene.h"
#include "GameLayer.h"
GameScene::~GameScene() {}
GameScene* GameScene::scene()
{
GameScene *scene = GameScene::create();
GameLayer *layer = GameLayer::create();
scene->addChild(layer);
return scene;
}
bool GameScene::init()
{
if (!CCScene::init()) return false;
return true;
}
# GameLayer
#ifndef __GAMELAYER_H__
#define __GAMELAYER_H__
#include "cocos2d.h"
using namespace cocos2d;
class GameLayer : public cocos2d::CCLayer
{
public:
~GameLayer();
virtual bool init();
virtual void draw();
void update(float dt);
CREATE_FUNC(GameLayer);
};
#endif // __GAMELAYER_H__
#include "GameLayer.h"
GameLayer::~GameLayer() {}
bool GameLayer::init()
{
if (!CCLayer::init())
return false;
this->schedule(schedule_selector(GameLayer::update));
return true;
}
void GameLayer::draw() {}
void GameLayer::update(float dt) {}
And finally within the AppDelegate CPP
bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director
...
...
// Create a scene
GameScene *pScene = GameScene::scene();
// Run
pDirector->runWithScene(pScene);
return true;
}
I also have a thread on this topic on cocos2dx:
http://discuss.cocos2d-x.org/t/layer-instantiates-scene/18149/4

There is a confusion between base class names and the subclass names.
For instance in the cocos2d-x wiki they subclass from Layer (CCLayer) but they name this Layer subclass GameScene even though it isn't an actual scene, it's a layer. Further down they create the actual Scene (CCScene) instance with the call to createScene, which I assume returns a generic Scene instance with the GameScene instance added to the scene:
auto scene = GameScene::createScene();
Director::getInstance()->replaceScene(scene);
So you do end up with the following hierarchy:
Scene
Layer (custom class: GameScene)
Nodes...
Now the origin of this weird naming philosophy is simply that it has been going around in the cocos2d community for ages. In very early cocos2d-iphone project templates you had a HelloWorldScene class that inherited from CCLayer. It contained a class method scene that created an instance of CCScene, created a HelloWorldScene instance and added it to the generic scene instance before returning it.
So basically this is simply a confusion due to badly named subclasses in project templates, tutorials and books. Against all rational thought the "tradition" prevailed in cocos2d-x. In cocos2d-iphone this was eventually fixed (in v2.x I believe) by renaming the template class to HelloWorldLayer.

Rodger Engelbert author of Cocos2d-x by Example, Beginners Guide responded to this question via email.
Hi Jason,
There is no need to follow the strategy used in the template. In fact
I don't know anyone who does it outside the Cocos2d-x group and I only
ever used it in the examples for the book for consistency.
A Scene is unique, and it's what the director requires to run. It's
possible to have two scenes running during transitions, but otherwise
a scene is structurally treated as One block in your architecture. You
may or may not organize your project into multiple blocks, but you
will need at least one.
But you're free to do it in any way you wish. You might use scenes
more prominently, as some developers do or use one only, for the sake
of the Director, and focus on master Layer objects. Also, keep in mind
that the generated code in the template is only trying to give you a
canvas as quickly as possible. It's not necessary the best starting
point for your project. It's up to you to make that decision.
Roger

Related

Must I declare own wxFrame class?

I'm creating simple c++ application with user interface. I have written own classes with needed mechanics, and now I must display some of its components using wxWidgets. MyApp contains objects of that classes, but they are also needed in MyFrame when handling events. It would be much more comfortable without passing pointers to that objects to MyFrame and implement everything in MyApp::OnInit function. Is that possible?
// should contain informations about game state, players, gameboard, etc
class MyApp : public wxApp {
GameBoard gb;
Player player;
bool lightTheme;
public:
virtual bool OnInit();
};
// should contain only window layout, button events, etc
class MyFrame : public wxFrame {
GameBoard *gb;
Player *player;
bool *lightTheme;
std::vector<wxStaticBitmap*> cardImages;
// some events here
void displayImages(wxGridSizer*);
public:
MyFrame(GameBoard*, Player*, bool*);
};
To answer your title question, you don't have to declare MyFrame and can just create and directly use wxFrame and use Bind() to connect the different event handlers. In all but the simplest situations, it's typically convenient to have a MyFrame class centralizing the data and event handlers for the window, but it is not required by any means.
If you decide to keep everything in MyApp instead, you may find wxGetApp() useful for accessing it from various places in your code.

Use variable declared in MainWindow Qt

I have the following problem in Qt, I'm trying to make a chess-game and I'm encountering some problems:
In the class mainwindow I have the following function:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
scene = new ChessBoard;
QGraphicsView *view = new QGraphicsView(scene);
setCentralWidget(view);
connect(scene,SIGNAL(clicked(int,int)),this,SLOT(clicked(int,int)));
//!!!!!!!!!!
scene->setInitialPositions();
}
I have a variable scene, scene is an object of the class ChessBoard.
In the whole class mainwindow I can use the scene-variable to use functions declared in ChessBoard.
However, I have another class called game.
In game I have this function
void game::setStartBord() {
scene->setInitialPositions();
}
It simply needs to launch scene->setInitialPositions();
However, I don't have access to the 'scene-variable' there. I tried to inherit the ChessBoard and MainWindow class, tried to make scene global, but none really were a good solution.
How would I do that?
Full code is visibly here:
https://github.com/UA-Niel/chess
You can use signal and slot technique. Connect your game class object to scene object.
connect(game, &Game::mySignal, scene, &ChessBoard::setInitialPositions);
Define in your Game-Class the signal.
class Game .. {
..
signals:
void mySignal();
..
};
Then define setInitialPositions in your ChessBorard class in public slots.
class ChessBoard {
...
public slots:
<datatype> setInitialPositions();
};
Then use
emit mySignal(); from Game class
to execute setIntialPositions() in your ChessBoad class.
You need to design your code that you have access to both objects at some point. Mostly this is MainWindow because you intialize classes upon program start.
If your code does not depend on the intialized class.
You can simply do a new ChessBoard object in Game class
ChessBoard myObject;
myObject.setIntialPositions();

OOP - Is this bad practice?

I am making a game in C++ using SFML (although that doesn't matter) and am struggling to come up with a good design. Right now I have a game class that holds level objects. When you click a button in the level, it needs to change the current game level. The only way I can figure is to pass a pointer of the game and store it in each level so I can call functions from within the level, but this seems like extremely bad structure and organization. Is this bad or not and what might be a better structure to use instead?
Here is the game class:
#include "SFML/Graphics.hpp"
#include "mainMenu.h"
#include "levelMenu.h"
class Level;
class Game {
public:
Game() { mainMenu = MainMenu(this); }
void input();
void setLevel(Level* level);
LevelMenu& getLevelMenu() { return levelMenu; }
private:
Level* currLevel;
MainMenu mainMenu;
LevelMenu levelMenu;
};
And in my mainMenu class I want to make the game class's current class change to levelMenu:
#include "game.h"
class MainMenu {
public:
MainMenu(Game* game) { this->game = game; }
void input(sf::Event event) {
if (event.type == sf::Event::MouseButtonReleased) {
game->setLevel(game->getLevelMenu());
}
}
private:
Game* game;
};
I think that looks decent, just some general suggestions:
An abstract base class Menu that handles the Game-variable for you.
Learn to use references and shared pointers of various types.
Keep interface, game mechanics and objects fairly seperate, look up the basics of MVC, model view controller.
I'd suggest that you don't worry too much about design like this, it's highly likely that you will realize that your design doesn't work or is suboptimal down the line after building the rest of the game, and then you can rewrite it at that point having learnt a lot more when building the other subsystems.

Trying to access QGLWidget from entire application

What I am basically trying to do is to create one instance of a QGLWidget (or rather a derived class of QGLWidget), add it to a QMainWindow, and then access the QGLWidget's rendering context from anywhere in my QTCreator program to be able to call naked OpenGL anywhere I chose to.
Things I have tried:
1) Creating a subclass of QGLWidget called OGLWidget and making that into a singleton, and then trying to subclass the singleton class "OGLWidget". I thought this would give me access to the same rendering context that the OGLWidget singleton was using but it didn't work.
2) using the constructor QGLWidget(QWidget * parent, QGLWidget * shared, Qt::WindowFlags). For this one I tried casting the singleton object to a QGLWidget and then sticking it in this constructor when I was subclassing QGLWidget in another class called "Display". I tried calling makeCurrent before each classes openGl calls but only the original singleton would draw. I also checked isSharing and that returned true.
First of all, although signals\slots are a powerful and awesome feature of Qt I would never use them in my rendering routines because of the added overhead and render order problems; especially the latter. Besides, it's not necessary to do it the way you propose.
Thus, your idea of scattering the rendering routines all over your project is a very bad idea in my opinion.
What I do in my own project is the following:
My derived QGLWidget owns a Renderer class that's implemented as a Singleton. It contains all of the OpenGl calls in a few functions. I've created a system where everything that's drawable derives from the same base class. When I want to render, I build a render queue which I implemented as a priority_queue with custom sort function. When It's time for rendering a frame I just keep poppin' and rendering until the queue is empty.
Doing this with an event driven render system, while maintaining correct render order would probably drive you insane.
For completeness, my (simplified) QGLWidget definition:
#include <QtOpenGL/QGLWidget>
#include "global.h"
#include "renderer.h"
/**
* Derivation of QGLWidget.
*/
class Engine : public QGLWidget
{
Q_OBJECT
private:
Renderer* renderer;
private slots:
void renderTimeout(); // my render-loop is timer based
void onTap(QMouseEvent* qme);
void onMove(QMouseEvent* qme);
protected:
void initializeGL();
void resizeGL(int w, int h);
/* for debugging I use QPainter for drawing overlays,
* so I can't use PaintGL */
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent* qme);
void mouseMoveEvent(QMouseEvent* qme);
public:
Engine( QWidget* parent = 0 );
~Engine();
signals:
void tapOccurred(QMouseEvent* qme);
void moveOccurred(QMouseEvent* qme);
};
Why don't you just use what Qt has been designed for: use signals and slots? Maybe your problem is more complicated than what I get from it at first glance, but it seems to me that if you add slots to your QGLWidget and connect them to signals anywhere in your application, you accomplish exactly what you want. Connecting them can for example be done in the QMainWindow. This slot can then make a call to an implementation of paintGL() or paintEvent() to update the area in QGLWidget. Like this:
class MyQGLWidget : public QGLWidget {
// constructors and destructor...
protected:
void paintGL(); // <-- implement this in any way you want if you use OpenGL
void paintEvent(); // <-- or implement this one if you prefer using QPainter
public slots:
void updateMyWindow();
}
void MyQGLWidget::updateMyWindow() {
// Change some data here in any way you like
// ...
paintGL();
}

C++ / SDL encapsulation design help

So I am semi-new to C++, and completely new to SDL. Most of my conceptual knowledge of OOP comes from Java and PHP. So bear with me.
I am trying to work out some simple design logic with my program / soon to be side-scroller. My problem lies with trying to make my 'screen' layer (screen = SDL_SetVideoMode(...)) accessible to all my other classes; Hero class, background layer, enemies, etc. I have been loosely following some more procedural tutorials, and have been trying to adapt them to a more object oriented approach. Here is a little bit of what I have so far:
main.cpp
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Game Game;
//Load hero
Hero Hero(Game.screen);
//While game is running
while(Game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Draw
Game.DrawBackground();
Hero.drawHero();
//Update
Game.Update();
}
//Clean up
Game.Clean();
return 0;
}
As you can see, I have a Game class, and a Hero class. The Game class is responsible for setting up the initial window, and placing a background. It also updates the screen as you can see.
Now, since my Game class holds the 'screen' property, which is a handle for SDL_SetVideoMode, I am stuck passing this into any other class (ex: Hero Hero(Game.screen);) that needs to update to this screen... say via SDL_BlitSurface.
Now, this works, however I am getting the idea there has GOT to be a more elegant approach. Like possibly keeping that screen handler on the global scope (if possible)?
TLDR / Simple version: What is the best way to go about making my window / screen handler accessible to all my subsequent classes?
I like the way you are doing it.
Though rather than passing the screen reference I would pass a reference to a game itself. Thus each hero object knows which game it belongs too, it can then ask the game object for the screen as required.
The reason I would do this is so that in a few years when your game is a wide and successful product and you convert it for online-play you really need to do no work. The game server will be able to easily support multiple game objects, each game object hosting multiple hero objects. As each hero object wants to draw it asks the game for the screen abd updates the screen (the screen can now very from game object to game object and still work perfectly (as long as they have the same interface).
class Game
{
public:
Game(Screen& screen)
: screen(screen)
{}
virtual ~Game() {}
virtual Screen& screen() { return theGameScreen;}
void update() { /* Draw Screen. Then draw all the heros */ }
private:
friend Hero::Hero(Game&);
friend Hero::~Hero();
void addHero(Hero& newHero) {herosInGame.push_back(&newHero);}
void delHero(Hero& newHeor) {/* Delete Hero from herosInGame */}
// Implementation detail about how a game stores a screen
// I do not have enough context only that a Game should have one
// So theoretically:
Screen& theGameScreen;
std::vector<Hero*> herosInGame;
};
class Hero
{
public:
Hero(Game& game)
: game(game)
{game.addHero(*this);}
virtual ~Hero()
{game.delHero(*this);}
virtual void Draw(Screen& screen) {/* Draw a hero on the screen */}
private:
Game& game;
};
Main.
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Screen aScreenObject
Game game(aScreenObject);
//Load hero
Hero hero(game); // or create one hero object for each player
//While game is running
while(game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Update
Game.update();
}
//Clean up
// Game.Clean(); Don't do this
// This is what the destructor is for.
}
I don't know if it's elegant, but what I do for the side-scrolling game I'm making is to make a show() function in each class than draws to the screen, and passing the screen handle as a parameter. Then whenever I want to draw something to the screen I just do foo.show(screen). The screen handle is in main().
The first, and honestly, easiest solution, is to use a global variable. Yes, yes, yes, everyone says global variables are horrible, but in this situation, it's perfectly fine.
The other solution, which is a bit more work, but can result in somewhat more portable code, is to encapsulate your drawing functions into a single, static class. This way, you can draw to the screen directly without having to pass around a variable, or have to lie awake at night thinking the code review police will get you because you used a global variable. Plus, this can potentially make it easier if you ever decide to port your game to a new library. Some quick and dirty pseudocode:
class Drawing
public:
static void Draw(x, y, sdl_surface graphic, sdl_rect & clip=null);
static void init(sdl_surface & screen);
private:
sdl_surface screen;
void Drawing::Draw(x, y, sdl_surface graphic, sdl_rect & clip=null)
{
sdl_blit(x, y, graphic, clip);
}
void Drawing::init(sdl_surface & screen)
{
this.screen=screen;
}
It sounds like you're looking for a way to implement the Singleton design pattern, where you would have a single Screen object. If you know you're only ever going to have a single Screen object it should work fine.
In this case you would implement a static method on the Game class:
class Game
{
public:
static Game *GetTheSceenObject();
private:
static Screen *theScreen; // details of initialisation ommitted
}
that would return a pointer to the single Screen object.
If there is a possibility that you'll end up using multiple SDL screens, though, it may be worth creating a Draw() method in your Hero class that is responsible for drawing the hero on each of the Screens managed by the Game class by iterating through a list provided by the Game class.
That functionality could be contained in the methods of a common DrawableThingy class that Hero and Enemy are derived from.
Passing Game.screen around is more OO (though it might be better to have a getter function) than having one instance of it that can be accessed from any class, because if you have one global version, you can't have more than one Game.screen at any one time.
However if you know you'll only ever need one in the entire lifetime of the program, you might consider making Game::Screen() a public static function in the Game class that returns a private static member screen. That way, anyone can call Game::Screen() and get the screen.
Example (assuming ScreenType is the type of screen and that you store a pointer to it):
class Game {
public:
static ScreenType* Screen() {
if (!screen)
screen = GetScreenType(args);
return screen;
}
}
private:
// if you don't already know:
// static means only one of this variable exists, *not* one per instance
// so there is only one no matter how many instances you make
// the same applies to static functions, which you don't need an instance to call
static ScreenType* screen;
};
// and somewhere in a .cpp file
ScreenType* Game::screen = NULL;
// and you use it like this
ScreenType* scr = Game::Screen();
// use scr