用简单思路做游戏—----怎么想得就怎么写
俄罗斯方块~经典中的经典,小时候玩方块机,经常一玩一下午,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
俄罗斯方块~经典中的经典,小时候玩方块机,经常一玩一下午,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