简单思路做游戏----俄罗斯方块

用简单思路做游戏—----怎么想得就怎么写


俄罗斯方块~经典中的经典,小时候玩方块机,经常一玩一下午,80后的回忆啊


首先定义方块的结构,一个方块由4个小块组成,假设每个小块就是一个点,方块结构如下:
//方块类
class Block
{
public:
    Block();
    Block(Vec2 b1, Vec2 b2, Vec2 b3, Vec2 b4);
    Block(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
    ~Block();
    
public:
    Vec2 m_pos;//位置
    Vec2 m_b[4];//4个小块
};


然后是方块的各种形态,假设每个方块第二个点是(0, 0),那么其他的也就好定义了


//定义7种类型,4种形态的方块
Block blocks[7][4] = {
    {Block(0, 1, 0, 0, 0, -1, 0, -2), Block(-1, 0, 0, 0, 1, 0, 2, 0), Block(0, 1, 0, 0, 0, -1, 0, -2), Block(-1, 0, 0, 0, 1, 0, 2, 0)},//直线
    {Block(0, 1, 0, 0, 1, 1, 1, 0), Block(0, 1, 0, 0, 1, 1, 1, 0), Block(0, 1, 0, 0, 1, 1, 1, 0), Block(0, 1, 0, 0, 1, 1, 1, 0),},//方块
    {Block(0, 1, 0, 0, 0, -1, 1, -1), Block(-1, 0, 0, 0, 1, 0, 1, 1), Block(-1, 1, 0, 1, 0, 0, 0, -1), Block(1, 0, 0, 0, -1, 0, -1, -1)},//正L
    {Block(0, 1, 0, 0, 0, -1, -1, -1), Block(-1, 0, 0, 0, 1, 0, 1, -1), Block(0, 1, 0, 0, 1, 1, 0, -1), Block(-1, 0, 0, 0, -1, 1, 1, 0)},//反L
    {Block(-1, 0, 0, 0, 0, -1, 1, -1), Block(0, -1, 0, 0, 1, 0, 1, 1), Block(0, 1, 0, 0, -1, 1, 1, 0), Block(-1, 0, 0, 0, -1, -1, 0, 1)},//正Z
    {Block(0, -1, 0, 0, -1, -1, 1, 0), Block(0, 1, 0, 0, 1, 0, 1, -1), Block(01, 0, 0, 0, 0, 1, 1, 1), Block(-1, 0, 0, 0, -1, 1, 0, -1)},//反Z
    {Block(-1, 0, 0, 0, 0, 1, 1, 0), Block(-1, 0, 0, 0, 0, 1, 0, -1), Block(-1, 0, 0, 0, 1, 0, 0, -1), Block(0, 1, 0, 0, 0, -1, 1, 0)}//凸
};


初始化地图,整个过程其实是控制小方块的显示与隐藏的


void TetrisLayer::initMap()
{
    auto winsize = Director::getInstance()->getWinSize();
    auto drawNode = DrawNode::create();
    addChild(drawNode);
    
    Vec2 point[4];
    point[0] = Vec2((winsize.width - KWidth * KTileSize) / 2, 0);
    point[1] = Vec2(winsize.width - (winsize.width - KWidth * KTileSize) / 2, 0);
    point[2] = Vec2(winsize.width - (winsize.width - KWidth * KTileSize) / 2, winsize.height);
    point[3] = Vec2((winsize.width - KWidth * KTileSize) / 2, winsize.height);
    
    drawNode->drawPolygon(point, 4, Color4F(1, 0, 0, 0), 3, Color4F(1, 0, 0, 1));
    
    for(int i = 0; i < KWidth; ++i)
    {
        for(int j = 0; j < KHeight; ++j)
        {
            //位置信息
            m_pos[i][j] = Vec2((winsize.width - KWidth * KTileSize) / 2 + KTileSize / 2 + i * KTileSize, KTileSize / 2 + KTileSize * j);
            
            //元素信息
            m_map[i][j] = 0;
            
            //资源
            auto sprite = Sprite::create("test/egg.png");
            sprite->setPosition(m_pos[i][j]);
            sprite->setScale(KTileSize / 50.0f);
            addChild(sprite, 0, KWidth * i + j);
            sprite->setVisible(false);
        }
    }
}


初始化一个方块
void TetrisLayer::initBlock()
{
    int type = rand() % 7;
    m_curType = m_nextType;
    m_nextType = type;
    m_curBlock = m_nextBlock;
    m_nextBlock = blocks[type][0];
    m_curIndex = 0;
}


接来下就开始移动方块了,方块消除的判断是:任意一个小块,只要下方有小方块,则停止。如果任意一行填满小方块,消除当前行


void TetrisLayer::step(float dt)
{
    m_curBlock.m_pos.y--;
    
    bool flag = false;
    
    //判断是否接触碰撞
    for(int i = 0; i < 4; ++i)
    {
        Vec2 pos = m_curBlock.m_b[i] + m_curBlock.m_pos;
        
        if(pos.y == 0)
        {
            //碰撞了
            flag = true;
            break;
        }
        else if(m_map[(int)pos.x][(int)pos.y - 1] == 1)
        {
            //碰撞了
            flag = true;
            break;
        }
    }
    
    if(flag)
    {
        for(int i = 0; i < 4; ++i)
        {
            Vec2 pos = m_curBlock.m_b[i] + m_curBlock.m_pos;
            
            if(m_map[(int)pos.x][(int)pos.y] == 0)
            {
                m_map[(int)pos.x][(int)pos.y] = 1;
            }
        }
    }
    
    //判断是否消除
    for(int i = 0; i < KWidth; ++i)
    {
        int count = 0;
        
        for(int j = 0; j < KHeight; ++j)
        {
            if(m_map[j][i] == 1)
            {
                count++;
            }
        }
        
        if(count == KWidth)
        {
            //本行满了,可消除, 消除后,所有上层的自动将一行
            releaseLine(i);
            --i;
        }
    }
    
    //判断是否gameover
    for(int i = 0; i < KWidth; ++i)
    {
        if(m_map[i][KHeight - 2] == 1)
        {
            //gameover
            unschedule(schedule_selector(TetrisLayer::step));
            return;
        }
    }
    
    //生成新块
    if(flag)
    {
        if(m_accelerateFlag)
        {
            m_accelerateFlag = false;
            unschedule(schedule_selector(TetrisLayer::step));
            schedule(schedule_selector(TetrisLayer::step), 0.5f);
        }
        
        initBlock();
    }
    
    //下一帧
    schedule(schedule_selector(TetrisLayer::updataImage), 0.01f);
}


消除行
void TetrisLayer::releaseLine(int line)
{
    for(int i = 0; i < KWidth; ++i)
    {
        for(int j = line; j < KHeight; ++j)
        {
            m_map[i][j] = m_map[i][j + 1];
        }
    }
}


更新image控制图片显示性
void TetrisLayer::updataImage(float dt)
{
    unschedule(schedule_selector(TetrisLayer::updataImage));
             
    for(int i = 0; i < KWidth; ++i)
    {
        for(int j = 0; j < KHeight; ++j)
        {
            auto sprite = getChildByTag(KWidth * i + j);
            
            if(m_map[i][j] == 1)
            {
                sprite->setVisible(true);
            }
            else
            {
                sprite->setVisible(false);
            }
        }
    }
    
    for(int i = 0; i < 4; ++i)
    {
        Vec2 pos = m_curBlock.m_pos + m_curBlock.m_b[i];
        
        auto sprite = getChildByTag(pos.x * KWidth + pos.y);
        sprite->setVisible(true);
    }
}


还有最重要的,按键功能


void TetrisLayer::buttonListener(Ref* ref)
{
    int tag = ((Button*)ref)->getTag();
    
    if(tag == ETagBtnLeft)//向左移动
    {
        bool flag = true;
        
        for(int i = 0; i < 4; ++i)
        {
            Vec2 pos = m_curBlock.m_b[i] + m_curBlock.m_pos;
            
            if(pos.x <= 0 || m_map[(int)pos.x - 1][(int)pos.y] == 1)
            {
                flag = false;
                break;
            }
        }
        
        if(flag)
        {
            m_curBlock.m_pos.x--;
        }
    }
    else if(tag == ETagBtnRight)//向右移动
    {
        bool flag = true;
        
        for(int i = 0; i < 4; ++i)
        {
            Vec2 pos = m_curBlock.m_b[i] + m_curBlock.m_pos;
            
            if(pos.x >= KWidth - 1 || m_map[(int)pos.x + 1][(int)pos.y] == 1)
            {
                flag = false;
                break;
            }
        }
        
        if(flag)
        {
            m_curBlock.m_pos.x++;
        }
    }
    else if(tag == ETagBtnTop)//变换形态
    {
        int index = m_curIndex + 1;
        
        if(index > 3)
        {
            index = 0;
        }
        
        Block block = blocks[m_curType][index];
        block.m_pos = m_curBlock.m_pos;
        
        bool flag = true;
        
        for(int i = 0; i < 4; ++i)
        {
            Vec2 p = block.m_b[i] + block.m_pos;
            
            if(p.x < 0 || p.x > KWidth - 1 || p.y < 0 || m_map[(int)p.x][(int)p.y] == 1)
            {
                flag = false;
                break;
            }
        }
        
        if(flag)
        {
            m_curIndex = index;
            m_curBlock = block;
        }
    }
    else if(tag == ETagBtnButtom)//加速下落
    {
        m_accelerateFlag = true;
        unschedule(schedule_selector(TetrisLayer::step));
        schedule(schedule_selector(TetrisLayer::step), 0.016f);
    }
}


我发现我的帖子基本上以代码为主的。。。因为我不知道都应该说些什么。。。。


完整源码地址:http://download.csdn.net/detail/heyanru/8893637

猜你喜欢

转载自blog.csdn.net/heyanru/article/details/46858521