Chap_16 纹理切换与帧频动画

一、概念

[wm_notice]

  • 纹理 :图片元素中显示的内容
  • 纹理切换:更换图片中显示的内容,可以让元素中的内容产生变化

[/wm_notice]

二、元素与纹理

元素与纹理通常一起创建

//  图片元素				 纹理
var plane = new PIXI.Sprite.fromImage("img/plane1.png");

plane就是图片元素 而 "img/plane.png" 就是纹理

创建纹理

语法

var 变量名 =  new PIXI.Texture.fromImage("路径");

var texture = new PIXI.Texture.fromImage("img/plane1.png");

创建图片元素并添加纹理

语法

var 变量名 = new PIXI.Sprite(纹理变量)

var plane = new PIXI.Sprite(texture);

修改图片元素中的纹理

语法

元素名.texture = 新纹理;

//创建纹理1
var t1 = new PIXI.Texture.fromImage("img/plane1.png");
var t2 = new PIXI.Texture.fromImage("img/plane2.png");
//创建图片元素并添加纹理 t1
var plane = new PIXI.Sprite( t1 );
//将plane元素中的纹理更改为t2
plane.texture  = t2;

三、通过快速切换纹理实现帧频动画

[wm_notice]PIXI中提供了一些可以通过快速切换纹理实现帧频动画的方法[/wm_notice]

运行效果

如下图所示

第一步 :准备一个存放所有纹理路径的数组

//用于保存所有纹理路径的数组
var ts = [];
//向数组中添加纹理路径
ts.push("img/planplay_1.png");
ts.push("img/planplay_2.png");
ts.push("img/planplay_3.png");
ts.push("img/planplay_4.png");
ts.push("img/planplay_5.png");
ts.push("img/planplay_6.png");
//略.....

第二步:创建纹理播放器

语法
var 变量名 = PIXI.extras.AnimatedSprite.fromImages( 纹理数组 );

var as = new PIXI.extras.AnimatedSprite.fromImages( ts );

第三步:调整属性并在应用中添加播放器

//创建纹理播放器
var as = new PIXI.extras.AnimatedSprite.fromImages( ts );
//设置播放器位置
as.x = 200;
as.y = 200;
//在应用中添加播放器
app.stage.addChild( as );

第四步:设置播放速度

播放速度0~1,数值越小速度越慢

语法

纹理播放器.animationSpeed = 播放速度;

//设置动画播放速度
as.animationSpeed = 0.15;

第五步:播放动画

语法

纹理播放器.play();

as.play();

完整代码

var app = new PIXI.Application(500,700);
document.body.appendChild( app.view );
			
//用于保存所有纹理路径的数组
var ts = [];
//向数组中添加纹理路径
ts.push("img/planplay_1.png");
ts.push("img/planplay_2.png");
ts.push("img/planplay_3.png");
ts.push("img/planplay_4.png");
ts.push("img/planplay_5.png");
ts.push("img/planplay_6.png");
ts.push("img/planplay_7.png");
ts.push("img/planplay_8.png");
ts.push("img/planplay_9.png");
ts.push("img/planplay_10.png");
ts.push("img/planplay_11.png");
			
//创建纹理播放器
var as = new PIXI.extras.AnimatedSprite.fromImages( ts );
//设置播放器位置
as.x = 200;
as.y = 200;
//在应用中添加播放器
app.stage.addChild( as );
//设置动画播放速度
as.animationSpeed = 0.15;
//播放动画
as.play();

 

Chap14_碰撞的判断及利用勾股定理计算出距离

[wm_tips]概念: 碰撞,指的是窗口中两张图片是否有交集。如果有交集,则认为两张图片发生碰撞。[/wm_tips]

一 、假想圆

因为图片形状各异,判断两张图片是否有交集,似乎不太好做,所以为了判断方便, 我们把每张图片都看做一个圆,这个圆,就是我们通常所说的假想圆。

二、碰撞距离

有了假想圆,在判断碰撞时就容易多了,我们只需要判断两个假想圆是否有交集就可以了。

通过上图可以看出,当A、B两张图片中心点距离小于A、B两个假想圆的半径之和时

我们就认为两张图片发生了碰撞。

可问题是:两个假想圆的半径是固定的,但AB中心点的距离如何获得呢?

三、利用勾股定理计算距离

如果我们想要获得AB两个中心点距离,那么必须要用上勾股定理了。

