cocos2d-x 3.0来做一个简单的游戏教程 win32平台 vs2012 详细解释献给初学者们!
原代码来自于网络,由于cocos2d-x 3.0的资料,的确不多,与以前版本的接口很难对上,
所以网上很多例子都无法调试,对于新学习cocos2d-x 的同学,难度增加了,所以出一个超详细的例子给大家。
文章图片
文章图片
源码地址:http://download.csdn.net/detail/adady/7293629
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 1.创建场景
auto scene = Scene::create();
// 2.创建图层,把当本类创建出来,至layer
auto layer = HelloWorld::create();
// 3.把layer放到 场景当中
scene->addChild(layer);
// 4.返回此场景
return scene;
}void HelloWorld::onEnter() //init() 之后就到这个函数
{
LayerColor::onEnter();
//运行 LayerColor 的 onEnter();
auto listener = EventListenerTouchOneByOne::create();
//创建监听事件
listener->setSwallowTouches(true);
//时间是否向下传递,true 就不会向下传递listener->onTouchBegan = [=](cocos2d::Touch* touch,cocos2d::Event* event)//****这还没懂,是什么意思,弄清楚了,告诉大家,或则大家可以与我分享
{
return true;
};
listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
//弹起后,调用onTouchEnded函数 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
//导演加入 listener 事件
}void HelloWorld::update(float t)
{
Vector targetsToDelete;
//列表targetsToDelete
Vector projectilesToDelete;
//列表projectilesToDelete for (int i = 0;
i < _projectiles.size();
i++)//从0至所有进入列表的子弹(所以还没有消失的子弹,包括屏幕外面的还没有结束的)
{
auto projectile = _projectiles.at(i);
//当前第i 个子弹 保存至 projectile//获取当前子弹的坐标及大小得到一个矩形这里减一个projectile->getContentSize().width / 2,是因为他的锚点在中心,所以要减掉
auto projectileRect = Rect(
projectile->getPositionX() - projectile->getContentSize().width / 2,
projectile->getPositionY() - projectile->getContentSize().height / 2,
projectile->getContentSize().width,
projectile->getContentSize().height );
for (int j = 0;
j < _targets.size();
j++)
{
auto target = _targets.at(j);
//当前第j 个目标 保存至 target
//获取当前目标的坐标及大小得到一个矩形
auto targetRect = Rect(
target->getPositionX() - target->getContentSize().width / 2,
target->getPositionY() - target->getContentSize().height / 2,
target->getContentSize().width,
target->getContentSize().height);
if (projectileRect.intersectsRect(targetRect))//一一比对,有没有子弹与目标碰撞了
{
targetsToDelete.pushBack(target);
//碰撞后,把要删除的目标,加入队列
}
}//C++11 的 range-based for循环
for (Sprite* target : targetsToDelete)//遍历targetsToDelete 里所有元素一一保存至 target
{
_targets.eraseObject(target);
//移除_target表里的target,并不是targetsToDelete
this->removeChild(target);
//当前 layer 移掉 target_projectilesDestroyed++;
//每打中一个 加一分
if (_projectilesDestroyed >3) {//大于3分 转换至 成功场景
auto gameOverScene = GameOverScene::create();
gameOverScene->getLayer()->getLabel()->setString("You Win!");
Director::getInstance()->replaceScene(gameOverScene);
}
}if (targetsToDelete.size() >0)//当第i个子弹 有碰撞,就意味着 size 大于0
{
projectilesToDelete.pushBack(projectile);
//把当前子弹添加入 子弹删除列表
}
targetsToDelete.clear();
// 清空 目标删除 列表
}
for (const auto& p : projectilesToDelete)//遍历targetsToDelete 里所有元素一一保存至 p
{
_projectiles.eraseObject(p);
//移除_projectiles表里的target,并不是projectilesToDelete
this->removeChild(p);
//当前 layer 移掉 projectiles
//p->removeFromParentAndCleanup(true);
}
projectilesToDelete.clear();
// 清空 目标删除 列表
}// on "init" you need to initialize your instance
bool HelloWorld::init()
{
if ( !LayerColor::initWithColor(Color4B(255,255,255,255)) ) //5. 把本图层的背景设置成白色
{
return false;
//如果图层没有被创建就false
}Size visibleSize = Director::getInstance()->getVisibleSize();
//getInstance()应该是得到导演的句柄,取得屏幕的尺寸auto player = Sprite::create("Player.png", Rect(0, 0, 27, 40));
//创建一个玩家的精灵,他的大小修改为width:27 hight:40
player->setPosition(Point(player->getContentSize().width/2, visibleSize.height / 2));
//设置精灵出现的位子,程序选择放在(27/2,屏幕中间)的位子,就是在左中,完全的可以显示图片
this->addChild(player, 0);
//添加玩家精灵,进入图层//更新函数
this->schedule(schedule_selector(HelloWorld::gameLogic), 1.0f);
//schedule是按时调用一个函数的方法,定义这个以后就会隔一段时间调用一次该方法,每一秒调用一次gameLogic函数//schedule_selector 应该是注册HelloWorld::gameLogic 这个函数 this->scheduleUpdate();
//这表示大概每0.01秒 调用一次 Update()函数CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic("background-music-aac.caf");
//加载声音文件return true;
}void HelloWorld::gameLogic(float dt)//每1秒调用一次
{
addTarget();
//每1秒调用一次
}void HelloWorld::addTarget()
{
Size visibleSize = Director::getInstance()->getVisibleSize();
//得到屏幕尺寸 auto target = Sprite::create("Target.png", Rect(0, 0, 27, 40));
//创建一个 目标精灵// Determine where to spawn the target along the Y axis
int minY = target->getContentSize().height / 2;
// 得到Target 可以显示的最小位置(相当于图片的height 的中点)
int maxY = visibleSize.height - target->getContentSize().height / 2;
// 得到Target 可以显示的最大位置
int rangeY = maxY - minY;
// 得到可显示区域的大小
int actualY = (CCRANDOM_0_1() * rangeY) + minY;
//(随机产生一个数(0,1) * rangeY) + minY得到(0-1)的小数
target->setPosition(Point(visibleSize.width + target->getContentSize().width / 2, actualY));
//设置Target 出现的位子
this->addChild(target,0);
//添加到本图层内target->setTag(1);
//设置这个Targer 的标签为1
_targets.pushBack(target);
//把Target 存于 _targets的列表 //下面4句,随即产生一个速度
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (CCRANDOM_0_1() * rangeDuration) + minDuration;
auto actionMove = MoveTo::create(actualDuration, Point(-target->getContentSize().width, actualY));
//创建一个速度移动, actualDuration速度, Point(-target->getContentSize().width, actualY)是起始点
auto actionMoveDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::spriteMoveFinished, this));
//这里是创建一个回调函数,就是调用spriteMoveFinished函数 并把自己传出去this。 target->runAction(Sequence::create(actionMove, actionMoveDone, NULL));
//运行一个动画actionMove 移动方法actionMoveDone回调的函数 //从上面看来,这个函数,每1秒创建一个Target 精灵,从屏幕的最右边,随机高度,至左移动}void HelloWorld::onTouchEnded(Touch* touch, Event* event)//按下事件
{
Size visibleSize = Director::getInstance()->getVisibleSize();
//获得屏幕尺寸 auto touchPoint = touch->getLocation();
//获得点击坐标 auto projectile = Sprite::create("Projectile.png", Rect(0, 0, 20, 20));
//创建一个子弹
projectile->setPosition(Point(20, visibleSize.height / 2));
//设置子弹位子 // Determine offset of location to projectile
int offX = touchPoint.x - projectile->getPosition().x;
//点击位置与子弹X位置的差值
int offY = touchPoint.y - projectile->getPosition().y;
//点击位置与子弹Y位置的差值 if (offX <= 0) return;
//如果 子弹 超出范围 return this->addChild(projectile);
//把 子弹 添加进图层projectile->setTag(2);
// 把子弹的标签设置为2
_projectiles.pushBack(projectile);
// 把子弹添加进子弹列表 // Determine where we wish to shoot the projectile to
int realX = visibleSize.width + (projectile->getContentSize().width / 2);
//求出屏幕最大 + 子弹的一半, (求出子弹消失的最大x)
float ratio = (float)offY / (float)offX;
//斜率
int realY = (realX * ratio) + projectile->getPosition().y;
//求出真实的y值,相同的斜率
auto realDest = Point(realX, realY);
//子弹要去位置 // 理解上面的话,下面5句就很好理解了
int offRealX = realX - projectile->getPosition().x;
//真实X值
int offRealY = realY - projectile->getPosition().y;
//真实Y值
float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
//求出 直线距离
float velocity = 960 / 1;
// 960pixels/1sec//960 像素/ 1秒
float realMoveDuration = length / velocity;
//速度 // 创建一个动作,移动动作,realMoveDuration速度,至realDest,并进入回调函数
projectile->runAction(Sequence::create(MoveTo::create(realMoveDuration, realDest),CallFuncN::create(CC_CALLBACK_1(HelloWorld::spriteMoveFinished, this)), NULL));
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("pew-pew-lei.caf");
//载入声音文件
}void HelloWorld::spriteMoveFinished(Ref* pSender)
{
Sprite *sprite = (Sprite *)pSender;
//获得的Target转成 sprite 类型if (sprite->getTag() == 1) {//如果 标签 等于 1
_targets.eraseObject(sprite);
//从_target列表里删掉Target只是从列表里删掉auto gameOverScene = GameOverScene::create();
//创建一个GameOver的场景
gameOverScene->getLayer()->getLabel()->setString("You Lose :[");
//显示youLose
Director::getInstance()->replaceScene(gameOverScene);
//替换成刚生成的GameOver场景
} else if(sprite->getTag() == 2) {//如果 标签 等于 2
_projectiles.eraseObject(sprite);
//从_projectiles列表里删掉 Projectiles只是从列表里删掉
}this->removeChild(sprite);
//删掉sprite 这个图层}void HelloWorld::menuCloseCallback(Ref* pSender)
{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
【cocos2d-x 3.0来做一个简单的游戏教程 win32平台 vs2012 详细解释献给初学者们!】
推荐阅读
- 情节33.0
- 影响力读后感
- webug3.0渗透基础第九、十关笔记
- 感恩日志|感恩日志 第【1237】天((2019.03.03))
- 解放全球宝妈,宝倍爽发布“纸尿裤3.0”开启母婴智能新生活
- 使用vue-cli3.0写一个todoList
- 复盘|复盘 2018.03.02 第51天
- vue-cli3.0使用proxytable解决跨域问题
- 一篇博文搞定goctl(V1.3.0新版本解决goctl|一篇博文搞定goctl:V1.3.0新版本解决goctl rpc protoc的问题)
- 学习的成本太高,你还要不要