How to restore a sprite to its original image after replacing it with another one in coco2dx?

In my game context, the sprite is a smiling child, when the child touches, the current image of the sprite changed to a crying child, and then after 3 seconds of the screaming sound effect has ended, the sprite will return to the smiling child.

My problem

  • How do I go back with the previous image?

I changed the smiling child to the crying one, but I have no idea how can I change it to the original smile?

  1. How to ensure one click at a time? Every time the child copes, the sound starts playing, which is not ideal because I hope the event function is only called after the previous process has finished.

here is my code and thanks a lot!

bool HelloWorld::init()
{
    // 1. super init first
if ( !Layer::init() )
{
    return false;
}

Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

//add background scene
auto backgroundSprite = Sprite :: create("scene001.jpg");
backgroundSprite->setAnchorPoint(Vec2(0,0));
backgroundSprite->setScaleX((visibleSize.width / backgroundSprite->getContentSize().width) * 1);
backgroundSprite->setScaleY((visibleSize.height / backgroundSprite->getContentSize().height) * 1);
addChild(backgroundSprite);

//add smileBaby sprite
auto smileBabySprite = Sprite :: create("figure001.png");

smileBabySprite -> setPosition(Vec2(500,400));
addChild(smileBabySprite);

//add crying audio
auto audio = CocosDenshion::SimpleAudioEngine::getInstance();

auto babyListener = EventListenerTouchOneByOne::create();
babyListener -> onTouchBegan = [smileBabySprite, audio](Touch* touch, Event* event)
{
    //change smileBaby sprite to cryingBaby sprite
    smileBabySprite->setTexture(CCTextureCache::sharedTextureCache()->addImage("figure002.png"));
    audio -> playEffect("babycry.mp3",false,1.0f,1.0f,1.0f);

    return true;
};

babyListener -> onTouchEnded=[smileBabySprite](Touch* touch, Event* event )
{

};



_eventDispatcher -> addEventListenerWithSceneGraphPriority(babyListener, this);

return true;

      

}

+3


source to share


1 answer


What you want is to maintain the state whether the baby is crying or not. It is best to keep this logic in a custom subclass Node

.

Here's some (almost pseudo) code to get you started:

Baby.h:

#pragma once

#include "cocos2d.h"

class Baby : public cocos2d::Node
{
private:
    cocos2d::Sprite *_sprite;    // Weak reference
    bool _crying;
    float _cryingTime;

public:
    CREATE_FUNC(Baby);

protected:
    virtual bool init() override;
    virtual void update(float delta) override;

public:
    void touched();
    bool isInside(cocos2d::Touch *touch) const
protected:
    void setSprite();
};

      

Baby.cpp:

#include "Baby.h"

USING_NS_CC;

bool Baby::init()
{
    if (!Node::init())
        return false;
    _crying = false;
    setSprite();
    scheduleUpdate();
    return true;
}

void Baby::update(float delta)
{
    Node::update(delta);
    if (_crying) {
        _cryingTime -= delta;
        if (_cryingTime <= 0.0f) {
            _crying = false;
            setSprite();
        }
    }
}

void Baby::touched()
{
    if (_crying)
        return;      // Already crying
    _crying = true;
    _cryingTime = 3.0f;    // Length of audio, I guess?
    setSprite();

    // Start crying sound here
}

bool Baby::isInside(Touch *touch) const
{
    Vec2 locationInNode = _sprite->convertToNodeSpace(touch->getLocation());
    Size size = _sprite->getContentSize();
    Rect rect = Rect(0.0f, 0.0f, size.width, size.height);
    return rect.containsPoint(locationInNode);
}

void Baby::setSprite()
{
    if (_sprite)
        _sprite->removeFromParent();

    _sprite = Sprite::initWithFile(_crying ? "baby_crying.png" : "baby.png");
    Vec2 size = getContentSize();
    _sprite->setPosition(size.width * 0.5f, size.height * 0.5f);
    addChild(_sprite);
}

      



You add a Baby

node to the parent instead of the sprite using:

_baby = Baby::create();
_baby->setPosition(Wherever);
addChild(_baby);

      

Where _baby

is an instance variable and uses a method isInside()

to check if the touch event is within the sprite and calls its method touched()

:

Touch *touch = ...;
if (_baby->isInside(touch)) {
    _baby->touched();
}

      

and the object Baby

ignores touch depending on the state.

+2


source







All Articles