Skip to content

Instantly share code, notes, and snippets.

@anzfactory
Last active August 29, 2015 13:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anzfactory/9382126 to your computer and use it in GitHub Desktop.
Save anzfactory/9382126 to your computer and use it in GitHub Desktop.
RPG風文字送り&ページ送りをするラベル

LabelAttributedBMFont

概要

一文字ずつ表示していくラベル
タップされた場合は、
複数ページあると次のページの文章を表示するようなページ送り機能つき

強調キーワードの設定も可能(複数可)

大元はコチラ これを元にcocos2d-x v3.0用に書き換え、自分用に幾つか機能の追加&削除

お気に召したら是非使ってみて(テストしてw)ください〜
そして何かアレば、コメントなり@AnzNetJpにリプなりくださいな

このラベルをつかってアプリを出してるので
どんなんなのか見てみたい人は落としてみてくださいな
なにげに宣伝(笑) https://itunes.apple.com/jp/app/cun-renano-fen-dou-futaride/id881344364?mt=8
https://play.google.com/store/apps/details?id=xyz.anzfactory.routerpg

簡単に使い方

// 表示文字準備
vector< string > pages;
pages.push_back("あいうえおー\nかきくけこー");
pages.push_back("さしすせそー");

auto label = LabelAttributedBMFont::create(pages, "hoge.fnt");

/*
普通に文字列でもok
auto label = LabelAttributedBMFont::create("ページ送りはないよー\n1ページだけだよー", "hoge.fnt");
*/

// 強調キーワードを設定する場合
label->addKeyWord("おー", Color3B::RED);   // 強調キーワード, 強調色
// 複数あるならもう繰り返し
label->addKeyWord("すせー", Color3B::YELLOW);   // 強調キーワード, 強調色

// コールバック設定するなら(全表示が終わったときにタップされると呼ばれる)
label->setCallback([](Object *sender){
  // 処理記述
});

// コールバック設定その2(ページ送りするたびに呼ばれる)
// もどってくる値はpagesのindex
label->setCallbackChangedPage([](int index) {
	// indexから現在何が表示されているのか判定して何か処理
	// ページ送りされたらなので、indexは1から(2ページ目からしかこない)
});

// 文字送りしない場合(ページ送りとキーワード強調は有効にしたい場合)
// label->setDispSpeed(0);

// 文字送り開始(これやんないと何も始まらないYo)
label->start();

リリースノート

2014.06.28 : cocos2d-x v3.1 に対応 : v3.1にしたら警告がでたので、それの修正 : 機能追加などは無し

2014.03.17 : cocos2d-x v3.0 rc0に対応

2014.03.10 : cocos2d-x v3.0 rcに対応 : 伴い、キーワード設定時の文字サイズ指定機能を廃止 : (すみません、対応できなかった…対応できれば復活させます。。)

2014.03.08 : ページ送りのcallbackプロパティを追加

2014.03.07 : DispSpeedに0設定することで一括表示にするように変更

2014.03.06 : 登録

LICENSE

The MIT License (MIT)

