【cocos2d-x-3.2】【高仿微信打飞机系列一】【开始界面 子弹生成 背景滑动 主飞机】
2015-03-04 11:13
573 查看
看了cocos2d有一段时间了,简单的小游戏还是可以写出来。这个过程主要还是看,而很少动手去写,这样本身水平很难提高。就好比看完设计模式,现在依旧不会用,时间一久,也忘记的差不多了。俗话说,纸上得来终觉浅,绝知此事要躬行。因此,决定写一个高仿发飞机的小游戏,虽然简单,但还是要坚持写完。
这个系列主要还是基于我想到哪就写到哪,不定期更新。
http://download.csdn.net/detail/q100036q/7524993
解压后:
![](http://img.blog.csdn.net/20150304111349762?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW1kMTIzNDU2Nzg5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
资源图片准备就绪,我们就可以开始编码工作了,依旧是看图写代码,一步一步搭建。
开始画面很简单,一张背景图片再加一个animation,便构成了开始界面。
代码如下:
显示效果如下:
![](http://img.blog.csdn.net/20150304112155328?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW1kMTIzNDU2Nzg5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
主要代码如下:
以上全部写完,基本的画面就出来了,画面如下
![](http://img.blog.csdn.net/20150304130212695?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW1kMTIzNDU2Nzg5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
好了 第一篇就先写到这里,后续会写第二篇。
这个系列主要还是基于我想到哪就写到哪,不定期更新。
1.开始界面
首先,我们得找到微信打飞机的图片资源,直接到下面链接下载就可以了:http://download.csdn.net/detail/q100036q/7524993
解压后:
资源图片准备就绪,我们就可以开始编码工作了,依旧是看图写代码,一步一步搭建。
开始画面很简单,一张背景图片再加一个animation,便构成了开始界面。
代码如下:
#ifndef _START_GAME_SCENE_H_ #define _START_GAME_SCENE_H_ #include "cocos2d.h" USING_NS_CC; class StartGameScene : public Layer { public: static cocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(StartGameScene); void loadingHandler(); void loadingDone(); }; #endif #include "StartGameScene.h" #include "PlayGameScene.h" Scene* StartGameScene::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = StartGameScene::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool StartGameScene::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); // add background image auto sprite = Sprite::create("shoot_background/background.png"); // position the sprite on the center of the screen sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); // add the sprite as a child to this layer this->addChild(sprite, 0); //加载页面 loadingHandler(); return true; } //loading handler void StartGameScene::loadingHandler() { Size visibleSize = Director::getInstance()->getVisibleSize(); //start:开始界面的animation auto loadingSp = Sprite::create(); loadingSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2)); this->addChild(loadingSp, 1); Vector<SpriteFrame*> framelist; for(int i = 1; i <=4; i++) { SpriteFrame* sf = SpriteFrame::create(String::createWithFormat("shoot_background/game_loading%d.png",i)->_string, Rect(0,0,186,38)); framelist.pushBack(sf); } Animation* an = Animation::createWithSpriteFrames(framelist, 0.5f); auto animate = Animate::create(an); auto repeat = Repeat::create(animate, 3);//播放三次 //回调函数 auto callback = CallFunc::create(CC_CALLBACK_0(StartGameScene::loadingDone,this)); auto sequence = Sequence::create(repeat, callback, NULL); loadingSp->runAction(sequence); //end:开始界面的animation } //开始界面播放完,直接进入游戏场景 void StartGameScene::loadingDone() { Director::getInstance()->replaceScene(PlayGameScene::createScene()); }
显示效果如下:
2.背景移动
进入游戏后,要让背景图片动起来,并且无缝衔接。实际上,用两张背景图片就可以达到这种效果。当第一张移出屏幕的时候,立即放置到最上面,衔接第二张,达到无缝衔接的效果。主要代码如下://run the background auto bg_1 = Sprite::create("shoot_background/background.png"); bg_1->setAnchorPoint(Point(0, 0 )); bg_1->setPosition(Point(0, 0)); bg_1->setTag(BG_1); this->addChild(bg_1, 0); auto bg_2 = Sprite::create("shoot_background/background.png"); bg_2->setAnchorPoint(Point(0, 0 )); bg_2->setPosition(Point(0, bg_1->getContentSize().height)); bg_2->setTag(BG_2); this->addChild(bg_2, 0); //run background image this->schedule(schedule_selector(PlayGameScene::runBackground), 0.01f); void PlayGameScene::runBackground(float dt) { auto visibleSize = Director::getInstance()->getVisibleSize(); auto bg_1 = this->getChildByTag(BG_1); auto bg_2 = this->getChildByTag(BG_2); int bg_height = bg_1->getContentSize().height; bg_1->setPositionY(bg_1->getPositionY() - bg_speed); bg_2->setPositionY(bg_2->getPositionY() - bg_speed); //bg2移出屏幕后衔接在bg1后面 if(bg_2->getPositionY() <= 0) { bg_1->setPositionY(bg_2->getPositionY() + bg_height); } //bg1移出屏幕后衔接在bg2后面 if(bg_1->getPositionY() <= 0) { bg_2->setPositionY(bg_1->getPositionY() + bg_height); } }
3.加载主飞机
经过步骤2,背景也可以无缝移动了,把主飞机(hero_plane)放上去,并且注册他的触碰事件检测,也就是我们手指触碰主飞机的时候,飞机能够跟着我们手指移动而移动。这样的效果也很简单,在层中去注册touchevent事件处理。点击时如果是touch飞机,设置一个标志位,touchmove事件的时候,不断去更新飞机的位置,这样就可以达到效果了。主要代码如下:
//add plane hero Sprite* hero = Sprite::create("hero1.png"); PlaneHero* hero_plane = PlaneHero::create(hero); hero_plane->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2)); hero_plane->setTag(HERO_PLANE); hero_plane->setAnchorPoint(Point(0,0)); this->addChild(hero_plane, 1); //touch event handler auto touchListener = EventListenerTouchOneByOne::create(); touchListener->setSwallowTouches(true); touchListener->onTouchBegan = CC_CALLBACK_2(PlayGameScene::onTouchBegan, this); touchListener->onTouchMoved = CC_CALLBACK_2(PlayGameScene::onTouchMoved, this); touchListener->onTouchCancelled = CC_CALLBACK_2(PlayGameScene::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); //Touch event handler bool PlayGameScene::onTouchBegan(Touch *touch, Event* event) { Point touchPoint = touch->getLocation(); bTouchPlane = false; auto hero_plane = this->getChildByTag(HERO_PLANE); Point hero_pos = hero_plane->getPosition(); Size hero_size = hero_plane->getContentSize(); log("hero_pos x = %f, y = %f", hero_pos.x, hero_pos.y); log("touchPoint x = %f, y = %f", touchPoint.x, touchPoint.y); log("hero_size width = %f, height = %f", hero_size.width, hero_size.height); if(touchPoint.x >= hero_pos.x && touchPoint.x <= (hero_pos.x + hero_size.width) && touchPoint.y >= hero_pos.y && touchPoint.y <= (touchPoint.y + hero_size.height)) { //touch the plane, mark this flag for use bTouchPlane = true; } return true; } void PlayGameScene::onTouchMoved(Touch *touch, Event* event) { if(bTouchPlane == true) { //move the hero_pane with out touch on screen auto hero_plane = this->getChildByTag(HERO_PLANE); Point pos = touch->getLocation(); hero_plane->setPosition(pos); } } void PlayGameScene::onTouchEnded(Touch *touch, Event* event) { bTouchPlane = false; }
4.子弹管理器
首先,我们写一个基类,用来绑定一个精灵,所有的飞机,子弹都会继承他。#ifndef _ENTITY_H_ #define _ENTITY_H_ #include "cocos2d.h" USING_NS_CC; class Entity : public Node { public: Entity(); ~Entity(); void bindSprite(Sprite* sprite); Sprite* getSprite(); private: Sprite* m_sprite; }; #endif #include "Entity.h" Entity::Entity() { m_sprite = NULL; } Entity::~Entity() {} void Entity::bindSprite(Sprite* sprite) { if(this->m_sprite != NULL) { m_sprite->removeFromParentAndCleanup(true); } this->m_sprite = sprite; this->addChild(m_sprite); Size size = m_sprite->getContentSize(); this->setContentSize(size); } Sprite* Entity::getSprite() { return this->m_sprite; }接着,写一个子弹的基类,继承自Entity,他包含子弹的共有属性。不同的子弹类型都会继承自这个子弹基类。方便扩展。
#ifndef _BULLETBASE_BASE_H_ #define _BULLETBASE_BASE_H_ #include "Entity.h" #define SPEED_DEFAULT 10 #define SPEED_NORMAL 5 class BulletBase : public Entity { public: BulletBase(); ~BulletBase(); //子弹是否在使用中 void setUsed(bool isUsed); bool isUsed(); bool isArrive(); //设置子弹速度 void setSpeed(int speed); int getSpeed(); //是否飞出屏幕 bool isMoveOutScreen(); void setIsMoveOutScreen(bool outScreen); //是否加进层里面 //bool isAddInLayer(); //void setIsAddInLayer(bool inLayer); protected: bool m_isArrive; int m_speed; private: bool m_isUsed; bool m_isOutScreen; //bool m_isAddInLayer; }; #endif #include "BulletBase.h" BulletBase::BulletBase() { m_isUsed = false; m_isArrive = false; m_speed = SPEED_NORMAL; m_isOutScreen = false; //m_isAddInLayer = false; } BulletBase::~BulletBase() { } void BulletBase::setUsed(bool isUsed) { this->m_isUsed = isUsed; } bool BulletBase::isUsed() { return this->m_isUsed; } bool BulletBase::isArrive() { return this->m_isArrive; } //设置子弹速度 void BulletBase::setSpeed(int speed) { this->m_speed = speed; } int BulletBase::getSpeed() { return this->m_speed; } //是否已经飞出屏幕 bool BulletBase::isMoveOutScreen() { return this->m_isOutScreen; } void BulletBase::setIsMoveOutScreen(bool outScreen) { this->m_isOutScreen = outScreen; } #if 0 //是否加进层里面 bool BulletBase::isAddInLayer() { return this->m_isAddInLayer; } void BulletBase::setIsAddInLayer(bool inLayer) { this->m_isAddInLayer = inLayer; } #endif紧接着,写一个普通类型的子弹,在这里其实主要是写入子弹的速度。不同类型的子弹拥有不同的属性值,我们先简单的设置子弹的速度就可以。以后需要扩展直接对这个类进行。
#ifndef _BULLET_NORMAL_H_ #define _BULLET_NORMAL_H_ #include "BulletBase.h" class BulletNormal : public BulletBase { public: BulletNormal(); ~BulletNormal(); CREATE_FUNC(BulletNormal); virtual bool init(); static BulletNormal* create(Sprite* sprite); bool init(Sprite* sprite); private: void moveEnd(); }; #endif
#include "BulletNormal.h" BulletNormal::BulletNormal() { m_speed = SPEED_NORMAL; } BulletNormal::~BulletNormal() {} bool BulletNormal::init() { return true; } BulletNormal* BulletNormal::create(Sprite* sprite) { BulletNormal* bNor = new BulletNormal(); if(bNor && bNor->init(sprite)) { bNor->autorelease(); } else { CC_SAFE_DELETE(bNor); } return bNor; } bool BulletNormal::init(Sprite* sprite) { bool ret = false; bindSprite(sprite); ret = true; return ret; } void BulletNormal::moveEnd() { m_isArrive = true; }最后,创建子弹管理器,生成子弹,保存到一个列表里面,需要的时候直接取出。同时,子弹的飞行也在管理器中做处理,不断检测子弹并且设置子弹的运行。
#ifndef _BULLET_MANAGER_H_ #define _BULLET_MANAGER_H_ #include "cocos2d.h" USING_NS_CC; #define BULLET_MAX_CACHE_NUM 20 //子弹缓存数量 class BulletBase; class BulletManager : public Node { public: BulletManager(); ~BulletManager(); static BulletManager* create(); bool init(); //获取未用的子弹 BulletBase* getUnusedBullet(); private: Vector<BulletBase*> m_bulletList;//子弹列表,保存子弹 void createBullets();//创建缓存子弹 void bulletLogicCheck(float dt);//子弹逻辑 }; #endif #include "BulletManager.h" #include "BulletBase.h" #include "BulletNormal.h" BulletManager::BulletManager() {} BulletManager::~BulletManager() {} BulletManager* BulletManager::create() { BulletManager* bulletMgr = new BulletManager(); if(bulletMgr && bulletMgr->init()) { bulletMgr->autorelease(); } else { CC_SAFE_DELETE(bulletMgr); } return bulletMgr; } bool BulletManager::init() { //创建子弹列表 createBullets(); log("m_bulletList size() = %d", m_bulletList.size()); //循环检测子弹列表 this->schedule(schedule_selector(BulletManager::bulletLogicCheck)); return true; } //获取未用的子弹 BulletBase* BulletManager::getUnusedBullet() { log("m_bulletList size() = %d", m_bulletList.size()); for(int i = 0; i < m_bulletList.size(); i++) { BulletBase* bullet = m_bulletList.at(i); if(bullet->isUsed() == false) { bullet->setUsed(true); bullet->setIsMoveOutScreen(false); return bullet; } } #if 0 //i don't know why for(auto bullet : m_bulletList) { if(bullet->isUsed() == false) { bullet->setUsed(true); bullet->setIsMoveOutScreen(false); return bullet; } } #endif log("no bullet unused"); return NULL; } //创建子弹缓存 void BulletManager::createBullets() { BulletBase* bullet = NULL; for(int i = 0; i < BULLET_MAX_CACHE_NUM; i++) { auto bullet_sprite = Sprite::create("bullet1.png"); bullet = BulletNormal::create(bullet_sprite); bullet->setUsed(false); bullet->setIsMoveOutScreen(false); m_bulletList.pushBack(bullet); this->addChild(bullet); } log("m_bulletList size() = %d", m_bulletList.size()); } //检测子弹 void BulletManager::bulletLogicCheck(float dt) { auto visibleSize = Director::getInstance()->getVisibleSize(); for(auto bullet : m_bulletList) { if(bullet->isUsed() == true) { //子弹运行 int posY = bullet->getPositionY(); posY += SPEED_DEFAULT; bullet->setPositionY(posY); //out of screen if(posY >= visibleSize.height) { bullet->setIsMoveOutScreen(true); bullet->setUsed(false); } } } }
以上全部写完,基本的画面就出来了,画面如下
好了 第一篇就先写到这里,后续会写第二篇。
相关文章推荐
- 【cocos2d-x-3.2】【高仿微信打飞机系列二】【敌机 碰撞检测 爆炸管理】
- Cocos2d-x 3.2 lua飞机大战开发实例(一)背景地图,飞机,子弹的封装,以及lua中定时器的使用
- Android之高仿微信“首次登录滑动界面”(五)
- cocos2d-x 3.2 |飞机大战:飞机与子弹
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 06.游戏界面 主角飞机产生子弹
- 【高仿微信系列】02、消息列表ListView滑动删除
- 从今天开始我将和大家分享下(仿微信飞机) cocos2d-x 2.2版的实现过程 (一)
- 用Quick-Cocos2d-x 3.3简单开发微信打飞机 -03 添加爆炸动画和子弹与敌机的碰撞
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 03.游戏界面 背景层实现滚动
- cocos2d-x 多平台高仿微信打飞机
- 项目飞机大战01:主要实现背景的移动,飞机的动画和触控,子弹的生成和发射
- [置顶] 【cocos2d-x入门实战】微信飞机大战之四:飞机登场咯
- 【cocos2d-x入门实战】微信飞机大战之一:搞个飞机来玩玩
- [置顶] 【cocos2d-x入门实战】微信飞机大战之六:子弹层的处理
- 【cocos2d-x入门实战】微信飞机大战之六:子弹层的处理
- Android中实现仿微信界面切换平滑滑动效果
- Cocos2d-x学习之---模仿微信打飞机游戏敌机层设计初想
- cocos2d-x的初步学习二十二之模仿微信打飞机
- 实例源码--IOS高仿微信打飞机游戏(完整功能)
- 微信打飞机源码,适配iphone5打飞机游戏源码(cocos2d-iphone:)