原生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.有食物 ...
随机推荐
- WePY的开发环境的安装
2020-03-24 1.安装Node.js 官网:https://nodejs.org/ 两个版本 LTS为稳定的长期支持版本 Current为最新的版本 安装完毕后,cmd下输入 node -v ...
- iOS 缩小 ipa 大小
一.爱奇艺 爱奇艺移动应用优化之路:如何让崩溃率小于千分之二 iOS8 对于 App 的 text 段有 60MB 的限制: 超过 200MB 的 App 需要连接 WIFI 下载(之前是 150MB ...
- [洛谷1649]障碍路线<BFS>
题目链接:https://www.luogu.org/problem/show?pid=1649 历经千辛万苦,我总算是把这个水题AC了,现在心里总觉得一万只草泥马在奔腾: 这是一道很明显的BFS,然 ...
- 20175314 《Java程序设计》第十周学习总结
20175314 <Java程序设计>第十周学习总结 教材学习内容总结 进程与线程:一个进程的进行期间可以产生多个线程. Java内置对多线程的支持,计算机只能执行线程中的一个,Java虚 ...
- 迁移桌面程序到MS Store(15)——通过注册表开启Developer Mode
没想到该系列不仅没有太监,还打算更新一个小短篇.在各种大厂小厂工作的各位想必都知道Windows域的概念.入域的机器很多的设置就由不得当前登入所使用的域账号了,Windows的更新和安全等众多的设置均 ...
- RecyclerView 的 Item 的单击事件
RecyclerView 的每个Item的点击事件并没有像 ListView 一样封装在组件中,需要 Item 的单击事件时就需要自己去实现,在 Adapter 中为RecyclerView 添加单击 ...
- Vertica的这些事(八)——-Vertica-管理
1.版本信息 dbadmin=> SELECT version(); version ------------------------------------ Vertica Analytic ...
- Redis底层结构概述
可以使用 object encoding <key> 查看使用的具体数据结构 原图链接
- Vue 实战项目: 硅谷外卖(1)
第 1 章: 准备 1.1. 项目描述 1) 此项目为外卖 WebApp(SPA) 2) 包括商家, 商品, 购物车, 用户等多个子模块 3) 使用 Vue 全家桶+ES6+Webpack 等前端最新 ...
- 讲真,这两款idea插件,能治愈你英语不好的病
时不时就有小伙伴问我,"二哥,能推荐一款 IDE 吗?"你看这话问的,现在搞 Java 的不都在用 Intellij IDEA 吗,还用得着推荐(我已经和 Eclipse 分手了) ...