问题概述
红警、帝国时代、星际争霸……想必很多玩家都对这类即时战略游戏保有极深的感情。其中有一个较为常见的逻辑便是——左键划动选中人物,然后右键标记目标地点,使得人物向目标地点移动。这个逻辑最常见的问题在于——可能会有不同的部队被选中,使得他们在同一时间向不同的地区进发。为了解决这个难点,博主想了一套相对简单的逻辑来实现。
解决方案
基本思路非常简单。首先我们先定义一个叫旗帜的物体,旗帜的本质意义就是玩家点击右键后留下的目标点,其他的按照逻辑编写代码即可。基本流程如下:
- 创建旗帜物体obj_mubiao.(建议给这个物体挂一个sprite,方便debug)
- 编写选中角色的逻辑代码。
- 编写在空白区域点击左键以取消选中的逻辑代码。
- 编写在空白区域点击右键以放置旗帜的逻辑代码。
- 编写旗帜的逻辑代码。
代码实现
按照上述思路,我们开始对各个物体分别编写代码。
obj_zhujue
一、创建
对于主角,先创建一个属于自己的旗帜。
具体方法是创建一个旗帜并把这个旗帜的id赋给一个变量mubiao中,然后再把自己(id)赋成旗帜(mubiao)的“主人”,这样把人物和自己旗子的关系确定下来
mubiao=instance_create(0,0,obj_mubiao); //创造一个以自己为对象的旗子
mubiao.zhuren=id; //将旗子的对象设置为自己
二、鼠标左键放开
里面就一句话,shubiao=1表示选中了主角(当时不习惯使用布尔值,表打我~)
shubiao=1; //表示鼠标选中了这号角色
三、全局左键按下
里面也只有一句话,表示空白区域点一下左键就取消所有选中
if (shubiao==1) shubiao=0; //判定:如果此时处于选中状态,则取消选中
四、全局右键按下
首先判断是否有人物被选中,如果有便进入创作
if (shubiao==1 ) //判定右键时是否是该物体被选中
{
move=1; //开启移动模式
zhan=0;
move_x=mouse_x; //移动目标:鼠标x值
move_y=mouse_y; //移动目标:鼠标y值
dertax=move_x-x; //横坐标远近
dertay=move_y-y; //纵坐标远近
if (dertax!=0) k=dertay/dertax; //斜率
if (dertax==0) k=dertay/(dertax+0.001); //补救当x=0时导致的运算错误
if (k<-1 || k>1 && dertay>0) fangxiang=1;
if (k>=-1 && k<=1 && dertax>=0) fangxiang=2;
if (k<-1 || k>1 && dertay<0) fangxiang=3;
if (k>=-1 && k<=1 && dertax<0) fangxiang=4;
}
五、步事件
这个是人物移动指令,不难理解
/* 向下移动 */
if (move==1 && fangxiang==1 && (image_index>=2)) image_index=0;
if (move==1 && fangxiang==1)
{
if (distance_to_point(move_x,move_y)>0.5)mp_potential_step_object(move_x,move_y,move_speed,obj_no);
if (distance_to_point(move_x,move_y)<=0.5)
{
speed=0;
move=0;
zhan=1;
}
}
/* 向右移动 */
if (move==1 && fangxiang==2 && (image_index<=10 or image_index>=13)) image_index=11
if (move==1 && fangxiang==2)
{
if (distance_to_point(move_x,move_y)>0.5) mp_potential_step_object(move_x,move_y,move_speed,obj_no);
if (distance_to_point(move_x,move_y)<=0.5)
{
speed=0;
move=0;
zhan=1;
}
}
/* 向上移动 */
if (move==1 && fangxiang==3 && (image_index<=1 or image_index>=4)) image_index=2
if (move==1 && fangxiang==3)
{
if (distance_to_point(move_x,move_y)>0.5) mp_potential_step_object(move_x,move_y,move_speed,obj_no);
if (distance_to_point(move_x,move_y)<=0.5)
{
speed=0;
move=0;
zhan=1;
}
}
/* 向左移动 */
if (move==1 && fangxiang==4 && (image_index<=3 or image_index>=6)) image_index=4
if (move==1 && fangxiang==4)
{
if (distance_to_point(move_x,move_y)>0.5) mp_potential_step_object(move_x,move_y,move_speed,obj_no);
if (distance_to_point(move_x,move_y)<=0.5)
{
speed=0;
move=0;
zhan=1;
}
}
obj_mubiao
步事件
表示如果对应主角处于被选中状态,那么就显示旗帜,否则会隐藏
一旦主角到达指定位置,旗帜消失
if (zhuren.shubiao=1) image_alpha=100;
if (zhuren.shubiao=0) image_alpha=0;
if collision_point(x,y,zhuren,0,0)
{
x=0;
y=0;
}
全局右键
这里面是设定终点位置
if (zhuren.shubiao==1)
{
x=zhuren.move_x;
y=zhuren.move_y;
}
if (collision_circle(x,y,1,obj_difang,1,0) && zhuren.duixiang=collision_circle(x,y,1,obj_difang,1,0))
{
zhuren.move=0;
zhuren.da=1;
}
else
{
zhuren.chetui=1;
}
if collision_point(x,y,1,obj_no,1)
{
x=0;
y=0;
}