本文主要是介绍原生JS实现打砖块,贪吃蛇,弹球小游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
来来来,先上效果图
赶快学习起来吧
话不多说,放代码
1.
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style type="text/css">* {margin: 0;padding: 0;cursor: none;}a {text-decoration: none;}ul,li {list-style: none;}body {font-size: 14px;font-family: "微软雅黑";background: url("images/bg.jpg") top/cover;}#ball {width: 15px;height: 15px;background: #b4ff0d;border-radius: 50%;position: absolute;top: 0;left: 0;box-shadow: 0 0 9px 9px #f3ff67;}#ward {width: 120px;height: 30px;z-index: 999;background-color: #336688;border-radius: 10px;box-shadow: 0 0 4px #333333;position: absolute;left: 0;}#score {width: 100px;height: 100px;font-size: 40px;position: absolute;right: 40px;top: 40px;color: #ff2541;}#wrap {width: 90%;height: 500px;position: relative;top: 100px;left: 0;right: 0;margin: auto;}#wrap div {width: 45px;height: 15px;border: 1px solid #ff645b;position: absolute;background: rgb(255, 99, 89);box-shadow: 0 0 9px 1px rgb(255, 187, 136) inset;top: 0;left: 0;transform-origin: top center}#gameover {position: absolute;left: 0;right: 0;top: 0;bottom: 0;margin: auto;width: 300px;height: 200px;box-shadow: 0 0 4px #222222;background-color: #e1e1e1;display: none}#gameover p {width: 100%;height: 40px;text-align: center;font-size: 36px;color: #336688;margin-top: 50px;}#gameover span {width: 60%;height: 40px;display: block;margin: 38px auto 0;text-align: center;font-size: 20px;background: #336688;color: #ffffff;border-radius: 10px;line-height: 40px;}</style>
</head><body><div id="wrap"></div><div id="ball"></div><div id="ward"></div><div id="score">0分</div><div id="gameover"><p>总分:74</p><span>确定</span></div><script type="text/javascript">/* javascript中严格区分大小写 a!==A;1.需要哪些元素小球 挡板 砖块区域 初始x位置 初始y位置2.要有那些行为初始化initinit用来存放初始化方法如果实例化对象调用所有方法很麻烦,所以一次性解决创建砖块creatBrickfor循环生成砖块计算每一个砖块初始化top和left计算金字塔中线位置初始化小球初始化小球x方向移动向量初始化小球y方向移动向量初始化小球宽度和高度初始化小球开始运动事件初始化小球位置 x,y初始化挡板初始化挡板位置 x,y初始化鼠标监听事件挡板的移动挡板中央跟随鼠标x方向移动挡板运动边界 左 右小球的移动小球移动方法 requestAnimationFrame小球x y 向量自增碰撞检测{1:小球和浏览器边框的碰撞反弹 x||y2:小球和挡板的碰撞反弹 y3.小球和砖块的碰撞反弹 y && 移除砖块}*/var oBall = document.querySelector("#ball"); //球var oWard = document.querySelector("#ward"); //挡板var oScore = document.querySelector('#score');//计分板var oWrap = document.querySelector('#wrap'); //砖块区域var over = document.querySelector('#gameover'); //结束function Breakout(ball, ward, score, wrap, over) { //打砖块小游戏对象 构造函数this.ball = ball;this.ward = ward;this.scores = score;this.wrap = wrap;this.over = over;this.x = 0;this.y = 0;this.score = 0;}Breakout.prototype = { //原型方法init: function () { //初始化系统this.ballstar(); //初始化小球this.creatBrick(); //创建砖块this.wardMove(); //挡板移动},creatBrick: function () { //砖块初始化var x = document.documentElement.offsetWidth / 2 - document.documentElement.offsetWidth * .05, //设置居中位置w = 45 * 2, //设置横向间距基准值h = 15 * 2; //设置纵向间距基准值for (var i = 1; i <= 8; i++) { //循环生成div 8层for (var j = 0; j < i * 2 - 1; j++) { //每一层的砖块个数为 层数*2-1var brick = document.createElement("div");brick.style.top = (i - 1) * h + 'px';brick.style.left = x - (i * w) + (j * w) + 'px';this.wrap.appendChild(brick);}}},wardMove: function () { //挡板初始化this.ward.style.top = window.innerHeight - 180 + 'px'; //初始化挡板的top位置this.ward.style.left = this.x - 60 + 'px'; //初始化挡板的left位置居中this.addEvent(document, 'mousemove', this.mouseMove.bind(this)); //监听鼠标移动},ballstar: function () { //小球初始化var This = this;this.y = window.innerHeight - 200; //初始化坐标X的位置 窗口底部上移200pxthis.x = window.innerWidth / 2; //初始化坐标Y的位置 窗口中间部位this.ball.style.top = this.y + 'px'; //初始化小球的top值为ythis.ball.style.left = this.x + 'px'; //初始化小球的left值为xthis.ball.speed = 10; //初始化小球的速度this.ball.width = 15; //初始化小球的宽度this.ball.height = 15; //初始化小球的高度document.onclick = function () { //点击开始游戏,小球运动This.ballMove(); //小球移动}},//挡板移动mouseMove: function (e) { //鼠标移动,挡板跟随鼠标运动e = e || window.event; //事件对象兼容性处理var _left = e.pageX - this.ward.offsetWidth / 2; //保证鼠标移动,挡板中间位置同步鼠标位置_left = Math.min(window.innerWidth - this.ward.offsetWidth, _left); //挡板向右移动不能超过屏幕右边界_left = Math.max(0, _left); //挡板向左移动不能超过屏幕左边界this.ward.style.left = _left + 'px'; //通过设置挡板left值实现挡板移动},ballMove: function () { //小球开始运动document.onclick = null; //先清除document的点击事件防止一直重置运动this.ball.xspeed = this.ball.speed; //初始化小球x运动速度和方向 +为往左 -为往右this.ball.yspeed = -this.ball.speed;//初始化小球y运动速度和方向 +为往上 -为往下function auto() { //运动函数 auto 通过requestAnimationFrame递归调用实现循环this.x += this.ball.xspeed; //x代表当前横向位置 += 横向移动速度 10 每一次都在自己原先的位置基础上+10this.y += this.ball.yspeed; //y代表当前横向位置 += 横向移动速度 10 每一次都在自己原先的位置基础上+10this.crash(); //碰撞检测this.ball.style.left = this.x + 'px'; //小球运动赋值 x轴运动this.ball.style.top = this.y + 'px'; //小球运动赋值 y轴运动requestAnimationFrame(auto.bind(this)); //原生js动画 根据cpu运算速度来实现更新}auto.call(this);},crash: function () {var maxWidth = window.innerWidth - this.ball.offsetWidth; //浏览器左边界=浏览器宽度-球的宽度var maxHeight = window.innerHeight - this.ball.offsetHeight; //浏览器右边界=浏览器高度-球的高度if (this.y >= maxHeight) { //小球掉下去之后,游戏结束this.gameOver();}if (this.x >= maxWidth) {this.ball.xspeed *= -1; //小球碰到右边墙壁后 横向移动速度取反 往返方向移动this.x = maxWidth; //重置小球位置}if (this.x < 0) { //碰到左边墙 重置横向移动速度 并且重置横向位置 为0this.ball.xspeed = this.ball.speed;this.x = 0;}if (this.y < 0) { //碰到上边墙壁之后 重置纵向移动速度 以及纵向位置 为0this.ball.yspeed = this.ball.speed;this.y = 0;}//挡板碰撞检测if (Math.abs(this.x - (this.ward.offsetLeft + (this.ward.clientWidth / 2))) < 60 && Math.abs(this.y - this.ward.offsetTop - 30) < 45) {var color = this.ranColor();this.ward.style.background = color;this.ball.yspeed *= -1;this.y = this.ward.offsetTop - 40;}for (var i = this.wrap.children.length - 1; i >= 0; i--) {var ballMx = this.ball.offsetLeft + (this.ball.width / 2);var ballMy = this.ball.offsetTop + (this.ball.height / 2);var brickMx = (this.wrap.children[i].offsetLeft + this.wrap.offsetLeft) + (45 / 2);var brickMy = (this.wrap.children[i].offsetTop + this.wrap.offsetTop) + (15 / 2);if (Math.abs(ballMx - brickMx) <= 45 && Math.abs(ballMy - brickMy) <= 15) {this.ball.yspeed *= -1;this.y = brickMy;this.wrap.removeChild(this.wrap.children[i]);if (this.wrap.children.length == 0) {this.gameOver();}this.scoreChange();}}},scoreChange: function () {this.score++;this.scores.innerHTML = this.score + '分';},gameOver: function () {this.over.style.display = 'block';this.over.children[0].innerHTML = '总分:' + this.score;var all = document.querySelectorAll('*');for (var i = 0; i < all.length; i++) {all[i].style.cursor = 'auto'}this.ward.style.display = 'none';this.ball.style.display = 'none';this.over.children[1].onclick = function () {window.location.reload();}},/* getStyle: function (ele, curr) { //获取属性值return ele.currentStyle ? parseInt(ele.currentStyle[curr]) : parseInt(getComputedStyle(ele, null)[curr]);},*/addEvent: function (element, e, fn) {//事件监听return element.attachEvent ? element.attachEvent('on' + e, fn) : element.addEventListener(e, fn, false);},ranColor: function () { //随机颜色var color = '#';for (var i = 0; i < 6; i++) {color += '0123456789abcdef'[Math.floor(Math.random() * 16)]}return color;},}var breakout = new Breakout(oBall, oWard, oScore, oWrap, over);breakout.init();</script>
</body></html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head><title>新建网页</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="description" content="" /><meta name="keywords" content="" /><script type="text/javascript">//① 绘制地图function Map() {//私有成员(不会随便发生变化)var w = window.innerWidth;var h = window.innerHeight;//成员方法,绘制地图this.showmap = function () {//创建div、设置css样式、追加给bodyvar tu = document.createElement('div');tu.style.width = w + "px";tu.style.height = h + "px";// tu.style.backgroundImage = "url(12.jpg)";// tu.style.backgroundSize = "100%"document.body.appendChild(tu);}}//② 绘制食物function Food() {var len = 20;//把食物(权值)坐标声明为公开的,以便在外部访问this.xFood = 0;this.yFood = 0;this.piece = null; //页面上唯一的食物对象//绘制this.showfood = function () {//创建div、设置css样式、追加给bodyif (this.piece === null) {this.piece = document.createElement('div');this.piece.style.width = this.piece.style.height = len + "px";this.piece.style.backgroundColor = "#b3d5f1";this.piece.style.position = "absolute";document.body.appendChild(this.piece);}//食物设置绝对定位(position/left/top)//食物位置“随机”摆放//移动步进值:20px//食物“权值”坐标: X轴(0-39) Y轴(0-19) //食物真实坐标:权值坐标 * 步进值this.xFood = Math.floor(Math.random() * 40); //0-39的随机数this.yFood = Math.floor(Math.random() * 20); //0-19的随机数this.piece.style.left = this.xFood * len + "px";this.piece.style.top = this.yFood * len + "px";}}//③ 小蛇function Snake() {var len = 20;this.redirect = "right"; //默认向右边移动//后期snakebody要变化,因此声明为公开的(每个蛇节:[x坐标,y坐标,颜色,蛇节对象])this.snakebody = [[0, 1, '#b3d5f1', null], [1, 1, '#b3d5f1', null], [2, 1, '#b3d5f1', null], [3, 1, '#cc6beb', null]];//a.绘制小蛇this.showsnake = function () {//遍历小蛇的各个蛇节,并依次创建即可for (var i = 0; i < this.snakebody.length; i++) {//this.snakebody[i]//代表每个蛇节//创建蛇节divif (this.snakebody[i][3] === null) {//判断没有创建对应的蛇节this.snakebody[i][3] = document.createElement('div');//设置css样式(宽度、高度、颜色)this.snakebody[i][3].style.width = this.snakebody[i][3].style.height = len + "px";this.snakebody[i][3].style.backgroundColor = this.snakebody[i][2];//绝对定位及位置this.snakebody[i][3].style.position = "absolute";//把蛇节追加给bodydocument.body.appendChild(this.snakebody[i][3]);}this.snakebody[i][3].style.left = this.snakebody[i][0] * len + "px";this.snakebody[i][3].style.top = this.snakebody[i][1] * len + "px";}}//b.移动小蛇this.movesnake = function () {//非蛇头蛇节(当前蛇节的新坐标 是"下个蛇节"的旧坐标)for (var i = 0; i < this.snakebody.length - 1; i++) {this.snakebody[i][0] = this.snakebody[i + 1][0];this.snakebody[i][1] = this.snakebody[i + 1][1];}if (this.redirect == "right") {//蛇头x坐标递增this.snakebody[this.snakebody.length - 1][0] += 1;}if (this.redirect == "left") {//蛇头x坐标递减this.snakebody[this.snakebody.length - 1][0] -= 1;}if (this.redirect == "up") {//蛇头y坐标递减this.snakebody[this.snakebody.length - 1][1] -= 1;}if (this.redirect == "down") {//蛇头y坐标递增this.snakebody[this.snakebody.length - 1][1] += 1;}//判断蛇头碰到食物//蛇头坐标var xSnake = this.snakebody[this.snakebody.length - 1][0];var ySnake = this.snakebody[this.snakebody.length - 1][1];//食物坐标food.xFood/food.yFood;if (xSnake == food.xFood && ySnake == food.yFood) {//吃食物增加蛇节var newjie = [this.snakebody[0][0], this.snakebody[0][1], '#b3d5f1', null];this.snakebody.unshift(newjie);//把newjie放到数组的第一个位置去//原食物消失,重新生成一个食物food.showfood();}//控制小蛇在地图范围内移动if (xSnake < 0 || xSnake > 77 || ySnake < 0 || ySnake > 35) {alert('game over');clearInterval(mytime);return false;}//吃到自己判断(蛇头坐标与其他蛇节坐标一致)for (var k = 0; k < this.snakebody.length - 1; k++) {if (this.snakebody[k][0] == xSnake && this.snakebody[k][1] == ySnake) {alert('game over kill you by yourself');clearInterval(mytime);return false;}}//根据新坐标绘制小蛇this.showsnake();}}window.onload = function () {var map = new Map();map.showmap();food = new Food();//声明为全局的以便在该加载事件函数外部访问food.showfood();snake = new Snake();//声明为全局的snake对象snake.showsnake();//移动小蛇//setInterval(全局变量,时间)mytime = setInterval("snake.movesnake()", 200);//设置键盘事件,控制器小蛇移动方向document.onkeydown = function (evt) {var num = evt.keyCode;//通过事件对象获得数值码,进而知道被触发键子if (num == 38) {snake.redirect = "up";}if (num == 40) {snake.redirect = "down";}if (num == 37) {snake.redirect = "left";}if (num == 39) {snake.redirect = "right";}}}</script><style type="text/css">body {margin: 0;background: url('https://cdn.pixabay.com/photo/2020/11/04/19/22/windmill-5713337_1280.jpg') no-repeat;background-size: cover;}</style>
</head><body></body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>小弹球</title><style>body {margin: 0;overflow: hidden;font-family: '微软雅黑', sans-serif;height: 100%;}h1 {font-size: 2rem;letter-spacing: -1px;position: absolute;margin: 0;top: -4px;right: 5px;color: #fff;}p {position: absolute;margin: 0;top: 35px;right: 5px;color: #aaa;}</style>
</head><body><h1>弹球</h1><p></p><canvas></canvas><script>const Ball_numbers = 25; //常量是块级作用域,很像使用 let 语句定义的变量。常量的值不能通过重新赋值来改变,并且不能重新声明。const Ball_size_min = 10;const Ball_size_max = 20;const Ball_speed_max = 14;// 设定画布和初始数据const para = document.querySelector('p');const canvas = document.querySelector('canvas');const context = canvas.getContext('2d');// 将画布窗尺寸置为窗口内尺寸 获取当前浏览器的大小const width = canvas.width = window.innerWidth;const height = canvas.height = window.innerHeight;// 定义一个shape的类class Shape {constructor(x, y, speedX, speedY, exists) {this.x = x;this.y = y;this.speedX = speedX;this.speedY = speedY;this.exists = exists;}}class Ball extends Shape { //Ball这个子类继承Shape这个父类constructor(x, y, speedX, speedY, color, size, exists) {super(x, y, speedX, speedY, exists);this.color = color;this.size = size;}draw() {context.beginPath();// beginPath() 来声明我们现在要开始在纸上画一个图形了。context.fillStyle = this.color;context.arc(this.x, this.y, this.size, 0, 2 * Math.PI);//arc() 方法来在纸上画出一段圆弧。context.fill();//fill() 方法,也就是声明我们结束了以 beginPath() 开始的绘画,}update() {if ((this.x + this.size) >= width) {this.speedX = -(this.speedX);}if ((this.x - this.size) <= 0) {this.speedX = -(this.speedX);}if ((this.y + this.size) >= height) {this.speedY = -(this.speedY);}if ((this.y - this.size) <= 0) {this.speedY = -(this.speedY);}this.x += this.speedX;this.y += this.speedY;}collisionDetect() { //碰撞检测for (let j = 0; j < balls.length; j++) {if (this !== balls[j]) { //判断当前小球是否和被循环到的小球是相同的const dx = this.x - balls[j].x;const dy = this.y - balls[j].y;const distance = Math.sqrt(dx * dx + dy * dy);if (distance < this.size + balls[j].size && balls[j].exists) {balls[j].color = this.color = randomColor();}}}}}class EvilCircle extends Shape { //白色小圆圈constructor(x, y, exists) {super(x, y, exists);this.speedX = Ball_speed_max;this.speedY = Ball_speed_max;this.color = "white";this.size = 10;this.setControls();}draw() {context.beginPath();context.strokeStyle = this.color;context.lineWidth = 3;context.arc(this.x, this.y, this.size, 0, 2 * Math.PI);context.stroke();}checkBounds() {if ((this.x + this.size) >= width) {this.x -= this.size;}if ((this.x - this.size) <= 0) {this.x += this.size;}if ((this.y + this.size) >= height) {this.y -= this.size;}if ((this.y - this.size) <= 0) {this.y += this.size;}}setControls() {window.onkeydown = e => {switch (e.key) {case 'a':case 'A':case 'ArrowLeft':this.x -= this.speedX;break;case 'l':case 'L':case 'ArrowRight':this.x += this.speedX;break;case 'x':case 'X':case 'ArrowUp':this.y -= this.speedY;break;case 'm':case 'M':case 'ArrowDown':this.y += this.speedY;break;}};}collisionDetect() {for (let j = 0; j < balls.length; j++) {if (balls[j].exists) {const dx = this.x - balls[j].x;const dy = this.y - balls[j].y;const distance = Math.sqrt(dx * dx + dy * dy);if (distance < this.size + balls[j].size) {balls[j].exists = false;count--;para.textContent = '还剩 ' + count + ' 个球';}}}}}// 球和恶魔圈const balls = [];const evilBall = new EvilCircle(random(0, width),random(0, height),true);let count = 0;// 执行动画loop();// 生成随机数的函数function random(min, max) {return Math.floor(Math.random() * (max - min)) + min;}// 生成随机颜色的函数function randomColor() {return 'rgb(' +random(0, 255) + ', ' +random(0, 255) + ', ' +random(0, 255) + ')';}// 定义一个循环来不停地播放function loop() {context.fillStyle = 'rgba(0, 0, 0, 0.25)';context.fillRect(0, 0, width, height);while (balls.length < Ball_numbers) {const size = random(Ball_size_min, Ball_size_max);const ball = new Ball(// 为避免绘制错误,球至少离画布边缘球本身一倍宽度的距离random(0 + size, width - size),random(0 + size, height - size),random(-Ball_speed_max, Ball_speed_max),random(-Ball_speed_max, Ball_speed_max),randomColor(),size,true);balls.push(ball);count++;para.textContent = '还剩 ' + count + ' 个球';}for (let i = 0; i < balls.length; i++) {if (balls[i].exists) {balls[i].draw();balls[i].update();balls[i].collisionDetect();}}evilBall.draw();evilBall.checkBounds();evilBall.collisionDetect();requestAnimationFrame(loop);//requestAnimationFrame() 方法再运行一次函数 —— 当//一个函数正在运行时传递相同的函数名,从而每隔一小段时//间都会运行一次这个函数,这样我们可以得到一个平滑的动//画效果。这主要是通过递归完成的 —— 也就是说函数每次运//行的时候都会调用自己,从而可以一遍又一遍得运行。}</script>
</body></html>
这篇关于原生JS实现打砖块,贪吃蛇,弹球小游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!