[wm_tips]勾股定理:在直角三角形中,两条直角边的平方和,等于斜边的平方[/wm_tips]

  • 虽然现在c边的距离我们不知道,但a边和b边的距离我们是能求出来的
  • a 边的距离长度 = 子弹的y坐标 – 飞机的y坐标
  • b 边的距离长度 = 子弹的x坐标 – 飞机的x坐标
  • 所以通过勾股定理,我们同样可以求出 c 边长度的平方值

计算公式如下

  • 如果两元素距离 小于等于 碰撞距离,则视为两元素发生碰撞
  • 如果两元素距离的平方值 小于等于 碰撞距离的平方值,则视为两元素发生碰撞

四、碰撞判断步骤总结

  1. 根据元素宽高特点划定假想圆,元素锚点为中心,作为假想圆的圆心位置
  2. 计算碰撞距离:两个元素假想圆半径之和,如果两元素间距小于或等于碰撞距离,则视为发生碰撞
  3. 计算两个元素x轴距离与y轴距离(距离既边长)
  4. 计算两个元素间距:根据勾股定理,得出x轴距离平方+y轴距离平方==间距平方
  5. 如果间距的平方<=碰撞距离的平方(间距<=碰撞距离,由于得到的间距是平方值,所以碰撞距离 也要用平方值)

五、多元素碰撞

示例代码

var app = new PIXI.Application(500,700);
document.body.appendChild( app.view );
			
//添加图片元素(飞机)
var plane = new PIXI.Sprite.fromImage("img/plane.png");
plane.x  = 250;
plane.y  = 650;
//设置飞机图片锚点为中心
plane.anchor.set(0.5,0.5);
app.stage.addChild( plane );
			
//定义变量,敌机计时器
var escount = 0;
//定义变量,子弹计时器
var bscount = 0;
			
//定义数组用于存储敌机元素
var es = [];
			
//定义数组用于存储子弹元素
var bs = [];
			
//自定义帧频函数
function animate(){
	//如果帧频函数执行次数等于60,证明时间过了1秒
	if(escount == 60){
		//添加图片元素(敌机图片)
		var enemy =  new  PIXI.Sprite.fromImage("img/enemy.png");
		//Math.random() * n 获取0~n-1之间的随机数
		enemy.x = Math.random() *(500 - 104 +1);
		//将创建的每个敌机元素添加到数组中
		es.push( enemy );
		app.stage.addChild( enemy );	
		//重置count变量,重新计时
		escount=0;
	}
				
//如果帧频函数执行次数等于120,证明时间过了2秒
	if(bscount == 120 ){
		//添加图片元素(子弹图片)
		var bullet = new PIXI.Sprite.fromImage("img/bullet.png");
		//位置与飞机一致
		bullet.x = plane.x;
		bullet.y = plane.y;
		//设置锚点为中心
		bullet.anchor.set(0.5,0.5);
		//添加到数组中
		bs.push( bullet );
		//添加到应用窗口
		app.stage.addChild( bullet );
					
		//计数器归零
		bscount  = 0;
	}
				
	//遍历数组获取每颗子弹元素,添加动画效果 
	for(var i=0; i<bs.length; i++){
		//子弹向上移动
		bs[i].y-=5;
		//如果敌机移出边界,从数组中移除该元素
		if(bs[i].y<=0){
			//将子弹从应用窗口中移除
			app.stage.removeChild( bs[i] );
			//将子弹从数组中移除
			bs.splice(i,1);
		}	
	}
				
				
	//遍历数组获取每架敌机元素,添加动画效果
	for(var i=0;  i<es.length; i++){ //敌机向下移动 es[i].y+=3; //如果敌机移出边界,从数组中移除该元素 if(es[i].y>=700){
			//将敌机从应用窗口中移除
			app.stage.removeChild( es[i] );
			//将敌机从数组中移除
			es.splice(i,1);				
		}			
	}
				
	//帧频函数执行一次,计数变量+1
	escount++;
	bscount++;
}
//添加帧频函数
app.ticker.add( animate );

敌机数组如下图所示

子弹数组如下图所示

多飞机与多子弹碰撞,必须用每一个子弹元素与每一个飞机分别做碰撞判断

原理如下所示

核心代码

//遍历bs数组获取每颗子弹
for(var i = 0; i<bs.length; i++){
    //获取子弹元素
	var bullet  =  bs[i];
    
	//与每架敌机 碰撞判断
	//遍历es数组获取每架敌机
	for(var j=0; j<es.length; j++){
        //获取敌机元素 
		var enemy = es[j];
		//判断 bullet 是否与 enemy 发生碰撞
		//1、根据元素宽高及特点划定假想圆 
		//敌机元素宽度 104  ,假想圆半径 52
		//子弹元素宽度 50   ,假想圆半径 25
        
		//2、计算碰撞距离:两个元素假想圆半径之和
		var pos =  52+25;
        
		//3、计算元素x,y间距
		//获取x轴间距(边长)
		var xl = bullet.x - enemy.x;
		
        //获取y轴间距(边长)
		var yl = bullet.y - enemy.y;
						
        //4、计算两元素间距
		//xl、yl等于两个直角边的边长,根据勾股定理计算
		//xl*xl + yl*yl 等于 两个元素 间距的平方
						
        //5、如果两元素间距平方<=碰撞距离平方,则视为两元素发生碰撞
		if(xl*xl + yl*yl <= pos*pos){
			//从应用窗口中移除子弹元素
			app.stage.removeChild( bullet );
			//从数中移除子弹元素
			bs.splice(i,1);
			//从应用窗口中移除敌机元素 
			app.stage.removeChild( enemy );
			//从数中移除敌机元素
			es.splice(j,1);
		
		}
    }
}

获取/修改图层编号

  •  页面中每个图片都有自己所对应的图层以及编号,编号从0开始,编号越大图层越高
  • 可以通过修改图层编号设置图片的图层
  • 通过修改图层,可以让子弹一直处于飞机图层的下级

获取图层编号

app.stage.getChildIndex(classify3);

设置图层编号

//将元素的图层设置为指定编号级别 
app.stage.setChildIndex(元素,图层编号);

[wm_warn]注意:如果两元素图层一致,后添加的元素会置于制定编号位置,先添加的元素会自动提高一级。[/wm_warn]

chap13_帧频控制与动画效果

一、定时(计时)动画

[wm_notice]概念:让元素按照一定的时间间隔变化[/wm_notice]

实现方式

  • 已知帧频函数每秒执行60次,可以自定义计数变量,当帧频函数执行时计数变量+1
  • 当计数变量的值为60时,证明帧频函数被调用了60次,也就是过了1秒

示例代码

//略......
//自定义计数变量
var count =  1;
			
//自定义帧频函数(每秒调用60次)
function animate(){
	//在console窗口中输出count变量
	console.log( count );
				
	//帧频函数执行一次,计数变量+1
	count++;
}
//在应用中添加帧频函数
app.ticker.add(animate);

[wm_tips]如果count变量的值为60,证明帧频函数执行了60次 ,时间过了1秒 当count变量的值为60时,执行一次动画效果并将count变量的值重置为0,重新计数[/wm_tips]

示例代码

var app = new PIXI.Application(500,700);
document.body.appendChild( app.view );
			
//添加图片(敌机图片)
var enemy1 = new PIXI.Sprite.fromImage("img/enemy1.png");
app.stage.addChild( enemy1 );
			
//自定义计数变量
var count =  1;
			
//自定义帧频函数(每秒调用60次)
function animate(){
				
	//如果count变量为60证明animate函数执行了60次,也就是过了1秒
	if(count == 60){
		//敌机向下移动30px
		enemy1.y += 30;
		//重置count变量,重新计时
		count = 0;
	}
				
	//帧频函数执行一次,计数变量+1
	count++;
}

//在应用中添加帧频函数
app.ticker.add(animate);

二、定时创建元素与动画效果

[wm_notice]在某个时间周期内创建多个元素并添加动画,让多个元素按照固定的频率变化[/wm_notice]

示例:每秒创建一架敌机

var app = new PIXI.Application(500,700);
document.body.appendChild( app.view );
			
//创建图片元素 (背景图片)
var bg = new PIXI.Sprite.fromImage("img/bg2.jpg");
app.stage.addChild( bg );
			
//定义变量,计时器
var count = 1;
			
//自定义帧频函数【核心代码,在帧频函数中添加元素】
function animate(){
	//时间过1秒,count等于60
	if(count == 60){
		//添加图片元素(敌机图片)
		var enemy1 =  new  PIXI.Sprite.fromImage("img/enemy1.png");
		//Math.random() * n 获取0~n-1之间的随机数
		enemy1.y = Math.random() *(700 - 74 +1);
		enemy1.x = Math.random() *(500 - 104 +1);
		app.stage.addChild( enemy1 );	
		//重置count变量,重新计时
		count=0;
	}
	//帧频函数执行一次,计数变量+1
	count++;
}
			
