玩游戏的大小孩开发整理笔记:平台cocos2d-x 2.2.6,第一个游戏速度略慢,服务器逻辑+客户端逻辑共两个礼拜,各种调试改界面两个礼拜多一点。
15/07/14结笔
游戏模式:服务器为主逻辑区,客户端响应服务器的各种消息事件,出牌、牛、出现叫庄按钮等
协议如下:部分
// user status----need
#define USER_STATUS_NULL 0
#define USER_STATUS_LOOK 1
#define USER_STATUS_PALY 2
#define USER_STATUS_ROB 3
#define USER_STATUS_NO_ROB 4
#define USER_STATUS_MULTIPLE 5
#define USER_STATUS_NIU 6
#define USER_STATUS_NO_NIU 7
// power--各类按钮
#define BUTTON_POWER_START 0x00000001
#define BUTTON_POWER_WAITNEXT 0x00002000
protocol--s-c发送协议
#define SUB_S_BUTTON_POWER 100
#define SUB_S_SEND_BET 122
//c-s响应协议
#define SUB_C_ROB 1001
#define SUB_C_SEND_GIFT 1007
// game state
#define GAME_STATUS_FREE 0
#define GAME_STATUS_ROB 1
#define GAME_STATUS_MULTIPLE 2
#define GAME_STATUS_CONTEST 3
#define GAME_STATUS_OVER 4
服务器注意点:断线重连,引入状态机概念,根据游戏状态和掉线玩家的玩家状态去发送当前应该显示的场景给玩家。
时间函数,时间到时应做好强制状态转换。同理客户端
客户端
问题一:
游戏昵称过长不好显示(如旺旺仔仔牛牛奶奶很很好好喝喝) 显示为xxx..(旺旺仔仔…)这里有字符编码问题,utf8是1~4个字节编码utf8传送门
字符需要转化。
代码转化代码如下
void layer_game::setTextEx(UILabel* l_uilabel,const std::string& text, int twidth){
l_uilabel->setText(text);
if (twidth <l_uilabel->getContentSize().width){
char fulline[100];
strcpy(fulline, text.c_str());
int sum = strlen(fulline);
std::string lines, s_name;
for (int cur = 0; cur < sum; cur++)
{
char t = fulline[cur];
if ((t & 0xF0) == 0xF0){ //4byte
lines = lines + t + fulline[cur + 1] + fulline[cur + 2] + fulline[cur + 3];
cur += 3;
}
if ((t & 0xE0) == 0xE0){ //3byte
lines = lines + t + fulline[cur + 1] + fulline[cur + 2];
cur += 2;
}
else if ((t & 0xC0) == 0xC0){ //2byte
lines = lines + t + fulline[cur + 1];
cur++;
}
else{ //1byte
lines = lines + t;
}
l_uilabel->setText(lines + "...");
if (twidth <= l_uilabel->getContentSize().width){
break;
}
s_name = lines;
}
l_uilabel->setText(s_name + "...");
}
else
l_uilabel->setText(text);
}
遇到的问题二:
聊天的话,需要有聊天记录框,根据记录长短分成一条或两条,uilabel据说有自动分行,然并软。还是得自己来设置,重要代码片段如下:
for (int i = 0; p != NULL; i++)
{
if (i > int_chat_temp_count)
break;
CCString* str = CCString::createWithFormat("%s:%s", p->_str_name.c_str(), p->_str_chat.c_str());
std::cout << str->getCString();
m_text_chat[i]->ignoreContentAdaptWithSize(true);
m_text_chat[i]->setText(str->getCString());
CCSize the_text_size = m_text_chat[i]->getSize();
m_int_text_height[i]= the_text_size.width / 350;
if (((int)the_text_size.width) % 350 != 0)
m_int_text_height[i] += 1;
sum_item_count += m_int_text_height[i];
m_text_chat[i]->ignoreContentAdaptWithSize(false);
m_text_chat[i]->setSize(CCSizeMake(350, m_int_text_height[i] * 30));
m_text_chat[i]->setTextAreaSize(CCSizeMake(350, m_int_text_height[i] * 30));
p = p->next;
}
问题三:
表情动画类作为方便统一管理,外部文件的形式来加加载动画。这里主要用到CCFileUtils,json数据存储json用法传送门
void UIGameChatPlay::play_emotion(int int_view_id, int int_emotion_id)
{
CCString* ptr_str_png_filename = CCString::createWithFormat("emotion/%d.png", int_emotion_id);
CCString* ptr_str_json_filename = CCString::createWithFormat("emotion/%d.json", int_emotion_id);
std::string str_png_filename = CCFileUtils::sharedFileUtils()->fullPathForFilename(ptr_str_png_filename->getCString());
std::string str_json_filename = CCFileUtils::sharedFileUtils()->fullPathForFilename(ptr_str_json_filename->getCString());
unsigned long size;
char *pFileContent = (char*)CCFileUtils::sharedFileUtils()->getFileData(str_json_filename.c_str(), "rb", &size);
if (pFileContent == NULL)
{
return;
}
Json::Reader the_reader;
Json::Value the_value;
if (the_reader.parse(pFileContent, the_value, false) == false)
return;
delete[] pFileContent;
float float_width = the_value["width"].asFloat();
float float_height = the_value["height"].asFloat();
int int_count = the_value["count"].asInt();
int int_turn = the_value["turn"].asInt();
float float_time = the_value["time"].asFloat();
CCAnimation* ptr_animation = CCAnimation::create();
CCSpriteFrame* ptr_sprite_frame = 0;
for(int i=0; i<int_turn; i++)
{
for(int j=0; j<int_count; j++)
{
ptr_sprite_frame = CCSpriteFrame::create(ptr_str_png_filename->getCString(), CCRectMake(float_width*j, 0, float_width, float_height));
ptr_animation->addSpriteFrame(ptr_sprite_frame);
}
}
// should last 2.8 seconds. And there are 14 frames.
ptr_animation->setDelayPerUnit(float_time / (float)(int_count * int_turn));
ptr_animation->setRestoreOriginalFrame(true);
_ptr_sprite_emotion[int_view_id]->stopAllActions();
CCCallFuncN* ptr_emotion_start = CCCallFuncN::create(this, callfuncN_selector(UIGameChatPlay::on_emotion_start));
CCAnimate* ptr_action = CCAnimate::create(ptr_animation);
CCCallFuncN* ptr_emotion_finish = CCCallFuncN::create(this, callfuncN_selector(UIGameChatPlay::on_emotion_finish));
_ptr_sprite_emotion[int_view_id]->runAction(CCSequence::create(ptr_emotion_start, ptr_action, ptr_emotion_finish, NULL));
}
客户端其他关注点:定时器设置,动画同步性,点击事件层级设置,判断是否为点击区域
bool Layout::hitTest(const CCPoint &pt)
void UIGameMenu::on_touch_event(CCObject* object, TouchEventType type)
{
if (type != TOUCH_EVENT_ENDED)
return;
CCPoint the_point = getTouchEndPos();
if (m_panel_menu->hitTest(the_point) == false)
{
setTouchEnabled(false);
widget->setTouchEnabled(false);
}
}
编码问题; win中和linux服务器一般直接生成的中文为GBK,IOS和安卓和通过cocos输入得到的字体为UTF8,用cocos自带的转码UTF8和GBK2UTF8坑爹啊(刚开始没进去看代码导致问题产生),win下没区别,其他有区别。
吐槽:IOS中输入函数不能实时显示,真是坑爹。写过程序加美工的图片命名,英文渣表示中文无爱,还是英语好。产品神奇般的对像素移动位置也是醉的不行,不行的。 有帮助博客字体讲解传送门
已发布—后续维护更新维护内容。
下个游戏:捕鱼达人