Copyright (c) 2014 AnzNetJp

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "LabelAttributedBMFont.h"
USING_NS_CC;
using namespace std;
#define NEWLINE_CHAR "\n"
#define NULL_CHAR ""
LabelAttributedBMFont::LabelAttributedBMFont(cocos2d::FontAtlas *atlas,
cocos2d::TextHAlignment hAlignment,
cocos2d::TextVAlignment vAlignment,
bool useDistanceField,
bool useA8Shader)
:Label::Label(atlas, hAlignment, vAlignment, useDistanceField, useA8Shader)
{
}
LabelAttributedBMFont::~LabelAttributedBMFont()
{
log("LabelAttributedBMFont ~LabelAttributedBMFont()");
}
LabelAttributedBMFont* LabelAttributedBMFont::createWithBMFont(const std::string& bmfontFilePath, const std::string &text,
const cocos2d::TextHAlignment& alignment, int lineWidth,
const cocos2d::Point& imageOffset)
{
vector< string >pages;
pages.push_back(text);
return LabelAttributedBMFont::createWithBMFont(bmfontFilePath, pages, alignment, lineWidth, imageOffset);
}
LabelAttributedBMFont* LabelAttributedBMFont::createWithBMFont(const std::string& bmfontFilePath, std::vector< std::string > pages,
const cocos2d::TextHAlignment& alignment, int lineWidth,
const cocos2d::Point& imageOffset)
{
LabelAttributedBMFont *ret = new LabelAttributedBMFont(nullptr, alignment);
if (!ret)
return nullptr;
if (ret->setBMFontFilePath(bmfontFilePath, imageOffset))
{
ret->setMaxLineWidth(lineWidth);
ret->initWithPages(pages);
ret->autorelease();
return ret;
}
else
{
delete ret;
return nullptr;
}
}
void LabelAttributedBMFont::initWithPages(const std::vector< std::string > &pages/*, const std::string& fntFile, float width, cocos2d::TextHAlignment alignment, cocos2d::Point imageOffset*/)
{
m_dispSpeed = 1;
m_dispCycle = 5;
m_isAllCharDisplayed = false;
setPages(pages);
// touch event
auto listner = EventListenerTouchOneByOne::create();
listner->setSwallowTouches(true);
listner->onTouchBegan = CC_CALLBACK_2(LabelAttributedBMFont::onTouchBegan, this);
listner->onTouchEnded = CC_CALLBACK_2(LabelAttributedBMFont::onTouchEnded, this);
getEventDispatcher()->addEventListenerWithSceneGraphPriority(listner, this);
}
void LabelAttributedBMFont::start()
{
unscheduleUpdate();
if (m_dispSpeed == 0) {
dispAllCharacters();
return;
}
m_isAllCharDisplayed = false;
scheduleUpdate();
}
void LabelAttributedBMFont::setPages(const std::vector<std::string> &pages)
{
m_pages.clear();
for (int i = 0; i < pages.size(); i++) {
m_pages.push_back(pages[i]);
}
m_iterator = m_pages.begin();
setString("", true);
}
void LabelAttributedBMFont::setCallback(const std::function<void (cocos2d::Ref *)> &callback)
{
m_callback = callback;
}
void LabelAttributedBMFont::setCallbackChangedPage(const std::function<void (long)> &callback)
{
m_callbackChangedPage = callback;
}
void LabelAttributedBMFont::setString(const std::string &text, bool isRest)
{
Label::setString(text);
if (! isRest) {
return;
}
// resetCurrentString();
updateContent();
m_isAllCharDisplayed = false;
searchKeywordsIndex(m_pages.at(m_iterator - m_pages.begin()));
}
bool LabelAttributedBMFont::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event)
{
return true;
}
void LabelAttributedBMFont::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event)
{
// 全ページ表示後なら
if (m_iterator == m_pages.end()) {
log("LabelAttributedBMFont : fin");
return;
}
// 文字送りがおわってなかったら
if (! this->getIsAllCharDisplayed()) {
this->dispAllCharacters();
return;
}
m_iterator++;
if (m_iterator == m_pages.end()) {
log("LabelAttributedBMFont : callback");
if (m_callback) m_callback(this);
return;
}
setString("", true); // 表示は初期化
if (m_callbackChangedPage) {
auto dif = m_iterator - m_pages.begin();
m_callbackChangedPage(dif);
}
start();
}
void LabelAttributedBMFont::updateColor()
{
if (nullptr == _textureAtlas)
{
return;
}
Color4B color4( _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity );
// special opacity for premultiplied textures
if (_isOpacityModifyRGB)
{
color4.r *= _displayedOpacity/255.0f;
color4.g *= _displayedOpacity/255.0f;
color4.b *= _displayedOpacity/255.0f;
}
cocos2d::TextureAtlas* textureAtlas;
V3F_C4B_T2F_Quad *quads;
for (const auto& batchNode:_batchNodes)
{
textureAtlas = batchNode->getTextureAtlas();
quads = textureAtlas->getQuads();
auto count = textureAtlas->getTotalQuads();
for (int index = 0; index < count; ++index)
{
// 指定文字が強調色指定されているかどうか
if (m_colorsMatchingWord.find(index) != m_colorsMatchingWord.end()) {
auto customColor = Color4B( m_colorsMatchingWord.at(index) );
if (_isOpacityModifyRGB)
{
customColor.r *= _displayedOpacity/255.0f;
customColor.g *= _displayedOpacity/255.0f;
customColor.b *= _displayedOpacity/255.0f;
}
quads[index].bl.colors = customColor;
quads[index].br.colors = customColor;
quads[index].tl.colors = customColor;
quads[index].tr.colors = customColor;
} else {
quads[index].bl.colors = color4;
quads[index].br.colors = color4;
quads[index].tl.colors = color4;
quads[index].tr.colors = color4;
}
textureAtlas->updateQuad(&quads[index], index);
}
}
}
/**
文字色、文字サイズを局所的に変更したいキーワードを追加する
@param keyword キーワード
@param fontColor キーワードの色
@param fontScale キーワードのサイズ 廃止
*/
void LabelAttributedBMFont::addKeyWord(string keyword, Color3B fontColor/*, float fontScale*/)
{
// 改行コードの場合は何もしない
if (keyword == NEWLINE_CHAR) {
log("LabelAttributedBMFont addKeyWord() keyword is newline character!!!");
return;
}
KeywordDataSet dataset;
dataset.word = keyword;
dataset.strongColor = fontColor;
// dataset.scaleTo = fontScale; 廃止
m_keyWords.push_back(dataset);
// キーワードに該当する文字があるか検索
searchKeywordsIndex(*m_iterator);
}
/**
キーワードを削除する
@param 削除したいキーワード
*/
void LabelAttributedBMFont::removeKeyWord(string keyword)
{
auto it = m_keyWords.begin();
while (it != m_keyWords.end()) {
auto &dataset = *it;
if (dataset.word != keyword) {
it++;
continue;
}
m_keyWords.erase(it);
return;
}
log("LabelAttributedBMFont not found keyword:%s", keyword.c_str());
}
/**
文字列の置換
@param targetStr 置換をかける文字列
@param fromStr 置換対象文字列
@param toStr 置換後文字列
@return 置換完了後文字列
*/
string replace(string &targetStr, string fromStr, string toStr)
{
string::size_type pos = targetStr.find_first_of(fromStr, 0);
while (string::npos != pos) {
targetStr.replace(pos, string(fromStr).length(), toStr);
pos = targetStr.find_first_of(fromStr, pos);
}
return targetStr;
}
/**
検索情報初期化
*/
void LabelAttributedBMFont::initKeyWordsVisualInfo()
{
m_colorsMatchingWord.clear();
}
/**
文字送り中の文字を全て表示させる
*/
void LabelAttributedBMFont::dispAllCharacters()
{
if (m_isAllCharDisplayed) {
return;
}
m_isAllCharDisplayed = true;
unscheduleUpdate();
auto line = *m_iterator;
setString(line, false);
}
/**
キーワードの存在する位置を検出する
*/
void LabelAttributedBMFont::searchKeywordsIndex(std::string targetString)
{
// 改行コードを除去
targetString = replace(targetString, NEWLINE_CHAR, NULL_CHAR);
if (targetString.empty()) {
return;
}
// 文字色、文字サイズを初期化
initKeyWordsVisualInfo();
auto it = m_keyWords.begin();
// 登録したキーワード分だけ検索処理を行う
while (it != m_keyWords.end()) {
auto &dataset = *it;
auto key = dataset.word;
u16string u16key;
StringUtils::UTF8ToUTF16(key.c_str(), u16key);
unsigned int keyLengthMultiByte = u16key.length(); // キーワードの長さ(マルチバイト)
unsigned long searchIndex = 0; // 現在の検出走査位置
unsigned long keyFindIndex = targetString.find(key, searchIndex); // キーワードが検出された位置
while (keyFindIndex != string::npos) {
unsigned int keyFindIndexMultiByte = 0; // キーワードが検出された位置(マルチバイト)
// キーワードが検出された位置(マルチバイト)を検出
string clipStr = targetString.substr(0, keyFindIndex);
u16string u16ClipStr;
StringUtils::UTF8ToUTF16(clipStr, u16ClipStr);
keyFindIndexMultiByte = u16ClipStr.length();
for (unsigned int i = 0; i < keyLengthMultiByte; i++) {
int index = keyFindIndexMultiByte + i;
m_colorsMatchingWord[index] = dataset.strongColor;
}
// 現在の検出走査位置をキーワード終了位置へ
searchIndex = (keyFindIndex + key.length());
// キーワード終了位置以降に存在するキーワードを検出
keyFindIndex = targetString.find(key, searchIndex);
}
it++;
}
}
/**
更新、文字送りを行う
表示している文字インデックスを進めて、文字を再設定することで実現
@param dt 前回コールされてからの経過時間
*/
void LabelAttributedBMFont::update(float dt)
{
if (m_dispSpeed == 0) {
dispAllCharacters();
return;
}
auto line = m_pages.at(m_iterator - m_pages.begin());
u16string u16Line;
StringUtils::UTF8ToUTF16(line.c_str(), u16Line);
int len = u16Line.length();
int currentLen = getStringLength();
if (currentLen >= len) {
m_isAllCharDisplayed = true;
unscheduleUpdate();
return;
}
if (Director::getInstance()->getTotalFrames() % m_dispCycle != 0) {
return;
}
auto newLen = len < (currentLen + m_dispSpeed) ? len - currentLen : currentLen + m_dispSpeed;
std::u16string u16NewLine;
for (int i = 0; i < newLen; ++i)
{
u16NewLine.push_back(u16Line[i]);
}
string newStr;
StringUtils::UTF16ToUTF8(u16NewLine, newStr);
setString(newStr, false);
}
/*
* RPG風文字送り&ページ送りをするラベル
*
* 検証バージョン cocos2d-x v3.1
*
* 更新履歴
* 2014.06.28 cocos2d-x v3.1 対応 (warning対応)
* 2014.03.17 cocos2d-x v3.0 rc0 対応
* 2014.03.10 cocos2d-x v3.0 rc 対応
* キーワードの文字サイズ指定は機能廃止
* 2014.03.08 ページ送りのコールバックを追加。
* 2014.03.07 DisplaySpeedプロパティに0を設定した場合は一括表示するようにしました
* 2014.03.06 追加
*
*/
#include "cocos2d.h"
struct KeywordDataSet {
std::string word;
cocos2d::Color3B strongColor;
// float scaleTo; 廃止
};
class LabelAttributedBMFont : public cocos2d::Label
{
public:
LabelAttributedBMFont(cocos2d::FontAtlas *atlas = nullptr,
cocos2d::TextHAlignment hAlignment = cocos2d::TextHAlignment::LEFT,
cocos2d::TextVAlignment vAlignment = cocos2d::TextVAlignment::TOP,
bool useDistanceField = false,
bool useA8Shader = false);
virtual ~LabelAttributedBMFont();
// 何フレーム周期で文字送りをするか
CC_SYNTHESIZE(unsigned int, m_dispCycle, DispCycle);
// 文字送りする際は何文字ずつ行うか (0を設定した場合は常に一括表示に。ただしページ送りやキーワード強調は有効)
CC_SYNTHESIZE(unsigned int, m_dispSpeed, DispSpeed)
// 文字送りが完了状態かどうか
CC_SYNTHESIZE(bool, m_isAllCharDisplayed, IsAllCharDisplayed);
/**
文字色、文字サイズを局所的に変更したいキーワードを追加する
@param keyword キーワード
@param fontColor キーワードの色
@param fontScale キーワードのサイズ 廃止
*/
void addKeyWord(std::string keyword, cocos2d::Color3B fontColor/*, float fontScale*/);
/**
キーワードを削除する
@param 削除したいキーワード
*/
void removeKeyWord(std::string keyword);
/**
文字送り中の文字を全て表示させる
*/
void dispAllCharacters();
virtual void update(float dt);
static LabelAttributedBMFont* createWithBMFont(const std::string& bmfontFilePath, const std::string &text,
const cocos2d::TextHAlignment& alignment = cocos2d::TextHAlignment::LEFT, int lineWidth = 0,
const cocos2d::Point& imageOffset = cocos2d::Point::ZERO);
static LabelAttributedBMFont* createWithBMFont(const std::string& bmfontFilePath, const std::vector< std::string > pages,
const cocos2d::TextHAlignment& alignment = cocos2d::TextHAlignment::LEFT, int lineWidth = 0,
const cocos2d::Point& imageOffset = cocos2d::Point::ZERO);
virtual void initWithPages(const std::vector< std::string > &pages/*, const std::string& fntFile, float width = -1, cocos2d::TextHAlignment alignment = cocos2d::TextHAlignment::LEFT, cocos2d::Point imageOffset = cocos2d::Point::ZERO*/);
void start(); // 文字送りスタート
virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
virtual void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);
virtual void updateColor();
void setPages(const std::vector< std::string > &pages);
void setCallback( const std::function<void(cocos2d::Ref*)> &callback );
void setCallbackChangedPage( const std::function<void( int )> &callback );
virtual void setString(const std::string &text, bool isRest);
protected:
std::vector< std::string > m_pages;
std::vector< std::string >::iterator m_iterator;
std::function<void(Ref*)> m_callback;
std::function<void(int)> m_callbackChangedPage;
std::map< int, cocos2d::Color3B > m_colorsMatchingWord;
private:
std::list< KeywordDataSet > m_keyWords;
/**
キーワードの存在する位置を検出する
*/
void searchKeywordsIndex(std::string targetString);
/**
ラベル上の文字色、文字サイズを初期化する
*/
void initKeyWordsVisualInfo();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment