Silverlight开发MMORPG游戏研讨(5):让浏览器更好地为Silverlight游戏服务

由于Silverlight游戏内嵌在浏览器页面中,处理好浏览器的控制对于Silverlight游戏的表现十分重要。本节归纳总结了Silverlight游戏开发中可能遇到的一些浏览器相关的问题,并给出解决方案。这些问题包括:如何令浏览器文档窗口最大化,如何防止误关浏览器窗口,用户关闭浏览器时如何通知服务器,如何阻止用户从多个浏览器窗口登录游戏。本来打算用四篇blog来分别阐述,不过每部分内容都不多,分开恐怕有多骗稿费的嫌疑,管理起来也不方便,索性就一并发了。
 

1 如何令浏览器文档窗口最大化

相信大多RPG游戏玩家都喜欢在全屏方式下玩游戏,即使不支持全屏,也希望可视窗口尽可能的大,可以包容尽可能多的游戏元素和信息。可是对于基于浏览器的网页游戏,由于浏览器可能包含菜单栏,地址栏,工具栏,状态栏等,可视文档窗口尺寸被挤占很多,留给silverlight游戏的空间可能会少的可怜。对于游戏来说,这些“栏”不但没有任何作用,反而干扰玩家的视线。浏览器只是silverlight游戏的一个容器,我们希望它保持最大化,同时去掉所有的“栏”,给我们的游戏留下最大的驰骋空间。
 
相信这时候大家百分之百想到的是JavaScript,具体怎样实现呢?假设在主页中包含一个游戏网页链接(game.htm),我们希望最大化显示game.htm。
 
第一步,在game.htm中,用JavaScript的window.open函数在本浏览器窗口重新打开game.htm,并设置window.name = "SelfWindow"。在本浏览器窗口重新打开game.htm的目的是在第三步关闭本窗口时不会显示讨厌的确认对话框。设置window.name的作用是防止打开窗口逻辑死循环。可以看到,这里用window.name来实现状态机,总共有三个状态:初始时window.name = "",打开自身后window.name = "SelfWindow",和新窗口window.name = "NewWindow"。
 
第二步,用window.open函数打开一个新浏览器窗口来显示game.htm,在参数设置中去掉所有的不需要的“栏”,同时令浏览器窗口的宽和高等与屏幕尺寸。设置新浏览器窗口window.name = "NewWindow"。这个新浏览器窗口就是我们需要的游戏窗口。
 
第三步,关掉原来窗口。初始的浏览器窗口只是一个过渡窗口,当新浏览器窗口打开后就完成了使命,继续存在只会干扰视线,造成混乱,所以需要将其关掉。正常情况下用window.close()关闭窗口时会弹出一个对话框来要求用户确认,十分讨厌。经过第一步的操作,这个对话框就不会出现了。
  
全部JavaScript代码如下:
<script language="javascript" type="text/javascript">
if (window.name == "")
{
// name is empty when opened at the first time.
window.name = "SelfWindow";
window.open(
"game.htm", "_self");
}
else if (window.name == "SelfWindow")
{
window.open(
"game.htm", "NewWindow", 'channelmode=0, directories=0, location=0, menubar=0, resizable=1, scrollbars=1,status=0,titlebar=0,toolbar=0,top=0,left=0,screenX=0,screenY=0,width=' + (screen.availWidth-10) + ',height=' + (screen.availHeight-35));
// close self
window.close();
}
</script>

 

 
 
 
注意,测试上面演示时必须暂时关闭浏览器的防止弹出窗口功能,IE8中, 如图所示:

2 如何防止误关浏览器窗口

很多朋友在使用浏览器时有过这样的体验,花了很多时间在网上填写了一个表单,不小心按了刷新或关闭浏览器按钮,所有的输入都不翼而飞,大骂stupid,砸了显示器的心都有。玩silverlight游戏也有相同的风险,一旦离开当前页面,所有游戏信息都会丢失。每个游戏玩家都不希望这种事情发生,比较理想的情况是,当试图离开当前页面,需要用户来确认是否真的要离开,以防止误操作带来的不便。
 
我们可以利用浏览器的onbeforeunload事件来实现上面的需求。我们的需求是,在任何情况下离开当前页面都需要确认。实现起来极其简单,JavaScript代码如下:
 
<body onbeforeunload='return "关闭当前浏览器窗口会丢失所有游戏信息。";'>

 

 
 
比较复杂的应用是根据状态来决定是否需要用户确认。对于表单的例子,只有当用户改变了输入的信息,才会要求用户确认,否则不用。这种应用往往需要服务器端代码来配合,不过实现起来也不困难。本文只讨论silverlight游戏,最简单的方式就足够用了。
 

3 用户关闭浏览器时如何通知服务器

理想状态下,用户每次离开silverlight游戏之前,都会点击一下“退出”按钮,告诉服务器:“我现在退出了”。然而现实中,很多用户可能没有这个耐心,或者忘记了点击“退出”按钮,直接关闭浏览器窗口离开游戏。虽然我们可以用上一部分的方法来提醒用户,但是用户依然可以确定关闭,然后扬长而去。这种情况下,我们如何来通知服务器,从而更新用户的状态呢?
 
我们知道,Silverlight的App.xaml.cs中的Application_Exit事件处理方法会在Silverlight应用程序即将关闭前触发,我们可否在这里通知服务器呢?
 
与服务器的通信可以由web service来完成。可是问题来了,Silverlight不支持在Application_Exit事件处理方法中调用web service!是不是很失望?很多Silverlight用户都抱怨这一点,希望开发团队在Silverlight下一个版本可以提供该特性。但是在这之前,我们需要想点办法来绕过这个障碍。对了,还是JavaScript,我们可以在Application_Exit中调用JavaScript方法,然后通过JavaScript来调用web service。代码如下:
 
Silverlight:
void Application_Exit(object sender, EventArgs e)
{
HtmlPage.Window.Invoke(
"NotifyWebserviceOnClose", new[] { guid.ToString() });
}

 

 
JavaScript:
function NotifyWebserviceOnClose(identifier)
{
PageMethods.SignOff(identifier, OnSignOffComplete);
}

 

演示起来麻烦一点,还是直接看源代码吧。
 

4 如何阻止用户从多个浏览器窗口登录游戏

对于网页游戏,我们往往希望每个用户只能打开并操作一个游戏窗口。如果用户试图从第二个窗口登录游戏,无论是在其他机器上,本机的其他浏览器,本机的相同浏览器新窗口,或者本机的相同浏览器的新tab窗口,都应该被禁止登录。实现这一功能的关键是如何知道某个用户正在操作一个游戏窗口。
 
纯客户端的方法看来是无能为力了,因为第二个窗口可能跨浏览器,甚至在不同机器上。我们只能通过服务器端来检测该用户当前是否在线。实现的方法可能很多,这里只提出一个简单方法供大家参考。
 
打开游戏窗口时,首先显示登录页面。用户登录时,在服务器端检测该用户当前是否在线。每个用户都有一个最后活动时间,如果登录时间在最后活动时间的5分钟内,我们认为该用户处于离线状态,因为对于一个MMORPG游戏,不可能5分钟内没有活动。如果用户处于离线状态,则允许登录,否则禁止。笔者偷个懒,本部分不提供演示和代码了。
 
 
综上所述,尽管浏览器与silverlight的游戏逻辑没有关系,但是对于玩家的游戏体验还是很有影响的。 处理好浏览器的细节问题,有助于游戏的更好的表现和用户体验。以上的讨论只是抛砖引玉,如果大家有更好的方法,还请不吝赐教。
 
本节的源代码请在这里下载
posted @ 2010-05-28 15:45  erichan  阅读(962)  评论(2编辑  收藏  举报