Funcode学习笔记:完成Run、Jump、Idle等动作【后续更新Roll、Attack动作的实现】【By Myself】

您所在的位置:网站首页 游戏人物跳跃动作怎么做视频 Funcode学习笔记:完成Run、Jump、Idle等动作【后续更新Roll、Attack动作的实现】【By Myself】

Funcode学习笔记:完成Run、Jump、Idle等动作【后续更新Roll、Attack动作的实现】【By Myself】

2024-07-13 22:14:53| 来源: 网络整理| 查看: 265

先来实现Run和Idle动作吧;

【以下是本菜在写游戏时犯下的一些错误,以及一些灵感,即如何解决逻辑错误的;】

首先,先大概说一下我们的愿景是什么,当我们按下A键时,人物向左边运动,且播放向左边运动的动画,我们按下右键时人物向右边运动,且播放一个向右运动的动画,当我们不按键时,人物不会有运动,且播放Idle动画;

这个思路很好实现;

我们先定义以下变量和方法;

class King { bool PressA;//PressA=1时说明A键按下 bool PressD;//PressD=1时说明D键按下 public: CAnimationSprite *KingRed; void KeyChangeSpeedLeft() { KingRed->//设置精灵向左速度 } } void KeyChangeSpeedRight(){ KingRed->//设置精灵向右的速度 } void SpritePlayAnimation(bool AnimatiomRection){//根据PressA和PressD来播放动画 if(AnimationRection) //播放向左的动画 else //播放向右的动画 } }

思路是这样的:

当按下就AD键时,funcode自动调用OnKeyDown函数,然后我们在OnKeyDown函数里按照按下键,调用以上3个函数,以实现左右移动和动画的播放;

但是,这里会有一个bug,即一般游戏中,能很明显地感觉到AD键对速度不是相互覆盖的关系,而是相互博弈的关系【什么意思呢?很简单,上面的函数我们可以知道,按下A键后,就直接给人物一个向左的速度,而不会去管是否按下D键,这就是相互覆盖的关系,但是正常游戏为了增加玩家的手感,都会采用AD键博弈的关系,即按下A键后,不是直接让人物直接向左移动,而是给人物一个向左的速度,如果此时D键是按下的,也给了人物一个向右的速度,那么两个速度会相结合,使人物速度为0】;

f702d48257a641909a08b0effdf4cd6f.png

