Python学习笔记(5.2.8 javascript打飞机实战练习)

本文是学习陆老师的《python全栈工程师 - web开发前端基础》课程的笔记,欢迎学习交流。同时感谢陆老师的精彩传授!
一、课程目标

  • 打飞机场景构建
  • 利用js实现动画
  • 构造函数及原型继承实例使用
  • 键盘鼠标事件
  • 元素碰撞检测
  • 文件管理
二、详情解读 2.1.打飞机场景 2.1.1.游戏场景-使用css实现飞机动画
【Python学习笔记(5.2.8 javascript打飞机实战练习)】1.css背景复习
2.css动画
3.元素动态创建
01-游戏场景-使用css实现飞机动画 > .container { position: relative; margin: 0; width: 600px; height: 800px; background: url(image/background.png) repeat-y; animation: background-move 10s linear infinite; } @-webkit-keyframes background-move { from {background-position: 0 0; } to {background-position: 0 852px; } } .plane { position: absolute; left: 0; top: 0; width: 100px; height: 122px; border: 0px solid #f0f; background: url(image/hero/hero1.png); animation: plane_engine 0.1s linear infinite; } @-webkit-keyframes plane_engine { from {background: url(image/hero/hero1.png)} to {background: url(image/hero/hero2.png)} }
type="text/javascript"> container = document.querySelector('.container'); function createPlane() { myplane = document.createElement('div'); myplane.style.top = 0; myplane.style.left = 0; myplane.className = 'plane'; container.appendChild(myplane); } myplane = createPlane()

运行结果:

2.2.js动画 动画原理:动画其实就是利用人的视觉停留输入关键字,快速切换图片形成的。
Python学习笔记(5.2.8 javascript打飞机实战练习)
文章图片

2.2.1.游戏场景-使用工厂函数创建飞机
02.游戏场景-使用工厂函数创建飞机 > .container { position: relative margin: 0; width: 400px; height: 600px; background: url(image/background.png); } .plane{ position: absolute; left: 0; top: 0; width: 100px; height; 122px; border: 0px solid #f0f; }
> container = document.querySelector('.container'); // 创建飞机节点元素函数 function createPlane() { plane = document.createElement('div'); container.appendChild(plane); img = document.createElement('img'); plane.appendChild(img); plane.style.top = 0; plane.style.left = 0; plane.image = img; return plane; } /* 工厂方法 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Plane() { var myPlane = { plane: createPlane(), // 飞机节点,是包含飞机的div // 飞机各种状态的图片文件 image_files: ['hero1.png', 'hero2.png', "hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"], images: [], first_frame: 0, // 动画首帧下标 last_frame: 1, // 动画尾帧下标 current_frame: 0, // 动画当前帧下标 // 加载飞机图片 load: function() { for (i = 0; i < this.image_files.length - 1; i++) { // 预加载图片 this.images[i] = new Image() this.images[i].src = 'https://www.it610.com/article/image/hero/' + this.image_files[i] } this.plane.image.src = https://www.it610.com/article/this.images[this.current_frame].src },// 飞机的变化 movies: function() { this.current_frame += 1 // 当前帧大于尾帧时,重新回到首帧 if (this.current_frame> this.last_frame) { this.current_frame = 0 } this.plane.image.src = https://www.it610.com/article/this.images[this.current_frame].src; } } return myPlane }// 初始化飞机 function init() { myplane = Plane() myplane.load() } // 使飞机“动”起来 function run() { myplane.movies() }init() // 每50毫秒执行一次 setInterval(run, 50)

运行结果与css实现的运行结果一致
2.3.通过构造函数实现对象 2.3.1.定义构造函数
1.构造函数本身就是对象
2.实例化使用 new 关键字
03.游戏场景-使用构造函数创建对象 > .container { position: relative; margin: 0; width: 400px; height: 600px; background: url(image/background.png); } .plane{ position: relative; top: 0; left: 0; width: 100px; height: 122px; border: 0px solid #f0f; }
> container = document.querySelector('.container'); /* 创建飞机节点元素函数 */ function createPlane() { plane = document.createElement('div'); container.appendChild(plane); img = document.createElement('img'); plane.appendChild(img) plane.style.top = 0; plane.style.left = 0; plane.image =img; return plane; } /* 构造函数 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Plane() {this.plane = createPlane(); this.image_files = ["hero1.png","hero2.png","hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"]; this.images = [] this.first_frame = 0 this.last_frame = 1 this.current_frame = 0 this.load = function() { for (i = 0; i < this.image_files.length - 1; i++) { this.images[i] = new Image() this.images[i].src = 'https://www.it610.com/article/image/hero/' + this.image_files[i] } this.plane.image.src = https://www.it610.com/article/this.images[this.current_frame].src } this.movies = function() { this.current_frame += 1 if (this.current_frame> this.last_frame) { this.current_frame = 0 } this.plane.image.src = https://www.it610.com/article/this.images[this.current_frame].src } } function init() { myplane = new Plane() myplane.load() } function run() { myplane.movies() }init() setInterval(run, 50)

运行结果与css实现的运行结果一致
2.4.利用原型继承实现多种类型飞机 2.4.1.为什么要使用继承
1.所有的动画他们的基本属性与方法都是一样的,比如需要一组图片,都需要定义第一帧位置,当前帧位置,最后一帧位置,以及load方法,movies方法
2.各种飞机实现不同的就是图片不一样,飞行控制不一样
3.通过继承就可以精简代码
04.游戏场景-使用原型继承 > .container{ position: relative; margin: 0; width: 400px; height: 600px; background: url(image/background.png); } .plane { position: absolute; top: 0; left: 0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1{ width: 51px; height: 39px; }
> container = document.querySelector('.container') enemy1_array = [] enemy1_count = 3 /* 构造函数 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Sprite() { this.init = function() { div = document.createElement('div') container.appendChild(div) img = document.createElement('img') div.image = img div.appendChild(img) this.div = div div = null this.div.style.left = init_data.x + 'px' this.div.style.top = init_data.y + 'px' this.div.className = init_data.className this.path = init_data.path this.image_files = init_data.image_files this.first_frame = init_data.first_frame this.last_frame = init_data.last_frame this.current_frame = init_data.current_frame this.speed = init_data.speed this.images = []this.load() } this.load = function() { for (i = 0; i < this.image_files.length - 1; i++) { this.images[i] = new Image() this.images[i].src = this.path+this.image_files[i] } this.div.image.src = https://www.it610.com/article/this.images[this.current_frame].src } this.movies = function() { this.current_frame += 1 if (this.current_frame> this.last_frame) { this.current_frame = 0 } this.div.image.src = https://www.it610.com/article/this.images[this.current_frame].src } }function HeroPlane() { init_data = { x: 300, y: 300, className:'plane hero', path: 'image/hero/', image_files: ["hero1.png","hero2.png","hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"], first_frame: 0, last_frame: 1, current_frame: 0 } HeroPlane.prototype.constructor.call(this, init_data) this.init() }HeroPlane.prototype = new Sprite() HeroPlane.prototype.fly = function() { this.div.style.top = this.div.offsetTop + this.speed + 'px' this.div.style.left = this.div.offsetLeft + 'px' }function Enemy1Plane(x, y) { init_data = https://www.it610.com/article/{ x: x, y: x, className:'plane enemy1', path: 'image/enemy1/', image_files: ["enemy1.png","enemy1_down1.png","enemy1_down2.png","enemy1_down3.png","enemy1_down4.png"], first_frame: 0, last_frame: 0, current_frame: 0, speed: 5 } Enemy1Plane.prototype.constructor.call(this, init_data) this.init() }Enemy1Plane.prototype = new Sprite() Enemy1Plane.prototype.fly = function() { console.log(this.div.offsetTop, this.speed) this.div.style.top = (this.div.offsetTop + this.speed) + 'px' if (this.div.offsetTop > container.clientHeight) { this.div.style.top = '-20px' } }function init() { // 创建一架我方飞机 myplane = new HeroPlane() // 根据游戏规则,创建多架敌机enemy1_count for (var i = 0; i < enemy1_count; i++){ x = getRand(50, 400) y = getRand(0, 100) - 100 enemy1_array[i] = new Enemy1Plane(x, y) } }function run() { myplane.movies() enemy1_array.forEach(function(obj){ obj.movies() obj.fly() }) setTimeout(run, 30) }init() run()/* 通过Math对象生成随机数,将生成的敌机随机分布在画面中 */ function getRand(min, max) { return Math.round((max-min)*Math.random()) }

运行结果:
Python学习笔记(5.2.8 javascript打飞机实战练习)
文章图片

2.5.利用键盘控制飞机 2.5.1.如何通过键盘控制飞机飞行
1.要实现一个fly方法,根据按键来进行不同的方向移动
2.要给飞机对象一个speed属性,控制飞机的移动速度
3.通过keydown事件监测用户的操作
4.keyup事件取消控制
05.利用键盘控制控制己方飞机 > .container { position: relative; margin: 0; width: 400px; height: 600px; background: url(image/background.png); overflow: hidden; } .plane{ position: absolute; left: 0; top: 0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1 { width: 51px; height: 39px; }
> container = document.querySelector('.container') enemy1_array = [] enemy1_count = 3 /* 构造函数 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Sprite() { this.init = function() { div = document.createElement('div') container.appendChild(div) img = document.createElement('img') div.image = img div.appendChild(img) this.div = div div = null this.div.style.left = init_data.x + 'px' this.div.style.top = init_data.y + 'px' this.div.className = init_data.className this.path = init_data.path this.image_files = init_data.image_files this.first_frame = init_data.first_frame this.last_frame = init_data.last_frame this.current_frame = init_data.current_frame this.speed = init_data.speed this.images = [] } this.load = function() { for (i=0; i this.last_frame) { this.current_frame = 0 } this.div.image.src = https://www.it610.com/article/this.images[this.current_frame].src } }function HeroPlane() { init_data = { x: 300, y: 300, className:'plane heor', path: 'image/hero/', image_files: ["hero1.png","hero2.png","hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"], first_frame : 0, last_frame : 1, current_frame : 0, speed : 10 } HeroPlane.prototype.constructor.call(this,init_data) this.init() this.load()}HeroPlane.prototype = new Sprite()HeroPlane.prototype.fly = function(){ plane = this.div if (this.key == "ArrowLeft"){ plane.style.left =( plane.offsetLeft - this.speed) +"px" } if (this.key == "ArrowRight"){ plane.style.left = ( plane.offsetLeft + this.speed) + "px" } if (this.key == "ArrowUp"){ plane.style.top = ( plane.offsetTop - this.speed) + "px" } if (this.key == "ArrowDown"){ plane.style.top = ( plane.offsetTop + this.speed) + "px" }} function Enemy1Plane(x,y){init_data = https://www.it610.com/article/{ x:x, y:y, className:"plane enemy1", path : "image/enemy1/", image_files : ["enemy1.png","enemy1_down1.png","enemy1_down2.png","enemy1_down3.png","enemy1_down4.png"], first_frame : 0, last_frame : 0, current_frame : 0, speed : 5 } HeroPlane.prototype.constructor.call(this, init_data) this.init() this.load()} Enemy1Plane.prototype = new Sprite() Enemy1Plane.prototype.fly = function(){ // console.log(this.div.offsetTop , this.speed ) this.div.style.top = (this.div.offsetTop + this.speed )+ "px" if (this.div.offsetTop > container.clientHeight){ this.div.style.top = "-20px" } }function init(){ myplane = new HeroPlane() for (var i=0; i

运行结果:
Python学习笔记(5.2.8 javascript打飞机实战练习)
文章图片

2.6.碰撞测试 Python学习笔记(5.2.8 javascript打飞机实战练习)
文章图片

代码实现:
type="text/css"> .container{ position: relative; margin: 0; /*padding: 0; */ width: 400px; height: 600px; background: url(image/background.png); } .plane{ position: absolute; left: 0; top:0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1{ width: 51px; height: 39px; }
type="text/javascript">container = document.querySelector(".container") enemy1_array = [] enemy1_count = 3 /* 构造函数 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Sprite(){this.init = function(){ // console.log(init_data) div = document.createElement("div") container.appendChild(div) img = document.createElement("img") div.image = img div.appendChild(img); this.div = div div = null this.div.style.left = init_data.x + "px" this.div.style.top= init_data.y + "px" this.div.className= init_data.className this.path = init_data.path this.image_files = init_data.image_files this.first_frame = init_data.first_frame this.last_frame = init_data.last_frame this.current_frame = init_data.current_frame this.speed = init_data.speed this.images = [] } this.load = function(){ // console.log(this.image_files) for (i=0; i this.last_frame){ this.current_frame = 0 } this.div.image.src = https://www.it610.com/article/this.images[this.current_frame].src } }function HeroPlane(){ init_data = { x:300, y:300, className:"plane hero", path : "image/hero/", image_files : ["hero1.png","hero2.png","hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"], first_frame : 0, last_frame : 1, current_frame : 0, speed : 3 } HeroPlane.prototype.constructor.call(this,init_data) this.init() this.load() }HeroPlane.prototype = new Sprite()HeroPlane.prototype.fly = function(){ plane = this.div if (this.key == "ArrowLeft"){ plane.style.left =( plane.offsetLeft - this.speed) +"px" } if (this.key == "ArrowRight"){ plane.style.left = ( plane.offsetLeft + this.speed) + "px" } if (this.key == "ArrowUp"){ plane.style.top = ( plane.offsetTop - this.speed) + "px" } if (this.key == "ArrowDown"){ plane.style.top = ( plane.offsetTop + this.speed) + "px" }} function Enemy1Plane(x,y){init_data = https://www.it610.com/article/{ x:x, y:y, className:"plane enemy1", path : "image/enemy1/", image_files : ["enemy1.png","enemy1_down1.png","enemy1_down2.png","enemy1_down3.png","enemy1_down4.png"], first_frame : 0, last_frame : 0, current_frame : 0, speed : 5 } HeroPlane.prototype.constructor.call(this, init_data) this.init() this.load()} Enemy1Plane.prototype = new Sprite() Enemy1Plane.prototype.fly = function(){ // console.log(this.div.offsetTop , this.speed ) this.div.style.top = (this.div.offsetTop + this.speed )+ "px" if (this.div.offsetTop > container.clientHeight){ this.div.style.top = "-20px" } }function init(){ myplane = new HeroPlane() for (var i=0; i
2.7.爆炸效果
1.飞机如果相撞,那么生命值就会减值,可以设定一个伤害值
2.如果一个飞机的生命值为0了,那么他的状态就是死亡状态,应该播放爆炸效果
3.爆炸效果通过播放后面的爆炸帧实现
4.飞机爆炸后,需要将这个节点移除
5.创建新的飞机实例
添加碰撞爆炸效果
type="text/css"> .container{ position: relative; margin: 0; /*padding: 0; */ width: 400px; height: 600px; background: url(image/background.png); } .plane{ position: absolute; left: 0; top:0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1{ width: 51px; height: 39px; }
type="text/javascript">container = document.querySelector(".container") myplane = null enemy1_array = [] enemy1_count = 3 /* 构造函数 创建飞机对象,定义飞机的图片,加载,变化等属性与方法 */ function Sprite(){} Sprite.prototype.init = function(){ // console.log(init_data) div = document.createElement("div") container.appendChild(div) img = document.createElement("img") div.image = img div.appendChild(img); this.div = div div = null this.div.style.left = init_data.x + "px" this.div.style.top= init_data.y + "px" this.div.className= init_data.className this.path = init_data.path this.image_files = init_data.image_files this.first_frame = init_data.first_frame this.last_frame = init_data.last_frame this.current_frame = init_data.current_frame this.speed = init_data.speed this.images = [] this.life = init_data.life this.dead = false this.remove = function(){ this.div.remove() } this.load = function(){ // console.log(this.image_files) for (i=0; i= this.last_frame){ this.dead = true } this.current_frame += 1 if (this.current_frame > this.last_frame){ this.current_frame = 0 }this.div.image.src = https://www.it610.com/article/this.images[this.current_frame].src} }function HeroPlane(){ init_data = { x:300, y:300, className:"plane hero", path : "image/hero/", image_files : ["hero1.png","hero2.png","hero_blowup_n1.png","hero_blowup_n2.png","hero_blowup_n3.png","hero_blowup_n4.png"], first_frame : 0, last_frame : 1, current_frame : 0, speed : 3, life: 10, dead:false } HeroPlane.prototype.constructor.call(this,init_data) this.init() this.load() }HeroPlane.prototype = new Sprite()HeroPlane.prototype.fly = function(){ this.movies() plane = this.divif (this.key == "ArrowLeft"){ plane.style.left =( plane.offsetLeft - this.speed) +"px" } if (this.key == "ArrowRight"){ plane.style.left = ( plane.offsetLeft + this.speed) + "px" } if (this.key == "ArrowUp"){ plane.style.top = ( plane.offsetTop - this.speed) + "px" } if (this.key == "ArrowDown"){ plane.style.top = ( plane.offsetTop + this.speed) + "px" } } function Enemy1Plane(x,y){ init_data = https://www.it610.com/article/{ x: getRand(50, 400), y: getRand(0, 100)-400, className:"plane enemy1", path : "image/enemy1/", image_files : ["enemy1.png","enemy1_down1.png","enemy1_down2.png","enemy1_down3.png","enemy1_down4.png"], first_frame : 0, last_frame : 0, current_frame : 0, speed : 5, life: 1, dead: false } Enemy1Plane.prototype.constructor.call(this, init_data) this.init() this.load() } Enemy1Plane.prototype = new Sprite()Enemy1Plane.prototype.fly = function(){ // console.log(this.div.offsetTop , this.speed ) this.movies() this.div.style.top = (this.div.offsetTop + this.speed )+ "px" if (this.div.offsetTop > container.clientHeight){ this.div.style.top = "-20px" } }function init(){ myplane = new HeroPlane() for (var i=0; i= rect1.offsetLeft){ // obj1在obj2的左上角原点左侧 x_conflict = rect2.offsetLeft - rect1.offsetLeft <= rect1.offsetWidth? true : false } else { // obj1在obj2的左上角原点右侧 x_conflict = rect1.offsetLeft - rect2.offsetLeft <= rect2.offsetWidth? true : false }if (rect2.offsetTop - rect1.offsetTop){ // obj1在obj2的左上角原点上方 y_conflict = rect2.offsetTop - rect1.offsetTop <= rect1.offsetHeight } else { // obj1在obj2的左上角原点下方 y_conflict = rect1.offsetTop - rect2.offsetTop <= rect2.offsetHeight } // console.log(x_conflict ,y_conflict)return x_conflict && y_conflict }window.onload=function(){ document.onkeydown = function(event){ if (event.key in {ArrowLeft:1,ArrowRight:1,ArrowUp:1,ArrowDown:1}){ myplane.key=event.key } } document.onkeyup=function(event){ console.log("key:"+event.key) if (event.key in {ArrowLeft:1,ArrowRight:1,ArrowUp:1,ArrowDown:1}){ myplane.key="" } } }
运行结果:

2.8.子弹发射 子弹发射与飞机飞行的不同:
1.飞机是根据飞机数量,判定是否要创建新的飞机实例
2.子弹只要用户触发相关事件就发射,比如按下键盘空格键
3.子弹的数量是动态变化的
4.子弹撞上飞机或者飞出可视化区域就表示这颗子弹生命期结束,需要移除。
添加子弹发射:
type="text/css"> .container{ position: relative; margin: 0; /*padding: 0; */ width: 400px; height: 600px; background: url(image/background.png); } .plane{ position: absolute; left: 0; top:0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1{ width: 51px; height: 39px; } .bullet { width: 9px; height: 21px; } type="text/javascript" src="https://www.it610.com/article/js/helper.js"> type="text/javascript" src="https://www.it610.com/article/js/sprite.js">
type="text/javascript"> container = document.querySelector(".container") myplane = null enemy1_array = [] enemy1_count = 3 bullet_array = [] //子弹构造函数 function Bullet(x,y){ init_data = https://www.it610.com/article/{ x: x, y: y, className:"plane bullet", path : "image/bullet/", image_files : ["bullet1.png","bullet2.png"], first_frame : 0, last_frame : 1, current_frame : 0, speed : 10, life: 1, dead: false } this.init() this.load() }Bullet.prototype = new Sprite() Bullet.prototype.fly = function(){ this.movies() this.div.style.top = (this.div.offsetTop - this.speed )+ "px" if (this.div.offsetTop <= 0){ this.dead = true } }function init(){ myplane = new HeroPlane() for (var i=0; i
运行结果:
Python学习笔记(5.2.8 javascript打飞机实战练习)
文章图片

2.9.代码整理 代码越来越多,就需要管理:
1.一般的前端会有这些文件夹:js,img,css,media,upload
2.将自己的文件分门别类放置,通过外部加载方式,可以让主页结构比较简洁
3.由于外部加载可能存在缓存,需要注意缓存,如果修改后没有变化,就清除浏览器缓存看看
整理后的全部代码:
type="text/css"> .container{ position: relative; margin: 0; /*padding: 0; */ width: 400px; height: 600px; background: url(image/background.png) repeat-y; animation:background-move 10slinear infinite; overflow: hidden; }@-webkit-keyframes background-move{ from{background-position: 0 0; } to{background-position: 0 852px; } }.plane{ position: absolute; left: 0; top:0; border: 0px solid #f0f; } .hero { width: 100px; height: 122px; } .enemy1{ width: 51px; height: 39px; } .bullet { width: 9px; height: 21px; } #start { margin: -webkit-calc(50%) } type="text/javascript" src="https://www.it610.com/article/js/helper.js"> type="text/javascript" src="https://www.it610.com/article/js/sprite.js">
type="text/javascript">container = document.querySelector(".container") start_btn = document.querySelector("#start") game_music = document.querySelector("#game_music") myplane = null enemy1_array = [] enemy1_count = 3 bullet_array = []function init(){ myplane = new HeroPlane() for (var i=0; i
运行结果:(运行是有声音效果的)

完整代码等我整理好上传到github后再分享给同学们哈 ^_^

推荐阅读


上一篇:scrapy爬取途牛网站旅游数据

下一篇:远程读取elasticSearch数据库并导出数据