资源描述
课程设计报告
课程名称:面向对象程序设计C++
设计题目:基于cocos2d-x开发俄罗斯方块
专 业:计算机科学与技术
姓 名:
学 号:
指导教师:李 晓 虹
2016 年 1 月 10 日
第一章 需求分析
1.1 游戏介绍
俄罗斯方块是一个精典的小游戏,从最早的家庭游戏机、掌上游戏机上都能看到它的身影,正是由于它的简单有趣,在全球得到广泛的传播,男女老少皆宜。而且俄罗斯方块的设计工作复杂且富有挑战性,可以锻炼人的空间想象能力,反映能力等等。在设计这款游戏的过程中,也用到了很多各方面的知识,这对于C++ 的学习者来说是个很好的练习机会。
1.2 游戏玩法
游戏区域会从顶部不断落下7种下坠物的一种,游戏区域的右侧有一方框可以提示用户下一个下坠物的形状,玩家可以移动、旋转、加速下落和一键到底自己窗口内落下的下坠物,通过用户的操作,下坠物在游戏区域以“摆积木”的形式出现。下坠物在一行或多行堆满后就可以自动消掉,消行后会得到相应的分数,如果当前下坠物堆积至窗口顶端,即游戏结束。
1.3 开发平台介绍
cocos2d是一个基于MIT协议的开源框架,用于构建游戏、应用程序和其他图形界面交互应用。可以让你在创建自己多平台游戏时节省很多的时间。Cocos是由触控科技推出的游戏开发一站式解决方案,包含了从新建立项、游戏制作、到 打包上线的全套流程。开发者可以通过cocos快速生成代码、编辑资源和动画,最终输出适合于多个平台的游戏产品。2012年发布的CocoStudio工具集是开源游戏引擎Cocos2d-x开发团队官方推出的游戏开发工具,目前已经进入稳定版。cocoStudio吸取了他们自己在游戏制作中的经验,为移动游戏开发者团队量身定做,旨在降低游戏开发门槛,提高开发效率,同时也为Cocos2D-X的进一步开发打下基础。在中国的2D手机游戏开发中,Cocos2d-x引擎份额超过了70%。
第二章 总体设计
2.1 游戏总体
图 2-1
2.2 系统功能设计
方块下落、旋转功能:在整个游戏中,方块是核心,系统每次随机产生一个方块。一共七种不同的方块,方块可以根据玩家的操作进行左移、右移、加速下落、顺时针进行旋转等
游戏胜利:当分数累计到一定大小时,游戏将达到胜利,并结束游戏
游戏失败:当累积的方块溢出游戏区域时,游戏以失败告终
游戏音乐:游戏开始时游戏背景音乐自动播放,暂停时与结束时音乐也同时结束
分数及下一块方块提示:在游戏区域的侧边栏显示分数及下一块方块的形状进行提示。
第三章 详细设计
3.1 功能模块
3.1.1速度模块
速度模块是制定游戏的速度,根据提升的关卡可以提升速度,难度越大掉落的方块速度越快。
3.1.2 难度模块
采取积分的方式闯关,每到到一定积分,增加相应的难度。
3.1.3 积分模块
积分模块是玩家对游戏消掉行的统计累加。
计算方法为:
sum=100*(2N-1)
sum是积分,N是一次消掉的行数。
例如:当消掉一行时,积分为100*(21-1)=100,消掉两行时,积分为100*(22-1)=300.
记分遵循一次消去一行加100,两行加300,三行加700,4行1500的模式,10000分升一级。
3.2 游戏层设计
3.2.1 方块形状
一共设计几种方块形状,用于4个小方块组成的方块组合,不考虑自身旋转变化的话,总共有7种,分别为L型,T型,I型,N型,田型,J型以及倒N型。方块这几种不同的形状,将会采用产生随机数的方法随机抽取一种。
3.2.2 游戏面板
游戏面板有12*20的大小,进游戏或者每个关卡初始化,清空原有方块,根据模版填充方块。
3.3 游戏界面设计
游戏界面是玩家直接接触到的最直观的东西,本游戏采用了简单明了的设计界面,所有的功能都一目了然。根据玩家的需求分析,采用单窗体设计,设计了游戏区,展示区、控制区三个设计区域。如图3-3所示,其中游戏区是方块下落显示区,预览区是下一个要出现的方块显示区,控制区是对游戏控制的操作区,包括速度、难度、积分显示、暂停游戏、开始游戏等等。
图3-3
对于方向键的使用,设计时使用上、下、左、右键来控制方块的移动,用上键来控制方块的旋转。
该游戏共有3个等级:低、中、高,级数为游戏当前等级,当分数达到当前等级的最高值,等级会提升、速度会加快。
图3-4
第四章 系统调试
开发环境OS X EI Capitan 版本10.11.2 ,X-code,X-code自带调试,4s平台下测试。
第五章 结果分析
部分源代码
//
// GameCtrlLayer.cpp
// AITetris
//
// Created by hansir on 16/1/10.
//
//
#include "GameCtrlLayer.h"
bool GameCtrlLayer::init()
{
if (!Layer::init()) {
return false;
}
m_AIOn = false;
Size visibleSize = Director::getInstance()->getVisibleSize();
// 开始游戏
Label *labelStartGame = Label::createWithSystemFont("开始游戏", "", 24);
labelStartGame->setWidth(36*3);
labelStartGame->setAlignment(TextHAlignment::CENTER);
MenuItemLabel *menuItemStartGame = MenuItemLabel::create(labelStartGame, CC_CALLBACK_0(GameCtrlLayer::clickStartGameButton, this));
Menu *menuStartGame = Menu::createWithItem(menuItemStartGame);
menuStartGame->setPosition(36+36/2, visibleSize.height/2-10);
this->addChild(menuStartGame);
// 开启智能
m_labelAISwitch = Label::createWithSystemFont("开启智能", "", 24);
m_labelAISwitch->setWidth(36*3);
m_labelAISwitch->setAlignment(TextHAlignment::CENTER);
MenuItemLabel *menuItemAISwitch = MenuItemLabel::create(m_labelAISwitch, CC_CALLBACK_0(GameCtrlLayer::clickAISwitchButton, this));
Menu *menuAISwitch = Menu::createWithItem(menuItemAISwitch);
menuAISwitch->setPosition(36+36/2, visibleSize.height/2-60);
this->addChild(menuAISwitch);
// 智能速度
m_labelAISpeed = Label::createWithSystemFont("", "", 24);
m_labelAISpeed->setWidth(36*3);
m_labelAISpeed->setAlignment(TextHAlignment::CENTER);
m_labelAISpeed->setPosition(36+36/2, visibleSize.height/2-4*36);
this->addChild(m_labelAISpeed);
// 左
MenuItemImage *menuItemLeft = MenuItemImage::create("images/btn_left.png", "images/btn_left.png", CC_CALLBACK_0(GameCtrlLayer::clickLeftButton, this));
m_menuLeft = Menu::createWithItem(menuItemLeft);
m_menuLeft->setPosition(36/2, visibleSize.height/2-4*36);
this->addChild(m_menuLeft);
// 下
MenuItemImage *menuItemDown = MenuItemImage::create("images/btn_down.png", "images/btn_down.png", CC_CALLBACK_0(GameCtrlLayer::clickDownButton, this));
Menu *menuDown = Menu::createWithItem(menuItemDown);
menuDown->setPosition(36+36/2, visibleSize.height/2-5*36);
this->addChild(menuDown);
// 右
MenuItemImage *menuItemRight = MenuItemImage::create("images/btn_right.png", "images/btn_right.png", CC_CALLBACK_0(GameCtrlLayer::clickRightButton, this));
m_menuRight = Menu::createWithItem(menuItemRight);
m_menuRight->setPosition(2*36+36/2, visibleSize.height/2-4*36);
this->addChild(m_menuRight);
return true;
}
void GameCtrlLayer::clickStartGameButton()
{
m_delegate->gameCtrlLayerClickStartGame();
}
void GameCtrlLayer::clickAISwitchButton()
{
m_AIOn = !m_AIOn;
if (m_AIOn) {
m_labelAISwitch->setString("关闭智能");
float speed = m_delegate->gameCtrlLayerGetAISpeed();
m_labelAISpeed->setVisible(true);
m_labelAISpeed->setString(StringUtils::format("%.1f个/秒", speed));
m_menuLeft->setVisible(false);
m_menuRight->setVisible(false);
}
else {
m_labelAISwitch->setString("开启智能");
m_labelAISpeed->setVisible(false);
m_menuLeft->setVisible(true);
m_menuRight->setVisible(true);
}
m_delegate->gameCtrlLayerStartAI(m_AIOn);
}
void GameCtrlLayer::clickLeftButton()
{
m_delegate->gameCtrlLayerClickLeft();
}
void GameCtrlLayer::clickRightButton()
{
m_delegate->gameCtrlLayerClickRight();
}
void GameCtrlLayer::clickUpButton()
{
if (m_AIOn) {
m_delegate->gameCtrlLayerClickAccelerate();
float speed = m_delegate->gameCtrlLayerGetAISpeed();
m_labelAISpeed->setString(StringUtils::format("%.1f个/秒", speed));
}
else {
m_delegate->gameCtrlLayerClickRotate();
}
}
void GameCtrlLayer::clickDownButton()
{
if (m_AIOn) {
m_delegate->gameCtrlLayerClickDecelerate();
float speed = m_delegate->gameCtrlLayerGetAISpeed();
m_labelAISpeed->setString(StringUtils::format("%.1f个/秒", speed));
}
else {
m_delegate->gameCtrlLayerClickThrowDown();
}
}
游戏区逻辑代码
//
// GameLayer.cpp
// AITetris
//
// Created by hansir on 16/1/10.
//
//
#include "GameLayer.h"
#include "SimpleAudioEngine.h"
bool GameLayer::init()
{
if (!Layer::init()) {
return false;
}
m_gameRun = false;
m_actionAI = NULL;
m_speedAI = 0.2f;
Size visibleSize = Director::getInstance()->getVisibleSize();
// 游戏区
float leftBrickMatrix = 120;
m_spriteBrick = new Sprite*[Row_Tetris*Column_Tetris];
for (int r = 0; r < Row_Tetris; r++) {
for (int c = 0; c < Column_Tetris; c++) {
m_spriteBrick[r*Column_Tetris+c] = Sprite::createWithTexture(Director::getInstance()->getTextureCache()->getTextureForKey("images/tetris_0.png"));
m_spriteBrick[r*Column_Tetris+c]->setPosition(leftBrickMatrix+c*16+8,
visibleSize.height/2+153-r*16+8);
this->addChild(m_spriteBrick[r*Column_Tetris+c]);
}
}
// Tetris逻辑
m_tetris = new Tetris(Row_Tetris, Column_Tetris);
return true;
}
void GameLayer::startGame()
{
m_gameRun = true;
// 清空方块矩阵
m_tetris->clearBrickMatrix();
// 设置新方块
BrickType brickType = (BrickType)(rand()%BrickType_Count);
m_tetris->setNewBrick(brickType, (BrickCellValue)(brickType+1));
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
this->startAI(false);
this->stopAllActions();
CallFunc *callFunc = CallFunc::create([=]{
if (m_gameRun) {
this->fallBrick();
}
else {
Size visibleSize = Director::getInstance()->getVisibleSize();
Label *labelGameOver = Label::createWithSystemFont("GameOver", "", 40);
labelGameOver->setColor(Color3B::RED);
labelGameOver->setPosition(visibleSize.width/2, visibleSize.height/2);
this->addChild(labelGameOver);
labelGameOver->runAction(Sequence::create(DelayTime::create(2), CallFuncN::create([=](Node *node){node->removeFromParent();this->stopAllActions();}), NULL));
}
});
this->runAction(RepeatForever::create(Sequence::create(DelayTime::create(1), callFunc, NULL)));
}
void GameLayer::startAI(bool AIOn)
{
if (!m_gameRun) {
return;
}
if (AIOn) {
// 求解
if (TetrisAI::seekSolution(m_tetris->getBrickMatrix(), m_tetris->getRow(), m_tetris->getColumn(), m_tetris->getCurrentBrick(), m_tetris->getCurrentBrickType(), m_tetris->getPosRowOfCurrentBrick(), m_tetris->getPosColOfCurrentBrick(), m_operationList)) {
this->commitOperationList(0);
}
}
else {
if (NULL != m_actionAI) {
this->stopAction(m_actionAI);
m_actionAI = NULL;
}
}
}
void GameLayer::accelerateAI()
{
m_speedAI -= 0.05f;
if (m_speedAI < 0.05f) {
m_speedAI = 0.05f;
}
}
void GameLayer::decelerateAI()
{
m_speedAI += 0.05f;
if (m_speedAI > 1) {
m_speedAI = 1;
}
}
// 方块操作
void GameLayer::moveLeftBrick()
{
if (m_tetris->moveLeftBrick()) {
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
}
}
void GameLayer::moveRightBrick()
{
if (m_tetris->moveRightBrick()) {
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
}
}
void GameLayer::rotateBrick()
{
if (m_tetris->rotateBrick()) {
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sounds/rotate.wav");
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
}
}
void GameLayer::fallBrick()
{
if (!m_tetris->fallBrick())
{
int lineIndex = 0;
while (m_tetris->clearOneLine(lineIndex)) {
printf("消行:%d\n", lineIndex);
}
// 下一个方块
BrickType brickType = (BrickType)(rand()%BrickType_Count);
if (!m_tetris->setNewBrick(brickType, (BrickCellValue)(brickType+1)))
{
m_gameRun = false;
printf("结束---\n");
}
}
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
}
void GameLayer::throwDownBrick()
{
m_tetris->throwDownBrick();
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sounds/throwdown.wav");
int lineIndex = 0;
while (m_tetris->clearOneLine(lineIndex)) {
printf("消行:%d\n", lineIndex);
}
// 下一个方块
BrickType brickType = (BrickType)(rand()%BrickType_Count);
if (!m_tetris->setNewBrick(brickType, (BrickCellValue)(brickType+1)))
{
m_gameRun = false;
printf("结束---\n");
}
// 刷新方块矩阵
this->updateTetrisBrickMatrix();
}
// 刷新方块矩阵
void GameLayer::updateTetrisBrickMatrix()
{
for (int r = 0; r < Row_Tetris; r++) {
for (int c = 0; c < Column_Tetris; c++) {
std::string filePath = StringUtils::format("images/tetris_%i.png", m_tetris->getBrickValue(r, c));
m_spriteBrick[r*Column_Tetris+c]->setTexture(Director::getInstance()->getTextureCache()->getTextureForKey(filePath));
}
}
// 在log中显示游戏
this->showTetrisInLog();
}
// 在log中显示游戏
void GameLayer::showTetrisInLog()
{
for (int r = 0; r < m_tetris->getColumn()+2; r++) {
printf("_");
}
printf("\n");
for (int r = 0; r < m_tetris->getRow(); r++) {
printf("|");
for (int c = 0; c < m_tetris->getColumn(); c++) {
printf("%s", m_tetris->getBrickValue(r, c)>0?"1":"");
}
printf("|\n");
}
for (int r = 0; r < m_tetris->getColumn()+2; r++) {
printf("T");
}
printf("\n");
}
// 执行AI系统返回的操作列表
void GameLayer::commitOperationList(int index)
{
if (OperationType_ThrowDown != m_operationList[index]) {
switch (m_operationList[index]) {
case OperationType_Rotate:
{
this->rotateBrick();
}
break;
case OperationType_Left:
{
this->moveLeftBrick();
}
break;
case OperationType_Right:
{
this->moveRightBrick();
}
break;
default:
break;
}
if (m_gameRun) {
m_actionAI = Sequence::create(DelayTime::create(m_speedAI), CallFunc::create([=]{this->commitOperationList(index+1);}), NULL);
this->runAction(m_actionAI);
}
}
else {
this->throwDownBrick();
if (m_gameRun) {
TetrisAI::seekSolution(m_tetris->getBrickMatrix(), m_tetris->getRow(), m_tetris->getColumn(), m_tetris->getCurrentBrick(), m_tetris->getCurrentBrickType(), m_tetris->getPosRowOfCurrentBrick(), m_tetris->getPosColOfCurrentBrick(), m_operationList);
m_actionAI = Sequence::create(DelayTime::create(m_speedAI), CallFunc::create([=]{this->commitOperationList(0);}), NULL);
this->runAction(m_actionAI);
}
}
}
游戏层逻辑代码
//
// Tetris.cpp
// AITetris
//
// Created by hansir on 16/1/10.
//
//
#include "Tetris.h"
// 方块模板初始化
unsigned char Tetris::m_BrickMode[7] = {0x66, 0xe4, 0xe2, 0xe8, 0x6c, 0xc6, 0xf0};
Tetris::Tetris(int row, int column)
{
// 行列数
if (row < MinRow) {
row = MinRow;
}
if (column < MinColumn) {
column = MinColumn;
}
m_row = row;
m_column = column;
// 根据行数和列数申请内存
long size = m_row*m_column;
m_brickMatrix = new BrickCellValue[size];
for (int i = 0; i < size; i++) {
m_brickMatrix[i] = BrickCellValue_NULL;
}
}
Tetris::~Tetris()
{
delete[] m_brickMatrix;
}
// 指定行号和列号的方块单元值
BrickCellValue Tetris::getBrickValue(int r, int c)
{
if ((r >= 0 && r < m_row) && (c >= 0 && c < m_column)) {
// 方块矩阵的该位置有方块则返回该值
if (BrickCellValue_NULL != m_brickMatrix[r*m_column+c]) {
return m_brickMatrix[r*m_column+c];
}
// 否则,如果(r,c)为当前方块上的值,则返回当前方块相应位置的值
else if ((r >= m_posRow && r < m_posRow+4) && (c >= m_posCol && c< m_posCol+4)) {
return m_currentBrick[r-m_posRow][c-m_posCol];
}
}
return BrickCellValue_NULL;
}
// 清空方块矩阵
void Tetris::clearBrickMatrix()
{
for (int i = 0; i < m_row*m_column; i++) {
m_brickMatrix[i] = BrickCellValue_NULL;
}
}
// 设置新方块
bool Tetris::setNewBrick(BrickType brickType, BrickCellValue brickCellValue)
{
m_currentBrickType = brickType;
return Tetris::setNewBrick(m_brickMatrix,
展开阅读全文