用Cocos2dx实现超级玛丽,首先用帧循环定时器判断方向,再在类中实现运行以及判断是否能运动。

方向控制

void LayerGame::moveMario(float dt)
{
#ifdef WIN32
    short key;

    key = GetKeyState('F');
    if (key < 0) _marioDir = Common::RIGHT;

    key = GetKeyState('D');
    if (key < 0) _marioDir = Common::LEFT;

    key = GetKeyState('J');
    if (key < 0)_mario->jump();

#endif

    if (_marioDir==Common::LEFT)
    {
        //cclog("left\n");
        _marioDir=Common::NONE;
        _mario->moveLeft(dt);

    }else if(_marioDir==Common::RIGHT)
    {
        //cclog("right\n");
        _marioDir=Common::NONE;
        _mario->moveRight(dt);
    }else
    {
        //cclog("stop\n");
        _menuShow->setTexture(_textureDirNone);
        _mario->stop();
    }

    _mario->moveUp(dt);
    _mario->moveDown(dt);
}

判断是否能向上,向左,向右,向下运动,利用碰撞检测

bool Mario::canMoveLeft(float dt)
{
    //judge if mario is out of the map
    CCRect rcMario=this->boundingBox();
    CCPoint ptMario=ccp(rcMario.getMinX(),rcMario.getMinY());
    CCTMXTiledMap *map=getMap();
    CCPoint ptMarioInWorld=map->convertToWorldspace(ptMario);
    if (ptMarioInWorld.x-dt*_speed<0)   
    {
        return false;
    }

    //judge if partition by a wall
    CCPoint pt[3];
    pt[0] = ccp(rcMario.getMinX() - dt*_speed,rcMario.getMidY());
    pt[1] = ccp(rcMario.getMinX() - dt*_speed,rcMario.getMinY());
    pt[2] = ccp(rcMario.getMinX() - dt*_speed,rcMario.getMaxY());

    //transform position,change pt into tile and get gid to decide whether be stoped by wall
    for(int i=0;i<3;i++)
    {
        if (pt[i].y >= map->getContentSize().height)
            continue;
        CCPoint ptTile=Common::Point2Tile(map,pt[i]);
        //wall water pipe and floor
        static const char* layerName[3] = { "block","pipe","land" };
        for(int j=0;j<3;j++)
        {
            CCTMXLayer *layer=map->layerNamed(layerName[j]);
            int gid=layer->tileGIDAt(ptTile);
            if (gid!=0)
            {
                return false;
            }
        }

    }


    return true;
}
bool Mario::canMoveRight(float dt)
{
    CCRect rcMario = boundingBox();
    CCTMXTiledMaP* map = getMap();
    CCPoint pt[3];
    pt[0] = ccp(rcMario.getMaxX() + dt*_speed,rcMario.getMidY());
    pt[1] = ccp(rcMario.getMaxX() + dt*_speed,rcMario.getMinY());
    pt[2] = ccp(rcMario.getMaxX() + dt*_speed,rcMario.getMaxY());

    // 坐标转换,将pt转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡
    for (int i = 0; i < 3; ++i)
    {
        if (pt[i].y >= map->getContentSize().height)
            continue;

        CCPoint ptTile = Common::Point2Tile(map,pt[i]);
        // 水管、砖头,地板
        static const char* layerName[3] = { "block","land" };
        for (int j = 0; j < 3; ++j)
        {
            CCTMXLayer* layer = map->layerNamed(layerName[j]);
            int gid = layer->tileGIDAt(ptTile);
            if (gid != 0)
            {
                return false;
            }
        }
    }
    return true;
}
bool Mario::canMoveDown(float dt)
{
    CCRect rcMario = boundingBox();
    CCTMXTiledMaP* map = getMap();
    CCPoint pt[3];
    //dt*_speedDown
    pt[0] = ccp(rcMario.getMidX(),rcMario.getMinY() - dt*_speedDown);
    pt[1] = ccp(rcMario.getMinX(),rcMario.getMinY() - dt*_speedDown);
    pt[2] = ccp(rcMario.getMaxX(),rcMario.getMinY() - dt*_speedDown);

    if (pt[0].y >= map->getContentSize().height)
        return true;

    // 坐标转换,将pt转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡
    for (int i = 0; i < 3; ++i)
    {
        CCPoint ptTile = Common::Point2Tile(map,"land" };
        for (int j = 0; j < 3; ++j)
        {
            CCTMXLayer* layer = map->layerNamed(layerName[j]);
            int gid = layer->tileGIDAt(ptTile);
            if (gid != 0)
            {
                // 微调
                CCPoint ptLB = Common::Tile2PointLB(map,ptTile+ccp(0,-1));
                this->setPositionY(ptLB.y);

                return false;
            }
        }
    }

    return true;
}
bool Mario::canMoveUp(float dt)
{
    CCRect rcMario = boundingBox();
    CCTMXTiledMaP* map = getMap();
    CCPoint pt[3];
    pt[0] = ccp(rcMario.getMidX(),rcMario.getMaxY() + dt*_speedUp);
    pt[1] = ccp(rcMario.getMinX(),rcMario.getMaxY() + dt*_speedUp);
    pt[2] = ccp(rcMario.getMaxX(),rcMario.getMaxY() + dt*_speedUp);

    if (pt[0].y >= map->getContentSize().height)
        return true;

    // 坐标转换,将pt转化成地图格子坐标,ptTile);
                this->setPositionY(ptLB.y);

                return false;
            }
        }
    }

    return true;
}

