javascript面向对象编程(精灵大战)
来源:互联网 发布:ocr表格识别软件 编辑:程序博客网 时间:2024/06/10 05:00
//this是Javascript语言的一个关键字。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。
//随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用本函数的那个对象。
//.prototype 属性使您有能力向对象添加属性和方法。
//.push(element…) 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
//.appendChild(DOM对象)
//.removeChild(DOM对象)
//.setInterval(function(){}); //创建定时器
//clearInterval(a.timer) //清除掉a的定时器timer
//.parentNode标签父结点
//Math.random()方法可返回介于 0 ~ 1 之间的一个随机数。
//parseInt(实数)方法返回一个整型数字
//setTimeout(function(){}); //只执行一次里面的代码
//.innerHTML = “得分:” + score ; //设置标签对象的内容
//类方法EnemyMonster.timer与类对象方法this.timer是不一样的。
效果图如下
创建公共变量
var score = 0 ; //得分var song ; //游戏背景音乐var bgTimer ; //背景移动定时器
扩展了javascript的内置对象Array
Array.prototype.remove=function(element){ for(i=0;i<this.length;i++){//遍历数组对象的元素 if(this[i]==element){ //当相等时 //调用javascript的内置方法splice(规定要删除的项目的位置,要删除的项目数量),返回删除后的this this.splice(i,1); } } return this; //返回调用remove方法的对象 }
自定义(射手-射箭)类 MyShooter的构造函数function MyShooter(x,y,container){}
function MyShooter(x,y,container){ this.arrows = []; //自定义一个弓箭集合 this.x = x; //射手的坐标初始化 this.y = y; this.container = container; //引入游戏面板 this.init(); }
扩展init()方法
MyShooter.prototype={ init : function(){ this.Shooter(); this.ShooterMove(); var that = this ; //此处的this指的是MyShooter MyShooter.timer = setInterval(function(){ //为MyShooter对象定义一个弓箭发射定时器 //此处的this指的是timer that.Arrow(); //每隔0.4秒执行一次 },400); }, //自定义射手对象 Shooter : function(){ this.shooter = document.createElement("img"); //创建一个img标签 this.shooter.src = "images/shooter.gif" ; //设置src this.shooter.style.cssText = "position:absolute; left:" + this.x + "px; top:" + this.y + "px;"; //设置坐标 this.container.appendChild(this.shooter); //添加到游戏面板中 }, //射手随鼠标移动事件 ShooterMove : function(){ var that = this; //此处的this指的是MyShooter对象,其DOM父结点为container //鼠标监听器 this.container.mousemove = function(e){ //此处的this指的是container,其DOM父结点为body //在此处的that和this代表的对象不同 e = e||event; //根据鼠标的坐标确定射手的坐标 var sx = e.clientX - this.offsetLeft - that.shooter.offsetWidth/2 ; var sy = e.clientY - this.offsetTop -that.shooter.offsetHeight/2 ; that.shooter.style.left = sx + "px" ; that.shooter.style.top = sy + "px" ; //如果射手走出游戏面板的右边界限 if(that.shooter.offsetLeft + that.shooter.offsetWidth >= this.offsetWidth){ that.shooter.style.left = this.offsetWidth - that.shooter.offsetWidth +"px" ; } //左边界限 if(that.shooter.offsetLeft <= 0){ that.shooter.style.left = "0px" ; } //顶边界限 if(that.shooter.offsetTop <= 0){ that.shooter.style.top = "0px" ; } //底边界限 if(that.shooter.offsetTop + that.shooter.offsetHeight >= this.offsetHeight){ that.shooter.style.top = this.offsetHeight - that.shooter.offsetHeight + "px" ; } } }, //自定义弓箭对象 Arrow : function(){ this.arrow = document.createElement("img"); this.arrow.src = "images/arrow.png"; //根据射手的位置确定弓箭的初始坐标 var ax = this.shooter.offsetLeft + this.shooter.offsetWidth/2 - 1 ; var ay = this.shooter.offsetTop - 10 ; this.arrow.style.cssText = "position:absolute; left:" + ax + "px; top:" + ay +"px;" ; this.container.appendChild(this.arrow); //添加到游戏面板 this.arrows.push(this.arrow); //添加到弓箭集合中 var a = this.arrow; //此处的this指的是MyShooter var aArr = this.arrows; a.timer=setInterval(function(){ //弓箭的控制移动/清除 的定时器 //此处的this指的是定时器timer a.style.top = a.offsetTop- 8 + "px" ; //每隔0.2秒弓箭向上移动8个像素 if(a.offsetTop == -60){ //60像素是弓箭图片的高度 aArr.remove(a); //从弓箭集合中移除弓箭对象a a.parentNode.removeChild(a); //从弓箭的DOM父结点(游戏面板)中移除 clearInterval(a.timer); //清除掉弓箭的定时器 } },200); }}
自定义(怪兽-创建、碰撞)类EnemyMonster的构造函数function EnemyMonster(shooter,arrows,container){}
图1
function EnemyMonster(shooter,arrows,container){ this.enemyList = [] ; //怪兽集合 初始化 this.shooter = shooter ; //射手 this.arrows = arrows ; //弓箭 this.container = container ; //游戏面板,即DOM父结点 this.probability = 0 ; //出发的怪兽数量,这里约定最大为20,最小为0 this.num = 0 ; //出发的怪兽数量,这里约定最大为10,最小为0 this.sWidth = 34; //怪兽图片的宽度 this.mWidth = 46; this.bWidth = 110; this.smallURL = "images/smallLive.png"; //图片URL初始化 this.middURL = "images/middleLive.gif"; this.bigURL = "images/bigLive.gif"; this.blastSmallURL = "images/smallDied.png"; this.blastMiddURL = "images/middleDied.png"; this.blastBigURL = "images/bigDied.png"; this.init();}
扩展init()方法
EnemyMonster.prototype={ init : function(){ var that = this; //只能是EnemyMonster.timer不能是this.timer,因为这里的this指的是EnemyMonster类的一个enemy对象,但是EnemyMonster类可以有多个enemy对象,EnemyMonster.timer指的是timer是属于所有enemy对象的监听器,是类方法,而不是只属于一个enemy对象。 EnemyMonster.timer = setInterval(function(){ //每隔0.8秒创建一只怪兽 that.probability ++ ; //出发怪兽数量加一 if(that.probability = 20){ //出发怪兽数量为20时 var bx = parseInt(Math.random() * (that.container.offsetWidth-that.bWidth)); that.BigMonster(bx); //创建一只大型怪兽 that.probability = 0 ; //将probability清零 } else if(that.probability % 5 == 0){ //出发怪兽数量为5的倍数时 var mx = parseInt(Math.random() * (that.container.offsetWidth-that.mWidth)); that.MiddMonster(mx); } else { //每隔0.8秒出发一只小型怪兽 var sx = parseInt(Math.random() * (that.container.offsetWidth-that.sWidth)); that.SmallMonster(sx); } },800); }, //自定义小型怪兽对象 SmallMonster : function(x){ //x指的是怪兽的左边距 this.small = document.createElement("img") ; this.small.src = this.smallURL ; //小型怪兽图片的高度为34像素 this.small.style.cssText = "position:absolute; left:" + x + "px; top:-34px;" ; this.container.appendChild(this.small) ; //加入游戏面板 this.enemyList.push(this.small) ; //加入怪兽集合 this.RelationListener(this.small,this.arrows,this.blastSmallURL,1); }, //自定义中型怪兽对象 MiddMonster : function(x){ this.midd = document.createElement("img"); this.midd.src = this.middURL; //中型怪兽图片的高度为60像素 this.midd.style.cssText = "position:absolute; left:" + x + "px; top:-60px;" ; this.container.appendChild(this.midd); this.enemyList.push(this.midd); this.RelationListener(this.midd,this.arrows,this.blastMiddURL,2); }, //自定义大型怪兽对象 BigMonster : function(x){ this.big = document.createElement("img"); this.big.src = this.bigURL; //大型怪兽图片的高度为164像素 this.big.cssText = "position:absolute; left:" + x + "px; top:-164px;" ; this.container.appendChild(this.big); this.enemyList.push(this.big); this.RelationListener(this.big,this.arrows,this.blastBigURL,3); }, //关系监听器 RelationListener : function(monsterObj,arrows,diedImgUrl,monsterType){ this.num++ ; //出发的怪兽数量加一 var blastedSmall = false; //碰撞标识 var blastedMidd = false; var blastedBig = false; var hitMidd = 0; //碰撞次数 var hitBig = 0; var topIncrement = parseInt(Math.random()*3) ; //topIncrement为顶部随机增量,返回0或1或2或3 topIncrement = topIncrement == 0 ? 1 : topIncrement ; //返回1或2或3 //根据现实世界的法则来看,大型怪兽的速度不能快于中、小型怪兽,故只随机加快中、小型怪兽的行走速度 //当对象为大型怪兽时,topIncrement不变 if(monsterType!=3){ //当对象为中、小型怪兽时 if(this.num == 10) this.num = 0 ; //num清零 //根据怪兽的出发数量num的奇偶性,来修改怪兽的顶部随机增量topIncrement if(this.num % 3 == 0){ //当num为奇数时 topIncrement = monsterType == 2 ? 3 : 6 ; } //当num为偶数时,topIncrement不变 } var that = this ; //监听一只怪兽与所有弓箭的关系、与父结点的关系、与射手的关系 monsterObj.timer = setInterval(function(){ monsterObj.style.top =monsterObj.offsetTop + topIncrement; //每隔0.02秒怪兽的top加topIncrement个像素 for(i=0; i<arrows.length; i++){ //遍历弓箭集合 //弓箭的头部位置和尾部位置,如图1的左边图 if(arrows[i].offsetTop < monsterObj.offsetTop + monsterObj.offsetHeight && arrows[i].offsetTop + arrows[i].offsetHeight > monsterObj.offsetTop){ //弓箭的左边位置和右边位置,如图1的右边图 if(arrows[i].offsetLeft + arrows[i].offsetWidth > monsterObj.offsetLeft && arrows[i].offsetLeft < monsterObj.offsetLeft + monsterObj.offsetWidth){ if(monsterType == 1){ monsterObj.src = diedImgUrl; //更换死亡图片 that.enemyList.remove(monsterObj); //从怪兽集合中移除该怪兽 clearInterval(monsterObj.timer); //清除该怪兽的定时移动器 blastedSmall = true ; //标记为已碰撞 score += 5; //分数加五 scoretext.innerHTML = "得分:" + score; //修改分数面板内容 } if(monsterType == 2){ hitMidd ++ ; //碰撞次数加一 if(hitMidd == 4 ){ //如果与中型怪兽的碰撞次数为4 hitMidd = 0 ; //将hitMidd清零 monsterObj.src = diedImgUrl; //更换死亡图片 that.enemyList.remove(monsterObj); //从怪兽集合中移除该怪兽 clearInterval(monsterObj.timer); //清除该怪兽的定时移动器 blastedMidd = true ; //标记为已碰撞 score += 10; //分数加十 scoretext.innerHTML = "得分:" + score; //修改分数面板内容 } } if(monsterType == 3){ hitBig ++ ; //碰撞次数加一 if(hitBig == 6){ //如果与大型怪兽的碰撞次数为6 hitBig = 0 ; //将hitMidd清零 monsterObj.src = diedImgUrl; //更换死亡图片 that.enemyList.remove(monsterObj); //从怪兽集合中移除该怪兽 clearInterval(monsterObj.timer); //清除该怪兽的定时移动器 blastedBig = true ; //标记为已碰撞 score += 20; //分数加十 scoretext.innerHTML = "得分:" + score; //修改分数面板内容 } } //必须在发生碰撞的那一刹那,就立即销毁掉发生碰撞的弓箭,否则以上判断失效 arrows[i].parentNode.removeChild(arrows[i]); arrows.remove(arrows[i]); } } } //设置不同类型的怪兽在发生碰撞后消失的延迟时间 if(blastedSmall){ //0.4秒后消失 blastedSmall = false ; setTimeout(function(){ that.container.removeChild(monsterObj); },400); } if(blastedMidd){ //0.5秒后消失 blastedMidd = false; setTimeout(function(){ that.container.removeChild(monsterObj); },500); } if(blastedBig){ //0.6秒后消失 blastedBig = false; setTimeout(function(){ that.container.removeChild(monsterObj); },600); } //我的射手被怪兽近了身,则游戏结束 if(that.shooter.offsetTop < monsterObj.offsetTop + monsterObj.offsetHeight && that.shooter.offsetTop + that.shooter.offsetHeight > monsterObj.offsetTop){ if(that.shooter.offsetLeft + that.shooter.offsetWidth > monsterObj.offsetLeft && that.shooter.offsetLeft < monsterObj.offsetLeft + monsterObj.offsetWidth){ that.over(); } } //如果怪兽的顶距>=父结点(即游戏面板)的高度,则从怪兽集合、游戏面板中删除该怪兽,并清除其移动定时器 if(monsterObj.offsetTop >= that.container.offsetHeight){ that.enemyList.remove(monsterObj); monsterObj.parentNode.removeChild(monsterObj); clearInterval(monsterObj.timer); } },20); }, //游戏结束:善后处理 over : function(){ StopSong(); //销毁音乐 this.MyShooter.src = "images/smallDied.png"; clearInterval(MyShooter.timer); //清除弓箭发射定时器 for(var i=0; i<this.arrows.length; i++){ //清除弓箭移动/清除定时器 clearInterval(this.arrows[i].timer); } clearInterval(EnemyMonster.timer); //清除怪兽创建定时器 for(var i=0; i<this.enemyList.length; i++){ //清除怪兽移动/碰撞/清除定时器 clearInterval(this.enemyList[i].timer); } clearInterval(bgTimer); //清除游戏背景移动定时器 this.container.onmousemove = null ; //清空鼠标移动事件 enddiv.style.display = "block"; //显示游戏结束面板 }}
移动背景函数
function moveBG(){ var backgroundY = 0; //初始化backgroundY bgTimer = setInterval(function(){ backgroundY += 1; //每隔0.02秒backgroundY加一 //设置container的背景位置background-position: 水平位置 垂直位置。 container.style.backgroundPosition = "0 "+backgroundY + "px"; //当backgroundY与container的高度一样时,将backgroundY清零,以达到循环 if(backgroundY == container.offsetHeight){ backgroundY = 0; } },20); }
游戏开始时的初始化界面显示
function play(){ //得分归零 score = 0; scoretext.innerHTML = "分数:0"; //替换游戏背景图 container.style.background = "url(images/bg.png)"; //背景移动 moveBG(); //调用MyPlan()实例化玩家飞机 var myShooter = new MyShooter(0,500,container); //调用EnemyPlan(我的飞机,我的子弹,游戏场地)实例化敌机 var enemy = new EnemyMonster(myShooter.shooter,myShooter.arrows,container); //每次点击继续按钮,都会创建出一个新的myShooter对象 和一个新的enemy对象,问题是之前创建的对象都还存在着,并没有消失 }
相当于java中的main()方法,即加载网页后, 加载以下变量和方法
window.onload = function(){ var container = document.getElementById("container"); //为container对应的标签 ,创建container变量。 var startBtn = document.getElementById("startBtn"); //为startBtn对应的标签 ,创建startBtn变量。 //点击开始按钮 startBtn.onclick = function(){ StartSong(); this.style.display = "none"; //隐藏 开始按钮 play(); }}
点击继续按钮时触发该函数
function restartGame(){ StartSong(); //创建音乐 enddiv.style.display = "none"; //隐藏 结束面板且不占地方。 container.innerHTML = scoretext.outerHTML + enddiv.outerHTML + startBtn.outerHTML; play(); }
创建音乐
function StartSong(){ //动态添加游戏背景音乐 song=document.createElement("embed"); song.src="song.mp3"; song.style="width:0; height:0; " document.body.appendChild(song);}
销毁音乐
function StopSong(){ document.body.removeChild(song); }
游戏面板如下
<body> <!-- <embed id="song" src="song.mp3" width="0" height="0" autostart="false" enablejavascript="true" /> --> <div id="container"> <p id="scoretext"></p> <div id="enddiv"> <p class="plantext">游戏结束</p> <div><button onclick="restartGame()" id="restart">继续</button></div> </div> <input type="button" value="开始游戏" id="startBtn"> </div></body>
游戏面板的css设置如下
<style> #container{ width:320px; height:568px; background: url(images/start.png); margin:20px auto; /* 距顶部20px,水平居中 */ position: relative; overflow: hidden; } /* 开始按钮样式 */ #container input{ width:120px; height: 38px; background: #ff6600; border:0; color:#fff; font-size:14px; font-family: 微软雅黑; position: absolute; left: 100px; bottom:50px; } /* 结束面板 */ #enddiv{ position: absolute; top: 400px; left: 75px; border: 1px solid gray; border-radius: 5px; text-align: center; background-color:#d7ddde; display: none; z-index: 2; } /* 结束面板里面的 文本面板 */ .plantext{ width: 160px; height: 30px; line-height: 30px; font-size: 16px; font-weight: bold; } /* 结束面板里面的 继续按钮面板 */ #enddiv div{ width: 160px; height: 50px; } /* 结束面板里面的 继续按钮面板里面的 继续按钮 */ #enddiv div button{ margin-top:10px ; width: 90px; height: 30px; border: 1px solid gray; border-radius: 30px; } /* 分数面板 */ #scoretext{ margin: 0; font-family: arial; font-size:12px; font-weight: bold; color:#ff6600; position: absolute; left: 4px; top: 4px; z-index: 100; }</style>
- javascript面向对象编程(精灵大战)
- 用javascript 面向对象制作坦克大战(二)
- js面向对象编程小游戏(坦克大战1.0版本)
- 【JavaScript面向对象编程】20160104(对象)
- 【JavaScript面向对象编程】20160105(对象)
- JavaScript 面向对象编程
- JavaScript 面向对象编程
- javascript面向对象编程
- javascript 面向对象编程
- JavaScript面向对象编程
- JavaScript 面向对象编程
- JAVASCRIPT - - 面向对象编程
- JavaScript面向对象编程
- JavaScript面向对象编程
- JavaScript面向对象编程
- javascript面向对象编程
- JavaScript面向对象编程
- javascript面向对象编程
- 解读阿里云oss-android/ios-sdk 断点续传(多线程)
- jvm类的加载过程
- 算法题:判断一个IP是否是合法IP
- 算法仓库(一) 什么是信息增益
- Algorithm之路十六:3Sum Closest
- javascript面向对象编程(精灵大战)
- 谈谈Android的so
- Linux下性能测试
- day01
- 【python】tensorflow常用方法
- pg_dump 迁移表到其他模式
- 2017级校赛总结
- python 断言
- Java运算符