原生Js贪吃蛇游戏实战开发笔记
前言
本课程是通过JavaScript结合WebAPI DOM实现的一版网页游戏---贪吃蛇的开发全过程,采用面向以象的思想设计开发。通过这个小游戏的开发, 不仅可以掌握JS的语法的应用,还可以学会DOM的使用, 更重要的是可以学习程序开发的业务逻辑,和项目开发过程,以及一些常用的游戏算法。
代码和课程来源:https://www.bilibili.com/video/BV1aE411K7Ga?from=search&seid=11376138008125697092
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>贪吃蛇桌面版小游戏</title>
<link rel="icon" href="https://www.meitubk.com/my/avator.jpg" type="image/x-icon"/>
<style type="text/css">
body{margin: 0; padding: 0;}
div#main{margin: 40px;}
input.btn{width: 100px;height: 40px;}
span.gtitle{font-size: 25px;font-weight: bold;}
span#gnum, span#glen, span#gspeed{color:red}
</style>
</head>
<body>
<div id="main">
<h1>贪吃蛇桌面版 -- 需 <span id="glen">1</span> 节 -- 第 <span id="gnum">1</span> 关 -- 速度间隔 <span id="gspeed">1</span></h1>
<input class="btn" type="button" value="开始游戏" id="begin"/>
<input class="btn" type="button" value="暂停游戏" id="pause"/>
<input class="btn" type="button" value="我的博客" id="myblog"/>
<input class="btn" type="button" value="视频教程" id="video"/>
<script type="text/javascript">
var main = document.getElementById("main");
//是否开启画布格子
var showcanvas = false;
//地图对象构造方法
function Map(atom, xnum, ynum){
//原子、像素点
this.atom = atom;
//地图宽度
this.xnum = xnum;
//地图高度
this.ynum = ynum;
this.canvas = null;
//创建画布函数
this.create = function(){
this.canvas = document.createElement("div");
this.canvas.style.cssText = "position:absolute;top:170px;border:1px solid darkred;background:#FAFAFA;"
this.canvas.style.width = this.atom * this.xnum + 'px';
this.canvas.style.height = this.atom * this.ynum + 'px';
main.appendChild(this.canvas);
if(showcanvas){
for(var y=0; y<ynum; y++){
for(var x=0; x<xnum; x++){
var item = document.createElement("div");
item.style.cssText = "border:1px solid yellow;"
item.style.width = this.atom + 'px';
item.style.height = this.atom + 'px';
item.style.backgroundColor = "green";
this.canvas.appendChild(item);
item.style.position = "absolute";
item.style.left = x * this.atom + 'px';
item.style.top = y * this.atom + 'px';
}
}
}
}
}
//创建食物函数
function Food(map){
this.width = map.atom;
this.height = map.atom;
this.bgColor = "rgb("+Math.floor(Math.random()*200)+","+Math.floor(Math.random()*200)+","+Math.floor(Math.random()*200)+")";
//食物放在第几格
this.x = Math.floor(Math.random() * map.xnum);
this.y = Math.floor(Math.random() * map.ynum);
//设置食物的样式
this.flag = document.createElement("div");
this.flag.style.width = this.width + 'px';
this.flag.style.height = this.height + 'px';
this.flag.style.backgroundColor = this.bgColor;
this.flag.style.position = "absolute";
this.flag.style.left = this.x * this.width + 'px';
this.flag.style.top = this.y * this.height + 'px';
map.canvas.appendChild(this.flag);
}
//创建蛇对象
function Snake(map){
//设置宽、高
this.width = map.atom;
this.height = map.atom;
//设置起始方向
this.direction = 'right';
this.body = [
{x: 2, y: 0}, //头
{x: 1, y: 0}, //身
{x: 0, y: 0} //尾
]
//显示蛇
this.display = function(){
for(var i=0;i < this.body.length; i++){
//当吃到食物时,要把x设置为null
if(this.body[i].x != null){
var item = document.createElement('div');
//将节点保存到一个状态变量中,以便以后删除使用
this.body[i].flag = item;
//设置蛇的样式
item.style.width = this.width + 'px';
item.style.height = this.height + 'px';
item.style.backgroundColor = "rgb("+Math.floor(Math.random()*200)+","+Math.floor(Math.random()*200)+","+Math.floor(Math.random()*200)+")";
item.style.position = "absolute";
item.style.left = this.body[i].x * this.width + 'px';
item.style.top = this.body[i].y * this.height + 'px';
map.canvas.appendChild(item);
}
}
}
//让蛇运动
this.run = function(){
for(var i=this.body.length-1; i>0 ; i--){
this.body[i].x = this.body[i-1].x;
this.body[i].y = this.body[i-1].y;
}
//判断方向
switch(this.direction){
case "left": this.body[0].x -= 1; break;
case "right": this.body[0].x += 1; break;
case "up": this.body[0].y -=1; break;
case "down": this.body[0].y += 1; break;
}
//判断蛇头吃到食物
if(this.body[0].x == food.x && this.body[0].y == food.y){
//蛇加一节,根据最后节点
this.body.push({x: null, y:null, flag: null});
//判断下一级别
if(this.body.length >= level.slength){
level.setlevel();
}
map.canvas.removeChild(food.flag);
food = new Food(map);
}
//判断是否出界
if(this.body[0].x < 0 || this.body[0].x > map.xnum - 1 || this.body[0].y < 0 || this.body[0].y > map.ynum - 1){
clearInterval(timer);
alert("真笨呀,活活的撞墙死掉了!");
//重新开始游戏
restart(map, this, level);
return false;
}
//判断是否吃到自己
for(var i=4; i<this.body.length;i++){
if(this.body[0].x == this.body[i].x && this.body[0].y == this.body[i].y){
alert("哎,把自己给咬死了!");
//重新开始游戏
restart(map, this, level);
return false;
}
}
for(var i=0; i < this.body.length; i++){
if(this.body[i].flag != null){
map.canvas.removeChild(this.body[i].flag);
}
}
this.display();
}
}
//重新开始游戏
function restart(map, snake, level){
for(var i=0; i<snake.body.length;i++){
map.canvas.removeChild(snake.body[i].flag);
}
snake.body = [
{x: 2, y: 0}, //头
{x: 1, y: 0}, //身
{x: 0, y: 0} //尾
]
snake.direction = 'right';
snake.display();
map.canvas.removeChild(food.flag);
food = new Food(map);
level.num = 1;
level.speed = 100;
level.slength = 6;
level = new Level();
level.display();
}
//设置级别对象
function Level(){
this.num = 1;
this.speed = 100;
this.slength = 6; //通过目标长度
this.setlevel = function(){
this.num++;
if(this.speed <= 20){
this.speed = 20;
}else{
this.speed -= 20;
}
this.slength += 3;
this.display();
start();
}
this.display = function(){
document.getElementById("gnum").innerHTML = this.num;
document.getElementById("gspeed").innerHTML = this.speed;
document.getElementById("glen").innerHTML = this.slength;
}
}
var level = new Level();
level.display();
var map = new Map(20, 40, 20);
map.create()
var food = new Food(map);
var snake = new Snake(map);
snake.display();
//键盘监听
window.onkeydown = function(e){
var event = e || window.event;
//上下左右
switch(event.keyCode){
case 38:
if(snake.direction != "down"){
snake.direction = "up";
}
break;
case 40:
if(snake.direction != "up"){
snake.direction = "down";
}
break;
case 37:
if(snake.direction != "right"){
snake.direction = "left";
}
break;
case 39:
if(snake.direction != "left"){
snake.direction = "right";
}
break;
}
}
function start(){
clearInterval(timer);
timer = setInterval(function(){
snake.run();
}, level.speed);
}
var timer;
document.getElementById('begin').onclick=function(){
start();
}
document.getElementById('pause').onclick=function(){
clearInterval(timer);
}
document.getElementById('myblog').onclick=function(){
location.href = "https://www.meitubk.com/";
}
document.getElementById('video').onclick=function(){
location.href = "https://www.bilibili.com/video/BV1aE411K7Ga";
}
</script>
</div>
</body>
</html>
预览
请访问 https://www.meitubk.com/my/demo2/
原生Js贪吃蛇游戏实战开发笔记的更多相关文章
- Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录
一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...
- JS贪吃蛇游戏
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- Android快乐贪吃蛇游戏实战项目开发教程-02虚拟方向键(一)自定义控件概述
该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.自定义控件简介 在本项目中,无论是游戏主区域还是虚拟方向键都是通过自定义控件 ...
- Android快乐贪吃蛇游戏实战项目开发教程-06虚拟方向键(五)绘制方向键箭头
本系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html本系列教程项目源码GitHub地址:https://github.com/jack ...
- Android快乐贪吃蛇游戏实战项目开发教程-05虚拟方向键(四)四个三角形按钮
该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.如何判断点击的是哪个方向键按钮 在上篇教程中我们实现了左边的三角形按钮效果, ...
- Android快乐贪吃蛇游戏实战项目开发教程-04虚拟方向键(三)三角形按钮效果
该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.知识点讲解 当我们点击系统自带的按钮时,按钮的外观会发生变化.上篇博文中我们 ...
- Android快乐贪吃蛇游戏实战项目开发教程-03虚拟方向键(二)绘制一个三角形
该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.绘制三角形 在上一篇文章中,我们已经新建了虚拟方向键的自定义控件Direct ...
- 原生js贪吃蛇
<!DOCTYPE html> <html> <head> <title></title> <meta charset="u ...
- 一个原生JS实现的不太成熟的贪吃蛇游戏
一个初初初初级前端民工 主要是记录一下写过的东西,复习用 大佬们如果看到代码哪里不符合规范,或者有更好写法的,欢迎各位批评指正 十分感谢 实现一个贪吃蛇游戏需要几步? 1.有地图 2.有蛇 3.有食物 ...
随机推荐
- mybatis诡异的bug
在使用mybatis中使用 foreach 时,出现了一个诡异的bug java文件中是 List<ImportTaskInfoEntity> selectByCalcBatchIds(@ ...
- Java常用类__装箱/拆箱
以下是常用的各两种方法(各类提供了构造方法,静态方法) 一.基本数据类型 转化为 包装类(装箱) 例:int i=10: Integer num=i;//num=10 二.包装类 转化为 基本数据类 ...
- linux压缩及归档
一.解析 压缩:把大文件,通过压缩成一个比之前小的文件. 归档(打包):把多个文件,归档成一个文件. 二.压缩 1.zip(归档压缩,可以压缩目录,要保存源文件) 压缩:zip 压缩后的文件名 压缩 ...
- Python学习-第四节:常用模块-logging,re,time
1:logging模块 import logging logging.debug('This is debug message') logging.info('This is info message ...
- 系统警告,Bronya请求支援(两遍最短路)
系统警告,Bronya请求支援 Description 休伯利安号的一行人来到了由逆熵镇守的前文明遗迹[海渊城],他们准备用巨大的传送装置[海渊之眼]进入量子之海,寻找丢失的渴望宝石.然而在行动前夜爱 ...
- Pointer Lock API(3/3):一个Demo
简单的Demo演练 点击跳转至Code Pen以查看演示和源码 完整代码 <!DOCTYPE HTML> <html lang="en-US"> <h ...
- 从测试点点君跨入年薪30W的自动化逍遥君的人生感悟--测试君请进,绝对让你不虚此行!
一.前言:人生感悟 人生,就是一个苏醒的过程,生命就是一次历练,从鲜衣怒马,到银碗里盛雪,从青葱岁月到白发染鬓,人总是会在经历中成长,在成长中懂得,在懂得里看透,看透而不说透,从而一步一步的走向成熟, ...
- find的基本查询命令《二》
Linux find命令详解 由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下.即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只你 ...
- 如何在 Array.forEach 中正确使用 Async
本文译自How to use async functions with Array.forEach in Javascript - Tamás Sallai. 0. 如何异步遍历元素 在第一篇文章中, ...
- 会话技术(session/cookie)
session可保存int double bool array string object:cookie只能保存stringsession 可通过php.ini文件查看存放的位置:cookie不同浏览 ...