//添加帧频函数
app.ticker.add( animate );

示例:让飞机向下移动

1、animate函数会反复执行,与循环的效果一致,在animate函数中创建的元素会不断的被覆盖
使用数组,将animate函数创建的每架飞机存储起来避免被覆盖
2、遍历数组获取每架飞机,执行动画

如果飞机移出边界,那么该元素就没有存在的价值了,可以 从数组中移除该元素

//遍历数组获取每架敌机元素,添加动画效果
for(var i=0;  i<enemyList.length;  i++){
	//从数组中提取敌机元素
	var e = enemyList[i];
	//敌机向下移动 
	e.y+=3;
	//如果敌机移出边界,从数组中移除该元素 
	if(e.y>=700)enemyList.splice(i,1);
}

从数组中移除的元素并不会消失在应用窗口中,必须手动从应用窗口中移除

//遍历数组获取每架敌机元素,添加动画效果
for(var i=0;  i<enemyList.length;  i++){
	//从数组中提取敌机元素
	var e = enemyList[i];
	//敌机向下移动 
	e.y+=3;
	//如果敌机移出边界,从数组中移除该元素 
	if(e.y>=700){
        //将敌机从数组中移除
		enemyList.splice(i,1);
		//将敌机从应用窗口中移除
		app.stage.removeChild( e );
	}	
}

Chap12_数组与集中处理方法

一 、数组概念

[wm_notice]用来存储多个数据(变量)的容器,存储在数组中的数据称为数组的元素。【水彩笔】【月饼盒】 特点:便于集中统一管理某些数据[/wm_notice]

例:定义多个变量表示学生的成绩,不便于同一维护

var stu1 = 59;
var stu2 = 60;
var stu3 = 70;
var stu4 = 80;
var stu5 = 45;
var stu6 = 50;
var stu7 = 55;
var stu8 = 61;
//.....100名学生就要定义 100个变量
			
//如何同时为每位同学的成绩加十分?
//如何计算班级平均分?
//如何将不及格的学生成绩改为及格?

[wm_warn]生活中的统一操作:军训(稍息,立正),打仗。反例:《让子弹飞》[/wm_warn]

二、定义数组

1、定义数组语法

【对比变量】

var 数组名称 = [];

var as = [];

2、创建数组时添加数据语法

var as = [数据1,数据2,数据3...];

var as = [59 , 60 , 70 , 80 , 45 , 50 , 55 , 61];
//在控制台输出as中的内容
console.log( as );

此时 as 就表示了一组数据

三、数组存取与删除

[wm_notice]有些时候数组由系统创建 或 无法在创建时得到数据并存入数据 此时必须通过数组提供的函数,当得到数据时再存入数组中[/wm_notice]

1、添加元素(数据 )

语法

数组名称.push( 数据 );

例:向数组中添加数据

var as = [];
//向数组中添加一个元素10
as.push(  10 );
//向数组中添加一个元素20
as.push(  30 );
as.push(  40 );
as.push(  50 );

//在控制台中输出  as
console.log( as);

数组中可以存储任何类型的数据与元素

2、获取元素(数据)

【数据存进去了,怎么用?之前用变量还有个名字,现在每个元素叫什么】

【数组叫什么?as,as[],中括号里写下标,as[下标 ],这就是元素的名字】

数组为每个元素都进行了编号,编号表示该元素在数组中的位置 在程序中我们称该编号为数组的下标 下标从0开始到数组长度-1结束,通过下标可以获取数组中的元素

语法

数组名称[下标];

var as = [50,10,800];
as[0];//数组中的第 1 个元素【第一个变量,名为as[0]】
as[1];//数组中的第 2 个元素【第二个变量,名为as[1]】
as[2];//数组中的第 3 个元素

var a1 = as[0];//提取数组中的第 1 个元素【提取变量,a1可以表示as[0]但不属于数组】
var a2 = as[1];//提取数组中的第 2 个元素【如a = 10, b =  a; b变化不会影响a】
var a3 = as[2];//提取数组中的第 3 个元素
			
//输出数组中的第 1 个元素
console.log( as[0]  );
//输出数组中的第 2 个元素
console.log( as[1]  );
//输出数组中的第 3 个元素
console.log( as[2]  );

使用循环遍历数组【重点】

[wm_tips]遍历数组:获取数组中的每一个元素[/wm_tips]

例:当数组元素很多时不便于统一操作

