在线斯诺克html5,用HTML 5打造斯诺克桌球俱乐部
本文介绍了如何利用HTML5技术来打造一款非常酷的斯诺克桌球游戏,文章中详细地列出了开发的全过程,并解说了实现这个游戏的几个关键点。在文章末尾我向大家提供了游戏的在线实例页面和源码下载链接,如果你只是想玩玩(需要使用支持HTML5的浏览器,建议使用Chrome 12, Internet Explorer 9 或者 Fire Fox 5及其以上版本),那你可以跳过正文拉到页面最底端去玩玩那个游戏或者下载源码,但我建议你好好看看实现过程,对我们学习HTML5非常有帮助。
毫无疑问,我们已经目睹了HTML5背后的那场伟大的Web开发革命。经过那么多年HTML4的统治,一场全新的运动即将完全改变现在的Web世界。正是他释放出来的现代化气息和丰富的用户体验,让它很快地成为了一个独特的插件运行在类似Flash和Silverlight的框架之上。
如果你是一个非常年轻的开发者,也许你是刚刚在开始学习HTML5,所以可能你并没有注意到他有太大的变化。在任何时候,我希望这篇文章能够帮助到你,当然,也希望像我一样的老手能从中学到一些新的花样。
你的点评对我来说非常重要,所以我很期待你的来信。当然能让我更兴奋的是当你在那个游戏画面上右击时暗暗地说一句“Hey,这居然不是Flash!也不是Silverlight!”
系统要求
想要使用本文提供的HTML5桌球应用,你必须安装下面的这些浏览器:Chrome 12, Internet Explorer 9 or Fire Fox 5
游戏规则
也许你已经知道这是一个什么样的游戏了,是的,这是“英式斯诺克”,实际上更确切的说是“简易版英式斯诺克”,因为没有实现所有的斯诺克游戏规则。你的目标是按顺序将目标球灌入袋中,从而比其他选手得到更多的分数。轮到你的时候,你就要出杆了:根据提示,你必须先打进一个红色球得到1分,如果打进了,你就可以继续打其他的球 - 但是这次你只能打彩色球了(也就是除红色球以外的球)。如果成功打进,你将会得到各自彩球对应的分数。然后被打进的彩球会回到球桌上,你可以继续击打其他的红球。这样周而复始,直到你失败为止。当你把所有的红球都打完以后,球桌上就只剩下6个彩球了,你的目标是将这6个彩球按以下顺序依次打入袋中:黄(2分)、绿(3分)、棕(4分)、蓝(5分)、粉(6分)、黑(7分)。如果一个球不是按上面顺序打进的,那它将会回到球桌上,否则,它最终会留在袋里。当所有球都打完后,游戏结束,得分最多的人胜出。
犯规处理
为了处罚你的犯规,其他选手将会得到你的罚分:
◆ 白球掉入袋中罚4分
◆ 白球第一次击中的球是错误的话罚第一个球的分值
◆ 第一个错误的球掉入袋中罚第一个球的分值
◆ 处罚的分数至少是4
下面的这段代码展示了我是如何来计算犯规的:
varstrokenBallsCount=0;
console.log('strokenBalls.length: ' + strokenBalls.length);
for (vari=0; i
varball=strokenBalls[i];
//causing the cue ball to first hit a ball other than the ball on
if (strokenBallsCount== 0) {
if (ball.Points != teams[playingTeamID - 1].BallOn.Points) {
if (ball.Points== 1 || teams[playingTeamID - 1].BallOn.Points== 1 ||
fallenRedCount== redCount) {
if (teams[playingTeamID - 1].BallOn.Points<4) {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1]
.FoulList.length] = 4;
$('#gameEvents').append('
Foul 4 points : Expected ' +
teams[playingTeamID - 1].BallOn.Points + ', but hit ' + ball.Points);
}
else {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1]
.FoulList.length] = teams[playingTeamID - 1].BallOn.Points;
$('#gameEvents').append('
Foul ' + teams[playingTeamID - 1]
.BallOn.Points + ' points : Expected ' + teams[playingTeamID - 1]
.BallOn.Points + ', but hit ' + ball.Points);
}
break;
}
}
}
strokenBallsCount++;
}
//Foul: causing the cue ball to miss all object balls
if (strokenBallsCount== 0) {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length] = 4;
$('#gameEvents').append('
Foul 4 points : causing the cue ball
to miss all object balls');
}
for (vari=0; i
varball=pottedBalls[i];
//causing the cue ball to enter a pocket
if (ball.Points== 0) {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length] = 4;
$('#gameEvents').append('
Foul 4 points : causing the cue ball
to enter a pocket');
}
else {
//causing a ball different than the target ball to enter a pocket
if (ball.Points != teams[playingTeamID - 1].BallOn.Points) {
if (ball.Points== 1 || teams[playingTeamID - 1].BallOn.Points== 1
||fallenRedCount== redCount) {
if (teams[playingTeamID - 1].BallOn.Points<4) {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1]
.FoulList.length] = 4;
$('#gameEvents').append('
Foul 4 points : '
+ ball.Points + ' was potted, while ' + teams[playingTeamID - 1]
.BallOn.Points + ' was expected');
$('#gameEvents').append('
ball.Points: ' + ball.Points);
$('#gameEvents').append('
teams[playingTeamID - 1]
.BallOn.Points: ' + teams[playingTeamID - 1].BallOn.Points);
$('#gameEvents').append('
fallenRedCount: ' + fallenRedCount);
$('#gameEvents').append('
redCount: ' + redCount);
}
else {
teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1]
.FoulList.length] = teams[playingTeamID - 1].BallOn.Points;
$('#gameEvents').append('
Foul ' + teams[playingTeamID - 1]
.BallOn.Points + ' points : ' + ball.Points + ' was potted, while '
+ teams[playingTeamID - 1].BallOn.Points + ' was expected');
}
}
}
}
}
得分
我们根据下面的规则来计算得分:红(1分)、黄(2分)、绿(3分)、棕(4分)、蓝(5分)、粉(6分)、黑(7分)。代码如下:
if (teams[playingTeamID - 1].FoulList.length== 0) {
for (vari=0; i
varball=pottedBalls[i];
//legally potting reds or colors
wonPoints += ball.Points;
$('#gameEvents').append('
Potted +' + ball.Points + ' points.');
}
}
else {
teams[playingTeamID - 1].FoulList.sort();
lostPoints=teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length - 1];
$('#gameEvents').append('
Lost ' + lostPoints + ' points.');
}
teams[playingTeamID - 1].Points += wonPoints;
teams[awaitingTeamID - 1].Points += lostPoints;
选手的闪动动画头像
游戏是有两位选手参与的,每一位选手都有自己的昵称和头像,选手的昵称我们就简单地以“player 1”和“player 2”来命名了(也许让用户自己输入会更漂亮)。每位选手的头像是一只正在打桌球的可爱小狗。当轮到其中一位选手时,他的头像就会有一闪一闪的动画效果,同时对手的头像会停止闪动。
这个效果我们是通过改变img元素的CSS3属性opacity的值来实现的:我们使用jquery的animatio函数让opacity的值在0-1.0之间变化。
function animateCurrentPlayerImage() {
varotherPlayerImageId=0;
if (playingTeamID== 1)
otherPlayerImageId='player2Image';
else
otherPlayerImageId='player1Image';
varplayerImageId='player'+ playingTeamID + 'Image';
$('#' + playerImageId).animate({
opacity: 1.0
}, 500, function () {
$('#' + playerImageId).animate({
opacity: 0.0
}, 500, function () {
$('#' + playerImageId).animate({
opacity: 1.0
}, 500, function () {
});
});
});
$('#' + otherPlayerImageId).animate({
opacity: 0.25
}, 1500, function () {
});
}
力量控制条
一个优秀的斯诺克选手都能很好地把握住每一杆的力度.不同的技巧需要不同的击球方式:直接的,间接的,或者利用边角的等等。不同方向和不同力度的组合可以构造成千上万种可能的路径。幸运的是,这个游戏提供了一个非常漂亮的力度控制条,可以帮助选手在击球前调整他们的球杆。
为了达到这一点,我们使用了HTML5的meter元素标签,它可以完成测量距离的工作。meter标签最好在知道这次测量的最小值和最大值的情况下使用。在我们的这个例子中,这个值在0到100之间,因为IE9不支持meter,所以我用了一张背景图来替代,这样效果也是一样的。
#strengthBar { position: absolute; margin:375px 0 0 139px;
width: 150px; color: lime; background-color: orange;
z-index: 5;}
当你点击了力度条后,你实际上是选择了一个新的力度。一开始你可能不是很熟练,但在真实世界中,这是需要时间来训练自己的能力的。点击力度条的代码如下:
$('#strengthBar').click(function (e) {
varleft= $('#strengthBar').css('margin-left').replace('px', '');
varx=e.pageX - left;
strength= (x / 150.0);
$('#strengthBar').val(strength * 100);
});
在当前选手的头像框里面,你会注意到有一个小球,我叫他“ball on”,就是当前选手在规定时间内应该要击打的那个球。如果这个球消失了,那选手将失去4分。同样如果选手第一次击中的球不是框内显示的球,那他也将失去4分。
这个“ball on”是直接将canvas元素覆盖在用户头像上的,所以你在头像上看到的那个球,他看起来像是在标准的div上盖了一个img元素,但是这个球并不是img实现的。当然我们也不能直接在div上画圆弧和直线,这就是为什么我要将canvas覆盖到头像上的原因了。看看代码吧:
varplayer1BallOnContext=player1BallOnCanvas.getContext('2d');
varplayer2BallOnContext=player2BallOnCanvas.getContext('2d');
.
.
.
function renderBallOn() {
player1BallOnContext.clearRect(0, 0, 500, 500);
player2BallOnContext.clearRect(0, 0, 500, 500);
if (playingTeamID== 1) {
if (teams[0].BallOn != null)
drawBall(player1BallOnContext, teams[0].BallOn, new Vector2D(30, 120), 20);
}
else {
if (teams[1].BallOn != null)
drawBall(player2BallOnContext, teams[1].BallOn, new Vector2D(30, 120), 20);
player1BallOnContext.clearRect(0, 0, 133, 70);
}
}
旋转屋顶上的电风扇
在这个游戏中这把电风扇纯属拿来玩玩有趣一把的。那为什么这里要放一把电风扇?是这样的,这个游戏的名字叫HTML5斯诺克俱乐部,放一把电风扇就有俱乐部的气氛了,当然,我也是为了说明如何实现CSS3的旋转。
实现这个非常简单:首先我们需要一张PNG格式的电扇图片。只是我们并没有用电扇本身的图片,我们用他的投影。通过显示风扇在球桌上的投影,让我们觉得它在屋顶上旋转,这样就达到了我们目的:
#roofFan { position:absolute; left: 600px; top: -100px; width: 500px; height: 500px;
border: 2px solid transparent; background-image: url('/Content/Images/roofFan.png');
background-size: 100%; opacity: 0.3; z-index: 2;}
.
.
.
在线斯诺克html5,用HTML 5打造斯诺克桌球俱乐部相关推荐
- HTML5斯诺克桌球俱乐部【译】
不久前,我翻译了一些技术文章,放在我的博客上,没看过的且有兴趣的朋友可以去看看:Javascript中的陷阱大集合[译].轻松学习正则表达式[译].jQuery调用Google翻译实例[译].这次这篇 ...
- 【转】HTML5斯诺克桌球俱乐部【译】
[http://www.cnblogs.com/sxwgf/archive/2011/11/20/2256359.html] 不久前,我翻译了一些技术文章,放在我的博客上,没看过的且有兴趣的朋友可以去 ...
- 有7克、2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50、90克各一份?
微软面试题:有7克.2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50.90克各一份?(4种解法) 解法很多,仁者见仁智者见智: 1 ): 把2g和7g砝码放在同一边称量出9g盐 把 ...
- C语言给出点坐标进行克里金插值,Arcgis笔记之克里金插值——求助surfer8.0
arcgis的插值方法比较丰富,但是有一点,那就是克里金插值.arcgis中克里金插值的结果不平滑,看起来非常难看.如下图,是对图中点数据某个属性值的插值结果. arcgis克里金插值结果 使用su ...
- mad和php的区别,独家揭秘评测恩雅eutx1尤克里里和卡卡mad尤克里里有啥区别?哪个好?深度剖析曝光...
这两个恩雅eutx1尤克里里和卡卡mad尤克里里都还可以的哈,老牌子的,质量不错的,但是恩雅EUTX1整体要精致点儿,性价比也蛮高的,看个人吧,我自己用的是恩雅EUTX1,款式是我喜欢的,整体看着大气 ...
- 面试题:有7克、2克砝码各一个,天平一只,如何只用这些物品称三次,将140克的盐分成50、90克各一份?...
问题:面试题:有7克.2克砝码各一个,天平一只,如何只用这些物品称三次,将140克的盐分成50.90克各一份? 解法一: ①用天平将盐分成70g两份,即140 ->70 + 70; ②用天平将其 ...
- 用计算机做一克拉等于多少克的单位换算,克和克拉怎么换算(克拉和克的换算单位是多少)...
克拉(Ct)是宝石的质量(重量)单位,现定1克拉等于0.2克或200毫克.一克拉又分为100分,如50分即0.5克拉,以用作计算较为细小的宝石.因为宝石的密度基本上相. 1克拉=0.0002千克 克拉 ...
- 【面试智力题】有7克、2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50、90克各一份?
问题描述 有7克.2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50.90克各一份? 解法一 第一次:2+7->称9g盐 第二次:9+7->称16g盐 第三次:16+7- ...
- 克里金插值的定义----普通克里金插值算法
点击打开链接https://xg1990.com/blog/archives/222 点击打开链接: 百度文库克里金算法详解及实例计算过程 https://wenku.baidu.com/view/2 ...
最新文章
- 运维企业专题(7)LVS高可用与负载均衡中篇——VS/NAT模式配置详解
- Windows Server 2016 简介和安装
- Linux 技巧:让进程在后台可靠运行的几种方法
- STM32H743+Keil-将变量定义到指定内存
- opencv打开的图片应用于nn.Conv2d()(二)
- 离婚前一晚是什么心情呢?
- python输出输入的字符串_python笔记3-输出输入、字符串格式化
- 查询oracle数据库错误修改了,【案例】Oracle报错ora-00600[2662] 修改控制文件scn推进数据库scn...
- MATLAB 语言基础知识 矩阵和数组 从矩阵中删除行或列
- paper的经验和会议排名
- 第六讲 复数和复指数
- 安装win10 ltsc应用商店
- 异步4月新书,送出一本你爱的!
- 【小家Spring】注意BeanPostProcessor启动时对依赖Bean的“误伤”陷阱(is not eligible for getting processed by all...)
- 创建本地的https证书
- python中“羊车门问题”的简单分析与代码实现
- CAS和hotspot源码
- 瞬时频率函数matlab,Hilbert 变换与瞬时频率
- maven的下载安装,setting.xml配置教程,Idea 配置maven
- CSS--实现照片墙
热门文章
- 飞畅科技-工业级POE交换机解决方案专家
- 【渝粤教育】电大中专电子商务网站建设与维护 (27)作业 题库
- java hessian rmi_RMI,socket,rpc,hessian,http比较
- bitmap的java原理_布隆算法的原理及JAVA实现
- 【卷积码系列2】(n,k,m)卷积码的生成多项式矩阵系数转网格图描述(不使用MATLAB库函数)
- 2020-08-21 光纤通信第四章知识点整理
- 安卓手机背景变黑色怎么改_别着急扔掉旧手机 你的电脑可能需要它
- flask-mail异步发送邮件_SpringBoot 2.0 集成 JavaMail ,实现异步发送邮件
- 如何搭建socks5和ss节点_redis cluster搭建实践(非常详细,值得收藏)
- 第一单元总结:基于基础语言、继承和接口的简单OOP