一个原生JS实现的不太成熟的贪吃蛇游戏
一个初初初初级前端民工
主要是记录一下写过的东西,复习用
大佬们如果看到代码哪里不符合规范,或者有更好写法的,欢迎各位批评指正
十分感谢
实现一个贪吃蛇游戏需要几步?
1.有地图
2.有蛇
3.有食物
4.有游戏规则
----->面向对象的思想:
完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
#map{
width: 800px;
height: 600px;
background-color: #e6e6e6;
position: relative;
}
#talk{
color: red;
position: absolute;
right: -20px;
top: 20px;
}
#scoreList{
border: 1px solid cadetblue;
border-left: none;
box-shadow: 1px 1px 1px #A9A9A9;
width: 200px;
height: 400px;
overflow-y: auto;
position: absolute;
right: -200px;
}
#scoreList h3{
text-align: center;
}
.name,.score{
display: inline-block;
width: 45%;
text-align: center;
}
#start{
position: absolute;
right: -200px;
bottom: 20px;
background-color: cornflowerblue;
color: white;
box-shadow: 2px 2px 3px #d6d6d6;
padding: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="map">
<div id="scoreList">
<h3>排行榜</h3>
<hr />
<div id="container"></div>
</div>
<div id="start" onclick="start()">开始游戏</div>
</div>
<script>
var name = '';
var scoreList = [];
var result = {};
function my$(id){
return document.getElementById(id);
}
if(document.cookie){
// listShow();
}
function listShow(){
var scoreStr='';
console.log(document.cookie);
var cookies = document.cookie.split(',');
for(var i = 0;i<cookies.length;i++){
var item = JSON.parse(cookies[i]);
scoreStr += '<span class="name">'+item.userName+'</span><span class="score">'+item.userScore+'</span>';
}
my$('container').innerHTML = scoreStr;
}
//食物
(function(){
var elements = [];
//用来存储食物【实例对象】的数组,在被蛇'吃掉'之后,可以通过数组来找到这个对象,进而实现在html中删除相应结点。 //食物的构造函数
function Food(x,y,width,height,color){
this.x = x||0; //没有传入值时横坐标默认为0
this.y = y||0;
this.width = width||20;
this.height = height||20;
this.color = color||'#a0c9fb';
}
//初始化,将设置好的属性值转化为样式
Food.prototype.init = function(map){
remove(); //将之前的所有食物删除
var div = document.createElement('div'); //创建一个div元素
div.style.position = 'absolute';
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.backgroundColor = this.color;
this.x = parseInt(Math.random()*(map.offsetWidth/this.width))*this.width;
this.y = parseInt(Math.random()*(map.offsetHeight/this.height))*this.height;
div.style.left = this.x + 'px';
div.style.top = this.y + 'px';
map.appendChild(div); //将div添加到地图中
elements.push(div); //将div对象追加到数组当中
}
//删除食物
function remove(){
for(var i=0;i<elements.length;i++){
var ele = elements[i];
ele.parentNode.removeChild(ele);
elements.splice(i,1);
}
}
window.Food = Food; //Food构造函数是在自调用函数中写的(目的是避免变量重名的问题),这里用Food构造函数来创建window对象的Food方法,使其可以在自调用函数之外被调用
}());
//蛇
(function(){
var elements = [];
function Snake(width,height,direction){
this.width = width||20;
this.height = height||20;
this.direction = direction||'right';
this.currentDir = this.direction;
this.score = 0;
this.body = [
{x:3,y:2,color:'red'},
{x:2,y:2,color:'orange'},
{x:1,y:2,color:'orange'}
] //蛇的每一块身体是一个div,通过它们坐标的改变来实现蛇的移动.
}
//初始化,
Snake.prototype.init = function(map){
remove();
for(var i=0;i<this.body.length;i++){ //body的每一块都有相应的坐标,颜色,宽高等,要通过循坏为每一块进行初始化
var obj = this.body[i];
var div = document.createElement('div');
map.appendChild(div);
div.style.position = 'absolute';
div.style.width = this.width + 'px';
div.style.height = this.height + 'px';
div.style.backgroundColor = obj.color;
div.style.left = obj.x*this.width + 'px';
div.style.top = obj.y*this.height + 'px';
elements.push(div);
}
}
//让蛇动起来(改变body每一块的坐标 每次调用整体动一下)
Snake.prototype.move = function(food,map){ //food参数在用来判断蛇是否吃掉食物时使用,map参数在对food进行初始化时使用
var i = this.body.length-1; //判断蛇的body中 最后一块的下标
for(;i>0;i--){ //Step1: 从最后一块开始到第二块的坐标值改变
this.body[i].x = this.body[i-1].x;
this.body[i].y = this.body[i-1].y;
}
switch(this.direction){ //Step2: 根据之前设定的方向来判断蛇头(第一块)的坐标变化
case 'right':this.body[0].x+=1;break;
case 'left':this.body[0].x-=1;break;
case 'top':this.body[0].y-=1;break;
case 'bottom':this.body[0].y+=1;break;
} //判断是否吃到 蛇头的坐标 == 食物的坐标 即为吃到
var headX = this.body[0].x*this.width;
var headY = this.body[0].y*this.height;
if(headX == food.x && headY == food.y){
var last = this.body[this.body.length-1];
this.body.push({
x:last.x,
y:last.y,
color:last.color
}); //在body最后增加一个对象,坐标等于最后一块的坐标即可
this.score = this.score+1;
food.init(map); //重新初始化一个食物出来
}
}
function remove(){
var i = elements.length-1;
for(;i>=0;i--){
elements[i].parentNode.removeChild(elements[i]);
elements.splice(i,1);
}
}
window.Snake = Snake;
}());
//游戏
(function(){
var that; //setInterval中的this是window,所以先定义一个that,将我们要使用的this对象存在that中,这样就可以在setInterval中使用了
function Game(map){
that = this; //this是新的实例对象
this.food = new Food(); //创建food实例对象
this.snake = new Snake(); //创建snake实例对象
this.map = map; //将这些都作为game实例对象的属性
}
Game.prototype.init = function(){
this.food.init(this.map);
this.snake.init(this.map);
this.run();
this.bindKey();
} // 之前的snake.move是让蛇动一下,在这里放在setInterval中让它一直移动.
Game.prototype.run = function(){
var timeId = setInterval(function(){ //timeId用于clearInterval
this.snake.move(this.food,this.map); //1.蛇的坐标改变
this.snake.init(this.map); //2.画出蛇
var xMax = this.map.offsetWidth/this.snake.width; //横坐标最大值
var yMax = this.map.offsetHeight/this.snake.height;//纵坐标最大值
var headX = this.snake.body[0].x;
var headY = this.snake.body[0].y;
if(headX>=xMax||headX<0||headY>=yMax||headY<0){ //判断是否撞墙
this.scoreFunction(timeId);
//尝试变色
// var i=0;
// setInterval(function(){
// this.snake.body[i].color = 'red';
// this.snake.init();
// i++;
// }.bind(that),500)
//本来想写一个 蛇撞墙之后身体都变成红色的效果 emmm失败了
}
for(var i=1;i<this.snake.body.length;i++){ //判断是否撞自己
if(headX==this.snake.body[i].x&&headY==this.snake.body[i].y){
this.scoreFunction(timeId);
}
}
}.bind(that),150); //bind的作用是将bind后面括号中的值作为函数中this的值
}
//分数结算函数
Game.prototype.scoreFunction = function(timeId){
alert('啊啊啊wsl!!!!');
name = prompt('请问高手尊姓大名?');
result.userName = name;
result.userScore = this.snake.score;
scoreList.push(JSON.stringify(result));
scoreList.sort(function(a,b){
var a = JSON.parse(a);
var b = JSON.parse(b);
return b.userScore - a.userScore;
}) //排行榜排序功能
var cookieStr = JSON.stringify(scoreList);
cookieStr = cookieStr.replace(',',';');
document.cookie = 'list = '+cookieStr; //尝试写在cookie中并没有成功 嘤
//将分数写入scoreList盒子
var scoreStr='';
for(var i in scoreList){
var item = JSON.parse(scoreList[i]);
scoreStr += '<span class="name">'+item.userName+'</span><span class="score">'+item.userScore+'</span>';
}
my$('container').innerHTML = scoreStr;
clearInterval(timeId); //清除定时器 蛇停止移动
} //按下键盘相应键,给蛇的direction赋值,需要注意的是蛇不可以掉头
Game.prototype.bindKey = function(){
document.addEventListener('keydown',function(e){
switch(e.keyCode){
case 37:
if(this.snake.currentDir!='right'){
this.snake.direction='left';
this.snake.currentDir='left';
}
break;
case 38:
if(this.snake.currentDir!='bottom'){
this.snake.direction='top';
this.snake.currentDir='top';
}
break;
case 39:
if(this.snake.currentDir!='left'){
this.snake.direction='right';
this.snake.currentDir='right';
}
break;
case 40:
if(this.snake.currentDir!='top'){
this.snake.direction='bottom';
this.snake.currentDir='bottom';
}
break;
}
}.bind(that),false)
}
//把Game暴露给window
window.Game = Game;
}())
//创建游戏对象并初始化
function start(){
var game = new Game(my$('map'));
game.init(my$('map'));
} </script>
</body>
</html>
1.自调用函数除了避免变量重名外还有其他的作用吗?
2.原型的作用是共享数据,节约内存空间。
3.setInterval 中的this是window。
4.bind的作用是将bind后面括号中的值作为函数中this的值。
一个原生JS实现的不太成熟的贪吃蛇游戏的更多相关文章
- 100行JS实现HTML5的3D贪吃蛇游戏
js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...
- JS贪吃蛇游戏
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- 用OpenGL简单编写的一个最简单贪吃蛇游戏
刚学OpenGL的时候,写的一个最简单的贪吃蛇游戏代码 如下: //贪吃蛇游戏 #include<stdio.h> #include<stdlib.h> #include< ...
- JS高级---面向对象的编程思想(贪吃蛇梳理)
面向对象的编程思想(贪吃蛇梳理) 模拟贪吃蛇游戏,做的项目 地图: 宽,高,背景颜色,因为小蛇和食物都是相对于地图显示的, 这里小蛇和食物都是地图的子元素, 随机位置显示, 脱离文档流的, 地图也需要 ...
- 原生Js贪吃蛇游戏实战开发笔记
前言 本课程是通过JavaScript结合WebAPI DOM实现的一版网页游戏---贪吃蛇的开发全过程,采用面向以象的思想设计开发.通过这个小游戏的开发, 不仅可以掌握JS的语法的应用,还可以学会D ...
- 手把手教你做一个原生js拖动滑块【兼容PC和移动端】
废话少说: 在PC端可以用mousedown来触发一个滑块滑动的效果,但在手机上,貌似无法识别这个事件,但手机上有touchstart事件,可以通过一系列"touch"事件来替代P ...
- 自己封装的一个原生JS拖动方法。
代码: function drag(t,p){ var point = p || null, target = t || null, resultX = 0, resultY = 0; (!point ...
- 一个原生js写的加减乘除运算
根据我的经验我说的再多也没人看,不过还是简单介绍下效果吧,可以选择+,-,*,/,去计算数据,喜欢的话就粘贴复制自己看去吧! <!DOCTYPE html PUBLIC "-//W3C ...
- js编写简单的贪吃蛇游戏
css代码 *{ margin:; padding:; } td{ width: 4px; height: 4px; background: #ccc; border: 2px solid #ccc; ...
随机推荐
- 区间dp专题
HDU4283You Are the One区间dp, 记忆话搜索运行时间: #include <iostream> #include <cstdio> #include ...
- Vert.x Web 文档手册
Vert.x Web 中英对照表 Container:容器 Micro-service:微服务 Bridge:桥接 Router:路由器 Route:路由 Sub-Route: 子路由 Handler ...
- BZOJ 刷题总结(持续更新)
本篇博客按照题号排序(带*为推荐题目) 1008 [HNOI2008]越狱 很经典的题了..龟速乘,龟速幂裸题,, 1010 [HNOI2008]玩具装箱toy* 斜率优化 基本算是裸题. 1012 ...
- Qt 模拟一个导航定位系统
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/lihuidashen/p/115397 ...
- Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)
继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类 派生类Person ...
- 利用github搭建私人maven仓库
一.背景 最近在做HBase的项目,不免会引用到一些工具类,如StringUtils,NumberUtils,DateUtils这些,公司底层有封装好可以直接使用. 但是项目完成,用maven打包部署 ...
- redis的几个知识点
Redis的全称是Remote Dictionary Server,即远程字典服务,通常用作服务器缓存服务. 这里通过Redis的几个知识点来了解Redis. Redis的通讯协议 Redis的通讯协 ...
- 62 (OC)* leetCode 力扣 算法
1:两数之和 1:两层for循环 2:链表的方式 视频解析 2:两数相加 两数相加 3. 无重复字符的最长子串 给定一个字符串,请找出其中长度最长且不含有重复字符的子串,计算该子串长度 无重复字符的最 ...
- Android的有序广播和无序广播(解决安卓8.0版本之后有序广播的接收问题)
前言 Google从Android8.0版本开始,对在清单文件中静态注册广播做了限制. *** 特殊广播(动态注册广播接收者) 说:有序广播和无序广播之前,咱们先来说下Android中一些特殊的广播如 ...
- Spring Cloud 负载均衡初体验
目录 服务搭建 1.注册中心--Eureka Server 2.服务提供方--Service Provider 3.服务消费方--Service Consumer 服务消费 Feign 与断路器 Hy ...