运行实现

void Mario::moveLeft(float dt)
{
    if (_dirRun!=Common::LEFT)
    {
        _dirRun=Common::LEFT;
        _dirFace=Common::LEFT;
        updateStatus();
    }
    if (!canMoveLeft(dt))
        return;
    Common::moveNode(this,ccp(-dt*_speed,0));

    //scroll map
    CCNode *map=this->getParent();
    CCPoint ptWorld=map->convertToWorldspace(this->getPosition());
    if (ptWorld.x<winSize.width/2&&map->getPositionX()<0)
    {
        Common::moveNode(map,ccp(dt*_speed,0));
    }
}

void Mario::moveRight(float dt)
{
    if (_dirRun!=Common::RIGHT)
    {
        _dirRun=Common::RIGHT;
        _dirFace=Common::RIGHT;
        updateStatus();
    }
    if (!canMoveRight(dt))
        return;
    Common::moveNode(this,0));

    //scroll map
    CCNode *map=this->getParent();
    CCPoint ptWorld=map->convertToWorldspace(this->getPosition());
    if (ptWorld.x>winSize.width/2)
    {
        Common::moveNode(map,0));
    }
}

void Mario::moveUp(float dt)
{
    if (_speedUp<=0)
    {

        return;
    }
    if (!canMoveUp(dt))
    {
        // 反弹效果
        _speedDown = _speedUp;
        _speedUp = 0; // 不继续上升了
        return;
    }

    Common::moveNode(this,ccp(0,dt*_speedUp));
    _speedUp-=_speedAcc;
    //_speedDown=_speedUp;
}
void Mario::moveDown(float dt)
{
    if(_speedUp<=0)
    {

    if (canMoveDown(dt))
    {
        if (_bFly==false)
        {
            _bFly=true;
            updateStatus();
        }
        Common::moveNode(this,-dt*_speedDown));
        _speedDown+=_speedAcc;
    }
    else
    {
        if (_bFly)
        {

            _bFly = false;
            _speedDown = _speedAcc;
            updateStatus();
        }

    }
    }

}

void Mario::stop()
{
    if (_dirRun!=Common::NONE)
    {
        _dirRun=Common::NONE;
        updateStatus();
    }
}
void Mario::jump()
{
    static int i=0;
    cclog("speed%d=%d",++i,_speedUp);
    if (_bFly)
        return;
    _speedUp=300;
    _bFly=true;
    updateStatus();
}

运行状态机,控制运行时的动画

void Mario::updateStatus()
{
    stopAllActions();
    if (_bFly)
    {
        if (_dirFace==Common::LEFT)
        {
            setdisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("SmallJumpLeft")); }else if(_dirFace==Common::RIGHT) { setdisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("SmallJumpRight")); } return; } if (_dirRun==Common::LEFT) { this->runAction(CCRepeatForever::create(CCAnimate::create(CCAnimationCache::sharedAnimationCache()->animationByName("SmallWalkLeft")))); }else if (_dirRun==Common::RIGHT) { this->runAction(CCRepeatForever::create(CCAnimate::create(CCAnimationCache::sharedAnimationCache()->animationByName("SmallWalkRight")))); }else { if (_dirFace==Common::LEFT) { this->setdisplayFrameWithAnimationName("SmallWalkLeft",0);
        }else if(_dirFace==Common::RIGHT)
        {
            this->setdisplayFrameWithAnimationName("SmallWalkRight",0);
        }
    }
}

