钟摆小游戏的开发过程

框架

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>钟摆游戏</title>
    <style>
        * {
			box-sizing: border-box;
			margin: 0;
		}
        /* game盒子 采用 相对布局 ,便于后续添加 绝对定位的item*/
        .game {
			position: relative;
			height: 500px;
			width: 500px;
		}
        
        /* 分数 绝对布局,在 正中间 */
        .score {
			position: absolute;
			left: 250px;
			top: 250px;
			transform: translate(-50%, -50%);
		}
    </style>
</head>
<body>
    <div class="score">分数:<label id="val">0</label></div>
	<div class="game"></div>
</body>
</html>

 整个游戏我们都放在500 * 500 的区域中进行。 所以我们使用了 box-sizing属性,具体用法可见 盒子模型中box-sizing: border-box;的作用_Eric加油学!的博客-CSDN博客

得分圈和钟摆

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>钟摆游戏</title>
    <style>
        * {
			box-sizing: border-box;
			margin: 0;
		}
        /* game盒子 采用 相对布局 ,便于后续添加 绝对定位的item*/
        .game {
			position: relative;
			height: 500px;
			width: 500px;
		}
        .item {
			display: flex;
			justify-content: center;
			align-items: center;
			background-color: cadetblue;
			border-radius: 100%;
			color: #fff;
			width: 85px;
			height: 85px;
			border: 1px solid rgb(55, 101, 103);
			position: absolute;
			left: 50%;
			top: 50%;
			margin: -40px 0 0 -40px;
		}
        .item-name {
			position: relative;
			z-index: 1;
		}
        /* 摆锤动画 */
        .tool {
			animation: run 2s linear infinite;
		}
		@keyframes run {
			0% {
				transform:rotate(0deg);
			}
			100% {
				transform:rotate(360deg);
			}
		}
        .paused {
			animation-play-state: paused;
		}
		.tool,.tool-circle {
			position: absolute;
			width: 60px;
			height: 60px;
			left: 50%;
			top: 50%;
			margin: -30px 0 0 -30px;
			background-color: rgb(117, 68, 68);
			border-radius: 100%;
		}
		.tool:after {
			content: '';
			position: absolute;
			height: 100px;
			width: 10px;
			background-color: rgb(117, 68, 68);
			left: 50%;
			margin-left: -5px;
			bottom: 30px;
		}
		.tool-circle {
			top: -78px;
			display: flex;
			justify-content: center;
			align-items: center;
		}
        /* 分数 绝对布局,在 正中间 */
        .score {
			position: absolute;
			left: 250px;
			top: 250px;
			transform: translate(-50%, -50%);
		}
    </style>
</head>
<body>
    <div class="score">分数:<label id="val">0</label></div>
	<div class="game"></div>
</body>
<script>
    const game = document.querySelector('.game')
    const score = document.querySelector('#val')
    // 定义一圈设置9个得分点
    const max = 9
    let index = 0
    const data = Array.from(new Array(max)).map((v, i) => {
        // 均分角度
        const deg = i * 360 / max;
        return `<div class="item" style="transform: rotate(${deg}deg) translate(160px);z-index:${i === index ? '10' : ''}">
			<span class="item-name"></span>
			${i === index ? `<div class="tool">
				<div class="tool-circle"><span id="curr"></span></div>	
			</div>`:''}
		</div>`
    })
    game.innerHTML = data.join('')
</script>
</html>

 

 首先获取到相应的元素,并设置一共9个得分圈,从正右边开始(0号),index从0起。

const data = Array.from(new Array(max)).map((v, i) => {
        // 均分角度
        const deg = i * 360 / max;
        return `<div class="item" style="transform: rotate(${deg}deg) translate(160px);z-index:${i === index ? '10' : ''}">
			<span class="item-name"></span>
			${i === index ? `<div class="tool">
				<div class="tool-circle"><span id="curr"></span></div>	
			</div>`:''}
		</div>`
    })
game.innerHTML = data.join('')

这段代码,就是利用JS添加这9个item得分圈。 并计算旋转角度,设置平移距离160px;

然后如果当前索引上有钟摆,我们添加钟摆,并为其设置动画。

tool 就是 得分圈上的钟摆座, tool-circle就是正在旋转的钟摆,我们利用 .tool:after 为其添加中间的杆  tool-name和curr分别是得分圈和钟摆的中心点

这里其实是用拼接innerHTML属性的字符串,各个字符串追加game里面,最后调用数组的join方法生成目标字符串 。 这种方法其实效率更高,但是可读性并不是很强。

也有最简单的方法,就是将元素先写好,然后再设置属性

<div class="game">
		<div class="item">1</div>
		<div class="item">2</div>
		<div class="item">3</div>
		<div class="item">4</div>
		<div class="item">5</div>
		<div class="item">6</div>
		<div class="item">7</div>
		<div class="item">8</div>
		<div class="item">9</div>
</div>
    const game = document.querySelector('.game')
	const item = game.getElementsByClassName("item")
    const score = document.querySelector('#val')
    // 定义一圈设置9个得分点
    const max = 9
    let index = 0
    const data = Array.from(new Array(max)).map((v, i) => {
        // 均分角度
        const deg = i * 360 / max;
		item[i].style.webkitTransform = "rotate(" + deg + "deg)" + " translate(160px)";
    })

这里用JS设置transform属性,常用的setAttribute不起作用,可以使用:

element.style.webkitTransform = "40deg"

这种方法,看上去很清楚明了,但是效率最慢 

动态得分规则

当我们点击屏幕的时候,暂停动画,计算 当前摆锤的中心点位置 和 目标得分圈的中心点位置,由二者差值得出 是否成功得分。如果得分,将摆锤底座 添加至 下一个得分圈,重新开始动画,否则游戏结束。