 8bc8b1727b3e466e93334090c414c0ca.png

明白了真正的需求,那么我们就得想办法怎么去实现;

本菜查了funcode的API发现没有给某个方向直接加上一个速度的函数,而只有直接设置某个方向的速度;

这里有一个方法,即我们定义一个变量LevelSt,这个变量的作用是AD键博弈关系和人物速度之间的一个桥梁;

LevelSt有3种状态,Level=1时,说明人物要向右移动;

LevelSt=0时,说明人物水平无速度;

LevelSt=-1,说明人物要向左移动;

当我们按下A键时LevelSt--,当A键弹起时LevelSt++;

当我们按下D键时LevelSt++,当D键弹起时LevelSt--;

然后我们再定义一个函数LevelStChangeLevelSpeed()

如字面意思,这个函数是通过LevelSt改变水平Speed状态的;

我们对上面的King类进行优化:

class King { bool PressA; bool PressD; int LevelSt; public: CAnimationSprite *KingRed; King() :LevelSt(0), PressA(0), PressD(0) { KingRed = new CAnimationSprite("KingRed"); }//构造函数 ~King(){ delete KingRed; } void KeyAChangeLevelSt(int Measure){ LevelSt+=Measure; } void KeyDChangeLevelSt(int Measure){ LevelSt+=Measure; } void LevelStChangeLevelSpeed(){ if(LevelSt==1) //设置向右的速度 else if(LevelSt==0) //设置向左的速度 else //设置零速度 } void SpritePlayAnimation(){//根据LevelSt if(LevelSt==1) //播放向左的动画 else if(LevelSt==-1) //播放向右的动画 else //播放Idle动画,毕竟速度为0嘛 } }

这个时候我们将各各函数放到CGameMain类中的各各函数中即可;

因为要受键影响,所以KeyDChangeLevelSt和KeyAChangeLevelSt函数应该放到OnKeyDown函数和OnKeyUp函数中,而函数播放是每时每刻在进行的,所以应该放到GameRun函数中;

然后按照以上框架写上写代码;

...bug出现了,因为我们每时每刻都在调用SpritePlayAnimation函数,所以一直在调用播放动画的函数,因为没次调用播放动画的函数,所以都是从第一帧开始播放的,所以我们是看不到一连串图像构成的动画的,而是只能看到第一帧图;

那么我们该怎么修该这个bug呢??

有一个思路是这样的,当我们播放完动画后再重新播放就行了;

那么我们该怎么判断动画是否播放完了呢?

funcode还算是有点用哈,它提供了一个获取当前播放动画的名字的函数;

这里啰嗦几句,说一下什么是动画的名字;

动画的名字是程序与制作好的动画的接口,当我们要在程序中调用对应的动画时,对应的接口就是动画的名字,动画的名字可以在funcode界面制作动画时自定义;

funcode提供了一个函数:AnimateSpritePlayAnimation(char* AnimationName,bool IsRestore);

第一个参数就是动画的名字,第二个是一个选择播放完此动画是否回到原先的动画;

好,回归正题;

我们可以用funcode提供的函数:char *GetAnimateSpriteAnimationName();来获取当前动画的名字;

本菜的逻辑是这样的:

先获取当前动画的名字,如果当前的动画名字不等于我们需要播放的动画的名字,那么我们就播放我们需要播放的动画,反之我们不播放;

比如,我们当前要播放向右移动的动画,然后我程序发现正在播放向右移动的动画,那么我们为了不重新播放导致卡帧,我们就不播放。

注意,实现这套逻辑要将IsRestore参数调为1,即我们播放完该动画后要回到之前的动画;

那么下面是我们优化后的类:

class King { bool PressA; bool PressD; int LevelSt; public: CAnimationSprite *KingRed; King() :LevelSt(0), PressA(0), PressD(0) { KingRed = new CAnimationSprite("KingRed"); }//构造函数 void KeyAChangeLevelSt(int Measure) { LevelSt += Measure; } void KeyDChangeLevelSt(int Measure) { LevelSt += Measure; } void LevelStChangeLevelSpeed() { if (LevelSt == 1) //设置向右的速度 else if (LevelSt == 0) //设置向左的速度 else //设置零速度 } void SpritePlayAnimation() {//根据LevelSt static std::string AnimationName; AnimationName = KingRed->GetAnimateSpriteAnimationName(); if (LevelSt == 1 && AnimationName != KingRunLeft) //播放向左的动画 else if (LevelSt == -1 && AnimationName != KingRunRight) //播放向右的动画 else if (AnimationName != KingIdle)//播放Idle动画,毕竟速度为0嘛 } }

那么下面来实现Jump动作了;

这个的话,比较好弄。

因为现在动作多了起来,我们为了后期继续写下去,我们定义一些变量来记录当前的状态,因为有一些动作是要建立在一些状态之上才能调用的;

比如跳跃要在处于地面上的基础之上,Run动作要在处于地面的基础之上【除非你的角色是斗宗强者】

所以我们要新加以下变量:

int VertSt;//垂直速度>0时VertSt=1,垂直速度0,那么我们就播放Jump动画,如果垂直速度=0.05时,我们认为人物在地面上,即将IsGround=1;

如果垂直速度不等于0,那么IsGround=0;

然后我们要来实现跳跃动作;

首先要在funcode界面给人物一个重力:

c56dfe3ac38c4f0a93cd21a2d1941484.png

这个其实很好弄,当在IsGround=1且按下K键时,我们给人物一个向上的速度;

因为有重力,所以速度会递减,如何我们在GameRun中不断用funcode提供的获取垂直速度的函数来判断VertSt的数值,如何不断用VertSt判断该播放那个动画:

d592d031bbee4d6081360afa736c1153.png

 b3025f31c9df461aa80142a72c8126b6.png

 如果VertSt>0播放Jump,如果=0.05){ IsGround=1; OnGroundTime=0; } } void VertSpeedChangeVertSt(){ static SpeedY; SpeedY=KingRed->GetSpriteLinearVelocityY(); if(SpeedY0) VertSt=-1; else VertSt=0; } void SpritePlayAnimation(){//根据LevelSt static std::string AnimationName; AnimationName=KingRed->GetAnimateSpriteAnimationName(); if(IsGround==0){//说明在地面上 if(LevelSt==1&&AnimationName!=KingRunLeft) //播放向左的动画 else if(LevelSt==-1&&AnimationName!=KingRunRight) //播放向右的动画 else if(AnimationName!=KingIdle)//播放Idle动画,毕竟速度为0嘛 }else{ if(VertSt==1&&AnimationName!="KingJump") //播放向上跳跃的动画 else if(Vert==-1&&AnimationName!="KingFall")//播放Fall动画 } } }

大概的思路就是如此;

以后会更新Attack和Roll动作;

为了可以拓展出更多的动画,我们必须写一些具有普适性的函数,和一些有普适性的变量,以及播放动画遍历的函数尽量路径统一,否则会多出很多bug,写出一坨屎山;

这里本菜总结出一个大概的框架,即人物状态因该为如何:

等待输入->播放动画->状态判断和状态校正->等待输入;



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