cocos2d::Vector<T>是一个封装好的能动态增长顺序访问的容器。
cocos2d::Vector<T>中的元素是按序存取的,它的低层实现数据结构是标准模版库中的标准顺序容器std::vector。
在cocos2d-x v3.0 beta之前,使用的是另外一个顺序访问容器cocos2d::CCArray,不过它将会被废弃。
设计者们将cocos2d::Vector<T>设计为cocos2d::CCArray的替代品,所以建议优先考虑使用cocos2d::Vector<T>。
cocos2d::Vector<T>的一些操作的时间复杂度如下:
•T的类型必须是继承自cocos2d::Object类型的指针。因为已经将cocos2d-x的内存管理模型集成到了cocos2d::Vector<T>中,所以类型参数不能是其他的类型包括基本类型。
Vector<Sprite *> allBullet; this->allBullet.pushBack(bullet);
void GameScene::moveBullet(float t){
for(int i=0;i<allBullet.size();i++)
{ auto nowbullet=allBullet.at(i);
nowbullet->setPositionY(nowbullet->getPositionY()+3);
if(nowbullet->getPositionY()>Director::getInstance()->getWinSize().height)
{
nowbullet->removeFromParent();
allBullet.eraseObject(nowbullet);
i--;
}***************************设计者们谨慎地设计了cocos2d::Map<K,V>用来替代cocos2d::CCDictionary,所以应该尽量使用cocos2d::Map而不是cocos2d::CCDictionary
警告:cocos2d::Map<K,V>并没有重载[]操作,不要用下标[i]来取cocos2d::Map<K,V>对象中的元素。
最佳用法
•将cocos2d::Map<K,V>()作为参数传递时,将它声明为常量引用const cocos2d::Map<K,V>()&
•V类型必须为cocos2d::Object的子类指针,不能用其他的类型包括基本类型。
if(!map1.empty()){
auto spTemp = (Sprite*)map1.at(mapKey0);
log("sprite tag = %d", spTemp->getTag());
auto sp1 = Sprite::create();
sp1->setTag(1);
map1.insert(mapKey1, sp1);
cocos2d-x 3.0 数据结构(3/3) cocos2d::Value . cocos2d::Value是许多基本类型(int,float,double,bool,unsigned char,char*和std::string)这些类的包装类型。
Value val; // call the default constructor
if (val.isNull()) {
log("val is null");
}else{
std::string str =val.getDescription();
log("The description of val0:%s",str.c_str());
}Value val1(65); // initialize with a integer
//Value val1(3.4f); // initialize with a float value
//Value val1(3.5); // initialize with a double value
log("The description of the integer value:%s",val1.getDescription().c_str());
注意:当处理基本类型和和容器时,请使用cocos2d::Vector<T>, cocos2d::Map<K,V>和cocos2d::Value。
当处理 cocos2d::Value 的内存时请坚持以 c++ 内存管理规则进行最佳实践
description[英] [disˈkripʃən
********************************************************
游戏中的状态机设计
Quick-Cocos2d-x内置了对状态机的支持,所以这里的状态机就要自己想办法了,初步的想法是设计一个状态机对象,然后让Player类持有一个状态机对象。当然也可以让Player继承状态机对。不过我们先考虑用组合的方法把。
状态机的必备构件:
1. 状态(State)
这里的状态有 idle,walking,attacking, dead 等。
先假设他们是互斥的。虽然一边walking一边attacking也是可能的。
2. 事件(Event)
可以理解为指令,即要求满足一定条件的状态机改变状态到指定态。
例如:
{name="walk", from="idle", to="walking"}
如果令状态机执行这个事件,则当其处于idle状态时,会变化至walking态。
所以状态机对象需要保存所有状态,以及所有的事件,以供使用。
3.动作(Action)
例如在进入dead状态后,角色需要播放dead动画,并移除自身。
每个状态都要提供一个函数如onIdleEnter,在进入这个态时调用,当然也可为空。
按理说退出一个状态也应该调用一个函数,如onIdleExit,不过我们暂时可以不用这个。
状态和事件是否需要单独设计class?如果是class是否要继承Ref?纠结了半天,也写了下Event类和State类,感觉直接用字符串表示状态也是可行的。所以果断删了,直接用字符串。
123 set<string> _states; 用这个保存所有的状态,这里不应该有两个状态名字相同。 map<string, map<string, string>> _events; 用于保存所有的事件,形式为<eventName, <from, to>> map<string, function<void()>> _onEnters; 保存每个态的回调函数,如果不为空就在进入状态时调用这个函数。
这个函数做什么用呢?当然是状态转换后的行为控制了。例如_onEnters["idle"]可以负责停止所有帧动画的播放。
_onEnters["dead"]让角色播放死亡动画,然后处理后事等等。
然后还需要保存当前状态,前一个状态。
******************************************************************************************************
01.void Mutou::update( float dt ) {
02. /* 判断在每一种状态下应该做什么事情 */
03. switch(enCurState) {
04. case enStateWriteCode:
05. /* 如果累了就休息,并且切换到休息状态 */
06. if(isTire()) {
07. rest();
08. changeState(enStateRest);
09. }
10. break;
11. case enStateWriteArticle:
12. /* 如果累了就休息,并且切换到休息状态 */
13. if(isTire()) {
14. rest();
15. changeState(enStateRest);
16. }
17. break;
18. case enStateRest:
19. /* 一定的概率写代码,一定的概率写教程,并且切换到相应的状态 */
20. if(isWantToWriteArticle()) {
21. writeArticle();
22. changeState(enStateWriteArticle);
23. }
24. else {
25. writeCode();
26. changeState(enStateWriteCode);
27. }
28. break;
29. }
30.}
update函数会先判断木头当前所在的状态,然后再去执行相对应的逻辑
但是啊,要是木头有好多好多状态,那这个函数也太庞大了~!是的,我们现在就要用到状态模式了
3. 状态基类 class MutouT;
12.
13.class I_State {
14.public:
15. virtual void execute(MutouT* mutou) = 0;
16.};
4 三种状态对应的状态类 class StateWirteCode : public I_State {
15.public:
16. virtual void execute( MutouT* mutou ); if(mutou->isTire()) { mutou->rest(); mutou->changeState(new StateRest()); }}
17.};
和以前的代码区别并不大,有两处修改:
1. changeState的参数变了,变成了I_State,同时,表示状态的枚举类也删掉了,因为已经有了状态类。
2. 多了一个I_State成员变量,表示当前的状态,同时,表示状态的枚举变量删掉了,因为已经有了状态类。
********************************************************************************** 游戏归根揭底:不停的渲染 及画图。 帧率越小 游戏越差--卡 应为能看清每个变换过称 看电视
A: 锚点(Anchor Point)
将一个节点添加到父节点里面时,需要设置其在父节点上的位置,本质上是设置节点的锚点在父节点坐标系上的位置。
在Cocos2d-x中Layer的Anchor Point为默认值(0,0),其他Node的默认值为(0.5, 0.5)。
B: 触摸点(Touch position)
Touch position是屏幕坐标系中的点---- 原点在左上角,OpenGL position是cocos2d-x用到的OpenGL坐标系上的点坐标。
通常我们在开发中会使用两个接口`getLocation()`和`getLocationInView()`来进行相应坐标转换工作。
//此时添加到的是世界坐标系,也就是OpenGL坐标系 //将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的本地(节点)坐标系统的 位置坐标
Point point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
//将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的世界坐标系统的 位置坐标 Point point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
***************************************************************3D跑酷教程(二)
Player::Player()
{ this->player = Sprite3D::create("model/zhanshi_pao.c3b"); player->setScale(0.1);
player->setRotation3D(Vec3(0,165,0)); auto aniamtion =Animation3D::create("model/zhanshi_pao.c3b");
.auto animate =Animate3D::create(aniamtion);
player->runAction(RepeatForever::create (animate));}
三维笛卡儿坐标系:
向前伸出右手,让拇指和食指成“L”形,大拇指向右,食指向上。其余的手指指向你。这样就建立了一个右手坐标系。拇指、食指和其余手指分别代表x,y,z轴的正方向。 左手一样道理
在这个demo中,我们对跑酷主角的移动进行了一些简化,只允许它向右和向左移动。实现的方式非常简:
当确定了方向之后,我们就要给主角一个action,让它能向左或者向右移动,在run这个Action之前,我们要首先判断,主角是否应在执行action了,在同一时刻,我们只允许用户执行一个运动,这是为了,不让用户移除我们设定的边界,以及不让用户连续滑动屏幕时速度,主角的移动的速度也突然加快。在这里我们使用了一个自己定义的Action——MoveBy3D
-------------*******要创建100个敌人 精灵 和 动画 -- 要不要占内存,占多大? 每一次不用从图片文件中加载数据,从缓存中 --- 所以不管几千几万个精灵 都只占用一分内存空间 会被重复利用
注:图片最好内存 -- 解决方按
1: 缓存是指临时文件交换区,电脑把最常用的文件从存储器里提出来临时放在缓存里,
2: VS -》没出来,说明前面有错误; CC_RANDOM_0_1*320
3: 越是底层,就越和更件相关
4:容量 回影响打包出来的 包 APK 大小, 区别:zhan内存大小觉得 W*h*RGB 像素个数×每个
5: 游戏优化: 底层优化 内存优化 纹理优化 --1尺寸+像素格式 渲染优化:就是当渲染很多精灵时,效率会低,就与因为渲染批次多 咋办:拼图方式, 不管渲染那个图片, 始终使者一个纹理
CCSpriteBatchNode就是cocos2d-x为了降低渲染批次而建立的一个专门管理精灵的类
6: 可视化开源工具 unity3d cocosBuild --- 美术师都可以用 程序员 导入 -- 所以提高开发效率
举例介绍:
1、使用CCSprite创建1000个Icon.png到场景中,这样渲染批次就是1000
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
为什莫要加密: 防盗版(盗版游戏) 防作弊(无敌模式)
修改游戏的方式:
1:比较高级的: 游戏运行中修改 如血量, 其实修改的内存中数据
2:直接修改文件, 进入后就修改了数据
加密那些:
1: 游戏数据 如ccuserdefault XML 读取时 解密
2: 资源加密 如 图片,音乐,地图 被别人拿过去使用
3: 网络游戏
加密方式: (都公开的)
1:MD5加密, 如网络请求 中的get请求, 不同的版本有不同的语言C++ java 等等
2: BASE64
《游戏修改大师9.0》是一个拥有强大功能的视窗软体修改工具