document.onclick = () => {
        const tool = game.querySelector('.tool')
        // 动画暂停
        tool.classList.add('paused')
        // 计算下一个点
        const nextIndex = index === max - 1 ? 0 : index + 1
        const list = game.children
        // 当前摆锤的位置,获得其中心点位置
        const currRect = document.getElementById('curr').getBoundingClientRect()
        // 找到下一个得分圈的中心点
        const moveEl = list[nextIndex].querySelector('.item-name')
        // 下一个得分圈中心点位置信息
        const moveRect = moveEl.getBoundingClientRect()

        // 计算两者之间差值 (得分圈和钟摆大小差值为25)
        if(Math.abs(currRect.left - moveRect.left) < 15 && Math.abs(currRect.top - moveRect.top) < 15){
            // 摆锤 停的位置 是正确的
            // 将摆锤底座 添加到 下一个得分圈上
            list[nextIndex].appendChild(tool)
            // 移除 暂停状态
			tool.classList.remove('paused')
            // 清空当前状态的index,并将下一个得分圈的index设为10
			list[index].style.zIndex = ''
			list[nextIndex].style.zIndex = '10'
			if (index === max - 1) {
				index = 0
			} else {
				index++
			}
            // 得分+1
			score.innerHTML = parseInt(score.innerHTML) + 1
        } else if (score.innerHTML.indexOf(',') ===  - 1) {
			score.innerHTML += ',游戏结束'
		}
    }

调整游戏难度

如果想要调整游戏的难度,可以 设置 钟摆旋转动画的快慢,或者判定得分的差值大小。

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>钟摆游戏</title>
    <style>
        * {
			box-sizing: border-box;
			margin: 0;
		}
        /* game盒子 采用 相对布局 ,便于后续添加 绝对定位的item*/
        .game {
			position: relative;
			height: 500px;
			width: 500px;
		}
        .item {
			display: flex;
			justify-content: center;
			align-items: center;
			background-color: cadetblue;
			border-radius: 100%;
			color: #fff;
			width: 85px;
			height: 85px;
			border: 1px solid rgb(55, 101, 103);
			position: absolute;
			left: 50%;
			top: 50%;
			margin: -40px 0 0 -40px;
		}
        .item-name {
			position: relative;
			z-index: 1;
		}
        /* 摆锤动画 */
        .tool {
			animation: run 3s linear infinite;
		}
		@keyframes run {
			0% {
				transform:rotate(0deg);
			}
			100% {
				transform:rotate(360deg);
			}
		}
        .paused {
			animation-play-state: paused;
		}
		.tool,.tool-circle {
			position: absolute;
			width: 60px;
			height: 60px;
			left: 50%;
			top: 50%;
			margin: -30px 0 0 -30px;
			background-color: rgb(117, 68, 68);
			border-radius: 100%;
		}
		.tool:after {
			content: '';
			position: absolute;
			height: 100px;
			width: 10px;
			background-color: rgb(117, 68, 68);
			left: 50%;
			margin-left: -5px;
			bottom: 30px;
		}
		.tool-circle {
			top: -78px;
			display: flex;
			justify-content: center;
			align-items: center;
		}
        /* 分数 绝对布局,在 正中间 */
        .score {
			position: absolute;
			left: 250px;
			top: 250px;
			transform: translate(-50%, -50%);
		}
    </style>
</head>
<body>
    <div class="score">分数:<label id="val">0</label></div>
	<div class="game"></div>
</body>
<script>
    const game = document.querySelector('.game')
    const score = document.querySelector('#val')
    // 定义一圈设置9个得分点
    const max = 9
    let index = 0
    const data = Array.from(new Array(max)).map((v, i) => {
        // 均分角度
        const deg = i * 360 / max;
        return `<div class="item" style="transform: rotate(${deg}deg) translate(160px);z-index:${i === index ? '10' : ''}">
			<span class="item-name"></span>
			${i === index ? `<div class="tool">
				<div class="tool-circle"><span id="curr"></span></div>	
			</div>`:''}
		</div>`
    })
    game.innerHTML = data.join('')
    document.onclick = () => {
        const tool = game.querySelector('.tool')
        // 动画暂停
        tool.classList.add('paused')
        // 计算下一个点
        const nextIndex = index === max - 1 ? 0 : index + 1
        const list = game.children
        // 当前摆锤的位置,获得其中心点位置
        const currRect = document.getElementById('curr').getBoundingClientRect()
        // 找到下一个得分圈的中心点
        const moveEl = list[nextIndex].querySelector('.item-name')
        // 下一个得分圈中心点位置信息
        const moveRect = moveEl.getBoundingClientRect()

        // 计算两者之间差值 (得分圈和钟摆大小差值)
        if(Math.abs(currRect.left - moveRect.left) < 15 && Math.abs(currRect.top - moveRect.top) < 15){
            // 摆锤 停的位置 是正确的
            // 将摆锤底座 添加到 下一个得分圈上
            list[nextIndex].appendChild(tool)
            // 移除 暂停状态
			tool.classList.remove('paused')
            // 清空当前状态的index,并将下一个得分圈的index设为10
			list[index].style.zIndex = ''
			list[nextIndex].style.zIndex = '10'
			if (index === max - 1) {
				index = 0
			} else {
				index++
			}
            // 得分+1
			score.innerHTML = parseInt(score.innerHTML) + 1
        } else if (score.innerHTML.indexOf(',') ===  - 1) {
			score.innerHTML += ',游戏结束'
		}
    }
</script>
</html>

参考:js实现钟摆小游戏_哔哩哔哩_bilibili

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值