Recreating scene or repositioning sprites?

im profiling my game right now and some people are telling after they push the try again button it kind of lags at first, right now the try again button is just recreating the gamescene over and over , is this the right thing to do or would it be better to just re position the sprites to where they are at the beginning of the game instead of keep recreating the game scene ?

It’s hard to say without seeing your scenes themselves, but having delays is pretty bad. What about having all the sprites cached between scenes, so even if you rebuild the scene, you already have the sprites built?

There’s the threading thing you can do to make the loading happen in the background too.

this is an overview of what my scene look slike I have all the sprites in the update method and they are just moving from bottom of screen to the top and then once they reach the top being repositioned at the bottom

class LevelOne : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();

virtual bool init();
// implement the "static create()" method manually
CREATE_FUNC(LevelOne);

void update( float dt );

cocos2d::Sprite *ball;

cocos2d::Sprite *red1left;
cocos2d::Sprite *red1right;

cocos2d::Sprite *green2left;
cocos2d::Sprite *green2right;

cocos2d::Sprite *yellow3left;
cocos2d::Sprite *yellow3right;

cocos2d::Sprite *red4left;
cocos2d::Sprite *red4right;

cocos2d::Sprite *green5left;
cocos2d::Sprite *green5right;

cocos2d::Sprite *yellow6left;
cocos2d::Sprite *yellow6right;

cocos2d::Sprite *red7left;
cocos2d::Sprite *red7right;

cocos2d::Sprite *green8left;
cocos2d::Sprite *green8right;

cocos2d::Sprite *yellow9left;
cocos2d::Sprite *yellow9right;

cocos2d::Sprite *red10left;
cocos2d::Sprite *red10right;

cocos2d::Sprite *green11left;
cocos2d::Sprite *green11right;

cocos2d::Sprite *yellow12left;
cocos2d::Sprite *yellow12right;



bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event);
void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event);

bool onContactBegin(cocos2d::PhysicsContact &contact);


bool moveLeft = false;
bool moveRight = false;


int start = 0;
// 0 = false
// 1 = true
// 2 = gameover

bool scoreOne = false;
bool scoreTwo = false;
bool scoreThree = false;
bool scoreFour = false;
bool scoreFive = false;
bool scoreSix = false;
bool scoreSeven = false;
bool scoreEight = false;
bool scoreNine = false;
bool scoreTen = false;
bool scoreEleven = false;
bool scoreTwelve = false;

void Try();
void Share();
void LevelSelect();

cocos2d::ui::Button *tryagain;
cocos2d::ui::Button *shareB;
cocos2d::ui::Button *levelselectB;

unsigned int score;
cocos2d::Label *scoreLabel;
cocos2d::Label *scoreFinal;
cocos2d::Label *highScore;

cocos2d::Label *gameLabel;
cocos2d::Label *overLabel;
cocos2d::Label *startL;

cocos2d::Sprite *highscorebox;

};

#endif // LEVELONE_SCENE_H

Are you using a texture map for all those sprites? like loading from a spriteframe instead of from disk? I use TexturePacker for that and it helps cut down loading times. Although if you get the sprite once, pretty sure cocos2dx caches the texture in the future.

1 Like

no im not sure what a texture map is I just load them all like that, but it doesn’t always lag at the beginnging only sometimes thats why im confused on what it could do, one beta tester told me it only lagged 2 out of 10 times. its also weird because hes testing on an iphoneX, and I tested on lowend android and iphone6 and I haven’t seen the lag

I noticed in docs it says “Also don’t do heavy compute operations in your game loop which means don’t let the heavy operations called 60 times per frame.” if not in our game loop then where should we do these operations ? i feel like I kind of have a lot of stuff going on in my game loop but not sure where else I could place it or does it look alrite to you ?

   void LevelOne::update(float dt)
 {
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

auto ballPosition = ball->getPosition();

if(start == 1) {

if(moveLeft == true){
    
    ball->setPositionX(ball->getPositionX() - 9);
    
    if(ballPosition.x <= origin.x + 15){
        ball->setPositionX(origin.x + 15);
    }
    
} else if(moveRight == true)
{
    ball->setPositionX(ball->getPositionX() + 9);
    
    if(ballPosition.x >= visibleSize.width - 15){
        ball->setPositionX(visibleSize.width - 15);
    }
    
    
}
    

auto position = red1left->getPosition();
auto position2 = green2left->getPosition();
auto position3 = yellow3left->getPosition();
auto position4 = red4left->getPosition();
auto position5 = green5left->getPosition();
auto position6 = yellow6left->getPosition();
auto position7 = red7left->getPosition();
auto position8 = green8left->getPosition();
auto position9 = yellow9left->getPosition();
auto position10 = red10left->getPosition();
auto position11 = green11left->getPosition();
auto position12 = yellow12left->getPosition();
    
position.y += 4.8;
position2.y += 4.8;
position3.y += 4.8;
position4.y += 4.8;
position5.y += 4.8;
position6.y += 4.8;
position7.y += 4.8;
position8.y += 4.8;
position9.y += 4.8;
position10.y += 4.8;
position11.y += 4.8;
position12.y += 4.8;


if(position.y > visibleSize.height + 60) {
    
    int random = arc4random_uniform(45);
    
    position.y = position12.y - 216;
    position.x = random + 201;
    red1right->setPositionX(position.x + 708);
    scoreOne = false;
    
}
    
    if(ballPosition.y < position.y && scoreOne == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("greenball.png");
        scoreOne = true;
    }


if(position2.y > visibleSize.height + 60){
    position2.y = position.y - 216;
    scoreTwo = false;
}
    
    if(ballPosition.y < position2.y && scoreTwo == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("yellowball.png");
        scoreTwo = true;
    }

if(position3.y > visibleSize.height + 60){
    
    int random = arc4random_uniform(45);
    
    position3.y = position2.y - 216;
    position3.x = random + 201;
    yellow3right->setPositionX(position3.x + 708);
    scoreThree = false;
}
    
    if(ballPosition.y < position3.y && scoreThree == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("redball.png");
        scoreThree = true;
    }

if(position4.y > visibleSize.height + 60){
    position4.y = position3.y - 216;
    scoreFour = false;
}

    if(ballPosition.y < position4.y && scoreFour == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("greenball.png");
        scoreFour = true;
    }
    
if(position5.y > visibleSize.height + 60){
    
    int random = arc4random_uniform(45);
    
    position5.y = position4.y - 216;
    position5.x = random + 201;
    green5right->setPositionX(position5.x + 708);
    
    scoreFive = false;
}
    
    if(ballPosition.y < position5.y && scoreFive == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("yellowball.png");
        scoreFive = true;
    }

if(position6.y > visibleSize.height + 60){
    position6.y = position5.y - 216;
    scoreSix = false;
}
    
    if(ballPosition.y < position6.y && scoreSix == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("redball.png");
        scoreSix = true;
    }

if(position7.y > visibleSize.height + 60){
    
    int random = arc4random_uniform(45);
    
    position7.y = position6.y - 216;
    position7.x = random + 201;
    red7right->setPositionX(position7.x + 708);
    
    scoreSeven = false;
}
    
    if(ballPosition.y < position7.y && scoreSeven == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("greenball.png");
        scoreSeven = true;
    }

if(position8.y > visibleSize.height + 60){
    position8.y = position7.y - 216;
    
    scoreEight = false;
}
    
    if(ballPosition.y < position8.y && scoreEight == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("yellowball.png");
        scoreEight = true;
    }
    
if(position9.y > visibleSize.height + 60){
    
    int random = arc4random_uniform(45);
    
    position9.y = position8.y - 216;
    position9.x = random + 201;
    yellow9right->setPositionX(position9.x + 708);

    scoreNine = false;
}
    
    if(ballPosition.y < position9.y && scoreNine == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("redball.png");
        scoreNine = true;
    }

if(position10.y > visibleSize.height + 60){
    position10.y = position9.y - 216;
    scoreTen = false;
}
    
    if(ballPosition.y < position10.y && scoreTen == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("greenball.png");
        scoreTen = true;
    }

if(position11.y > visibleSize.height + 60){
    
    int random = arc4random_uniform(45);
    
    position11.y = position10.y - 216;
    position11.x = random + 201;
    green11right->setPositionX(position11.x + 708);
    scoreEleven = false;
}
    
    if(ballPosition.y < position11.y && scoreEleven == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("yellowball.png");
        scoreEleven = true;
    }

if(position12.y > visibleSize.height + 60){
    position12.y = position11.y - 216;
    scoreTwelve = false;
}
    
    if(ballPosition.y < position12.y && scoreTwelve == false){
        SimpleAudioEngine::getInstance()->playEffect("Drip.wav");
        score++;
        __String *tempScore = __String::createWithFormat("%i", score );
        scoreLabel->setString(tempScore->getCString());
        ball->setTexture("redball.png");
        scoreTwelve = true;
    }


red1left->setPosition(position);
red1right->setPositionY(position.y);

green2left->setPosition(position2);
green2right->setPositionY(position2.y);

yellow3left->setPosition(position3);
yellow3right->setPositionY(position3.y);

red4left->setPosition(position4);
red4right->setPositionY(position4.y);

green5left->setPosition(position5);
green5right->setPositionY(position5.y);

yellow6left->setPosition(position6);
yellow6right->setPositionY(position6.y);

red7left->setPosition(position7);
red7right->setPositionY(position7.y);

green8left->setPosition(position8);
green8right->setPositionY(position8.y);

yellow9left->setPosition(position9);
yellow9right->setPositionY(position9.y);

red10left->setPosition(position10);
red10right->setPositionY(position10.y);

green11left->setPosition(position11);
green11right->setPositionY(position11.y);

yellow12left->setPosition(position12);
yellow12right->setPositionY(position12.y);
    
}

}

The indentation is all wrong in that, so it’s a little tough to read but I didn’t see anything egregious within it.

What the docs are saying is that you shouldn’t do stuff like regenerate all the AIs pathfinding nodes every frame, or like rebuild the entire scene every frame. Do as little as you can as often as you can, if you want to put it vaguely.

Having variableXXX is always a sign you’re doing something wrong, is there no way you can use a loop for this stuff or something?

2 Likes

I’m not sure how I could put it in a loop , because their all different sprites ? Another weird thing only the ball sprite lags , and the framerate stays at 60 but it’s lagging I don’t get it ?

I am not sure if it will solve your lag issue, but maybe instead of using ‘static’ speed use frame time for calculating new position, e.g. newPositionX = oldPositionX + dt * speedX.

1 Like

The way you’re moving sprites around is what may be causing the “lags”, or what would more likely be jerkiness in the movement. You should considering using interpolation, and not simply adding a value to the X or Y position on every update.

The way to do this would be to use Actions. Check out the MoveTo, MoveBy actions etc. In the cpp-tests project they have a lot of examples of how actions work, so run the demo and you’ll quickly figure out if they’re useful for your specific case.

1 Like

I was thinking it might be his touch screen responding late because all the sprites move fine and screen stays at 60fps , only the ball doesnt move sometimes when he presses the screen (he’s using an iPhoneX)

Does anyone know is it bad practice to preload audio in a init method in my game scene ? Because when I push try again button it calls the init method to preload background music again and it does this every time the player pushes (try again) the scene gets recreated & audio gets preloaded, does the sound keep getting loaded or does it not have any effect, or it doesn’t matter since audio was already loaded once , preloadBackground music doesn’t matter getting called on each time the game scene is created again ? Do I need to call unload effect and unlock background music since it will be gettinbrg preloaded again ?

Follow the function calls to see what the preload actually does, and then you’ll know if it there are any issues with calling it multiple times for the same resource.

You could also just have a separate scene which loads everything that is common to all of your game scenes (assuming you have more than one game scene), and once this scene is finished preloading resources, then you go into the game scene. What happens then is every time you recreate the game scene, it won’t be recreating the loading scene, so you won’t have any problems. This assumes you don’t unload the resources.

Another option is to create some kind of resource manager that keeps track of what you have loaded, so all loads and unloads go through it. Implement it as a singleton to make your life easier, so it’s persistent regardless of which scenes you create and destroy.

1 Like

I figure out the issue, for some reason onTouchBegan is not being called sometimes, could this have to do with not having implemented onTouchMoved ? i only implemented on touchBegan and onTouchEnded i seen here (http://ttaiit.blogspot.com/2015/01/tutorial-create-first-simple-game-touch.html) it says “Although we don’t use all three functions, but for Touch event to process completely, you must declare all three functions as follow:” this is all I can think of why touchBegan is not being called