网上无聊看到一个类似飞镖的游戏,就想到动手做一个2d的版本.后续看看3d的版本如何实现
html文件
<!DOCTYPE html>
<html>
<head>
<title>飞镖游戏</title>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<style type="text/css"></style>
<link rel="stylesheet" type="text/css" href="feibiao-game.css">
</head>
<body>
<figure>
<div class="circle" id="circle">
</div>
<div class="arrow" id="arrow">
</div>
<div class="buttonBar">
<div class="shoot" id="shoot">Begin</div>
</div>
<div class="arrow-bag" id="arrow-bag">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
<img src="arrow.png">
</div>
</figure>
<script type="text/javascript" src="feibiao-game.js"></script>
</body>
</html>复制代码
css文件
* {
margin: 0;
padding: 0;
}
figure {
width: 600px;
height: 600px;
margin: auto;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.circle {
width: 200px;
height: 200px;
margin: 50px auto;
border-radius: 50%;
background-image: url(target.jpg);
background-repeat:no-repeat;
background-size:100% 100%;
position: absolute;
left: 50%;
transform: translate(-50%);
transform-origin: 50% 50%;
}
.embed-arrow {
width: 20px;
height: 50px;
text-align: center;
position: absolute;
margin: 0 auto;
transform-origin: 0px 130px ;
left: 50%;
top: -30px;
}
.embed-arrow img {
width: 60px;
height: 50px;
transform: rotate(-117deg);
}
.arrow-bag {
color: purple;
position: absolute;
width: 120px;
height: 300px;
bottom: 10px;
left: 20%;
font-weight: bold;
font-size: 0;
}
.arrow-bag img {
width: 60px;
height: 50px;
transform: rotate(50deg);
}
.arrow {
position: absolute;
bottom: 150px;
left: 50%;
transform: translate(-50%);
}
@keyframes shoot {
0% {
bottom: 150px;
}
100% {
bottom: 300px;
}
}
.arrow img {
width: 60px;
height: 50px;
transform: rotate(50deg);
}
.shoot {
position: absolute;
width: 100px;
height: 100px;
bottom: 40px;
left: 50%;
transform: translate(-50%);
background-color: blue;
color: #fff;
font-weight: bold;
font-size: 24px;
text-align: center;
line-height: 100px;
border-radius: 50%;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
.shoot:hover {
box-shadow: 0 0 20px blue, 0 0 30px purple;
}
@keyframes circle-run {
0% {
transform: translate(-50%) rotate(0deg);
}
100% {
transform: translate(-50%) rotate(360deg);
}
}
复制代码
js文件
let docCircle = document.getElementById('circle');
let arrow = document.getElementById('arrow');
let shoot = document.getElementById('shoot');
let arrowBag = document.getElementById('arrow-bag');
let beginDeg = 180; //因从180度开始射箭
let targetArrow = []; //已经射中的角度
let target = false; //是否命中目标
let remainArrowNum = 10; //初始10只箭
let body = document.body || document.documentElement;
let style = body.style;
let animationEndName = (function() {
let animEndEventNames = {
WebkitAnimation: 'webkitAnimationEnd',
animation: 'animationend'
};
for (var name in animEndEventNames) {
if (typeof style[name] === "string") {
return animEndEventNames[name]
}
}
})();
let arrowImgUrl = 'arrow.png';
let gameStartTime = 0;
//事件绑定
let addHandler = function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element["e" + type] = function() {
handler.call(element)
};
element.attachEvent("on" + type, element["e" + type]);
} else {
element["on" + type] = handler;
}
};
//事件解绑
let removeHandler = function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, element["e" + type]);
element["e" + type] = null;
} else {
element["on" + type] = null;
}
};
//发射按钮绑定事件
let shootFunc = function() {
arrow.style.animation = "shoot 0.1s linear 1"
};
//开始按钮时间
let beginFunc = function() {
//剩余飞镖
remainArrowNum--;
//箭袋减少一根箭
arrowBag.removeChild(arrowBag.firstElementChild);
//装备一只箭
let arrowImg = document.createElement('img');
arrowImg.src = arrowImgUrl;
arrow.appendChild(arrowImg);
//修改按钮名称
shoot.innerHTML = 'Arrow';
//解绑按钮开始事件
removeHandler(shoot, 'click', beginFunc);
//绑定射击新事件
addHandler(shoot, 'click', shootFunc);
//飞镖盘一直转
docCircle.style.animation = 'circle-run 3.6s linear infinite';
//游戏开始时间
gameStartTime = new Date().getTime();
};
//重新开始事件
let reStartFunc = function() {
targetArrow = []; //已经射中的角度
target = false; //是否命中目标
remainArrowNum = 10; //初始10只箭
//修改按钮名称
shoot.innerHTML = 'Begin';
//解绑按钮重新开始事件
removeHandler(shoot, 'click', reStartFunc);
//绑定开始事件
addHandler(shoot, 'click', beginFunc);
//箭袋放入10只箭
for (let i = 0; i < remainArrowNum; i++) {
let arrowImg = document.createElement('img');
arrowImg.src = arrowImgUrl;
arrowBag.appendChild(arrowImg);
}
//清除转盘上的箭
docCircle.innerHTML = '';
//飞盘停止转动
docCircle.style.animation = '';
};
//绑定开始按钮新事件
addHandler(shoot, 'click', beginFunc);
function isTarget(currentCircleDeg) {
target = targetArrow.every(
function(val, index, arr) {
if (currentCircleDeg > val - 10 && currentCircleDeg < val + 10) {
return false;
} else {
return true;
}
}
);
if (targetArrow.length <= 0) {
target = true;
}
}
function targetFunc(currentCircleDeg) {
let newArrow = document.createElement('div');
let arrowImg = document.createElement('img');
arrowImg.src = arrowImgUrl;
newArrow.appendChild(arrowImg);
newArrow.className = 'embed-arrow';
newArrow.style.transform = 'rotate(' + (beginDeg - currentCircleDeg) + 'deg) translate(-50%)';
docCircle.appendChild(newArrow);
targetArrow.push(currentCircleDeg);
}
//飞镖射到飞镖盘结束事件
addHandler(arrow, animationEndName, function() { //动画结束时事件
arrow.style.animation = "";
//转盘旋转时间ms
let time = new Date().getTime() - gameStartTime + 100;
let gameTime = time % 3600;
let currentCircleDeg = gameTime * 0.1;
isTarget(currentCircleDeg);
//发射之后箭袋及按钮样式处理
calRemainArrowNum();
if (!target) {
target = false;
return;
} else {
//命中目标样式处理
targetFunc(currentCircleDeg);
}
}, false);
let calRemainArrowNum = function() {
//剩余飞镖
remainArrowNum--;
//解绑发射按钮
if (remainArrowNum < 0) {
//解绑按钮射击事件
removeHandler(shoot, 'click', shootFunc);
//最后一支箭消失
arrow.removeChild(arrow.firstElementChild);
//修改按钮名称
shoot.innerHTML = 'ReStart';
//绑定按钮开始事件
addHandler(shoot, 'click', reStartFunc);
} else {
arrowBag.removeChild(arrowBag.firstElementChild);
}
};复制代码
js文件中事件绑定的方法是从网上寻找的资源. 为了实战下js源码写功能.所以未使用jq等等插件.兼容性测试了chrome(最新版 70.0.3538.77) ,safari(最新版 ),ie10, ie11
效果图
图片资源是从其他素材网站copy的,感谢!如果涉及版权,请联系会及时删除