js css实现3D打年兽小游戏,老好玩了

js css实现3D打年兽小游戏,老好玩了

首页战争策略新游js更新时间:2024-05-11
前言

快过年,各大游戏中都陆续添加了打年兽的休闲玩法。之前学习了css的3D相关知识,一直想实践一下,这次就使用css加上js实现3D版打年兽小游戏。

效果演示

游戏玩法说明
  1. 完全模拟打地鼠游戏的玩法,将地鼠换成年兽,使用锤子敲击得分。
  2. 每敲钟5次速度提升一次,速度提升100毫秒。
  3. 3次失败后游戏结束。
实现流程设计3D地面

将main层div作为3D容器,ground层div作为地面,通过X,Y坐标旋转调整地面的默认角度`transform: rotateY(30deg) rotateX(60deg);`,同时将ground层设置成3D容器,为后面在地面上添加年兽准备。代码如下。

页面元素:

<div class="main"> <div class="ground"> </div> </div>

样式布局:

.main{ width:400px;height:400px; margin:0px auto; perspective-origin: 50% 200px; perspective: 2000px; transform-style: preserve-3d; backface-visibility: hidden; } .main .ground{ width:100%;height:100%; transform: rotateY(30deg) rotateX(60deg); background: rgb(7, 255, 138); position: relative; perspective-origin: 50% 100px; perspective: 1000px; transform-style: preserve-3d; backface-visibility: hidden; }设计3D相机效果

我们知道3D坐标分为X、Y、Z三个方向,X轴为水平方向,Y轴为竖直方向,Z轴为垂直与屏幕方向。要实现上图中的效果,保持Z轴不变,只改变X、Y轴旋转角度即可。

具体操作逻辑为监听鼠标点击后的移动事件,通过计算当前鼠标位置相对于鼠标刚点击时的位置X、Y轴像素偏移量动态调整、Y轴的旋转角度,代码如下。

document.addEventListener("mousedown",function(e){ click = true; sp = {x:e.clientX,y:e.clientY} }); document.addEventListener("mousemove",function(e){ if(!click){ return; } var ydeg = (deg.y (e.clientX - sp.x)/10); var xdeg = (deg.x - (e.clientY - sp.y)/10); $('.ground').css({transform:'rotateY(' ydeg 'deg) rotateX(' xdeg 'deg)'}) deg = {x:xdeg,y:ydeg}; sp = {x:e.clientX,y:e.clientY} }); document.addEventListener("mouseup",function(e){ click = false; })设计地洞效果

通过白色背景线条在水平和竖直方向将地面分成4X4棋盘,每一片代表一个地洞,代码如下。

var topVal = 100; for (var i = 0; i < 4; i ) { var div = document.createElement("div"); div.style.top = topVal "px"; div.style.left = "0px"; div.style.width = '100%'; div.style.height = '2px'; $('.ground').append(div) topVal = 100; } var leftVal = 100; for (var i = 0; i < 4; i ) { var div = document.createElement("div"); div.style.left = leftVal "px"; div.style.top = "0px"; div.style.width = '2px'; div.style.height = '100%'; $('.ground').append(div) leftVal = 100; }设计年兽

在第一个地洞的位置画一个3D盒子作为年兽身体,长80px,宽30px,高30px,离地面高度为10px,代码如下。

页面元素

<div class="main"> <div class="ground"> <div class="nian body front"></div> <div class="nian body left"></div> <div class="nian body back"></div> <div class="nian body right"></div> <div class="nian body top"></div> <div class="nian body bottom"></div> </div> </div>

style样式

.main .ground > .body{ top:0px; left:35px; background: rgb(243, 253, 255); height: 80px; width: 80px; } .main .ground > .front{ width: 30px; transform: translateZ(40px); } .main .ground > .left{ width:30px; transform: translateZ(40px) rotateY(90deg); transform-origin: left center; } .main .ground > .back{ width: 30px; transform: translateZ(10px) rotateY(180deg); } .main .ground > .right{ width: 30px; transform:translateZ(40px) rotateY(-90deg); transform-origin: right; } .main .ground > .top{ height: 30px; width: 30px; transform: translateZ(40px) rotateX(-90deg); transform-origin: top center; } .main .ground > .bottom{ height: 30px; width: 30px; top:50px; transform: translateZ(40px) rotateX(90deg); transform-origin: bottom center; }

然后一次画出年兽的头部、脚步3D盒子,效果如下,代码见底部完整代码。

设计年兽出现效果

`transVal`对象存储了年兽每个部位的最终tansform变换值,用来提供jQuery展示动画;年兽出现位置随机,通过随机函数生成年兽最终的位置,通过top、left样式属性定位,通过Jquery的animate函数动态调整translateZ的值,形成年兽重地下钻出来的效果。

设置定时器,到期自动执行游戏主体函数,游戏主体函数逻辑在下面的内容介绍。

var transVal = { front:{ translateZ:{val:40,un:'px'} }, left:{ translateZ:{val:40,un:'px'}, rotateY:{val:90,un:'deg'} }, right:{ translateZ:{val:40,un:'px'}, rotateY:{val:-90,un:'deg'} }, back:{ translateZ:{val:10,un:'px'}, rotateY:{val:180,un:'deg'} }, top:{ translateZ:{val:40,un:'px'}, rotateX:{val:-90,un:'deg'} }, bottom:{ translateZ:{val:40,un:'px'}, rotateX:{val:90,un:'deg'} }, 'head-front':{ translateZ:{val:80,un:'px'} }, 'head-left':{ translateZ:{val:80,un:'px'}, rotateY:{val:90,un:'deg'} }, 'head-right':{ translateZ:{val:80,un:'px'}, rotateY:{val:-90,un:'deg'} }, 'head-back':{ translateZ:{val:41,un:'px'}, rotateY:{val:180,un:'deg'} }, 'head-top':{ translateZ:{val:80,un:'px'}, rotateX:{val:-90,un:'deg'} }, 'head-bottom':{ translateZ:{val:65,un:'px'}, rotateX:{val:-90,un:'deg'} }, 'foot-front':{ translateZ:{val:10,un:'px'} }, 'foot-left':{ translateZ:{val:10,un:'px'}, rotateY:{val:90,un:'deg'} }, 'foot-right':{ translateZ:{val:10,un:'px'}, rotateY:{val:-90,un:'deg'} }, 'foot-back':{ translateZ:{val:0,un:'px'}, rotateY:{val:180,un:'deg'} }, 'foot-top':{ translateZ:{val:10,un:'px'}, rotateX:{val:-90,un:'deg'} }, 'foot-bottom':{ translateZ:{val:10,un:'px'}, rotateX:{val:90,un:'deg'} } } function showNianshou() { $('.nian').show() if(!start){ return; } var topNum = parseInt(Math.random()*4) var leftNum = parseInt(Math.random()*4) $('.body').css({top:topNum*100 'px',left:leftNum*100 35 'px'}) $('.head').css({top:topNum*100 60 'px',left:leftNum*100 30 'px'}) $('.head-bottom').css({top:topNum*100 60 'px',left:leftNum*100 27 'px'}) $('.foot1').css({top:topNum*100 'px',left:leftNum*100 35 'px'}) $('.foot2').css({top:topNum*100 'px',left:leftNum*100 55 'px'}) $('.foot3').css({top:topNum*100 75 'px',left:leftNum*100 35 'px'}) $('.foot4').css({top:topNum*100 75 'px',left:leftNum*100 55 'px'}) $('.nian').animate({opacity:1},{ step:function(now,fix){ var obj = transVal[$(this).attr('class').split(' ')[2]] if(obj){ var s = ' ' for (var v in obj){ if(v.indexOf('translate') >= 0){ s = v '(' (obj[v].val - 80 now * 80) obj[v].un ') ' }else{ s = v '(' obj[v].val obj[v].un ') ' } } $(this).css({transform:s}) } }, duration:timer },'linear') setTimeout(function(){ hiding = false setTimeout(function(){clickFun(undefined,true)},timer) },timer) }设计年兽消失效果

同上通过Jquery的animate函数动态调整translateZ的值,形成年兽钻回地下果,代码如下。

function hideNianshou(){ $('.nian').animate({opacity:0},{ step:function(now,fix){ var obj = transVal[$(this).attr('class').split(' ')[2]] if(obj){ var s = ' ' for (var v in obj){ if(v.indexOf('translate') >= 0){ s = v '(' (obj[v].val - 80 now * 80) obj[v].un ') ' }else{ s = v '(' obj[v].val obj[v].un ') ' } } $(this).css({transform:s}) } }, duration:timer },'linear'); }设计年兽打中效果

同上通过Jquery的animate函数动态调整translateZ的值,形成年兽被打死的效果,码如下。

function deadNianshou(){ $('.nian').animate({opacity:0},{ step:function(now,fix){ $(this).css({transform:'translateZ(' now * 40 'px)'}) }, duration:timer },'linear'); }设计打击效果

锤子素材

页面中添加锤子元素,同时给main层添加鼠标移动监听,调整锤子的位置使其跟随鼠标的光标移动。

<img id="chui" src="${rc.contextPath}/static/image/chuizi.png" width="50" style="position: absolute;">

在移动锤子的位置时判断锤子是否正在执行打击动画,正在执行时锤子的位置不变,动画执行完,再次跟随鼠标光标移动。

$('.main')[0].addEventListener('mousemove',function(e){ if(!hiting){ $('#chui').css({left:e.clientX-5 'px',top:e.clientY - 55'px'}) } })

给ground层添加点击时间监听,执行锤子的打击动画

$('.ground')[0].addEventListener('click',function(e){ $('#chui').addClass("hit"); hiting = true setTimeout(function(){ hiting = false $('#chui').removeClass("hit'); },300) })

打击动画通过`keyframes `实现。

.hit{ animation: hit ease 0.3s; } @keyframes hit { 0%{ transform: rotate(0deg) ; } 80%{ transform: rotate(30deg) translateX(50px) translateY(-100px); } 100%{ transform: rotate(0deg); } }游戏主体函数设计

给年兽添加点击事件,当年兽被点击后执行游戏主体函数。

$('.nian').on('click',clickFun);

游戏主题函数两个参数,第一个为点击时间Event,第二个参数为是否自动执行自动则为true手动点击为undefinded.

通过hiding值防止主体函数并发执行导致游戏画面不可控。

主体函数被自动执行则说明,点击得慢了,此时执行年兽消失函数,执行点击失败后逻辑,重新执行年兽出现函数。

主体函数因年兽被点击后执行,则说明打到了年兽,此时计算成功次数并判断是否提升游戏速度,每成功击中5次提升一次速度,重新执行年兽出现函数。

function clickFun(e,auto){ if(e){ e.stopPropagation(); } if(hiding){ return; } hiding = true if(auto){ hideNianshou() setTimeout(function(){ dealAfterFail(); showNianshou() },timer) }else{ $('#chui').addClass("hit"); hiting = true setTimeout(function(){ hiting = false $('#chui').removeClass("hit"); sucTimes if(sucTimes%5==0){ showMsg('速度加快了') timer -= 100 } if(timer < 400){ timer = 400 } deadNianshou(); setTimeout(function(){ showMsg('成功打到' sucTimes '只年兽') showNianshou() },timer) },300) } }设计打击年兽失败后函数

累加失败次数,当失败次数达到3时,游戏结束,弹出游戏结束消息。

function dealAfterFail(){ failTimes if(failTimes == 3){ showMsg('GAME OVER,成功打到' sucTimes '只年兽'); start = false } } 游戏弹出消息设计

页面添加div设置其位于页面右上角,默认隐藏,提供`showMsg`函数动态修改div文字内容,2秒后自动消失。

<div class="msg">速度加快了</div>

.msg{ display: none; width:300px; height:50px; line-height: 50px; text-align: center; color: #CC2222; position: absolute; right: 10px; top:10px; background: rgba(255,255,255,.8); border-radius: 5px; } .msg:after{ content: ' '; clear: both; }

function showMsg(msg){ $('.msg').html(msg); $('.msg').show(); setTimeout(function(){$('.msg').hide();},2000) } 设计开始菜单

页面添加列表元素,添加点击时间。

<ul class="hover"> <li onclick="reStart()">开始</li> </ul>

ul{ display: block; position: absolute; top:10px; left:10px; width: 200px; background: rgba(255,255,255,.3); } li{ display: block; list-style: none; width:100px; height: 30px; text-align: center; line-height: 30px; color: #fff; background: rgba(255,0,0,.7); border-radius: 2px; margin:10px auto; cursor: pointer; } li:hover{ background: rgba(255,0,0,1); transform: scale(1.1); }

年兽默认隐藏。

$('.nian').hide()

点击开始后,重置游戏参数,执行年兽消失函数,执行年兽出现函数。

function reStart(){ start = true sucTimes = 0 failTimes = 0 timer = 800 hideNianshou() setTimeout(showNianshou,timer) }完整代码

3D兽小游戏源码:https://gitee.com/tech-famer/farmer-game-nianshou

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved