1. 程式人生 > >遊戲——網頁版別踩白塊

遊戲——網頁版別踩白塊

百度 name 完整 是否 使用 建行 classname 內容 必須

一 項目簡介

主要知識點:JavaScript、HTML、CSS
這是一個主要用JS實現的網頁版小遊戲,遊戲規則很簡單,通過點擊不斷下落的黑塊來消滅它並獲取分數,如果不幸黑塊掉落下來或點到了白色區域那麽遊戲就會終止。
遊戲截圖如下:
技術分享圖片

二 遊戲框架

整個遊戲可分為以下幾個步驟實現:
1. HTML和CSS畫出靜態的遊戲框架;
2. DOM結構說明:
遊戲元素使用嵌套的div元素來實現,是一個4*4的方格地圖:最外層容器main(一個) > 次外層容器container(一個) > 行容器row(四行) > 方塊cell(每行4塊)
3. JS邏輯:
1)圖形的繪制:用js來動態創建div元素,並逐級添加到上層節點當中;
2)實現下落:通過動態增加包裹所有方塊的container容器的top的值來實現下落效果;
3)持續下落:動態在最上層創建一行方塊,同時刪除最下層一行方塊;隔一段時間調用一次;
4)用戶交互:用戶通過點擊事件,綁定到整個動畫中,通過改變屬性名來使黑塊轉變為白塊,實現視覺上的“消滅黑塊”;
5)加分規則:用戶成功點擊黑塊,則調用一次加分函數,並將分數實時寫入頁面中;
6)犯規處理:A. 通過判斷方塊元素屬性名來判斷用戶是否點擊白塊從而終止遊戲;B. 通過判斷最後下落的一行是否含有黑塊從而判斷是否應該終止遊戲;
7)遊戲加成:當分數達到某個階段可通過增加下落的像素值的大小來加快下落速度從而增加遊戲難度,增加趣味性;
8)結束遊戲:犯規後,清除調用函數,來終止遊戲運行。

三 完整代碼

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>別踩白塊</title>
<style>
#main{ /*遊戲背景板的樣式*/
width:400px;
height:400px;
background:white;
border:1px solid green;
margin:0 auto;
position:relative; /*position 屬性規定元素的定位類型。relative:生成相對定位的元素,相對於其正常位置進行定位。*/


overflow:hidden;
} /*overflow屬性規定當內容溢出元素框時發生的事情。hidden::內容會被修剪,並且其余內容是不可見的。*/
#container{ /*下落方塊所在的容器樣式*/
width:100%;
height:400px;
position:relative;
top:-100px; /*黑塊最開始不能出現在最下面,否則遊戲直接結束,因此容器整體上移100px*/
}
.row{ /*一行容器的樣式*/
height:100px;
width:100%;
}
.cell{ /*單個方塊的樣式*/

height:100px;
width:100px;
float:left; /*float 屬性定義元素在哪個方向浮動*/
}
.black{ /*黑塊的樣式*/
background:black;
}
h1{
text-align:center;
}
p{
display:inline-block; /*display 屬性規定元素應該生成的框的類型,inline-block為行內塊元素。*/
}
</style>
</head>
<body>
<h1>Score: <p id="score">0</p></h1>
<div id="main">
<div id="container"></div>
</div>
<script>
var clock=null; //定時器操作句柄
var state=0; //定義遊戲當前狀態:0初始化,1進行中,2暫停,3失敗
var speed=2; //方塊下落的速度,初始值為2像素

//初始化
function init(){
for(var i=0; i<4; i++){ //創建4行row
crow();
}
$(‘main‘).onclick=function(ev){ //向main添加點擊事件
judge(ev); //調用判斷函數來判斷用戶的點擊行為是否合規,參數為事件對象
}
}