var as = [50,10,800];			
//输出数组中的第 1 个元素
console.log( as[0]  );
//输出数组中的第 2 个元素
console.log( as[1]  );
//输出数组中的第 3 个元素
console.log( as[2]  );

(重复的步骤放到循环中,不重复的步骤放到循环之外,有规律的变量想办法用循环变量替代)

例:使用循环遍历【重点】

var as = [50,10,800];
//已知as数组长度为3,下标范围0~2
//使用循环变量i充当下标,控制下标范围区间在0~2
//每次循环可以获取数组中的一个元素,直到最后一个元素
for(var i=0; i<3; i++){
    //输出数组中的某个元素
    console.log( as[i]  );
}

【遍历失败案例】例:数组长度改变,遍历失败(准备一个长度为4的数组)

3、获取数组长度

[wm_notice]数组的长度等于数组中的元素个数 在程序中可以动态的获取数组长度,以便在数组元素个数改变时,依然能够正确遍历[/wm_notice]

动态获取数组长度

数组名.length;
例如
var as = [10,20,30];
as.length;//获取as数组长度

使用数组长度增强遍历

//遍历数组
for( var i = 0; i<数组名.length; i++){
    //获取数组中的某个数据
	var a = as[i]);
    //输出到控制台中
	console.log( a );
}

4、删除元素(数据 )

语法

数组名称.splice(下标 , 个数);
个数:从下标位置开始(含下标位置的元素)删除几个元素

例:删除数组中的某一个元素

var as = [100,200,300,400,500];
//删除数组中的某一个元素  数组名称.splice(下标 , 1);
//2:下标
//1:删除1个元素
as.splice(2,1);
//结果:[100,200,400,500];

例:删除数组中的多个元素

var as = [100,200,300,400,500];
//输出as数组中的元素
//从下标0开始删除3个元素 0、1、2元素将被删除
as.splice(0,3);
//结果[400,500];

chap11_循环条件与循环分类

一、循环结构

[wm_notice]概念:循环结构可以 通过某个条件,重复且有规律的执行程序代码[/wm_notice]

顺序执行流程 : 从第一个行开始 执行到最后一行 每行代码的执行次数:1

条件分支执行流程: 经过某个条件决定代码是否执行,每行代码的执行次数:0~1

循环执行流程: 经过某个条件决定代码是否执行,每行代码的执行次数:0~N

var i = 1;
//条件满足 执行 1次
if(i <= 10){
console.log("hello");
}
var i = 1;
//条件满足 执行 n 次
while(i <= 10){
console.log("hello");
}

二、循环分类

1、while循环

语法

while( 循环条件 ){
当满足循环条件时执行
  执行完毕后再次判断条件是否满足,满足则再次执行,直至条件不满足停止循环
}

有限次数循环的三要素

1、定义循环变量:var i = 1;

2、定义循环条件:( i <= 10)

3、改变循环变量的值:i++;

有限次数循环示例(循环输出10个hello)

//1、定义循环变量 (定义起点)
var i = 1;
//2、定义循环条件 (设置终点)
while( i<=10 ){
//需要重复执行的功能代码
  console.log("hello");
//3、改变循环变量的值(控制步长)例:跑步、爬楼梯
i++;
}

2、for循环

[wm_notice]特点:将明确次数循环的三要素融入语法整体[/wm_notice]

语法

for(定义循环变量;定义循环条件 ;改变循环变量的值 ){
当满足循环条件时执行
  执行完毕后再次判断条件是否满足,满足则再次执行,直至条件不满足停止循环
}

示例(输出10个hello)

for(var i = 0; i < 10;  i++){//循环10次
console.log("hello");
}

执行流程与while一致,但代码位置不一样

三、使用循环创建元素

示例代码

var app = new PIXI.Application(500,700);
document.body.appendChild( app.view );
for(var i = 1; i<=10; i++){
//添加图片元素(飞机图片)
var enemy1 = new  PIXI.Sprite.fromImage("img/enemy1.png");
//Math.random() * n:得到0~n-1之间的随机数
//y坐标 随机范围 :0~应用窗口高度-图片高度 +1
enemy1.y = Math.random() * (700-74 +1);
//x坐标 随机范围 :0~应用窗口宽度-图片宽度 +1
enemy1.x = Math.random() * (500-104 +1);
app.stage.addChild( enemy1 );
}

利用JS实现在QQ空间自动为好友点赞功能

