
扑克翻牌游戏就是桌面24张牌,玩家翻到两张相同扑克牌则消去,如果2分钟仍然没有翻到两张相同扑克牌则游戏失败。
扑克翻牌游戏的运行界面如上图所示。
游戏设计的思路
HTML5 倒计时功能
HTML5倒计时功能可以使用setTimeout()函数或者setInterval()函数来实现。
1.使用setTimeout()函数实现倒计时功能
setTimeout()函数会在一个指定的延迟时间之后调用一个函数或执行一段指定的代码。它的应用非常广泛。例如,希望用户在浏览器某个页面一段时间后弹出一个对话框,或者是单击某个元素后隔几秒再删除这个元素。
setTimeout()函数的语法如下:
setTimeout(code,millisec)
例如:
var t = setTimeout("javascript语句", 毫秒)
setTimeout()函数的第一个参数code是含有JavaScript语句的字符串。这个语句可以是"alert('5 seconds!')"的形式,或者是对函数的调用,如"alertMsg()"。第二个参数millisec指从当前起等待多少毫秒后执行第一个参数code。
setTimeout()函数会返回某个值。在上面的语句中,值被存储在名为t的变量中。假如希望取消这个setTimeout()函数,可以使用clearTimeout(t)来实现。
需要强调的是,setTimeout()函数只执行code一次。如果要多次调用,可以让code自身再次调用setTimeout()函数。
例如,下面代码调用setTimeout()函数实现1小时倒计时。
<body>
<div id="timer"></div>
<script type="text/javascript" language="javascript">
var d1=new Date();//年月日时分秒
var d2=d1.getTime()+60*60*1000
var endDate=new Date(d2)
function daoJiShi()
{
var now=new Date();//获取当前时间
//now返回自 1970年1月1日 00:00:00 以来的总毫秒数
var oft=Math.round((endDate-now)/1000);
var ofd=parseInt(oft/3600/24);//天
var ofh=parseInt((oft%(3600*24))/3600);//小时
var ofm=parseInt((oft%3600)/60);//分
var ofs=oft%60;//秒
document.getElementById('timer').innerHTML='还有 '+ofd+' 天 ' +ofh+ ' 小时 ' +ofm+ ' 分钟 ' +ofs+ ' 秒';
if(ofs<0){document.getElementById('timer').innerHTML='倒计时结束!';return;};
setTimeout('daoJiShi()',1000);//自身再次调用daoJiShi()函数
};
daoJiShi();
</script>
</body>
2.使用setInterval()函数实现倒计时功能
由于setTimeout()函数只能执行代码code一次,想要多次调用code可以使用setInterval()函数。setInterval()函数可按照指定的周期(以毫秒计)来调用需要重复执行的函数代码。
setInterval()函数的语法如下:
setInterval(function,interval[,arg1,arg2,…,argn])
其中,function参数可以是一个匿名函数或是一个函数名,interval是设定的调用function的时间间隔,单位为毫秒(默认值为10毫秒),arg1,arg2,…,argn为可选参数,是传递给function的参数。
下面的例子是每隔1秒调用一次匿名函数。
setInterval(function(){trace("每隔1秒钟我就会显示一次")} , 1000);
其中,function(){}是没有函数名的函数,称为匿名函数,后面的1000是时间间隔,单位是毫秒,即1秒。
下面的例子用于展示如何带参数运行。
function show1(){
trace("每隔1秒显示一次");
}
function show2(str){ //带参数函数show2()
trace(str);
}
setInterval(show1,1000);
setInterval(show2,2000,"每隔2秒我就会显示一次"); //调用带参数函数show2()
setInterval()函数会不停地调用函数,直到clearInterval()函数被调用或窗口被关闭。由setInterval()函数返回的ID值可用作clearInterval(ID)函数的参数。在游戏开发中,常常使用setInterval()函数制作游戏动画或其他间隔性渲染效果。
var intervalID=setInterval(show1,1000);
clearInterval(intervalID); //取消该定时设置
例如,下面代码用setInterval()函数实现1小时倒计时。


扑克牌的显示与隐藏
游戏中使用的扑克牌牌面及背面采用1张图片(deck.png)存储,如图8-2所示。其中上面4行分别为4种花色的扑克牌,最后一行是扑克牌背面,每行高度为120px。如何分割显示某一张扑克牌,这里使用CSS3技术来实现。

■ 图8-2存储扑克牌的图片deck.png
例如,显示扑克牌背面图案可按如下代码写CSS类别。
.front
{
width: 80px; height: 120px;
background -image: url("../images/deck.png");
background-position: 0 -480px;
z-index: 10;
}
类别.front的背景图片是deck.png,background-position设置背景图片的位置。例如,background-position: 0 0; 表示背景图片的左上角将与容器元素的左上角对应。该设置与background-position: left top; 或者background-position: 0% 0%; 设置的效果是一致的。
而background-position: 0-480px; 表示图片以容器左上角为参考向左偏移0px,向上偏移480px,从而正好是扑克牌背面图片区域。
z-index属性设置元素的堆叠(显示)顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素前面。z-index的值越大,元素的堆叠层级越高。
background简写属性可在一个声明中设置所有的背景属性。可以设置如下属性:background-color、background-position、background-size、background-repeat、background-origin、background-clip、background-attachment、background-image。如果不设置其中的某个值,也是允许的。例如:
background:#999 url("../images/deck.png")0-480px;
background:#ff0000 url('smiley.gif');
显示扑克牌牌面图案可按如下代码写CSS类别。
其中:
.cardAJ{background-position:-800px 0;}
background-position: -800px 0; 表示图片以容器左上角为参考向左偏移800px,由于图片中每张牌宽度为80px,所以正好显示出黑桃J。
.cardBJ{background-position:-800px-120px;}
background-position: -800px-120px; 表示图片以容器左上角为参考向左偏移800px,向上偏移120px,所以正好显示出红桃J。
.cardCJ{background-position:-800px-240px;}
background-position: -800px-240px; 表示图片以容器左上角为参考向左偏移800px,向上偏移240px,所以正好显示出梅花J。
.cardDJ{background-position:-800px-360px;}
background-position: -800px-360px; 表示图片以容器左上角为参考向左偏移800px,向上偏移360px,所以正好显示出方块J。
因此,<div class="backcardAJ"/>就能显示出黑桃J,<div class="back cardBJ"/>就能显示出红桃J,<div class="back cardCJ"/>就能显示出梅花J,<div class="back cardDJ"/>就能显示出方块J。同理,可以显示出其他牌的牌面,仅background-position中的偏移量不同。
z-index设置为8,所以牌面显示在扑克牌背面下方,被隐藏。
扑克牌的删除
扑克牌的删除利用设置透明度来实现。
.card-removed/*移除牌*/
{
opacity: 0;
}
opacity: 0设置div的不透明度为0。Opacity取值从0.0(完全透明)到1.0(完全不透明)。也可以使用visibility: hidden来实现,这两个效果都是让元素不显示,但visibility: hidden 是让元素不可见,但仍会占据页面上的空间。
添加删除类别Class
扑克牌的显示、隐藏和删除都是CSS中类别Class。需要将这些类别设置到HTML的标记元素(如<div>)上,jQuery中的addClass方法用于添加类别Class,而removeClass方法用于删除类别Class。
addClass(className)中的className为一个字符串,为指定元素添加这个className类别。removeClass(className)指定元素移除的一个或多个用空格隔开的样式名或类别。
举例说明:
有一个<div>:

使用jQuery实现,当单击“中原工学院”的时候自动添加class="select",代码自动变成:

然后,单击“郑州大学”,代码又变成:

jQuery可以用下述代码实现:


