这一章是一个简单的实例,当做练习,熟练一下代码。 首先介绍个地图软件,然后就是贴代码。
1.Tiled Map Editor软件这款软件用于生成tmx格式的地图文件,我们利用他来制作地图。
(1)新建一个文件,会d出下面的提示框,填写自己想要的参数即可:
(2)把图片拖到图块窗口,图片包含我们需要的元素,这样,我们就可以利用图片的元素,对新建的文件进行简单的绘图。
(3)最后,点击图块的图片元素,再到新建的文件点击,就可以覆盖上面的格子,也就完成画图。
(4)注意要把生成的地图文件tmx和所用的图片放在resource文件夹下,以免找不到资源,报错,需要打开tmx文件,修改png的路径,直接名字就好了。
把tmx文件用文本编辑器打开,这个是最终版本:
<?xml version="1.0" enCoding="UTF-8"?><map version="1.0" orIEntation="orthogonal" renderorder="right-up" wIDth="60" height="10" tilewIDth="70" tileheight="70"> <tileset firstgID="1" name="map" tilewIDth="70" tileheight="70"> <image source="map.png" wIDth="980" height="490"/> </tileset> <tileset firstgID="99" name="Meta_tiles" tilewIDth="70" tileheight="70"> <image source="Meta_tiles.png" wIDth="280" height="70"/> <tile ID="0"> <propertIEs> <property name="CollIDable" value="true"/> </propertIEs> </tile> <tile ID="1"> <propertIEs> <property name="food" value="true"/> </propertIEs> </tile> <tile ID="2"> <propertIEs> <property name="win" value="true"/> </propertIEs> </tile> </tileset> <layer name="块层 1" wIDth="60" height="10"> <data enCoding="base64" compression="zlib"> eJxjYBhZwGOEYW8g9qJKyA1+YM0w6t/hDEb9O7zBqH+HNwD5d6DrQ3pikH8B3KEnZA== </data> </layer> <objectgroup name="objects"> <object name="PlayerPoint" x="72" y="353.333" wIDth="66.6667" height="70.6667"/> <object x="94.6667" y="394.667"/> </objectgroup> <layer name="barrIEr" wIDth="60" height="10"> <data enCoding="base64" compression="zlib"> eJxjYBgFowACeAfaATQEvEgYm9hw8zuyv/iQxGCAD0PH0Abo/uVjIC5+h2r84/IvjD3cAK78O5LAcC6vhisaajOfAis= </data> </layer> <layer name="Meta" wIDth="60" height="10"> <data enCoding="base64" compression="zlib"> eJxjYBgFowACUgbaATQEKUgYm9hw8zuyv5KRxGAgGUPH0Abo/k1mIC1+U2nqOuoDXP6FsWFguMQzrvw7ksBwLq+GKwAAN1oP/Q== </data> </layer></map>(5)让生成的图片显示出来,只需加以下一句代码
TMXTiledMaP* map = TMXTiledMap::create("level101.tmx"); this->addChild(map);
(6)添加对象图层,命名为Objects,如下图:
(6)故名思义,在对象绘制一个矩形,它代表一个对象,顺带设置他的属性,名称。
在代码里面,我们需要加载这个对象层,如何加载呢,且看代码:
TMXObjectGrouP* objGroup = map->getobjectGroup("objects");ValueMap = playerPointMap = objGroup->getobject(PlayerPoint);float playerx = playerPointMap.at("x").asfloat();float playery = playerPointMap.at("y").asfloat();mPlayer->setposition(Point(playerx,playery));
(7)在图层菜单,我们再添加两个图层,首先添加的层命名为barrIEr,把水果放上去,其次,再添加Meta层,把红色格子放上去作为障碍物,并设置红色格子的属性,自己添加属性。
(8)我们把水果添加为食物,只要碰到,就表示吃了水果,水果就自动消失,需要添加属性food。
(9)最后,我们也添加一个win属性的水果,迟到了就表示游戏结束,步骤和上面的一样,然后选中Meta层将该格子覆盖到地图某个格子
玩家和怪物有一些共同的 *** 作,我们将他定义为一个实体,作为父类,玩家和怪物都继承他。
#include"cocos2d.h"#include"Controller.h"using namespace cocos2d;class Entity:public Node,public ControllerListener{public: voID bindSprite(Sprite* sprite); voID setController(Controller* controller); virtual voID setTagposition(int x,int y); virtual Point getTagposition();protected: Sprite* m_sprite;//bind this sprite Controller* m_controller;};#endifcpp#include"Entity.h"voID Entity::bindSprite(Sprite* sprite){ m_sprite = sprite; this->addChild(m_sprite);}voID Entity::setController(Controller* controller)//important{ this->m_controller = controller; m_controller->setControllerListener(this);}voID Entity::setTagposition(int x,int y)//设置精灵的坐标{ setposition(x,y);}Point Entity::getTagposition()//获取精灵的坐标{ return getposition();}上面的实体类很简单,用bindsprite来绑定精灵。其余的方法有ControllerListener继承而来,下面会讲到。
#ifndef _CONTRolLERListENER_H_#define _CONTRolLERListENER_H_#include"cocos2d.h"using namespace cocos2d;class ControllerListener {public: virtual voID setTagposition(int x,int y) = 0; virtual Point getTagposition() = 0;};#endif
下面,我们来定义一个玩家类,Player,继承自Entity。
#ifndef _PLAYER_H_#define _PLAYER_H_#include"Entity.h"class Player:public Entity{public: CREATE_FUNC(Player); virtual bool init(); voID run(); voID setTiledMap(TMXTiledMaP* map); voID setVIEwPointByPlayer(); virtual voID setTagposition(int x,int y);private: TMXTiledMaP* m_map;//用来加载地图文件 bool isJumPing; TMXLayer* Meta;//检测碰撞的地图层 Point tileCoordForposition(Point pos);//将像素坐标转换为地图格子坐标};#endifcpp文件#include"Player.h"#include"WinScene.h"bool Player::init(){ isJumPing = false; return true;}voID Player::run()//animation{ SpriteFrameCache* framecache = SpriteFrameCache::getInstance(); framecache->addSpriteFramesWithfile("boys.pList","boys.png"); SpriteFrame* frame = NulL; Vector<SpriteFrame*> frameList; for(int i = 1; i <= 15; i++) { frame = framecache->getSpriteFrameByname(StringUtils::format("run%d.png",i)); frameList.pushBack(frame); } // Animation* animation = Animation::createWithSpriteFrames(frameList); animation->setLoops(-1); animation->setDelayPerUnit(0.08F); // Animate* animate = Animate::create(animation); m_sprite->runAction(animate);}voID Player::setTiledMap(TMXTiledMaP* map)//加载tmx地图文件{ this->m_map = map; this->Meta = m_map->getLayer("Meta");//直接获取我们加的图层 this->Meta->setVisible(false);}voID Player::setVIEwPointByPlayer()//让主角始终在屏幕中央,地图向后滑动{ if(m_sprite == NulL) return; Layer* parent = (Layer*)getParent(); Size tiledSize = m_map->getTileSize();//地图方块数量 Size mapTilednum = m_map->getMapSize();//地图单个格子大小 Size MapSize = Size(mapTilednum.wIDth * tiledSize.wIDth,mapTilednum.height * tiledSize.height);//整个地图的大小 Size visibleSize = Director::getInstance()->getVisibleSize(); Point spritepos = getposition(); float x = std::max(spritepos.x,visibleSize.wIDth/2); float y = std::max(spritepos.y,visibleSize.height/2); x = std::min(x,MapSize.wIDth - visibleSize.wIDth/2); y = std::min(y,MapSize.height - visibleSize.height/2); Point destPos = Point(x,y); Point centerpos = Point(visibleSize.wIDth/2,visibleSize.height/2); Point vIEwPos = centerpos - destPos; parent->setposition(vIEwPos);}voID Player::setTagposition(int x,int y)//设置精灵的位置,里面包含对碰撞的判断,食物的判断检测{ Size Spritesize = m_sprite->getContentSize(); Point dstPos = Point(x + Spritesize.wIDth/2,y);//主角前方的坐标 Point tiledPos = tileCoordForposition(Point(dstPos.x,dstPos.y));//前方坐标在地图里面格子的位置 int tiledGID = Meta->getTileGIDAt(tiledPos);//获取地图格子唯一的标志 if(tiledGID != 0)//不为0表示存在这个格子 { Value propertIEs = m_map->getPropertIEsForGID(tiledGID);//获取格子的属性 //Value prop = propertIEs.asValueMap().at("CollIDable");//我们加的属性 ValueMap propMap = propertIEs.asValueMap(); if(propMap.find("CollIDable") != propMap.end()) { Value prop = propMap.at("CollIDable"); if(prop.asstring().compare("true") == 0 && isJumPing == false) { isJumPing = true; auto jumpBy = JumpBy::create(0.5f,Point(-100,0),80,1); CallFunc* callfunc = CallFunc::create([&]() { isJumPing = false; }); auto action = Sequence::create(jumpBy,callfunc,NulL); this->runAction(action); } } //food if(propMap.find("food") != propMap.end()) { Value prop = propMap.at("food"); if(prop.asstring().compare("true") == 0) { TMXLayer* barrIEr = m_map->getLayer("barrIEr"); barrIEr->removeTileAt(tiledPos); } } if(propMap.find("win") != propMap.end()) { Value prop = propMap.at("win"); if(prop.asstring().compare("true") == 0) { TMXLayer* barrIEr = m_map->getLayer("barrIEr"); barrIEr->removeTileAt(tiledPos); Director::getInstance()->replaceScene(WinScene::createScene()); } } } Entity::setTagposition(x,y); setVIEwPointByPlayer();}Point Player::tileCoordForposition(Point pos)//将像素坐标转换为地图格子坐标{ Size mapTilednum = m_map->getMapSize();//地图单个格子大小 Size tiledSize = m_map->getTileSize();//地图方块数量 int x = pos.x/tiledSize.wIDth; //cocos2d-x的默认y坐标是由下至上的,所以要做一个相减 *** 作 int y = (700 - pos.y)/tiledSize.height; //格子坐标从0开始计算 if(x > 0) { x-=1; } if(y > 0) { y-=0; } return Point(x,y);}run函数,其实就是一个animation,让精灵看起来是在跑的样子,几张图片轮流播放。 2.2添加控制器
我们把让精灵向前跑作为一个类,为了以后方便扩展,我们首先实现控制器的父类。
#ifndef _CONTRolLER_H_#define _CONTRolLER_H_#include"cocos2d.h"#include"ControllerListener.h"using namespace cocos2d;class Controller:public Node{public: voID setControllerListener(ControllerListener* controllerListener);protected: ControllerListener* m_controllerListener;};#endif#include"Controller.h"voID Controller::setControllerListener(ControllerListener* controllerListener){ this->m_controllerListener = controllerListener;}主要是通过继承这个控制基类,来实现不同的控制需求。
2.3子类控制器
最后,根据需求,制定我们的控制子类。
#ifndef _SIMPLECONTRolLER_H_#define _SIMPLECONTRolLER_H_#include"cocos2d.h"#include"Controller.h"using namespace cocos2d;class SimpleMoveController:public Controller{public: CREATE_FUNC(SimpleMoveController); virtual bool init(); virtual voID update(float dt); voID setxSpeed(int xspeed); voID setySpeed(int yspeed);private: int x_speed; int y_speed; voID registertouchEvent();};#endif
#include"SimpleMoveController.h"bool SimpleMoveController::init(){ this->x_speed = 0; this->y_speed = 0; registertouchEvent(); this->scheduleUpdate(); return true;}voID SimpleMoveController::update(float dt)//update函数,需要在init()那里调用this->scheduleUpdate()才会调用{ if(m_controllerListener == NulL) return; Point pos = m_controllerListener->getTagposition(); pos.x += x_speed; pos.y += y_speed; m_controllerListener->setTagposition(pos.x,pos.y);}voID SimpleMoveController::setxSpeed(int speed){ this->x_speed = speed;}voID SimpleMoveController::setySpeed(int speed){ this->y_speed = speed;}voID SimpleMoveController::registertouchEvent()//触摸事件处理{ auto Listener = EventListenertouchOneByOne::create(); Listener->ontouchBegan = [](touch* touch,Event* event) { return true; }; Listener->ontouchmoved = [&](touch* touch,Event* event) { Point touchPos = Director::getInstance()->convertToGL(touch->getLocationInVIEw()); Point pos = m_controllerListener->getTagposition();//记得引用时,luba里面 【&】 int speed = 0; if(touchPos.y > pos.y) { speed = 1; } else { speed = -1; } setySpeed(speed); }; Listener->ontouchended = [&](touch* touch,Event* event) { setySpeed(0); }; _eventdispatcher->addEventListenerWithSceneGraPHPriority(Listener,this);//分发事件}2.4场景代码
#include "HelloWorldScene.h"#include "Player.h"#include "SimpleMoveController.h"USING_NS_CC;Scene* HelloWorld::createScene(){ // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } TMXTiledMaP* map = TMXTiledMap::create("level101.tmx");//加载tmx地图文件 this->addChild(map);//将他加到场景 addplayer(map);//把玩家添加到地图 return true;}voID HelloWorld::addplayer(TMXTiledMaP* map){ Size visibleSize = Director::getInstance()->getVisibleSize(); Sprite* playerSprite = Sprite::create("Player.png"); //将精灵绑定到玩家对象上面 Player* mPlayer = Player::create(); mPlayer->bindSprite(playerSprite); mPlayer->run(); mPlayer->setTiledMap(map); mPlayer->setposition(Point(100,visibleSize.height/2)); map->addChild(mPlayer);//将Player加到地图 //给玩家设置控制器 SimpleMoveController* smc = SimpleMoveController::create(); smc->setxSpeed(1); smc->setySpeed(0); this->addChild(smc);//加到场景,因为继承自Node mPlayer->setController(smc);}voID HelloWorld::menuCloseCallback(Ref* pSender){#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. windows Store Apps do not implement a close button.","Alert"); return;#endif Director::getInstance()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0);#endif}2.5效果图
总结
以上是内存溢出为你收集整理的Cocos2dx学习第八章(游戏实例之跑跑跑)全部内容,希望文章能够帮你解决Cocos2dx学习第八章(游戏实例之跑跑跑)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)