注:在实现这个功能的时候,由于把等于写成赋值,发生了许多灵异的错误,要小心啊,等于与赋值。

运行结果

实现超级玛丽上下左右运动的更多相关文章

  1. Xcode iOS Notability“缩放框”

    Notability和其他笔记应用程序具有此“缩放框”功能,您可以在底部的放大框中绘制.用户还可以拖动顶部的框以更改底部放大的内容.我已经尝试了我能想到的所有内容,以便在我的应用中添加此功能.我在两个视图中添加了相同的文档,但后来我遇到了很多内存问题,我已经复制了文件但是再次出现了内存问题.有谁知道一个简单的方法来做到这一点?

  2. PHP+javascript模拟Matrix画面

    直接存为*.php文件运行即可。

  3. PHP也可以當成Shell Script

    不过﹐这次要讲的主题不是PHP在网页设计上的应用﹐而是PHP在ShellScript上的应用﹐一般所知的ShellScript大约就是tcsh、bash、perl或是python这几类语言﹐我所要谈的就是将PHP当成ShellScript来使用。第一个程序开始撰写我们的第一个PHPShellScript程序﹐这个例子印出"Helloworld!>注意到PHP原本是应用在网页应用的﹐因此它内定会送出HTML的HEADER﹐但是在此我们是要将PHP用作ShellScript﹐"-q"就是表示不要送出HEADE

  4. PHP+javascript液晶时钟

    $size_small=5;//液晶宽度$size_big=25;//液晶长度$distance=10;//间距$color_back="#DDDDDD";$color_dark="#CCCCCC";$color_light="#000000";$number=0;?>";}}functionchange//处理数字显示{switch{case0:swapcolor;swapcolor;swapcolor;swapcolor;swapcolor;swapcolor;swapcolor;break;case

  5. 对javascript和select部件的结合运用

    php//对Javascript和select部件的结合运用//在写程序的过程,我想实现在select对象选中选项后,//不需要提交按钮,而直接触发动作,且在动作发生后//的页面中要保持所选择的选项。经过形容,终于通过//使用Javascript及select对象的onchange属性及//value值而实现了这种功能。>

  6. css中的px、em、rem、pt 特点和区别及换算详解

    这篇文章主要介绍了css中的px、em、rem、pt 之间的特点和区别及换算,各大小单位是否继承父元素大小及浏览器兼容与否等方面也做了详细解释,需要的朋友可以参考下

  7. PHP与javascript的两种交互方式

    在网页制作过程中怎样在不刷新页面的情况下使前台页面和后台CGI页面保持交互一直是个问题。这里介绍两个我在实践中使用的方法。action.php将信息放入cookie中,main.htm通过读取cookie来实现交互。index.htm---------------------------------------------------------------Test

  8. JSP由浅入深(8)—— JSP Tags

    JSP另外一个重要的语法是Tags(标记)。JSPtags可以有一个“starttag”、一个“tagbody”以及一个“endtag”。标志可以分成两种类型:一种是从外部标志库中转载的,另外一种是预先定义的标志。预先定义的标志是以jsp:字符开始的。其实它跟jsp:include是很相似的。再给出本节的练习吧,编写一个JSP,使之根据一个布尔型变量来对一个包含的文件。这里还是提示一下吧,要用到HTML和scriptlets的混合编程来处理JSP标志。

  9. JSP由浅入深(4)—— Scriptlets

    上面的教程我们已经学会了如何在JSP网页中通过在字符系列之间嵌入Java表达式。但是通过将Java表达式放置到HTML进行大量的编程工作是很困难的。代码块就是我们熟知的“scriptlet”。如果单单是scriptlet,对于HTML起不了任何作用。而每次scriptlet包含了被执行的Java代码的时候,JSP就被调用。下面的代码是对上一节JSP教程进行修改后的代码,我们增加了一个scriptlet:

  10. PHP与javascript对多项选择的处理

    我们经常要给用户作出多项选择进行处理,例如允许用户对列表项选择多项后删除选定项等。今天举个例子说明PHP和JavaScript分别是怎样处理多项选择的。表itemtable是通过以下MySQL语句建立的:CREATETABLE`itemtable`;其中字段“name”是列表项目名,“votes”是所得票数。我们还要建立一个表“voteiptable”来记录投票用户的IP:CREATETABLE`voteiptable`;下面我们编写文件“multivote.php”,今天我们要用到一个数据库类文件“db

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部