Typewriting effect?

Hi,

How to add typewriting effect to a label, like in rpg games, so it feels like someone is typing the text…

Thanks…

Create Label. Loop through letters getLetter(i) and letter->setOpacity(0). Schedule an update and update the next letter’s opacity to 255. Unschedule update once all letters are visible. Could also add if a second action input then loop through again, set all to 255, and unschedule update to allow for skipping the animation.

1 Like

Thanks… :grinning:

Thanks @stevetranby for your response.

I am a bit new to the Cocos universe and I find your explanation a little confusing. Can you explain it to me a little more?

I’m studying using the Cocos Beginner’s book.

UPDATES:
. I got the creation of the Label, I am going now to make the loop.
. And that is the far I got.

Thanks once again.

here’s the code, if any doubt let me know -

//creating label
label = Label::createWithTTF("Hello", "fonts/arial.ttf", 48);

// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
                        origin.y + visibleSize.height/2));


label->setColor(Color3B(124,115,127));
label->setOpacity(0);
this->addChild(label);

//calling scheduled function
this->schedule(schedule_selector(HelloWorld::type),0.1f);


// function to be scheduled..

void HelloWorld::type(float dt)
{
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
if(i<label->getStringLength())
{
    log("called");
            
    letter = label->getLetter(i);
    letter->setColor(Color3B(124,115,127));
    letter->setOpacity(255);
    i++;
}
else{
    i=0;
    unschedule(schedule_selector(HelloWorld::type));
    
}

}
2 Likes

lol i was doing the same just now

:smile: :smile: :+1:

Hey @mihir77 thanks for your response.

I am quite impressed, the people of Cocos2d-x are really kind and willing to guide and help. I think it was a good decision to use Cocos for my game development career!

Thanks to you also @Lazy_Gamer for taking almost all the time to do it too.

I will implement it right now, let’s see how it goes :man_with_gua_pi_mao:

Update
. The code is great thanks @mihir77! But I am just facing a small issue. It marks schedule_selector that "Error: Class “HelloWorld” has no member “type” I tried to create a member of HelloWorld by myself but I didn’t succeed. I am using the default HelloWorld code. What can this be?

[quote=“JETeran, post:8, topic:26091”]
Thanks to you also @Lazy_Gamer for taking almost all the time to do it too.
[/quote]Thanks i guess my typing skills needs to be imroved :stuck_out_tongue_closed_eyes:

In you HelloWorldScene.h file under public: define method void type(float dt);
Also don’t forget to initialize other variables in HelloWorldScene.h file

Label* label, *letter;

Edit

[quote=“mihir77, post:5, topic:26091”]
this->schedule(schedule_selector(HelloWorld::type),0.1f);
[/quote]You might need to modify this line to

this->schedule(schedule_selector(&HelloWorld::type),0.1f);

[quote=“Lazy_Gamer, post:9, topic:26091”]
Thanks i guess my typing skills needs to be imroved
[/quote] :joy:

Good. I defined the new method in the header file (Gosh, I was close! :sweat_smile:) and I initialized the variables, but it seems that it is not correct.

If I write:

this->schedule(schedule_selector(&HelloWorld::type), 0.1f);

Gives me “Expected an expression”

If I write:

this->schedule(schedule_selector(HelloWorld::type), 0.1f);

Gives me no error, only down in the function:

void HelloWorld::type(float dt)

“Member function “HelloWorld::type” may not be redeclared outside its class”

Hm… what do you think?

:sweat_smile: appologies i was using SEL_SCHEDULE instead of schedule_selector in expression, typo mistake, use this one
this->schedule(SEL_SCHEDULE(&HelloWorld::type), 0.1f);

Ha! Nice catch! :joy:

But I changed it and still the same. Here is the code (I add some things that was missing, including “int”)

//calling scheduled function
	this->schedule(SEL_SCHEDULE(&HelloWorld::type), 0.1f);

	// function to be scheduled..
	void HelloWorld::type(float dt)
	{
		Size visibleSize = Director::getInstance()->getVisibleSize();
		Vec2 origin = Director::getInstance()->getVisibleOrigin();

		if (int i<label->getStringLength())
		{
			log("called");

			letter = label->getLetter(i);
			letter->setColor(Color3B(124, 115, 127));
			letter->setOpacity(255);
			i++;
		}
		else
		{
			i = 0;
			unschedule(schedule_selector(HelloWorld::type));
		}

	}

Besides it, I see that the console throws me:

error C2227: left of '->setColor' must point to class/struct/union/generic type
type is 'int'
error C2227: left of '->setOpacity' must point to class/struct/union/generic type
type is 'int'
illegal else without matching if

Don’t get it! What do you think?

Update
. Also getLetter.
. I ran this good guy but I get an error of a missing file (glew32.lib)

Code shared by @mihir77 is working fine, you just needed to initialize them properly, this one is a slight modification of mihir77 code and is working fine. In your init() method

 label = Label::createWithTTF("hellllloooooo", "fonts/Marker Felt.ttf", 60);

    label->setPosition(Vec2(568, 320));
        label->setOpacity(0);
    this->addChild(label);
    
    
    //calling scheduled function
    this->schedule(SEL_SCHEDULE(&TestClass::type), 0.1f);
    
    // init returns true 
    return true;
}




// function to be scheduled..
    void TestClass::type(float dt)
    {
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        
        if ( i<label->getStringLength())
        {
            log("called");
            
            letter = label->getLetter(i);
            if(letter==NULL)return;
            letter->setColor(Color3B(124, 115, 127));
            letter->setOpacity(255);
            i++;
        }
        else
        {
            i = 0;
            unschedule(schedule_selector(TestClass::type));
        }
    }

In your HelloWroldScene.h file

private:
          void type(float dt);
           Label *label;
           Sprite *letter;
           int i=0;

Note:- Avoid new line operator while creating a label, Label::createWithTTF("hellllloooooo \n hiiii ", "fonts/Marker Felt.ttf", 60); won’t work

Thanks @Lazy_Gamer!

Yes I had a mess! I create a new project and started from the beginning.

Ok for the init() I change &TestClass::type to &HelloWorld::type, it was giving me the same error as before.

But there is a new strange problem. I am receiving a “there is a missing ; before *” error, but if I change it a little [I commented the int i=0 (I looked for the solution in the net)] compile, and it gives me another error, letter and label “undeclared identifier”. Even if I uncomment the int again.

Maybe is something wrong with my Visual Studio (Community 2013) ?

Thanks for your kindles @Lazy_Gamer and for having the patient of helping me.

Update
. The strange problem is in the header file.

You need to specify the full type of Label. This is a good practice IMHO as opposed to adding a using clause in any headers. If that doesn’t fix, maybe type is a reserved keyword (99% sure it’s not), beyond that you’ll have to prob post your exact code so we can check compiling it real quick.

cocos2d::Label *label;
cocos2d::Sprite *letter;
1 Like

Bingo mate @stevetranby !

Yes, I knew something was missing. Not using using is a good programming practice for what I have learned in other languages (C++, where you use using namespace std). Thanks for confirming me it :grinning:

Something else, if I want to make more animated text, what is the best approach? Do I have to create different labels for each line (label1, label2 …) or there is an optimized way to do it?

What I am trying to do is have a character in a room that speaks, each time I click next, the text changes. Like a basic RPG game.

Thank you and everybody for your great support; I am really happy to use Cocos2d-x :sparkling_heart:

Edit
I found this nice animated sequences and I was thinking how to do it by myself (here is the source) but I found it complex to implement. What do you think?

From the source just copy CCLabelBMFontAnimated.cpp and CCLabelBMFontAnimated.h file into your classes folder, HelloWorldScene.cpp shows the different capability of that class and how to use them. You might also need to replace/copy content of Resources/fonts folder into your folder also.

Well that depends.

  1. You could try to fix the issues you’ve found trying to use that AnimatedLabel. Add a method for stopping the dialog to show all (skip) if desired.

  2. You could create a custom action instead. Run the action, action tracks state and updates opacity. May not easily support the skip dialog make all letters immediately visible.

  3. You might get by with just a factory method that creates a label, and sets up the schedule and removes itself. One could create an action RepeatForever { Sequence { Delay(.1), CallFuncN(…) } } where the callfunc lambda/method receives the node where the action was run (label->runAction()) which does the letter updating and removing itself label->stopAllActions(); label->runAction(RemoveSelf) (using removeSelf to make sure it occurs on next frame to not cause weird destruction issues).

  4. Custom Class.

We have a DialogLayer : Layer class (built for 2.x so prob derive from Node or Sprite instead) where we have all necessary functionality wrapped up in one place. It does have extra stuff in order to allow configuring background, default font/color, and a list (vector) of optional choices (struct w/text and event) that the player can select.

We schedule the update and track all the state in there, but we also track touches and update the state from those as well: skip animation and display all, for choice selection and advancing to next dialog.

This does work with a mission manager so that a choice event triggers the mission dialog step and advances, potentially creating a new dialog layer in the next step, but this is not necessary for the dialog animating label part.

Anyway, long reply, hopefully gives ideas. I can’t share exact code at this time.

Thanks guys for your kindly responses.

[quote=“Lazy_Gamer, post:17, topic:26091”]
HelloWorldScene.cpp shows the different capability of that class and how to use them.
[/quote]Yes, I was looking this file yesterday but I didn’t understand it; right now it makes more sense, but (at the moment) I am unable to edit it for my own. If you have a suggestion to where to start, let us know :sunny:

What I can see is that there are different steps, and depending on what number holds (step 5 for typewriter) an animation is presented.

Unfortunately, I tried to compile it and it is throwing me link errors (fatal error LNK1120: 20 unresolved externals) I tried to play with it but didn’t go so far.

Thanks buddy for your long reply, I love them, you really are looking for me to understand about all this.

To be honest, I didn’t understand what you just told me :cry: but fear not, I am still studying Cocos and I hope I can understand your points in the near future.

I am going to try now implementing this both CCLabelBMFontAnimated.cpp and CCLabelBMFontAnimated.h to my current code.

Any suggestion or comment, if even small, that you can share with me is highly appreciated. I love learning from you guys. :sparkling_heart:

Keep having a wonderful day!