zoukankan      html  css  js  c++  java
  • 实现超级玛丽上下左右运动

    用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
    ");
            _marioDir=Common::NONE;
            _mario->moveLeft(dt);
    
        }else if(_marioDir==Common::RIGHT)
        {
            //CCLog("right
    ");
            _marioDir=Common::NONE;
            _mario->moveRight(dt);
        }else
        {
            //CCLog("stop
    ");
            _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", "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::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, pt[i]);
            // 水管、砖头,地板
            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)
                {
                    // 微调
                    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转化成地图格子坐标,然后获取gid,判断gid是不是被阻挡
        for (int i = 0; i < 3; ++i)
        {
            CCPoint ptTile = Common::Point2Tile(map, pt[i]);
            // 水管、砖头,地板
            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)
                {
                    // 微调
                    CCPoint ptLB = Common::Tile2PointLB(map, 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,ccp(dt*_speed,0));
    
        //scroll map
        CCNode *map=this->getParent();
        CCPoint ptWorld=map->convertToWorldSpace(this->getPosition());
        if (ptWorld.x>winSize.width/2)
        {
            Common::moveNode(map,ccp(-dt*_speed,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,ccp(0,-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);
            }
        }
    }

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

    运行结果

    结果

  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/jjx2013/p/6223748.html
Copyright © 2011-2022 走看看