【计算机游戏开发】二维游戏动画合成

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

github项目地址

一、实验目的与要求

  1. 了解二维游戏动画合成原理。
  2. 熟悉Cocos2d-x中的用户交互、触摸事件、碰撞检测机制。
  3. 熟悉CocoStudio动画编辑器的使用,了解骨骼动画。

二、实验内容与方法

  1. 完成游戏编译(50分)
    成功编译并运行教材P128“游戏动画实例-侠客行”。

  2. 修改英雄外型 (10分)
    利用CocoStudio修改英雄外型(骨骼),并将修改结果在游戏中读取,使英雄人物展示与教材源码中不同的形象。

  3. 增加英雄Defend动作 (10分)
    利用CocoStudio设计英雄Defend动作,并将此功能在游戏中加载。

  4. 增加计分板功能和回合制 (10分)
    记录成功/失败次数,增加计分板功能;将游戏改为回合制游戏。

  5. 修改和优化游戏(15分)
    修改游戏bug,优化游戏功能。

  6. 游戏升级(5分)
    自行发挥想象力,增加游戏功能。

三、实验步骤与过程

1.完成游戏编译

将源代码素材导入cocos2dx项目,并编译通过。
在这里插入图片描述 在这里插入图片描述
在这里插入图片描述

2.修改英雄外型

打开Cocos Studio,加入帽子、盾牌素材并连接到原素材的骨骼之上,完成新外形设计。

在这里插入图片描述 在这里插入图片描述
导出素材,并将Export文件夹加入相应素材位置。
在这里插入图片描述

3.增加英雄Defend动作

在Cocos Studio之中加入Defend动作设计,并导入(方法同上)
在这里插入图片描述
游戏代码实现部分:
① Config_set.h
该部分代码中枚举了各种动作状态
添加DEFEND状态

1.enum State  
2.{  
3.    STAND,  
4.    MOVELEFT,  
5.    MOVERIGHT,  
6.    ATTACK,  
7.    DEATH,  
8.    SMITTEN,  
9.    DEFEND  
10.};  

② AnimationScene.cpp
添加防守按键按钮,并将其添加到画面之中

1.auto defendItem = MenuItemImage::create(  
2.    "Chapter06/AnimationScene/animation/control/j-btn.png",  
3.    "Chapter06/AnimationScene/animation/control/j-btn.png",  
4.    CC_CALLBACK_1(AnimationScene::defendCallback, this));    
5.defendItem->setPosition(Vec2(visibleSize.width - 200, 200));  
6.auto menu2 = Menu::create(defendItem, NULL);  
7.menu2->setPosition(Vec2::ZERO);  
8.this->addChild(menu2, 6);  

绑定点击事件,当被点击时,将英雄状态更改为DEFEND,等待更新。

1.void AnimationScene::defendCallback(Ref* pSender)  
2.    m_player->play(DEFEND); 

③ Hero.cpp / Hero.h
首先添加防守状态判断,true时说明正处于防守状态,false时处于非防守状态。

1.private:  
2.    bool m_defence;   // 被防守状态 

根据英雄状态,更新动画
当状态更新为DEFEND时,且英雄未死亡时,触发Defend动画。

1.case DEFEND:  
2.    if (m_isdead == false)  
3.    {  
4.        m_armature->getAnimation()->play("defend");  
5.        m_defence = true;  
6.    }  
7.    break;  
8.}  

添加Defend状态效果(当英雄在Defend状态下被攻击时,受伤血量降低至5点附近)

1.void Hero::hurt()  
2.{  
3.    // 根据基础伤害造成随机伤害  
4.    if (m_defence)  
5.        showBloodTips(5);  
6.    else  
7.        showBloodTips(30);  
8.    this->play(SMITTEN);  
9.}  

展示效果:
在这里插入图片描述

4.增加计分板功能和回合制

设置全局变量,记录游戏成功轮数

1.int gamecnt = 0;  
添加防守按键按钮,并将其添加到画面之中
1.auto replayItem = MenuItemImage::create(  
2.    "replay.png",  
3.    "replay.png",  
4.    CC_CALLBACK_1(AnimationScene::menuReplayCallback, this));  
5.  
6.replayItem->setPosition(Vec2(visibleSize.width - 50, 50));  
7.menu2 = Menu::create(replayItem, NULL);  
8.menu2->setPosition(Vec2::ZERO);  
9.this->addChild(menu2, 7);  

在这里插入图片描述
绑定点击事件,如果重开一局时敌人已经死亡,则说明游戏胜利,胜利局数加一,并开始新的一局。

1.void AnimationScene::menuReplayCallback(Ref* pSender)  
2.{  
3.#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)  
4.    MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.", "Alert");  
5.    return;  
6.#endif  
7.    if (m_enemy->isDeath()) {  
8.        gamecnt++;  
9.        scoreboard->setString("Successful Round: " + std::to_string(gamecnt));  
10.    }  
11.    Director::getInstance()->replaceScene(AnimationScene::createScene());  
12.    Director::getInstance()->resume();  
13.  
14.#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
15.    exit(0);  
16.#endif  
17.}  

在这里插入图片描述

5.修改和优化游戏

  1. 优化一:英雄被攻击后不再接受玩家操作指令,卡在原地
    原因:源代码中设置了当英雄受伤后,不可执行向左向右操作。
    修改方案:删除对于受伤的判定
1.case MOVELEFT:  
2.    if ((this->getPositionX() > 0) && (m_isdead == false)&& (m_isAttack == false))  
3.    {  
4.        xxxxx  
5.    }  
6.    break;  
7.case MOVERIGHT:  
8.    if ((m_isAttack == false) && (this->getPositionX() < Director::getInstance()->getVisibleSize().width) && (m_isdead == false))  
9.    {  
10.        xxxxx  
11.    }  
12.    break;  
  1. 优化二:点击攻击按钮,英雄和敌人同时响应攻击操作
    原因:源代码中,当攻击按钮被点击时,英雄/敌人会同时相应攻击动作。
    修改方案:删除敌人对于攻击按钮的相应。
1.void AnimationScene::attackCallback(Ref* pSender)  
2.{  
3.    // m_player->play(ATTACK);  
4.    m_enemy->play(ATTACK);  
5.}  
  1. 优化三:SMITTEN动作没有执行
    原因:在受伤时未响应smitten动作
    修改方案:在受伤时,触发smitten动作
1.void Hero::play(State state)  
2.{  
3.    if (state == SMITTEN) // 控制被击中时颤抖动画只播放一次  
4.    {  
5.        m_armature->getAnimation()->play("smitten");  
6.        m_ishurt = true;  
7.    }  
8.    m_state = state;  
9.}  
  1. 优化四:ATTACK动作动画可以被打断
    原因:在attack动作触发时,未判断前一个attack动作是否已经完成。
    修改方案:当m_isAttack = true,说明英雄正在进行攻击动作,则不再触发下一次攻击动画。
1.void AnimationScene::attackCallback(Ref* pSender)  
2.{  
3.    if (m_player->isAttack() == false)  
4.        m_player->play(ATTACK);  
5.    // m_enemy->play(ATTACK);  
6.}  
  1. 优化五:敌人大概率向左走,最后会撞左边的墙
    原因:AI设计问题,向左1s,向右0.7s,因此会导致左右不平衡
    修改方案:更改AI动作序列
1.auto sss = Sequence::create(  
2.    DelayTime::create(0.8f),  
3.    CallFunc::create(CC_CALLBACK_0(AIManager::moveLeft, this)),  
4.    DelayTime::create(1.0f),  
5.    CallFunc::create(CC_CALLBACK_0(AIManager::attack, this)),  
6.    DelayTime::create(0.3f),  
7.    CallFunc::create(CC_CALLBACK_0(AIManager::moveRight, this)),  
8.    DelayTime::create(1.0f),  
9.    CallFunc::create(CC_CALLBACK_0(AIManager::stand, this)),  
10.    DelayTime::create(0.5f),  
11.    CallFunc::create(CC_CALLBACK_0(AIManager::attack, this)),  
12.    NULL  
13.    );  
14.auto act = RepeatForever::create(sss);  
15.this->runAction(act); 
  1. 优化六:动作结束判断错误
    原因:动画结尾帧,未加入帧事件,所以不会有响应。
    修改方案:利用Cocos Studio,给attack,smitten加入帧事件
    在这里插入图片描述
    并且在攻击结束后,将攻击状态修改未false,防止判定错误
1.void Hero::onFrameEvent(cocostudio::Bone *bone, const std::string& evt, int originFrameIndex, int currentFrameIndex)  
2.{  
3.    if (strcmp(evt.c_str(), "attack_end") == 0)  
4.    {  
5.        m_armature->getAnimation()->play("loading");  
6.        m_isAttack = false;  
7.    }  
8.    if (strcmp(evt.c_str(), "smitten_end") == 0)  
9.    {  
10.        m_armature->getAnimation()->play("loading");  
11.    }  
12.}  
0

评论区