原文地址:
让我们给角色加上在可移动范围之内可以上下左右任意移动的功能吧。
当我们斜向移动的时候,如果不把速度减为1/根号2,那么移动速度就不是1倍的速度了
斜着移动时,水平速度和竖直速度都需要进行变动。
—————————————————————————————————————————————————————————————————————————————
//--char.cpp的改动--
#include "../include/GV.h"
void calc_ch()
{
ch.cnt++;
ch.img=(ch.cnt%24)/6;
}
void ch_move() //角色的移动操作
{
int i,sayu_flag=0,joge_flag=0;
double x,y,mx,my,naname=1;
double move_x[4]= {-4.0,4.0,0,0},move_y[4]= {0,0,4.0,-4.0}; //{左,右,下,上}的速度
int inputpad[4];
inputpad[0]=CheckStatePad(configpad.left);
inputpad[1]=CheckStatePad(configpad.right);
inputpad[2]=CheckStatePad(configpad.down);
inputpad[3]=CheckStatePad(configpad.up);
if(CheckStatePad(configpad.left)>0) //按下左键的话
ch.img+=4*2; //使用往左移的角色图像
else if(CheckStatePad(configpad.right)>0) //右键按下的话
ch.img+=4*1; //使用往右移的角色图像
for(i=0; i<2; i++) //水平方向
if(inputpad[i]>0) //左右键有一个按下的话
sayu_flag=1; //设置左右键按下标志
for(i=2; i<4; i++) //竖直方向
if(inputpad[i]>0) //上下键有一个按下的话
joge_flag=1; //设置竖直方向按下标志
if(sayu_flag==1 && joge_flag==1)//水平和竖直都有键按下的话,说明是斜向移动
naname=sqrt(2.0); //移动速度变为1/根号2
for(int i=0; i<4; i++) //分四个方向循环
{
if(inputpad[i]>0) //i方向的键盘或者手柄有输入的话
{
x=ch.x , y=ch.y; //把当前的坐标先保存下来
mx=move_x[i];
my=move_y[i]; //移动量保存到mx和my
if(CheckStatePad(configpad.slow)>0) //如果是低速移动
{
mx=move_x[i]/3;
my=move_y[i]/3; //移动速度变为1/3
}
x+=mx/naname , y+=my/naname; //当前坐标和移动量相加
if(!(x<10 || x>FIELD_MAX_X-10 || y<5 || y>FIELD_MAX_Y-5)) //计算结果在移动范围内的话
{
ch.x=x , ch.y=y; //进行实际的移动
}
}
}
}
————————————————————————————————————————————————————————————————————————————
因为要使用 sqrt 函数,我们把 math.h 包含进来。
然后 ch_move 在 function.h 里添加一下。
————————————————————————————————————————————————————————————————————————————
--GV.h 里添加如下内容--
#include "math.h"
--function.h 添加如下内容--
GLOBAL void ch_move();
————————————————————————————————————————————————————————————————————————————
main 函数里,加入下面这行。
————————————————————————————————————————————————————————————————————————————
//--main.cpp改动--
#define GLOBAL_INSTANCE
#include "../include/GV.h"
//主循环里必须做的三大处理
int ProcessLoop()
{
if(ProcessMessage()!=0)
return -1 ; //Process处理出错的话,返回-1
if(ClearDrawScreen()!=0)
return -1; //画面清理出错的话,返回-1
GetHitKeyStateAll_2(); //当前键盘输入处理
GetHitPadStateAll(); //当前手柄输入处理
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
ChangeWindowMode(TRUE); //窗口模式
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1; //初始化和设置双缓冲模式
while(ProcessLoop()==0) //主循环
{
switch(func_state)
{
case 0:
load(); //载入数据
first_ini(); //第一次初始化
func_state=100;
break;
case 100:
calc_ch(); //计算角色的使用图片
<span style="white-space:pre"></span> ch_move(); //角色的移动操作
graph_main(); //主绘画函数
break;
default:
printfDx("未知的func_state\n");
break;
}
if(CheckStateKey(KEY_INPUT_ESCAPE)==1)
break; //按下ESC的话,break
ScreenFlip(); //交换双缓冲画面
}
DxLib_End(); //DxLib中止
return 0;
}
————————————————————————————————————————————————————————————————————————————
运行结果
接上游戏手柄,按上下左右,然后键盘上方向键上下左右也按下,
角色能像上图中这样移动的话就成功了
注:做一点简单解释吧。我刚写完也没看懂。
char.cpp 里面,ch.img+=4*2; 是设置 往左或者往右移时,角色的倾斜效果的图像的。
由于GV.h 里 定义的 int img_ch[2][12],而 load.cpp里把读入的12张图片放到 img_ch[0],也就是img_ch[0][0] 到 img_ch[0][3] 这四张是普通状态的循环图
4567,这四张是右移的图,89 10 11 是左移的图。
原本 ch.img=(ch.cnt%24)/6 就是 cnt 在每变化到24 的周期里面,分别设置为 0 1 2 3
所以上面的 +4 就 是设置为右移的一套图,+8就是左移的一套图。
因为这个值,是先算出 0 1 2 3, 如果按下左右键,则设置左右移动图。 放开左右键,自动还是 0 1 2 3 的原始图。
然后关于移动 move_x 和 move_y 是移动分量,里面有负数的。所以代码里只管加就对了。
下面的移动里,循环是分4个方向分别进行的。虽然代码里,x,y 都写了,但每次实际上是一个方向的移动处理,x,y有一个肯定移动量为0
所以刚开始,我看最后如果移动出范围,则坐标不变。以为如果斜着移动出去,会不能动。这其实是多余的担心。
斜着移动到边缘的时候,只有其中出去的那个分量走到最后保持坐标不变的逻辑。
本人CSDN博客目录: