我们先添加一个对象obj_map,在create事件里定义如下代码
map_h=1; map_w=3; map=ds_grid_create(map_w,map_h); map[# 0,0]=room_get_name(Room1); map[# 1,0]=room_get_name(Room2); open_map=false;
上面的代码,表示生成一个3列1行的网格,放了两个房间在里面,如图所示
房间0在0列0行,房间1在1列0行。
网格里现在有了两个房间元素,就不是0值了。我们可以利用这个特点,放入多个房间在不同的行列上,进行排兵布阵。
打开大地图时,游戏也是处于暂停的状态的。而,按暂停键,也会处于暂停状态。在做这两个动作时,其实这两个状态是一样的,这样游戏就不知道是要打开地图还是打开Menu。就会既打开了全屏地图,又打开了菜单项,而后面的进一步操作,又将变得更加不可预计。
嗯,这是计算机科学和编程中的一个常见问题,它称之为紊乱情况,或者竞态条件。
它的说明是这样的:当两个参与者试图访问相同的资源,试图修改它,从而影响彼此的计算结果。
举例,假如有两个人,叫Bob和Alice,他们共享一个银行账户。他们去ATM取钱,卡里还有50美元,两个在取之前,查看余额都有50美元的,于是他们决定取出40美元,这样账户里还有10美元。但实际情况上,银行分别给他们两个40美元,合计80美元。
我们要避免这种情况发生,就需要把打开全图和打开菜单这两个活动,设置为两个互斥的活动,推荐用互斥信号。
互斥信号专门用于控制资源访问,它可以是一个变量。例如,刚才的例子中,利用信号变量,当Bob和Alice要在同一时间进入相同账号时,ATM里的其中一台将会发现有别人正在进入这个账户,那么它强制性让别人在外面等着,直到当前用户操作完成。这样两个人就不能够同一时间进入这个账户,无奈,他们只能错开时间来取钱了。
在游戏中,我们也要控制用户,在同一时间,只能打开一个菜单,要么是全图查看,要么是其他菜单项。
在obj_map的step事件里,添加如下代码
map_key=keyboard_check_pressed(vk_tab) or gamepad_button_check_pressed(0,gp_select); show_debug_message(map_key); if map_key { audio_play_sound(snd_menu,1,false); if open_map { open_map=false; global.can_pause=true; global.game_state=states.playing; } else { if (not global.can_pause) exit; open_map=true; global.can_pause=false; global.game_state=states.paused; } }
上面的就是信号互斥的代码,用全局变量can_pause作为信号,来控制。当按地图打开键Tab或者手柄上的select键时,如果地图是关闭状态并且can_pause是真,那就打开地图,否则就不能开地图。
我们还要修改原来的obj_controller 的create事件,增加如下一行代码
global.can_pause = true;//默认为真,表示可以按暂停键,进行暂停
修改step事件里,关于菜单项的部分,修改如下
global.can_pause=true;//新增加的 //cursor move if move!=0 { if cur_moved { move=0; } cur_moved=true; } else { cur_moved=false; } //菜单项 if esc_pressed { audio_play_sound(snd_menu,1,false); if(global.game_state==states.playing and global.can_pause)//新增加的 { global.game_state=states.paused; menu_open=true; global.can_pause=false;//新增加的 } else if(global.game_state==states.paused and menu_open) { global.game_state=states.playing; menu_open=false; global.can_pause=true;//新增加的 } } if(menu_open) { menu_index+=move; if(move!=0) { audio_play_sound(snd_menu,1,false); } if(menu_index<0)//一直往上移动, { menu_index=opt_number-1; } else if(menu_index>opt_number-1)//一直往下移动 { menu_index=0; } if(enter_pressed) { switch(menu_index) { case 0: global.game_state=states.playing; instance_activate_all(); menu_open=false; global.can_pause=true;//新增加的 break; case 1: game_restart(); break; case 2: game_end(); break; } } }
最后,在obj_map里增加Draw GUI事件,代码如下
var cam_w=room_width; var cam_h=room_height; pos_x=ds_grid_value_x(map,0,0,map_w-1,map_h-1,room_get_name(room)); pos_y=ds_grid_value_y(map,0,0,map_w-1,map_h-1,room_get_name(room)); if open_map { draw_set_alpha(0.5); draw_set_color(c_black); draw_rectangle(0,0,cam_w,cam_h,0); draw_set_alpha(1); var cur_x=cam_w/3; var cur_y=cam_h/3; var box_h=50; var box_w=100; var box_offset=30; for(var i=0;i<map_h;i++) { for(var j=0;j<map_w;j++) { if (map[# j,i]!=0) { draw_set_color(c_white);//不是当前房间用白色标示 if (map[# j,i]==room_get_name(room)) { draw_set_color(c_yellow);//当前房间用黄色标示 } draw_rectangle(cur_x,cur_y,cur_x+box_w,cur_y+box_h,0); } cur_x+=box_offset+box_w; } cur_x=cam_w/3; cur_y+=box_offset+box_h; } }
这样,才会显示地图。按F5,运行一下游戏,效果如下
不要忘了,把obj_map对象拖入到房间里。
现在还差一个实时显示的小地图了。
暂无关于此日志的评论。