//start()啟動
function start(){
clock=window.setInterval(‘move()‘,30); //每30毫秒調用一次移動函數

//下落動畫
function move(){
var con=$(‘container‘); //通過自定義函數$()找到container

var top=parseInt(window.getComputedStyle(con,null)[‘top‘]); //window.getComputedStyle(element, [pseudoElt]);方法給出應用活動樣式表後的元素的所有CSS屬性的值,並解析這些值可能包含的任何基本計算。element用於獲取計算樣式的Element,pseudoElt(可選)指定一個要匹配的偽元素的字符串。必須對普通元素省略(或null)。返回的樣式是一個實時的 CSSStyleDeclaration 對象,當元素的樣式更改時,它會自動更新本身。CSSStyleDeclaration 表示一個CSS屬性鍵值對的集合。此處初始值為-100
if(speed + top >0){ //當最上面一行row走過頭了,無法與main上邊緣重合時
top=0; //直接將row的坐標置為0
}else{
top += speed;//調節每次下降的像素,必須是100的約數,這樣才能移動若幹次後剛好為100px,因為一個方塊為100px*100px,剛好能夠與main上下兩邊重合
}
con.style.top=top + ‘px‘;
if(top==0){ //當最上面一行row剛好落進main內
crow(); //調用函數在最上方插入一行row
con.style.top=‘-100px‘; //並使其位於main上面隱藏的部分
drow(); //當上下中間共有6行row時調用函數,刪除最下面一行row,避免遊戲過程中堆積太多元素,給瀏覽器增加負擔
}else if(top==(-100+speed)){ //一輪剛好進行第一次下落,此時最下面一行row剛好準備和main的下邊緣觸碰
var rows=con.children; //ParentNode.children 是一個只讀屬性,返回 一個Node的子elements ,是一個動態更新的 HTMLCollection
if((rows.length==5) && (rows[rows.length-1].pass !==1)){ //如果此時有5行row,並且最後一行未成功點擊黑塊
fail(); //遊戲失敗
}
}
}

//加速
function speedup(){
speed +=2;
if(speed==20){
alert(‘Excellent!‘);
}
}

//遊戲失敗
function fail(){
clearInterval(clock); //clearInterval() 方法可取消由 setInterval() 函數設定的定時執行操作。
state=3; //另遊戲狀態等於3,最開始定義的3為失敗
alert(‘Game Over!‘);
}

//計分
function score(){
var newscore=parseInt($(‘score‘).innerHTML)+1; //獲取score的innerHTML值並轉化為整數,再加一分
$(‘score‘).innerHTML=newscore; //增加後的分數寫入score
if(newscore % 10 == 0){ //分數每增加10分
speedup(); //遊戲加速
}
}

//判斷玩家點擊事件是否需合規
function judge(ev){
if(state==3){ //上文設定遊戲失敗時state為3,此處判斷遊戲是否已經結束
return;
}
if(ev.target.className.indexOf(‘black‘)==-1){ //如果點擊的元素的屬性名不含black,也就是點中了白塊
fail();
}else{
ev.target.className=‘cell‘; //否則點中了黑塊,重寫屬性名,將其改為白塊
ev.target.parentNode.pass=1;//用js獲取DOM節點對象後,可以增加一個自定義屬性,這裏的pass是自定義的,也就是說:當點中黑塊的時候,黑塊所在的row的pass屬性值是1
score(); //加分
}
}

//創建行row
function crow(){
var con=$(‘container‘);
var row=cdiv(‘row‘); //創建屬性名為row的div
var classes=createSn(); //一個row下面的屬性的數組
for(var i=0; i<4; i++){
row.appendChild(cdiv(classes[i])); //創建4個div添加給row,4個div的屬性名中隨機產生一個cell black,得到一個含有隨機位置黑塊的row
}
if(con.firstChild==null){ //如果con沒有子元素
con.appendChild(row); //那就添加row
}else{
con.insertBefore(row,con.firstChild); //否則將這個row插入到子元素前面
}
}

//刪除最後一行
function drow(){
var con=$(‘container‘);
if(con.childNodes.length==6){
con.removeChild(con.lastChild); //當有6行row時刪除最後一行
}
}

//創建一個div,className是其類名
function cdiv(className){
var div=document.createElement(‘div‘);
div.className=className;
return div;
}

//返回一個數組,隨機其中一個單元,值為‘cell black‘,其余皆為‘cell‘
function createSn(){
var arr=[‘cell‘,‘cell‘,‘cell‘,‘cell‘];
var i=Math.floor(Math.random()*4); //Math.random()隨機產生範圍為[0,1)之間的小數,Math.floor()向下取整,此處為0,1,2,3,
arr[i]=‘cell black‘;
return arr;
}

//按照id獲取對象,取代反復用到的document.getElementById()

function $(id){
return document.getElementById(id);
}

init();
start();

</script>
</body>
</html>

四 知識點整理

1. CSS:

-position:relative:position 屬性規定元素的定位類型。relative:生成相對定位的元素,相對於其正常位置進行定位。
-overflow:hidden:overflow屬性規定當內容溢出元素框時發生的事情。hidden::內容會被修剪,並且其余內容是不可見的。

-float:left:float屬性定義元素在哪個方向浮動。
-display:inline-block:display屬性規定元素應該生成的框的類型,inline-block為行內塊元素。

2. JS:

-window.setInterval(‘move()‘,30);setInterval()方法可按照指定的周期(以毫秒計)來調用函數或計算表達式。setInterval() 方法會不停地調用函數,直到 clearInterval() 被調用或窗口被關閉。
-parseInt(window.getComputedStyle(con,null)[‘top‘]):window.getComputedStyle(element, [pseudoElt])方法給出應用活動樣式表後的元素的所有CSS屬性的值,並解析這些值可能包含的任何基本計算。element用於獲取計算樣式的Element,pseudoElt(可選)指定一個要匹配的偽元素的字符串。必須對普通元素省略(或null)。返回的樣式是一個實時的 CSSStyleDeclaration對象,當元素的樣式更改時,它會自動更新本身。CSSStyleDeclaration表示一個CSS屬性鍵值對的集合。
-con.children:ParentNode.children 是一個只讀屬性,返回 一個Node的子elements,是一個動態更新的 HTMLCollection。
-ev.target.parentNode.pass=1:用js獲取DOM節點對象後,可以增加一個自定義屬性,這裏的pass是自定義的,也就是說:當點中黑塊的時候,黑塊所在的row的pass屬性值是1。
-Math.random():隨機產生範圍為[0,1)之間的小數。
-Math.floor():向下取整。

五 相關資源

剛開始是在實驗樓找的項目,看完之後有的地方不是很明白,百度的時候發現網易雲課堂剛好有現成的課,就跟著老師看完敲了一邊,收獲還是蠻大的,畢竟之前學習方式基本是“光看不練”,這算是第一個完整敲完整理完的項目。

其實這個遊戲還有很大的優化空間,比如實驗樓提出的那幾個問題都挺有價值的,之後如果有空了會嘗試一下吧:)

1. 給這個遊戲增加開始/暫停按鈕;
2. 用JQuery重寫一遍;
3. 最佳分數記錄(可能需要用到H5新增的web存儲)

最後貼一下鏈接:
實驗樓:https://www.shiyanlou.com/courses/306
網易雲課堂:http://study.163.com/course/courseMain.htm?courseId=652005

遊戲——網頁版別踩白塊