jQuery代码中$("a")选择所有的元素,在元素的单击事件中,each()方法遍历所有的元素并删除元素上的"select"类别。$(this)代表当前被单击的元素,$(this).addClass("select")是给当前被单击的元素增加"select"类别。
扑克翻牌游戏设计的步骤
设计CSS(matchgame.css)
根据程序设计的思路,设计如下的CSS文件。
body
{
text-align: center;
background-image: url("../images/bg.jpg");
}
#game
{
width: 502px;
height: 462px;
margin: 0 auto;
border: 1px solid #666;
border-radius: 10px;
background-image: url("../images/table.jpg");
position: relative;
display: -webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;
}
#cards
{
width: 380px;
height: 400px;
position: relative;
margin:30px auto;
}
.card
{
width: 80px;
height: 120px;
position: absolute;
}
.face
{
width: 100%;
height: 100%;
border-radius:10px;
position: absolute;
-webkit-backface-visibility: hidden;
-webkit-transition:all .3s;
}
.front
{
background: #999 url("../images/deck.png")0 -480px;
z-index: 10;
}
.back
{
background: #efefef url("../images/deck.png");
-webkit-transform-rotateY(-180deg);
z-index: 8;
}
.face:hover
{
-webkit-box-shadow: 0 0 40px #aaa;
}
/*牌面定位样式*/
.cardAJ{background-position: -800px 0;}
.cardAQ{background-position: -880px 0;}
.cardAK{background-position: -960px 0;}
.cardBJ{background-position: -800px -120px;}
.cardBQ{background-position: -880px -120px;}
.cardBK{background-position: -960px -120px;}
.card-flipped .front
{
/*保证牌底在牌面下面,z-index值切换为小值*/
z-index: 8;
-webkit-transform: rotateY(180deg);
}
.card-flipped .back
{
/*保证牌底在牌面上面,z-index值切换为大值*/
z-index: 10;
/*前面牌面已经翻过去,现在返回来*/
-webkit-transform: rotateY(0deg);
}
/*移除牌*/
.card-removed
{
opacity: 0;
}
游戏页面index.html
在游戏页面中,整个游戏区域是一个id="cards"的<div>,而每张牌的区域是一个class="card"的<div>,<div class="face front">其中含上下层两个,是上层显示牌面,<div class="faace back">是下层显示牌面。
<div class="card">
<div class="face front"></div>
<div class="face back"></div>
</div>
注意,最初仅仅有1张牌的区域,其余的23张牌的区域是页面加载后复制实现的。页面加载后,首先利用Array.sort()方法将deck数组存储的牌随机排序,实现洗牌效果;然后调整CSS坐标属性"left"、"top",设置每张牌的区域在屏幕上的位置;最后在每张牌的区域<div>中的下层<div class="face back">添加类别(如.cardAJ、.cardBJ)就可以显示对应牌面。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>html5扑克翻牌消除小游戏</title>
<link href="matchgame.css" rel="stylesheet">
</head>
<body>
<script type="text/javascript" src="matchgame.js"></script>
<script type="text/javascript" src="jquery-3.3.1.min.js"></script>
<section id="game">
<div id="cards">
<div class="card">
<div class="face front"></div>
<div class="face back"></div>
</div>
</div>
</section>
<script type="text/javascript">
$(function(){
//实现随机洗牌
matchingGame.deck.sort(shuffle);
//alert(matchingGame.deck);
var $card=$(".card");
for(var i= 0;i<23;i++)
{
$card.clone().appendTo($("#cards"));
}
//对每张牌进行设置
$(".card").each(function(index)
{
//调整坐标
$(this).css({
"left":(matchingGame.cardWidth+20)*(index%8)+"px",
"top":(matchingGame.cardHeight+20)*Math.floor(index/8)+"px"
});
//吐出一个牌号
var pattern=matchingGame.deck.pop();
//暂存牌号
$(this).data("pattern",pattern);
//把其翻牌后的对应牌面附加上去
$(this).find(".back").addClass(pattern);
//点击牌的功能函数挂接
$(this).click(selectCard);
});
});
</script>
<div style="text-align:center;margin:50px 0; font:normal 44px/56px ">
<p>扑克翻牌游戏</p>
<div id="timer"></div>
</div>
<script type="text/javascript" language="javascript">
var success=false;
var d1=new Date();//年月日时分秒
var d2=d1.getTime()+2*60*1000
var endDate=new Date(d2);
function daoJiShi()
{
var now=new Date(); //获取当前时间
//now返回自 1970 年 1 月 1 日 00:00:00 以来的总毫秒数
var oft=Math.round((endDate-now)/1000);
var ofd=parseInt(oft/3600/24);
var ofh=parseInt((oft%(3600*24))/3600);
var ofm=parseInt((oft%3600)/60);
var ofs=oft%60;
document.getElementById('timer').innerHTML='还有 '+ofm+ ' 分钟 ' +ofs+ ' 秒';
if(success==true) return;//停止计时
if(ofs<0){
document.getElementById('timer').innerHTML='倒计时结束!';
if(success==false)alert('你挑战失败了!');
return;
};
setTimeout('daoJiShi()',1000);
};
daoJiShi();
</script>
</body>
</html>
设计脚本
定义存储所有牌的数组deck。
var matchingGame={};
matchingGame.cardWidth=80;//牌宽
matchingGame.cardHeight = 120;
//存储所有的牌
matchingGame.deck=
[
"cardAK","cardAK", "cardAQ","cardAQ", "cardAJ","cardAJ",
"cardBK","cardBK", "cardBQ","cardBQ", "cardBJ","cardBJ",
"cardCK", "cardCK", "cardCQ", "cardCQ", "cardCJ", "cardCJ",
"cardDK", "cardDK", "cardDQ", "cardDQ", "cardDJ", "cardDJ"
]
//随机排序函数,返回-1或1
function shuffle()
{
//Math.random能返回0~1之间的数
return Math.random()>0.5 ? -1 : 1
}
单击牌事件的功能函数selectCard(),实现翻牌的功能。被翻过的牌都已添加"card-flipped"类别,所以$(".card-flipped")获取所有的翻过牌的<div>,数量超过1则说明已翻了两张牌,不能再翻牌,从而退出翻牌。
若翻动了两张牌,检测是否相同。
function selectCard() { //翻牌功能的实现
var $fcard=$(".card-flipped");
//翻了两张牌后退出翻牌
if($fcard.length>1)
{
return;
}
$(this).addClass("card-flipped");
//若翻动了两张牌,检测一致性
var $fcards=$(".card-flipped");
if($fcards.length==2)
{
setTimeout(function(){
checkPattern($fcards);},700);
}
}
//检测2张牌是否一致
function checkPattern(cards)
{
var pattern1 = $(cards[0]).data("pattern"); //第一张牌牌面数据
var pattern2 = $(cards[1]).data("pattern"); //第二张牌牌面数据
$(cards).removeClass("card-flipped") //删除"card-flipped"类别
if(pattern1==pattern2)
{
$(cards).addClass("card-removed") //透明效果
var $ fcards=$(".card-removed");
if($ fcards.length==24)
{
alert("恭喜你成功了!");
succcess=true;
}
}
}
至此,完成扑克翻牌游戏。
参考书籍


作者:夏敏捷、尚展垒
定价:69.90元
ISBN:9787302629771
编辑推荐:11个游戏实战案例,提供视频、源代码、教学课件、教学大纲、扩展案例
本书分为基础篇和实战篇。
基础篇包括第1~6章,主要讲解HTML5的基础知识和相关新技术,如JavaScript、Canvas API画图、CSS3和jQuery及其使用技巧;
实战篇包括第7~17章,综合应用前面技术,开发经典的大家耳熟能详的游戏,如人物拼图、扑克翻牌、推箱子、五子棋、黑白棋、俄罗斯方块、贪吃蛇、雷电飞机射击、Flappy Bird、中国象棋。通过本书读者将学会如何利用HTML5和JavaScript、CSS3制作交互式游戏、平台类游戏,学会网页游戏设计。











