一、实验目的与要求
- 理解A*寻路算法原理。
- 进一步熟悉地图编辑器的使用。
- 实现游戏中的人工智能。
二、实验内容与方法
1.完成游戏编译(60分)
成功编译并运行教材P200“游戏AI实例-迷宫寻宝”。
2.完成修改内容一 (5分)
修改游戏代码,实现修改内容一,即修改窗口大小。
3.完成修改内容二 (10分)
修改游戏代码,实现修改内容二,即增加DANGEROUS区域。
4.完成修改内容三 (10分)
修改游戏代码,实现修改内容三,即增加按键监听。
5.完成修改内容四 (10分)
修改游戏代码,实现修改内容四,即增加地图层次。
6.完成Bug修改 & 优化 (5分)
通过更改游戏代码的方式修复BUG,如:点击笑脸出现“No Way” 和“Found Treasure”的叠加。
三、实验步骤与过程
1.完成游戏编译
将源代码素材导入cocos2dx项目,并编译通过。
2.完成修改内容一 (5分)
修改AppDelegate.cpp中界面框大小
1.static cocos2d::Size designResolutionSize = cocos2d::Size(1024, 768);
3.完成修改内容二 (10分)
增加成员变量,指明危险区域
1.#define DANGEROUS 7
2.bool isDangerous = false;
在可行路径之中,随机产生危险点(概率为2%),并替换图中的地图图片
1.int randnum = rand() % (MAP_WIDTH * MAP_HEIGHT) + 1;
2.if (randnum < MAP_WIDTH * MAP_HEIGHT / 50) {
3. m_mapLayer->setTileGID(341, Vec2(i, j));
4. m_map[i][j].isDangerous = true;
5.}
更新A*算法,当搜索过程中碰到危险点则搜索结束,并在更新动画后显示失败展示
首先在生成路径节点链表时,添加危险判断属性
1.struct pathCoordinate { int x; int y; bool isDangerous; };
2.while (tempNode != nullptr)
3.{
4. path[loopNum].x = tempNode->xCoordinate;
5. path[loopNum].y = tempNode->yCoordinate;
6. path[loopNum].isDangerous = tempNode->isDangerous;
7. loopNum++;
8. tempNode = tempNode->parent;
9.}
在搜索过程中,如果发现经过危险节点,则提前
1.if (path[j].isDangerous) {
2. next = "dangerous";
3. break;
4.}
在路径动画展示完毕后,显示失败
1.//创建动作序列
2.auto actionSequence = Sequence::create(actionVector);
3.//笑脸精灵执行移动动作序列
4.smile->runAction(Sequence::create(actionSequence, CallFunc::create(CC_CALLBACK_0(MazeScene::Next, this, next)), NULL));
5.
6.
7.void MazeScene::Next(string s) {
8. if (s == "dangerous") {
9. //屏幕中央显示失败的提示
10. auto failedTip = Label::createWithBMFont("fonts/futura-48.fnt", "Dangerous!You're Dead!");
11. failedTip->setPosition(m_visibleSize.width / 2, m_visibleSize.height / 2);
12. this->addChild(failedTip, 2, TIP_TAG);
13. }
14. else if (s == "next_stage") {
15. STAGE++;
16. Director::getInstance()->replaceScene(MazeScene::createScene());
17. }
18. else if (s == "front_stage") {
19. STAGE--;
20. Director::getInstance()->replaceScene(MazeScene::createScene());
21. }
22.}
4.完成修改内容三 (10分)
添加键盘监听器
1.void MazeScene::addKeyPressedListener()
2.{
3. auto listener = EventListenerKeyboard::create();
4. listener->onKeyPressed = CC_CALLBACK_2(MazeScene::onKeyPressedBegan, this);
5. listener->onKeyReleased = CC_CALLBACK_2(MazeScene::onKeyPressedEnded, this);
6. Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
7.}
当按下R键时,重新载入游戏
1.bool MazeScene::onKeyPressedBegan(EventKeyboard::KeyCode keycode, Event* unused_event)
2.{
3. if (keycode == EventKeyboard::KeyCode::KEY_R) {
4. Director::getInstance()->replaceScene(MazeScene::createScene());
5. };
6. return true;
7.}
5.完成修改内容四 (10分)
生成一张新的地图,并且在两张图中红圈位置添加场景转换点
根据STAGE产生补充的地图画面
1.int STAGE = 1;
2.if (STAGE == 1) {
3. auto tileMap = TMXTiledMap::create("Chapter11/superMaze.tmx");
4. tileMap->setPosition(0, m_visibleSize.height - MAP_HEIGHT * UNIT);
5. this->addChild(tileMap, 1);
6. //获取地图中的主图层
7. m_mapLayer = tileMap->getLayer("mainLayer");
8.}
9.else if (STAGE == 2) {
10. auto tileMap = TMXTiledMap::create("Chapter11/superMaze2.tmx");
11. tileMap->setPosition(0, m_visibleSize.height - MAP_HEIGHT * UNIT);
12. this->addChild(tileMap, 1);
13. //获取地图中的主图层
14. m_mapLayer = tileMap->getLayer("mainLayer");
15.}
跳转条件是,在A*搜索过程中,如果碰到场景转换点,则进行场景的切换,
1.if (path[j].x == 3 && path[j].y == 0 && STAGE == 1) {
2. next = "next_stage";
3. break;
4.}
5.else if (path[j].x == 15 && path[j].y == 2 && STAGE == 2) {
6. next = "front_stage";
7. break;
8. }
9.
10.
11.//创建动作序列
12.auto actionSequence = Sequence::create(actionVector);
13.//笑脸精灵执行移动动作序列
14.smile->runAction(Sequence::create(actionSequence, CallFunc::create(CC_CALLBACK_0(MazeScene::Next, this, next)), NULL));
1.void MazeScene::Next(string s) {
2. if (s == "dangerous") {
3. //屏幕中央显示失败的提示
4. auto failedTip = Label::createWithBMFont("fonts/futura-48.fnt", "Dangerous!You're Dead!");
5. failedTip->setPosition(m_visibleSize.width / 2, m_visibleSize.height / 2);
6. this->addChild(failedTip, 2, TIP_TAG);
7. }
8. else if (s == "next_stage") {
9. STAGE++;
10. Director::getInstance()->replaceScene(MazeScene::createScene());
11. }
12. else if (s == "front_stage") {
13. STAGE--;
14. Director::getInstance()->replaceScene(MazeScene::createScene());
15. }
16.}
6.完成Bug修改 & 优化 (5分)
通过更改游戏代码的方式修复BUG,如:点击笑脸出现“No Way” 和“Found Treasure”的叠加。
在点击时,判断点击位置是否与当前笑脸所处位置相同,如果相同则禁止点击
1.//若该地图单元为墙体或超出地图范围或与笑脸重合,设置禁止图标
2.if (m_map[x][y].status == NOT_ACCESS || y >= MAP_HEIGHT || (m_destination && x == m_destination->xCoordinate && y == m_destination->yCoordinate))
3.{
4. auto forbid = this->getChildByTag(FORBID_TAG);
5. forbid->setPosition(0.5 * UNIT + x * UNIT, m_visibleSize.height - 0.5 * UNIT - y * UNIT);
6. forbid->setVisible(true);
7. return true;
8.}