每逢节假日或者有什么活动之类的,朋友同学发说说,求关注,自己又没时间去点赞。现在让我们来在QQ空间控制台加上一段代码,一段Javascript代码,让电脑自动为我们点赞。

来看下效果图

使用方法

打开自己的QQ空间,按f12键或右键审查元素 进入控制台,点击console,把下面代码粘贴复制到里面,就完事了。

完整代码

var x=5,y=10;
function autoClick()
{
y=y+5;
var zan=document.getElementsByClassName('item qz_like_btn_v3');
for(var i=0;i<zan.length;i++){
if(zan[i].attributes[6].value=='like'){
zan[i].firstChild.click();
}
};
window.scrollBy(x,y);
}
window.setInterval(autoClick,2000);

解释:window.setInterval(autoClick,2000);  //2000代表两秒屏幕下滑5px;可以自行调

Chap10_逻辑控制&循环与拓展知识

一 、使用变量

[wm_tips]常量:程序出现的固定的数值,例如某个元素的x坐标等于400,某个元素每次移动1px的距离 期中的400与 1就属于常量 使用变量替换程序中的常量,达到改变变量的值控制元素的变化[/wm_tips]

1、定义变量的语法

//在javascript中的变量可以存储任意类型的数据【弱类型】
var 变量名;

例如:

var a;
var b;

2、变量赋值

var 变量名;//定义变量
变量名 = 值;//为变量赋值

//定义变量同时赋值
var 变量名 = 值;

例如:

var a = 10;// a表示整数10
var b =  new PIXI.Text();//b表示文本元素

使用变量时的注意事项

1、先定义再使用

2、javascript中的var变量为全局变量,作用范围在整个应用中

3、变量可以重复定义但新的变量会替换旧变量(旧变量将无法使用)

二、使用变量控制逻辑

[wm_tips]使用变量替换常量,通过改变变量的值让元素产生变化 根据变量所存储的值不同,执行不同的逻辑代码[/wm_tips]

//speed变量:每帧移动的距离
var speed = 1;
//控制是否移动的变量
//1:移动
//0:不移动
var isMove = 1;

拓展知识1:多条件判断

在判断条件中可以使用&&或||进行多条件判断

var a = 10;
var b = 20;
// &&:表示并且,左右两边条件必须同时满足
if( a<b && a>100 )  :不满足
if( a<b && a== 10)  :满足
// ||:表示或者,左右两边条件有一个满足即可
if( a<b || a>100)  :满足
if( a>b || a<5 )  :不满足

拓展知识2:移除帧频动画效果

帧频动画是由自定义帧频函数来完成的,可以在应用中通过代码移除已添加的帧频函数,达到停止动画 的效果

//自定义帧频函数
function f1(){
 
}
//添加帧频函数
app.ticker.add( f1 );
//【移除帧频函数】
app.ticker.remove( f1 );

 

chap9_javascript添加的新知识代码与练习

添加的新知识代码

//设置飞机可移动的边界(包含僚机)
if(pos.x < 110) plane.x = 110;//左侧边界
if(pos.x > 400) plane.x = 400;//右侧边界
if(pos.y < 55)  plane.y = 55;//顶部边界
if(pos.y > 637) plane.y = 637;//底部边界
//在console中输出鼠标的x坐标与y坐标 便于调试
console.log(pos.x+" "+pos.y);
//获取随机数
Math.random() :会得到一个0~1的随机数(包含0不包含1)
Math.random() * 10 :会得到一个0~9的随机数
Math.random() * 100:会得到一个0~99的随机数
Math.random() * n  :会得到一个0~n-1 的随机数
//样式
enemy1.x = Math.random() *(513-113);

练习步骤

1.在页面中创建一个应用窗口(宽:512,高700)

2.在应用窗口中添加背景图片(宽:512默认,高1400)

3.让背景图片能够在应用窗口中向下移动,并在移出窗口前回到原始位置

4.添加云层图片,并实现云层下移

5.添加敌机1,为敌机添加血条,实现敌机1在随机x坐标位置下移

5.1添加敌机2,为敌机添加血条,实现敌机2在随机x坐标位置下移*

6.添加子弹元素

7.添加主战机,让主战机可以发射子弹

8.在主站机左右两侧添加僚机

9.让主站机与僚机能够跟随鼠标移动,但不能移出应用窗口(设置边界)

10.添加经验值图片 ,并实现经验值图标在随机x坐标位置下移

11.添加血条图标(HP+空血条+血条)

12.添加得分文本

参考代码