原生JavaScript實現彈球遊戲
阿新 • • 發佈:2018-12-30
開始後的html遊戲介面
開始後可按滑鼠左右鍵移動
擋板,當球擊中磚塊後,磚塊裡面可能藏有魔法棒,當掉落黃色魔法棒時擋板會變短,當掉落綠色魔法棒時擋板會變長。
html頁面佈局,即index.html檔案原始碼如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>彈球遊戲</title> <link rel="stylesheet" type="text/css" href="css/index.css"/> </head> <body> <center> <div id="gamePanel" tabindex="0"> <div class="score">分數: <span id="score">0</span> </div> <div id="startBtn" onclick="Start()"></div> </div> </center> <script type="text/javascript" src="js/magic.js"></script> <script type="text/javascript" src="js/brick.js"></script> <script type="text/javascript" src="js/ball.js"></script> <script type="text/javascript" src="js/stick.js"></script> <script type="text/javascript" src="js/game.js"></script> </body> </html>
index.css檔案原始碼如下:
#gamePanel{ width:504px; height:504px; background:Black; position:relative; } #gamePanel .score{ font-size:20px; color:White; position:absolute; left:0; top:0; z-index:9999; } #gamePanel .bullet{ width:5px; height:15px; position:absolute; background:url(../img/bullet.png); overflow:hidden; } #gamePanel .stick{ width:80px; height:18px; position:absolute; background:blue; } #gamePanel .ball{ width:15px; height:15px; position:absolute; background:url(../img/ball.gif); } #gamePanel .brick { width : 28px; height : 28px; position : relative; background : url(../img/brick.gif); float : left; } #gamePanel .hideBrick { width : 28px; height : 28px; position : relative; background : black; float : left; } #gamePanel .magic { width : 27px; height : 11px; position : absolute; background : green; } #gamePanel .shortMagic { width : 28px; height : 12px; position : absolute; background : yellow; } #gamePanel .bingo{ width:18px; height:18px; position:absolute; background:url(../img/bingo2.png); } #startBtn{ border-width:20px; border-style:solid; border-color:Black Black Black Green; position:absolute; left:240px; top:240px; cursor:pointer; width:0px; height:0px; overflow:hidden; }
JavaScript部分分為5個原始檔,即ball.js(球類)、brick.js(磚類)、game.js(遊戲類)、magic.js(魔法棒類)、stick.js(擋板類)
球類程式碼實現如下:
// 球類 var Ball = function() { // 彈球dom元素 this.dom = null; // 是否啟用 this.isFirst = true; // 彈球移動方向 this.direction = null; this.init(); } Ball.prototype = { // 彈球橫向移動速度 movepx : 3, // 彈球縱向移動速度 movepy : 2, // 彈球移動頻率 movesp : 20, // 彈球移動頻率對映 movespMap : { 1 : 75, 2 : 65, 3 : 50, 4 : 40 }, // 初始化 init : function() { this.dom = document.createElement("div"); this.dom.className = "ball"; }, // 設定彈球的初始化位置,x與y座標 setPosition : function(x, y) { this.dom.style.left = x + "px"; this.dom.style.top = y + "px"; }, // 彈球動畫,就是移動,傳入引數為遊戲背景的寬與高 animation : function(gameWidth, gameHeight, stick) { var _this = this; // 實際的橫向移動速度,左或者右 var _movepx = this.dom.offsetLeft > gameWidth/2 ? -1*this.movepx : this.movepx; var _movepy = this.dom.offsetTop > gameHeight/2 ? this.movepy : -1*this.movepy; // 處理移動函式 var process = function() { // 彈球的x,y座標 var left = _this.dom.offsetLeft; var top = _this.dom.offsetTop; // 是否要調轉方向 if (left <= 0 || left >= gameWidth - _this.dom.clientWidth) { _movepx *= -1; } var isCrashStick = _this.OnCheckCrashStick(); var isCrashBall = _this.OnCheckCrashBrick(); // 判斷是否想上調轉方向 if (top < 0 || isCrashStick || isCrashBall) { _movepy *= -1; } // 向下移動 top = top + _movepy; left = left + _movepx; // 設定彈球位置 _this.dom.style.top = top + "px"; _this.dom.style.left = left + "px"; if(top > gameHeight) { _this.onend(); alert("You Lose"); } else { setTimeout(process, _this.movesp); } // 判斷彈球移動方向 if (_movepx > 0 && _movepy < 0) { _this.direction = "RightUp"; return; } if (_movepx > 0 && _movepy > 0) { _this.direction = "RightDown"; return; } if (_movepx < 0 && _movepy < 0) { _this.direction = "LeftUp"; return; } if (_movepx < 0 && _movepy > 0) { _this.direction = "LeftDown"; return; } }; // 開始移動 process(); }, // 外部介面,檢測是否撞到魔法棒 OnCheckCrashStick : function() {}, // 外部介面,檢測是否撞到磚塊 OnCheckCrashBrick : function() {}, // 彈球結束事件 onend : function() {}, // 遊戲結束 gameover : function() {} }
磚類程式碼如下brick.js原始檔:
// 磚類
var Brick = function(gamePanel) {
// 磚的dom元素
this.dom = null;
// 磚塊所在的畫布
this.gamePanel = gamePanel;
// 是否啟用
this.isLive = true;
// 是否帶有魔法棒
this.magic = null;
this.width = 28;
this.height = 28;
this.left = 0;
this.top = 0;
this.init();
}
Brick.prototype = {
// 初始化
init : function() {
this.dom = document.createElement("div");
this.dom.className = "brick";
},
// 為position: relative的Brick初始化位置
setPosition : function(x, y) {
this.left = x;
this.top = y;
},
// 為positon : relative的Brick初始化尺寸
setSize : function(width, height) {
this.width = width;
this.height = height;
},
// 初始化生成魔法棒
initMagic : function() {
var _this = this;
// 隨機數
var random = parseInt(Math.random()*1000 + 1, 10);
var type = random % 5 == 0 ? "good" : random % 4 == 0 ? "bad" : "none";
// 新建一個魔法棒物件
var magic = new Magic(type);
this.magic = magic;
magic.initPosition(this);
// 將魔法棒新增進磚塊中
this.gamePanel.appendChild(magic.dom);
magic.onEnd = function() {
_this.gamePanel.removeChild(magic.dom);
};
magic.animation(this.gamePanel.clientHeight);
},
// 擊中後的動作
onEnd : function() {
this.isLive = false;
this.dom.className = "hideBrick";
this.initMagic();
}
}
魔法棒類程式碼即magic.js原始檔實現如下:
// 魔法棒類
var Magic = function(type) {
// Magic的dom元素
this.dom = null;
// Magic的dom資訊
this.left = 0;
this.top = 0;
this.width = 0;
this.height = 0;
this.type = type;
this.init();
}
Magic.prototype = {
// 魔法棒型別
magicType : {
"good" : "magic",
"bad" : "shortMagic",
"none" : ""
},
// 每次移動位移
movepy : 3,
// 移動速度
movespeed : 20,
// 初始化魔法棒
init : function() {
this.dom = document.createElement("div");
this.dom.className = this.magicType[this.type];
//this.dom.style.display = "none";
this.width = parseInt(this.dom.style.width, 10);
this.height = parseInt(this.dom.style.height, 10);
},
// 魔法棒初始化位置
initPosition : function(brick) {
this.left = brick.left;
this.top = brick.top;
this.dom.style.left = this.left + "px";
this.dom.style.top = this.top + "px";
},
// 更新位置
update : function() {
this.dom.style.left = this.left + "px";
this.dom.style.top = this.top + "px";
},
// 魔法棒動畫,height為遊戲背景高度
animation : function(height) {
if (this.type == "none") {
return;
}
var _this = this;
// 向下移動函式
var downMove = function() {
_this.top = _this.top + _this.movepy;
_this.update();
// 判斷魔法棒下移是否越界,是否擊中stick
if (_this.top < height && !_this.isBeatStick()) {
setTimeout(downMove, _this.movespeed);
} else {
// 動畫結束觸發事件
_this.onEnd();
}
};
downMove();
},
// 動畫結束觸發事件,外部覆蓋
onEnd : function() {},
// 魔法棒是否擊中擋板以及擊中後處理事件,外部覆蓋
isBeatStick : function() {}
}
擋板類程式碼即stick.js原始檔如下:
// 新建棒類
var Stick = function() {
// 飛機對應的dom元素
this.dom = null;
// 是否移動中
this.isMove = false;
// 移動的ID
this.moveId = null;
// 是否彈球中
this.isSend = false;
// 變大標記
this.bigCount = 0;
// 變小標記
this.smallCount = 0;
// 接棒的寬度變大變小時做儲存
this.width = 0;
this.init();
}
Stick.prototype = {
// 遊戲背景Dom
gamePanel : null,
// 遊戲背景寬度
gameWidth : 0,
// 遊戲背景高度
gameHeight : 0,
// 魔法棒移動速度
movepx : 10,
// 魔法棒移動頻率
movesp : 30,
// 方向鍵值對應
keyCodeAndDirection : {
37 : "left",
39 : "right"
},
// 初始化
init : function() {
this.dom = document.createElement("div");
this.dom.className = "stick";
},
// 設定位置
setPosition : function(gamePanel, width, height) {
// 將魔法棒新增進遊戲背景中
this.gamePanel = gamePanel;
this.gamePanel.appendChild(this.dom);
// 設定飛機的初始位置
this.dom.style.left = (width - this.dom.clientWidth)/2 + "px";
this.dom.style.top = height - this.dom.clientHeight + "px";
// 獲取到遊戲背景的寬和高
this.gameWidth = width;
this.gameHeight = height;
},
// 鍵盤按下事件
keydown : function(e) {
var keyCode = e.keyCode;
if (!this.isMove) {
this.move(keyCode);
}
},
// 鍵盤釋放事件
keyup : function(e) {
// 判斷是否為鍵盤釋放
if (this.keyCodeAndDirection[e.keyCode]) {
// 停止移動
this.stopMove();
} else if (e.keyCode == 32) {
// 設定為非發彈中
this.isSend = false;
}
},
// 移動
move : function(keyCode) {
// 設定為移動中
this.isMove = true;
var _this = this;
// 判斷移動方向
switch(this.keyCodeAndDirection[keyCode]) {
case "left" : {
this.moveId = setInterval(function() {_this.moveLeft();}, _this.movesp);
break;
}
case "right" : {
this.moveId = setInterval(function() {_this.moveRight();}, _this.movesp);
break;
}
default : break;
}
},
// 向左移動
moveLeft : function() {
var left = this.dom["offsetLeft"];
left = left - this.movepx >= 0 ? left - this.movepx : 0;
this.dom.style["left"] = left + "px";
if (left == 0) {
this.stopMove();
}
},
// 向右移動
moveRight : function() {
var left = this.dom["offsetLeft"];
var maxDistance = this.gameWidth - this.dom.clientWidth;
left = left + this.movepx <= maxDistance ? left + this.movepx: maxDistance;
this.dom.style["left"] = left + "px";
if (left == maxDistance) {
this.stopMove();
}
},
// 變小
changeSmall : function() {
if (this.smallCount >= 1) {
return;
} else {
this.dom.style.width = 80 + "px";
this.smallCount ++;
this.bigCount >= 1 ? this.bigCount -- : this.bigCount + 0;
}
this.dom.style.left = parseInt(this.dom.style.left, 10) + 20 + "px";
this.dom.style.width = 40 + "px";
},
// 變大
changeBig : function() {
if (this.bigCount >= 1) {
return;
} else {
this.dom.style.width = 80 + "px";
this.bigCount ++;
this.smallCount >= 1 ? this.smallCount -- : this.smallCount + 0;
}
if (parseInt(this.dom.style.left, 10) <= 75 ) {
this.dom.style.width = parseInt(this.dom.style.width, 10) + 75 + parseInt(this.dom.style.left, 10)+ "px";
this.dom.style.left = 0 + "px";
return;
} else if (this.dom.style.width + 150 + parseInt(this.dom.style.left, 10) >= this.gamePanel.clientWidth) {
this.dom.style.left = parseInt(this.dom.style.left, 10) - 150 + "px";
this.dom.style.width = this.dom.style.width + 150 + "px";
return;
} else {
this.dom.style.left = parseInt(this.dom.style.left, 10) - 75 + "px";
this.dom.style.width = 150 + "px";
}
},
// 停止移動
stopMove : function() {
this.isMove = false;
clearInterval(this.moveId);
},
// 發射彈球,外部介面,
onSendBall : function() {},
// 改分數外部介面
onChangeScore : function() {}
}
部分難點技術實現
通過鍵盤左右方向鍵移動擋板的程式碼實現:
// 鍵盤按下事件
keydown : function(e) {
var keyCode = e.keyCode;
if (!this.isMove) {
this.move(keyCode);
}
},
// 鍵盤釋放事件
keyup : function(e) {
// 判斷是否為鍵盤釋放
if (this.keyCodeAndDirection[e.keyCode]) {
// 停止移動
this.stopMove();
} else if (e.keyCode == 32) {
// 設定為非發彈中
this.isSend = false;
}
},
// 移動
move : function(keyCode) {
// 設定為移動中
this.isMove = true;
var _this = this;
// 判斷移動方向
switch(this.keyCodeAndDirection[keyCode]) {
case "left" : {
this.moveId = setInterval(function() {_this.moveLeft();}, _this.movesp);
break;
}
case "right" : {
this.moveId = setInterval(function() {_this.moveRight();}, _this.movesp);
break;
}
default : break;
}
},
// 向左移動
moveLeft : function() {
var left = this.dom["offsetLeft"];
left = left - this.movepx >= 0 ? left - this.movepx : 0;
this.dom.style["left"] = left + "px";
if (left == 0) {
this.stopMove();
}
},
// 向右移動
moveRight : function() {
var left = this.dom["offsetLeft"];
var maxDistance = this.gameWidth - this.dom.clientWidth;
left = left + this.movepx <= maxDistance ? left + this.movepx: maxDistance;
this.dom.style["left"] = left + "px";
if (left == maxDistance) {
this.stopMove();
}
},