【计算机游戏开发】游戏中的人工智能

Alex_Shen
2021-08-10 / 0 评论 / 0 点赞 / 132 阅读 / 4,601 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

github项目地址

一、实验目的与要求

  1. 理解A*寻路算法原理。
  2. 进一步熟悉地图编辑器的使用。
  3. 实现游戏中的人工智能。

二、实验内容与方法

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.}  
0

评论区