I have a singleton class named GameManager.
GameManager.h
#include "cocos2d.h"
using namespace cocos2d;
class GameManager : private CCObject
{
public:
GameManager(void);
virtual ~GameManager(void);
virtual bool init(void);
static GameManager* sharedGameManager(void);
CC_SYNTHESIZE(CCString*, email, Email);
CC_SYNTHESIZE(CCString*, nickName, NickName);
CC_SYNTHESIZE(int, currentGame, CurrentGame);
CCArray* gamesArray;
};
GameManager.cpp
#include "GameManager.h"
static GameManager* _sharedGameManager = NULL;
GameManager* GameManager::sharedGameManager(void)
{
if (!_sharedGameManager)
{
_sharedGameManager = new GameManager;
_sharedGameManager->init();
}
return _sharedGameManager;
}
GameManager::GameManager(void)
{
}
GameManager::~GameManager(void)
{
email->release();
nickName->release();
gamesArray->release();
}
bool GameManager::init()
{
CCLOG("GameManager Created");
email = CCString::create("");
email->retain();
nickName = CCString::create("");
nickName->retain();
currentGame = 0;
gamesArray = CCArray::create();
gamesArray->retain();
return true;
}
and I create the GameManager in my login page with
GameManager::sharedGameManager();
the flow of my app goes:
Login.cpp -> GameList.cpp -> GameScreen.cpp
In the login page I store the account email and nickname and also the gamesArray which is created within that page:
//store user info to gamemanager
GameManager::sharedGameManager()->setEmail((CCString*) parseOne->objectAtIndex(3));
GameManager::sharedGameManager()->setNickName((CCString*) parseOne->objectAtIndex(7));
GameManager::sharedGameManager()->gamesArray = gameObjectArray;
once the user has logged in, the GameList is created using the GameManager info.
so the info from the singleton exists at this point.
the GameList page creates a GameObject for each game in the gamesArray. each GameObject has a child button attached to it which is used to goto the GameScreen and saves that GameObjects id to the GameManager
GameManager::sharedGameManager()->setCurrentGame(gameNumber);
CCDirector * pDirector = CCDirector::sharedDirector();
CCScene* pScene = GameScreenScene::scene();
pDirector->replaceScene(pScene);
Now the weird part, when I get to the GameScreenScene the data from the GameManager is gone, except for the currentGame which is still showing the right values.
I have put in some logs to diagnose the problem but I can't seem to figure it out.
I can read the values right before the GameListScene changes to the GameScreenScene, but once it changes the values are gone.
I also tried reading the data in the GameObject button call, but the data also doesn't exist there also.
I can add more code if it can help figure this out, I just didn't want to flood this if it was something easy.
Any help would be awesome.
You are not retaining your autorelease objects (i.e, email and name strings) resulting in deletion of its data when it is released. The reason currentGame is still there is that it is an int (not an autorelease pointer).
You can use CC_SYNTHESIZE_RETAIN instead of CC_SYNTHESIZE to retain these two string to automatically retain them.
If i am right,
Constructor of CCObject (maybe Init() function) calls autorelease() and instances which are not attached to scenes automately destroy after one frame even if it is singleton instance.
I think your GameManager class have no reason to inherit from CCObject.
Related
Unity3D 2018.2
So I have a canvas that gets deactivated and reactivated at users choice. I have a List filled with transforms in which I populated the Grid with. I also have another List to hold all the images that will be used to populate the Grid with, since what the grid is being populated with are buttons containing the transform. For example if I click the button and run Debug.Log("transform.name"), I should see all my different transforms.
Problem 1: Every time this canvas gets enabled or disabled, the grid
keeps adding 1 element under the initial one, and after being
enabled/disabled again, another element is instantiated under that
one.
+
Problem 2: Also none of these instantiated buttons get called. Maybe
the problem here is due to the 1st problem?
Here is the code I have for inside the button I have
public class SatelliteButton : MonoBehaviour {
[SerializeField]
private Image myIcon;
public void SetIcon(Sprite mySprite)
{
myIcon.sprite = mySprite;
}
public void OnMouseEnter()
{
Debug.Log(transform.name);
}
}
Here is the code for populating the grid
public class SatelliteGridControl : MonoBehaviour {
private List<Transform> satelliteListFromPlanet;
[SerializeField]
private GameObject buttonTemplate;
[SerializeField]
private GridLayoutGroup gridGroup;
[SerializeField]
private List<Sprite> iconSprites;
// Use this for initialization
void OnEnable()
{
getSatellitesInPlanet();
genInventory();
}
// Get Satellites
private void getSatellitesInPlanet()
{
satelliteListFromPlanet = new List<Transform>();
// Get current planet
Transform currentPlanet = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<HandleCamera>().targetToLookAt;
// Check inside for satellites
foreach (Transform satellite in currentPlanet)
{
// Check transform for tag
if (satellite.CompareTag("Satellite"))
{
// Add each transform from planet to array
satelliteListFromPlanet.Add(satellite);
}
}
}
// Handle Grid
private void genInventory()
{
if (satelliteListFromPlanet.Count < 6)
{
gridGroup.constraintCount = satelliteListFromPlanet.Count;
}
else
{
gridGroup.constraintCount = 5;
}
foreach (Transform sat in satelliteListFromPlanet)
{
GameObject newButton = Instantiate(buttonTemplate) as GameObject;
newButton.SetActive(true);
newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
newButton.transform.SetParent(buttonTemplate.transform.parent, false);
}
}
}
I appreciate the help! Learning about grid layouts with List<>!
In genInventory() you Instantiate a new button for every Transform in satelliteListFromPlanet. Since only 1 is added it seems that your list only contains 1 element.
But you never destroy/remove this Instantiated GameObjects, so the next time you re-enable the object, OnEnable will be called again and new prefabs are Instantiated.
Solution:
Make sure to store the Instantiated objects somewhere e.g.
private List<GameObject> instances = new List<GameObject>();
//....
foreach (Transform sat in satelliteListFromPlanet)
{
GameObject newButton = Instantiate(buttonTemplate) as GameObject;
newButton.SetActive(true);
newButton.GetComponent<SatelliteButton>().SetIcon(iconSprites[Random.Range(0, iconSprites.Count)]);
newButton.transform.SetParent(buttonTemplate.transform.parent, false);
instances.Add(newButton);
}
And than you can destroy them when you disable the object:
private void OnDisable()
{
foreach(var instance in instances)
{
Destroy(instance);
}
}
Problem 1: Every time this canvas gets enabled or disabled, the grid keeps adding 1 element under the initial one, and after being enabled/disabled again, another element is instantiated under that one.
Right now you're calling getSatellitesInPlanet() on SatelliteGridControl's OnEnabled() method. This method is called every time the object is set to active. If you just want to call your method once, use Start.
Problem 2: Also none of these instantiated buttons get called. Maybe
the problem here is due to the 1st problem?
I don't think the problems are related. Can you confirm that your buttonTemplate prefab has an Image element and its RaycastTarget is enabled?
Just one tip, I would set the type of buttonTemplate to SatelliteButton, not GameObject. That way you can instantiate it as type SatelliteButton and avoid the need to call:
newButton.GetComponent<SatelliteButton>()
I've looked around but couldn't find what I'm looking for (not sure what keywords to use). I'm working on a C++ project myself. This project has windows, pages and fields. A window can contain one or more pages, and a page can contain one or more fields. What's shared across the window, page and field is they have an InputManager which takes care of all the IO of the user. The InputManager can act on the window, the page and the field (for example, some inputs act directly on the page, while some act on the field). Also, a field can generate status messages to be displayed at a location of the containing window.
Right now I have the following structure, but it doesn't seem optimal. There's a lot of pointer passing down, and I'm wondering if there's a better way to do so.
class InputManager
{
//do stuff to return input
}
class StatusManager
{
//do stuff to display statuses
}
class Field
{
friend class Page;
protected:
InputManager *input_manager;
StatusManager *status_manager;
/*
other methods that do stuff that
may recieve from input_manager and
send statuses through the status_manager
*/
}
class Page
{
friend class Window;
protected:
vector<Field* > fields;
InputManager *input_manager;
StatusManager *status_manager;
public:
AddField(Field *field)
{
field->input_manager = this->input_manager;
field->status_manager = this->status_manager;
}
}
class Window
{
protected:
vector<Page *> pages;
InputManager *input_manager;
StatusManager *status_manager;
public:
Window()
{
input_manager = new InputManager();
status_manager = new StatusManager();
}
AddPage(Page *page)
{
page->input_manager = this->input_manager;
page->status_manager = this->status_manager;
}
}
If I want to learn more about these types of problem, what keywords or fields should I be looking into?
Consider there are two classes, named User and Player. These classes, superficially, refer to users (accounts) in a game and players of them. Each user has one player, whereas each player could be owned by single user.
When user wants to join a game, a Player instance is created and the game abstraction will own the including players.
The instances of class Player should not be created by anyone other than a User. To be more precise, User has a method Player *createPlayer(...) in order to create a Player.
How this could be achieved? I considered User class could inherit from Player, so with a protected constructor of Player it will be okay. However, you know, this is ultimately odd. We would like to inherit Player from User, not the opposite.
Pseudocode of classes (as suggested by AndyG):
class User {
String username
String password
func createPlayer(type: GameType, owner: Game) {
var player = Player(type: type, owner: owner)
return player
}
}
class Player {
private(set) Game owner
private(set) GameType type
Set<Weapon> loadout
UInt kills
UInt deaths
init(type: GameType, owner: Game) {
self.type = type
self.owner = owner
}
}
Usage:
var user = User() // consider this gives you user
var game = Game() // consider there is a game
var player = user.createPlayer(.Deathmatch, game) // the way we should create it
var anotherPlayer = Player(.Deathmatch, game) // oops, compiler error.
You make Player's constructor private, and Player declares User to be a friend. Then createPlayer can call Player's constructor normally, but no other class can. Try not to declare any other friends for Player, using friend is ok in certain situations but overuse is generally a bad sign.
I have a collection of related classes, call them
class Manager {
private:
std::vector<Setting> m_settings;
}
class Setting {
private:
std::vector<Action> m_actions;
}
class Action {
private:
Keybind m_keybind;
}
class Keybind {
public:
UpdateKeybind;
private:
TYPE keybind;
}
As you can see from the pseudo-C++ code, Settings have actions, and actions have exactly one key binding. Now, as a user of my application you want to update the Keybind potentially, yes?
I currently have buttons in a keybind-type dialog associated with each action, so the action can handle updating it's own keybind.
My Problem:
How do I ensure that the Keybinding isn't bound to another object?
Possible solutions:
Move UpdateKeybind itself to the Manager class, then have Manager query all the settings.
Have a parent pointer in Action/Setting/Keybind so the Action can query the manager for updated keybind.
Have the Action query other Actions (not great conceptually as far as I can tell).
What I need from you:
What is the most rigorous approach, in terms of maintainability, speed, ease of understanding, and OOP appropriateness, to implementing checking if a Keybind is already found, whether out of my suggested solutions or something else entirely. I have already tried number 1 -- it works, but I feel like it could be better, ya dig?
I was unable to find similar questions on StackOverflow, but if you do I'd love to see them!
Any other pro tips, things to improve are helpful.
Just like #Amardeep says, you can try creating a class managing the mapping between actions and keybindings. Following is an example. It will automatically remove the keybind to the action if the there is new binding to that keybind.
class Manager {
private:
std::vector<Setting*> m_settings;
KeybindPool *m_keybindPool;
};
class Setting {
private:
std::vector<Action*> m_actions;
};
class Action {
public:
void Bind(Keybind* keybind) {
m_manager->m_keybindPool->Update(this, keybind)
}
Keybind* getKeybind() const {
return m_manager->m_keybindPool->getKeybind(this);
}
private:
Manager *m_manager;
};
class KeybindPool {
public:
void Update(Action* action, Keybind* keybind) {
if (m_keybindActionMap.find(keybind) != m_keybindActionMap.end()) {
m_actionKeybindMap.erase(action);
}
m_keybindActionMap[keybind] = action;
m_actionKeybindMap[action] = keybind;
}
Keybind* getKeybind(Action* action) {
return m_actionKeybindMap[action];
}
private:
map<Keybind*, Action*> m_keybindActionMap;
map<Action*, Keybind*> m_actionKeybindMap;
};
class Keybind {
private:
TYPE keybind;
}
Since you have an exactly 1:1 relationship between key bindings and actions, you could start with a pool of key binding objects and draw down from the pool as you configure actions. So when offering up available keys for configuration, any keys already bound would not be in the available pool.
Firstly, can anyone explain how a state object can be shared when the state object has no instance variables ?
This text is taken from GOF, page 308, item 3 (consequences section):
The state object can be shared.
If state objects have no instance variabkes - that is, the state they
represent is encoded entirely in their
type - then contexts can share a
state object. When states are shared in
this way, they are essentially
flyweight.
Can anyone explain this text ?
Secondly, what are the approaches to the state transition decision? I mean the decision of which next state to propagate?
Please help.
Thanks.
In the state pattern you have an represent the state of an object by using state-objects. These state-objects represent a certain state, but they do not have any mutable state of their own. This means they never change. Therefore, any number of objects can use the same state-object at the same time (even from different threads). If the state-object had mutable state, other objects would have to worry about their state-object being changed from elsewhere.
The using of one object instance by many others can be seen as an instance of the flyweight-pattern.
As for the second part of your question, here is an example:
class SomeStateMachine;
class AbstractState {
// abstract baseclass for all state-classes
void input(const std::string & data, SomeStateMachine & caller) = 0;
}
class FinalState : public AbstractState {
FinalState * getInstance(); // always returns same instance
}
class InitialState : public AbstractState {
public:
InitialState * getInstance(); // always returns same instance
void input(const std::string & data, SomeStateMachine & caller) {
std::cout << data << std::endl;
caller.m_State = FinalState::getInstance();
}
}
class SomeStateMachine {
public:
SomeStateMachine() : m_State(InitialState::getInstance())
void input(const std::string & data) {
m_State->input(data, *this);
}
private:
friend class InitialState;
AbstractState * m_State;
};
So you basically pass a reference to the calling object to every method of your state-object. This way, the state-object is able to change the state of the caller when needed. This example might not be very beautiful, but I hope you get the idea.
The paragraph is basically saying that you encode your states as individual classes - then the instance type is the "state" and the classes don't need any instance variables because their type encodes all the information you need.
E.g say I want to have three states "Open", "Active" and "Closed". I might define the following classes:
abstract class State {};
class Open extends State {
public Open() {}
}
class Active extends State {
public Active() {}
}
class Closed extends State {
public Closed() {}
}
--
Another option - I'd suspect this is the combination with flyweight being hinted at in the GOF text would be to create a state class which a bunch of static members (one for each state) which can then be shared -
public class State {
private string name;
private State(String name) {
this.name = name;
}
public final static State OPEN = new State("Open");
public final static State ACTIVE = new State("Active");
public final static State CLOSED = new State("Closed");
}
I had to go digging to remind myself of how all this stuff worked in detail. Kerievsky has a good description of this (I've heavily borrowed from one of his examples above!) and how the state transitions can be handled by sub-classing from the state class, to create classes that manage each transition. See "Refactoring to Patterns" (ISBN: 0321213351)
EDIT(2): His web site has a class diagram for his example - http://www.industriallogic.com/xp/refactoring/alteringConditionalsWithState.html