diff --git a/src/game.opa b/src/game.opa index 8d31c36..20421ef 100644 --- a/src/game.opa +++ b/src/game.opa @@ -39,6 +39,8 @@ type Game.t = { int ready_flags, //用于表示玩家是否准备好(1 + 2 + 4 + 8) int ok_flags, //用户表示玩家是否关闭了结算界面 int last_act, //最后一次出手时间,用于判断超时 + int round, //第几局 + int dealer, //庄家 bool change_flag, //标志这个游戏自上次广播之后状态(游戏人数,准备状态等)是否变化 list(int) winners, //游戏胜利玩家 option(Card.t) curr_card, //当前牌面上打出的牌 @@ -112,7 +114,9 @@ public function get_flag_cnt(flags){ } module Game { - + AUTO_READY = {false}; + AUTO_RESTART = {false}; + init_board = { //初始化创建10个房间 ignore(for(0,function(i){ @@ -125,6 +129,8 @@ module Game { last_act: 0, ready_flags: 0, ok_flags: 0, + round: 0, + dealer: -1, change_flag: {false}, curr_card: {none}, players: LowLevelArray.create(4,{none}), @@ -313,6 +319,8 @@ module Game { {id: game.id, st: encode_status(game.status), ct: game.curr_turn, + rd: game.round, + dl: game.dealer, cc: game.curr_card, rf: game.ready_flags, pls: game.players, @@ -326,6 +334,8 @@ module Game { { id: game.id, status: game.status, curr_turn: game.curr_turn, + round: game.round, + dealer: game.dealer, curr_card: game.curr_card, ready_flags: game.ready_flags, players: game.players, @@ -388,7 +398,7 @@ module Game { case {none}: void default: { Render.refresh(); - Render.play_sound("button.wav"); + play_sound("button.wav"); Mahjong.request_action(game.id,game.idx,action); } } @@ -407,7 +417,7 @@ module Game { Render.refresh(); } case {GAME_START: game_msg}:{ - Render.play_sound("start.wav"); + play_sound("start.wav"); Render.update(game_msg); Render.update_deck(); Render.start_timer(); @@ -427,7 +437,7 @@ module Game { refresh_players(game_msg.pls); } case {DISCARD_CARD: msg}:{ //玩家弃牌消息 - Render.play_sound("da.wav"); + play_sound("da.wav"); Render.stop_timer() Render.recv_discard_msg(msg); Render.refresh(); @@ -463,7 +473,7 @@ module Game { Render.refresh(); player_idx = get_game().idx; List.iter(function(win_idx){ - if(player_idx == win_idx) Render.play_sound("win.wav") + if(player_idx == win_idx) play_sound("win.wav") Render.draw_win(Board.get_rel_pos(player_idx,win_idx)) },winners); } @@ -480,7 +490,7 @@ module Game { set_game({game with ~players}); refresh_players(players); - Render.play_sound("countfan.wav"); + play_sound("countfan.wav"); Render.refresh(); Render.show_result(game,some,195,75); } @@ -524,9 +534,9 @@ module Game { //加载资源 imgs = ["table_bg.png","board.png","result.png","arrow.png","win.png","menu_bar.png","ting.png","dialog.png", "tiles.png","tiles_small.png","numbers.png","start.png","offline.png","player_frame_h.png","player_frame_v.png", - "portrait.jpg","eswn.png"]; + "portrait.jpg","eswn.png","btn_tutor.png"]; auds = ["start.wav","da.wav","button.wav","tray.wav","countfan.wav","win.wav"]; - Render.preload(imgs,auds,function(){ + preload(imgs,auds,function(){ Dom.set_value(#loading_info,"prepare game..."); game_obs = Network.observe(game_msg_received,game.game_channel); chat_obs = Network.observe(user_update,game.chat_channel); @@ -539,6 +549,8 @@ module Game { game = update_player(game,player); set_game(game_obj(game,player)); refresh_players(game.players); + + if(AUTO_READY || player.is_bot) Mahjong.set_ready(game,player.idx); //离开页面的提示(对Opera无效) Dom.bind_beforeunload_confirmation(function(_){ @@ -616,7 +628,7 @@ module Game { function game_view(game,idx){ //更新第idx个玩家的client_ctx player = Option.get(LowLevelArray.get(game.players,idx)); - /** _ = Client.setTimeout(function(){ + _ = ClientEvent.set_on_disconnect_client(function(ctx){ //如果ctx和game的第idx个client一致,说明这个玩家处于死链接状态,去除之。 with_game(game.id,function(game){ match(LowLevelArray.get(game.clients,idx)){ @@ -628,14 +640,12 @@ module Game { } } }); - jlog("timeout"); - },20);*/ - + }); Resource.styled_page("Mahjong",["/resources/style.css"], <>
-
+

loading

@@ -729,6 +739,8 @@ module Game { change_flag: {true}, ready_flags: 0, ok_flags: 0, + round: 0, + dealer: 0 } Mahjong.reset_actions(game); diff --git a/src/mahjong.opa b/src/mahjong.opa index 1138b75..d0a1abb 100644 --- a/src/mahjong.opa +++ b/src/mahjong.opa @@ -116,7 +116,10 @@ module Mahjong { //准备 if(not(test_flag(game.ready_flags,game.idx)) && Button.is_pressed(pos,Render.btn_ready)){ {set_ready} - } else {none} + } else{ + if(Button.is_pressed(pos,Render.btn_tutor)) Tutor.show_tutor(); + {none} + } } case {select_action}: { //选择弃掉的牌 @@ -379,7 +382,7 @@ module Mahjong { /** * 设置用户准备好 */ - private function set_ready(game,idx){ + exposed function set_ready(game,idx){ game = {game with ready_flags: set_flag(game.ready_flags,idx), change_flag: {true}} if(game.ready_flags == ALL_IS_READY){ game = Game.start(game) |> update(_); diff --git a/src/main.opa b/src/main.opa index fa7a25d..e0697c4 100644 --- a/src/main.opa +++ b/src/main.opa @@ -27,23 +27,22 @@ function login_required( -> resource page){ } } -function is_logged_in(){ - match(Login.get_user()){ - case {unlogged}: {false} - case {user:_}: {true} - } - } - - function with_user((Login.user -> 'a) f, 'a otherwise){ - match(Login.get_user()){ + match(get_user()){ case ~{user}: f(user); case {unlogged}: otherwise; } } +function get_username(){ + match(get_user()){ + case ~{user}: user.name + case {unlogged}: "anonymous" + } +} + function game_view(game_id,need_bot){ - match(Login.get_user()){ + match(get_user()){ case {unlogged}: Login.login_view(); case {user:player}: { match(Game.get(game_id)){ @@ -79,6 +78,7 @@ function start(url){ case {path:["gamex",id|_] ...} : game_view(id,{true}); case {path:["how_to_play.html"] ...}: @static_resource("resources/how_to_play.html"); case {path:["hall"] ...} : login_required(function(){Page.game_list_view()}) + case {path:["tutor"] ...} : Tutor.page_view(); case {path: _ ...} : Main.fourOffour() } @@ -98,4 +98,4 @@ module Main { <>

404

); } - } +} diff --git a/src/network.opa b/src/network.opa index cc7ddd9..92e1df8 100644 --- a/src/network.opa +++ b/src/network.opa @@ -30,6 +30,8 @@ type Game.msg = { string id, //游戏id int st, //游戏状态 status int ct, //当前玩家 curr_turn + int rd, //第几局 round + int dl, //庄家 dealer int rf, //玩家准备好标志 ready_flags option(Card.t) cc, //当前牌面上的牌 curr_card llarray(option(Player.t)) pls, //玩家列表 players diff --git a/src/render.opa b/src/render.opa index 8845104..7c8a06c 100644 --- a/src/render.opa +++ b/src/render.opa @@ -34,6 +34,8 @@ type Game.obj = { Status.t status, //游戏状态 int curr_turn, //当前玩家 int ready_flags, //玩家的准备好标志 + int round, + int dealer, option(Card.t) curr_card, //当前牌面上的牌 llarray(option(Player.t)) players, //玩家列表 llarray(Deck.t) decks, //所有玩家牌面 @@ -51,20 +53,46 @@ type Game.obj = { set_game = %%engine2d.set_game%%; get_game = %%engine2d.get_game%%; +PREFIX = "/resources/" + +function get_ctx(id){ + canvas = Canvas.get(id); + Option.get(Canvas.get_context_2d(Option.get(canvas))); +} + +/** 获得图片资源 */ +function get(key){ + {image: %%engine2d.get%%(PREFIX ^ key)} +} + +/** 预加载图片和声音资源 */ +function preload(imgs,auds,f){ + imgs = List.map(function(img){ + PREFIX ^ img + },imgs); + auds = List.map(function(aud){ + PREFIX ^ aud + },auds); + %%engine2d.preload%%(imgs,auds,f); +} + +function play_sound(key){ + %%engine2d.play_sound%%(PREFIX ^ key); +} + /** * 游戏的绘制引擎 */ client module Render { - bool DEBUG = {true} - bool SHOW_TILE = {true} + bool DEBUG = {false} + bool SHOW_TILE = {false} //常用颜色的定义 BLACK = {color:Color.rgb(0,0,0)}; RED = {color: Color.rgb(255,0,0)}; BLUE = {color: Color.rgb(0,0,255)}; - PREFIX = "/resources/" - + //等待时间 WAIT_TIME = 10 @@ -74,6 +102,7 @@ client module Render { Button.t btn_cancel = Button.simple(670,475,60,60,"放弃"); //放弃 Button.t btn_ready = Button.simple(330,555,150,57,"准备"); //准备 Button.t btn_hide_result = Button.simple(333,423,75,45,"确定"); //关闭结算 + Button.t btn_tutor = Button.simple(600,555,100,100,"指导"); //关闭结算 /** 是否在麻将牌上显示数字 */ g_show_number = Mutable.make(bool {false}); @@ -89,31 +118,7 @@ client module Render { refresh(); } - function get_ctx(id){ - canvas = Canvas.get(id); - Option.get(Canvas.get_context_2d(Option.get(canvas))); - } - /** 获得图片资源 */ - function get(key){ - {image: %%engine2d.get%%(PREFIX ^ key)} - } - - /** 预加载图片和声音资源 */ - function preload(imgs,auds,f){ - imgs = List.map(function(img){ - PREFIX ^ img - },imgs); - auds = List.map(function(aud){ - PREFIX ^ aud - },auds); - %%engine2d.preload%%(imgs,auds,f); - } - - function play_sound(key){ - %%engine2d.play_sound%%(PREFIX ^ key); - } - start_timer = %%engine2d.start_timer%% stop_timer = %%engine2d.stop_timer%% show_menu = %%engine2d.show_menu%% @@ -140,7 +145,10 @@ client module Render { if(game.status == {prepare} || ( game.status == {show_result} && game.is_ok)){ draw_prepare(ctx,game,game.idx); //绘制牌堆 - if(not(test_flag(game.ready_flags,game.idx))) Canvas.draw_image(ctx,get("start.png"),330,555); //绘制“准备”按钮 + if(not(test_flag(game.ready_flags,game.idx))){ + Canvas.draw_image(ctx,get("start.png"),330,555); //绘制“准备”按钮 + Canvas.draw_image(ctx,get("btn_tutor.png"),620,510); //绘制“指导”按钮 + } }else{ draw_discards(ctx,game.discards,game.idx); //绘制玩家弃牌 draw_handcards(ctx,game); //绘制玩家手牌(不包括自己) @@ -260,12 +268,12 @@ client module Render { },game.players); //绘制等待信息 - Canvas.set_fill_style(ctx,BLACK); + /** Canvas.set_fill_style(ctx,BLACK); Canvas.set_font(ctx,"normal bold 11pt serif"); Canvas.set_text_align(ctx,{align_center}); Canvas.fill_text(ctx,"Waiting for players to set ready",400,360); Canvas.fill_text(ctx,"Game will start when four players are",400,385); - Canvas.fill_text(ctx,"all ready",400,410); + Canvas.fill_text(ctx,"all ready",400,410);*/ Canvas.restore(ctx); } @@ -396,6 +404,9 @@ client module Render { } } } + + //绘制当前局数和庄家 + //Canvas.fill_text(ctx,"ROUND {game.round+1} EAST",15,15); } /** @@ -917,6 +928,8 @@ client module Render { status: decode_status(game_msg.st), curr_turn: game_msg.ct, curr_card: game_msg.cc, + round: game_msg.rd, + dealer: game_msg.dl, ready_flags: game_msg.rf, players: game_msg.pls, decks: game_msg.dks,