[初学]H5+PHP 在线坦克开发日记

      着手开始写原计划php小组项目的网络坦克对战。当时决定做游戏的原因是猫哥有h5开发能力,但现在自己做,自己要去学h5的东西。现在记录下学习和开发的过程。

2016.7.26

      实现了坦克在空白地图上的移动。

      途中遇到的问题:

          坦克图片空白位置覆盖地图:

      解决方案:通过美图秀秀抠图功能将坦克图抠下,并保存为png图片(如保存为jpg,则空白部分会变成白色,效果跟上图一样,原因是jpg没有alpha通道)

      这个问题困扰了我两天,一开始以为是绘图方式的问题,学习了两张绘图方式,之后发现,并不是。然后才在图片上找原因。

目前完成的代码:

main.js

var canvas_width = 1280,
	canvas_height = 900;
var key_up = 38,
	key_down = 40,
	key_left = 37,
	key_right = 39;
var canvas, stage;
var txt;
var tank;

window.onload = function() {
	creatcanvas();
	stage = new createjs.Stage(canvas)

	tank = new tankObj();
	txt = new createjs.Text("", "20px Arial", "#ff7700");
	stage.addChild(tank.now);

	createjs.Ticker.setFPS(60);
	createjs.Ticker.addEventListener("tick", tick);
}

document.onkeydown = function(e) {
	e = !e ? window.event : e;
	console.log(e.keyCode);
	switch (e.keyCode) {
		case key_up:
			tank.now = tank.up;
			tank.ctrlary[0] = true;
			break;
		case key_down:
			tank.now = tank.down;
			tank.ctrlary[1] = true;
			break;
		case key_left:
			tank.now = tank.left;
			tank.ctrlary[2] = true;
			break;
		case key_right:
			tank.now = tank.right;
			tank.ctrlary[3] = true;
			break;
			return;
	}
}
document.onkeyup = function(e) {
	e = !e ? window.event : e;
	console.log(e.keyCode);
	switch (e.keyCode) {
		case key_up:
			tank.ctrlary[0] = false;
			break;
		case key_down:
			tank.ctrlary[1] = false;
			break;
		case key_left:
			tank.ctrlary[2] = false;
			break;
		case key_right:
			tank.ctrlary[3] = false;
			break;
	}
}

function tick(e) {
	if (tank.ctrlary[0] == true) {
		if(tank.now.y - tank.speed > 0)
			tank.now.y = (tank.y -= tank.speed);
		else
			tank.now.y = tank.y;
		tank.now.x = tank.x;
		console.log(tank.now.x, tank.now.y);
	}
	if (tank.ctrlary[1] == true) {
		if(tank.now.y + tank.speed < canvas_height - 60)
			tank.now.y = (tank.y += tank.speed);
		else
			tank.now.y = tank.y;
		tank.now.x = tank.x;
		console.log(tank.now.x, tank.now.y);
	}
	if (tank.ctrlary[2] == true) {
		if (tank.now.x - tank.speed > 0)
			tank.now.x = (tank.x -= tank.speed);
		else
			tank.now.x = tank.x;
		tank.now.y = tank.y;
		console.log(tank.now.x, tank.now.y);
	}
	if (tank.ctrlary[3] == true) {
		if (tank.now.x + tank.speed < canvas_width - 60)
			tank.now.x = (tank.x += tank.speed);
		else
			tank.now.x = tank.x;
		tank.now.y = tank.y;
		console.log(tank.now.x, tank.now.x);
	}
	stage.removeChildAt(0);
	stage.addChild(tank.now);
	stage.update();
}

function timepass(e) {
	console.log(tank.now.x);
	var time = new Date();
	txt.text = "Now Time : " + time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds() + "!";
	stage.update();
}


tank.js
var tankObj = function(){
	this.x = 0; //坦克x坐标
	this.y = 0; //坦克y坐标
	this.speed = 10;
	this.up = new createjs.Bitmap("img/tank-up.png");
	this.left = new createjs.Bitmap("img/tank-left.png");
	this.right = new createjs.Bitmap("img/tank-right.png");
	this.down = new createjs.Bitmap("img/tank-down.png");
	this.now = this.down; //坦克朝向
	this.up.scaleX = this.up.scaleY =this.down.scaleX = this.down.scaleY = this.left.scaleX = this.left.scaleY =this.right.scaleX = this.right.scaleY =0.3;
	this.ctrlary = [false,false,false,false]; //按键数组,true为按下,0123分别对应上下左右
};


7.30

      27号出了不朽三,滚去玩了几天的dota。当然!我不可能单纯只玩dota!因为月末了嘛,炉石低保还是要拿的,这个月前半个月都在期末复习培训什么的,炉石天梯都没打,又花了些时间!不过!这几天空闲的时候我还是有想一些问题的。早上出去拿物流,下午才开工,7点完成。那么进入正题。

      今天完成了单机攻击AI坦克,主要实现了发射炮弹,炮弹判定(击中,出界),以及AI坦克。

首先是发射炮弹:

首先tank类添加了一些属性

增加:count(填弹计时器) ProV(填弹速度),bulV(炮弹速度),boomtime(爆炸状态)以及AIcontime(AI当前状态时间,在AI里说明)

修改:新增参数tanktpye,传递坦克模型。扩增ctrlyary数组空间,代表开火状态,即空格键状态

var tankObj = function(tanktpye) {
	this.x = 0; //坦克x坐标
	this.y = 0; //坦克y坐标
	this.speed = 5;
	this.count = 0; //填弹计时器
	this.ProV = 20; //填弹速度
	this.bulV = 8;
	this.AIcontime = 0; //AI保持当前状态时间
	this.boomtime = 0; //爆炸状态
	this.up = new createjs.Bitmap("img/" + tanktpye + "-up.png");
	this.left = new createjs.Bitmap("img/" + tanktpye + "-left.png");
	this.right = new createjs.Bitmap("img/" + tanktpye + "-right.png");
	this.down = new createjs.Bitmap("img/" + tanktpye + "-down.png");
	this.now = this.down; //坦克朝向
	this.up.scaleX = this.up.scaleY = this.down.scaleX = this.down.scaleY = this.left.scaleX = this.left.scaleY = this.right.scaleX = this.right.scaleY = 0.3;
	this.ctrlary = [false, false, false, false, false]; //按键数组,true为按下,0123分别对应上下左右,4代表开火状态
};

整合函数:将控制坦克函数封装入tank.js内

tankObj.prototype.movement = function() {
	if(this.boomtime != 0) 
		return;
	if (this.ctrlary[0] == true) {
		if (this.now.y - this.speed > 0)
			this.now.y = (this.y -= this.speed);
		else
			this.now.y = this.y;
		this.now.x = this.x;
	}
	if (this.ctrlary[1] == true) {
		if (this.now.y + this.speed < canvas_height - 60)
			this.now.y = (this.y += this.speed);
		else
			this.now.y = this.y;
		this.now.x = this.x;
	}
	if (this.ctrlary[2] == true) {
		if (this.now.x - this.speed > 0)
			this.now.x = (this.x -= this.speed);
		else
			this.now.x = this.x;
		this.now.y = this.y;
	}
	if (this.ctrlary[3] == true) {
		if (this.now.x + this.speed < canvas_width - 60)
			this.now.x = (this.x += this.speed);
		else
			this.now.x = this.x;
		this.now.y = this.y;
	}
}
新增爆炸函数用于处理坦克集中后动画及移除
tankObj.prototype.boom = function(){
	if(this.boomtime >= 20)
		return ;
	if(this.boomtime % 2 == 0){
	stage2.removeChild(this.now);
	this.now = new createjs.Bitmap("img/boom_"+this.boomtime/2+".png");
	this.now.x = this.x;
	this.now.y = this.y;
	this.now.scaleX = this.now.scaleY = (0.6 - 0.1*this.boomtime);
	stage2.addChild(this.now);
	}
	this.boomtime++;
}
爆炸图片编号为0-9,原本写boomtime上限是10即每一帧刷新换一张爆炸图片,效果不够明显,就换成2帧换一张,每一帧更新一次缩放,效果我说不清,就跟烟花一样,爆炸后向左上飘散,等我什么时候心情好了做个gif吧,下面附上爆炸每帧的原图


新增炮弹类

bullet.js

var bulletObj = function() {
	this.bullet = new createjs.Bitmap("img/bullet.png");
	this.bullet.scaleX = this.bullet.scaleY = 0.3;
	this.faceX = 0;
	this.faceY = 0;
}
bulletObj.prototype.movement = function(i) {
	this.bullet.x += this.faceX;
	this.bullet.y += this.faceY;
	if (bullet[i].bullet.x < 0 || bullet[i].bullet.y < 0 || bullet[i].bullet.x > canvas_width || bullet[i].bullet.y > canvas_height) {
		stage2.removeChild(bullet[i].bullet);
		bullet.splice(i, 1);
	}
}
其中faceX,faceY记录炮弹方向,faceX=-1代表向上发射

bullet为子弹数组定义在main.js中,movement函数每一次刷新都会调用,用于子弹移动已经出界判断

tank.js新增开火函数

tankObj.prototype.onfire = function() {
	if (this.boomtime != 0)
	return;
	if (this.count == 0) {
		if (this.ctrlary[4] == false)
			return;
		var len = bullet.length;
		bullet[len] = new bulletObj();
		switch (this.now) {
			case this.up:
				bullet[len].bullet.x = this.x + 27;
				bullet[len].bullet.y = this.y;
				bullet[len].faceY = -this.bulV;
				break;
			case this.down:
				bullet[len].bullet.x = this.x + 27;
				bullet[len].bullet.y = this.y + 60;
				bullet[len].faceY = this.bulV;
				break;
			case this.left:
				bullet[len].bullet.x = this.x;
				bullet[len].bullet.y = this.y + 20;
				bullet[len].faceX = -this.bulV;
				break;
			case this.right:
				bullet[len].bullet.x = this.x + 60;
				bullet[len].bullet.y = this.y + 20;
				bullet[len].faceX = this.bulV;
				break;
		}
		stage2.addChild(bullet[len].bullet);
		this.count = this.ProV;
	} else {
		this.count--;
	}
}
每一次刷新都会调用一次开火函数,只有当填弹完成(count=0)并且空格被按下(ctrlary[4]=true)才会触发开火,如果填弹未完成则填弹(count--),开火是通过判断坦克朝向设置子弹初始位置(bullet.x,bullet.y),已经子弹方向(faceX,faceY)

修改test.js

新增:敌人坦克数组entanks,爆炸中坦克数组boomtanks,子弹数组bullet,攻击判断函数AttackJudge,全局变量canvas2和stage2

修改:canvas创建函数createcanvas,帧刷新函数tick,主函数onload以及用于检测开火按键(空格)状态的对应函数

createcanvas函数

function creatcanvas() {
	canvas = document.createElement("canvas");
	canvas.id = "canvas";
	canvas.width = canvas_width;
	canvas.height = canvas_height;
	canvas.style.background = "green";
	document.body.appendChild(canvas);
	canvas2 = document.createElement("canvas");
	canvas2.id = "canvas2";
	canvas2.width = canvas_width;
	canvas2.height = canvas_height;
	canvas.style.position = canvas2.style.position = "absolute";
	canvas.style.buttom = canvas.style.left = canvas2.style.buttom = canvas2.style.left = 0;
	document.body.appendChild(canvas2);
}
增加第二个canvas标签创建,并设置两个canvas等大小,设置position为absolute,同时获取舞台2stag2,之后子弹,敌对坦克都在stage2刷新

attackjudge函数

function AttackJudge() {
	for (var i = 0; i < bullet.length; i++)
		for (var j = 0; j < entanks.length; j++) {
			if (bullet[i].bullet.x > entanks[j].x + 60)
				continue;
			if (bullet[i].bullet.y > entanks[j].y + 60)
				continue;
			if (bullet[i].bullet.x + 5 < entanks[j].x)
				continue;
			if (bullet[i].bullet.y + 5 < entanks[j].y)
				continue;
			stage2.removeChild(bullet[i].bullet);
			//			stage2.removeChild(entanks[j].now);
			bullet.splice(i, 1);
			boomtanks[boomtanks.length] = entanks[j];
			entanks[j].boom();
			entanks.splice(j, 1);
		}
}<strong>
</strong>

 遍历所有子弹,判定子弹与所有敌对坦克的位置关系,一旦有重合则将子弹移除数组,敌对坦克移动到爆炸中坦克数组,并执行爆炸函数 

onload函数

window.onload = function() {
	creatcanvas();
	stage = new createjs.Stage(canvas);
	stage2 = new createjs.Stage(canvas2);

	tank = new tankObj("tank");
	for (var i = 0; i < 3; i++) {
		entanks[i] = new tankObj("tank2");
		entanks[i].x = entanks[i].now.x = Math.random() * (canvas_width - 60);
		entanks[i].y = entanks[i].now.y = Math.random() * (canvas_height - 60);
		stage.addChild(entanks[i].now);
	}
	stage.addChild(tank.now);

	createjs.Ticker.setFPS(60);
	createjs.Ticker.addEventListener("tick", tick);
}
添加敌对(AI)坦克创建循环

tick函数
function tick(e) {
	tank.movement();
	tank.onfire();
	if (bullet.length != 0)
		for (var i = 0; i < bullet.length; i++) {
			bullet[i].movement(i);
		}
	stage.removeAllChildren();
	for(var i = 0; i<entanks.length;i++){
		entanks[i].AImove();
		entanks[i].movement();
		stage.addChild(entanks[i].now);
	}
	stage.addChild(tank.now);
	AttackJudge();
	for(var i = 0; i < boomtanks.length; i++){
		if(boomtanks[i].boomtime >= 20 ){
			stage2.removeChild(boomtanks[i].now);
			boomtanks.splice(i,1);
			continue;
		}
		boomtanks[i].boom();
	}
	stage.update();
	stage2.update();
}
封装坦克移动函数以tank.js,tick调用坦克移动函数movement,以及开火函数onfire。当屏幕中有子弹时遍历子弹数组调用子弹移动函数movement。新增循环用于调用AI坦克移动函数,新增循环用于爆炸中坦克动画处理。

坦克AI移动

tankObj.prototype.AImove = function() {
	if(this.AIcontime != 0){
		this.AIcontime--;
		return;
	}
	var x = parseInt(Math.random() * 5);
	for (var i = 0; i < 5; i++)
		this.ctrlary[i] = false;
	switch(x){
		case 0:
			this.now = this.up;
			this.ctrlary[0] = true;
			break;
		case 1:
			this.now = this.down;
			this.ctrlary[1] = true;
			break;
		case 2:
			this.now = this.left;
			this.ctrlary[2] = true;
			break;
		case 3:
			this.now = this.right;
			this.ctrlary[3] = true;
			break;
		case 4:
			this.ctrlary[4] = true;
			return;
			return;
	}
	this.AIcontime = 20;
}

AI坦克将保持移动动作20帧,随后从新随机选择一个方向移动,并重置AIcontime用于计算当前动作保持帧数,这里坦克移动方向随机,AI还没编写攻击性,只用于攻击判断attackjudge函数实验,计划中并不准备编写攻击性,毕竟要做成联网的。

7.31

在媳妇儿的监督下,效率提升,没几个小时就完成了昨天计划今天完成的东西。开始今天的正题。

今天完成了,地图,包括基础地形,特殊地形(坦克无法通行并且炮弹无法通行,坦克无法通行但炮台能通过)。写完这些还有半天以上的时间,本来想把坦克与坦克直接的碰撞也些,不过想了些细节的东西,因为涉及到AI要改很多地方,而且以后做成联网对战的还要不能用,就没去写。准备写完博客帮媳妇儿看算法。

新增地形类

landform.js

var landformObj = function() {
	this.landary = []; //地形数组
	this.tankland = []; //坦克通行数组,0为可通过
	this.bulletland = []; //炮弹通行数组,0为可通过
	this.landform = []; //地形图片
	this.background = []; //背景图片
}
地形数组landary中存放图片编号,,坦克通行数组tankland用于存放相对于tank的地形,炮弹通行数组bulletland用于存放相对于炮弹的地形

定义地图生成函数buildlandform

landformObj.prototype.buildlandform = function() {
	//	this.readlandform() //预留,从服务器上获取地形数组
	for (var i = 0; i < this.landary.length; i++) {
		this.landform[i] = new Array();
		this.background[i] = new Array();
		for (var j = 0; j < this.landary[i].length; j++) {
			this.background[i][j] = new createjs.Bitmap("img/land_0.png");
			this.background[i][j].x = j * 64;
			this.background[i][j].y = i * 60;
			stage2.addChild(this.background[i][j]);
			if (this.landary[i][j] != 0) {
				this.landform[i][j] = new createjs.Bitmap("img/land_" + this.landary[i][j] + ".png");
				this.landform[i][j].x = j * 64;
				this.landform[i][j].y = i * 60;
				stage2.addChild(this.landform[i][j]);
			}
		}
	}
}

每个地形尺寸都为64*60px。

附上地形素材:

草地(坦克以及炮弹都可通行)

河流(坦克不可通行但炮弹可通行)


岩石(坦克以及炮弹都不可通行)

这里需要补充,因为地形的原因,我修改了main.js中createcanvas函数

function creatcanvas() {
	canvas = document.createElement("canvas");
	canvas.id = "canvas";
	canvas.width = canvas_width;
	canvas.height = canvas_height;
	//	canvas.style.background = "green";
	canvas2 = document.createElement("canvas");
	canvas2.id = "canvas2";
	canvas2.width = canvas_width;
	canvas2.height = canvas_height;
	canvas.style.position = canvas2.style.position = "absolute";
	canvas.style.buttom = canvas.style.left = canvas2.style.buttom = canvas2.style.left = 0;
	//	canvas.style.z - index = 1;
	//	canvas2.style.z - index = 0;
	document.body.appendChild(canvas2);
	document.body.appendChild(canvas);
}
这里修改了下两个canvas的插入顺序,让stag2的canvas先插入,这样stag1就会在stag2上面,不这样做的,位于stag2的地形图片会覆盖位于stag1上的坦克图片


定义坦克通行判断函数tankJudge以及炮台通行判断函数bulletJudge

landformObj.prototype.tankJudge = function(x, y) {
	var ruj = Math.floor(x / 64); //右上角X坐标所在格子j坐标
	var rui = Math.floor(y / 60); //右上角Y坐标所在格子i坐标
	var ldj = Math.floor((x + 50) / 64); //左下角X坐标所在格子j坐标
	var ldi = Math.floor((y + 50) / 60); //左下角Y坐标所在格子i坐标
	if (rui < 0)
		rui = 0;
	if (ruj < 0)
		ruj = 0;
	if (ldi > 14)
		ldi = 14;
	if (ldj > 19)
		ldj = 19;
	if (this.tankland[rui][ruj] != 0) {
		console.log("rui,ruj");
		console.log(rui, ruj);
		return false;
	}
	if (this.tankland[rui][ldj] != 0) {
		console.log("rui,ldj");
		console.log(rui, ldj);
		return false;
	}
	if (this.tankland[ldi][ruj] != 0) {
		console.log("ldi,ruj");
		console.log(ldi, ruj);
		return false;
	}
	if (this.tankland[ldi][ldj] != 0) {
		console.log("ldi,ldj");
		console.log(ldi, ldj);
		return false;
	}
	return true;
}
landformObj.prototype.bulletJudge =function(x,y){
	var ruj = Math.floor(x / 64); //右上角X坐标所在格子j坐标
	var rui = Math.floor(y / 60); //右上角Y坐标所在格子i坐标
	var ldj = Math.floor((x + 5) / 64); //左下角X坐标所在格子j坐标
	var ldi = Math.floor((y + 5) / 60); //左下角Y坐标所在格子i坐标
	if (rui < 0)
		rui = 0;
	if (ruj < 0)
		ruj = 0;
	if (ldi > 14)
		ldi = 14;
	if (ldj > 19)
		ldj = 19;
	if (this.bulletland[rui][ruj] != 0) {
		console.log("rui,ruj");
		console.log(rui, ruj);
		return false;
	}
	if (this.bulletland[rui][ldj] != 0) {
		console.log("rui,ldj");
		console.log(rui, ldj);
		return false;
	}
	if (this.bulletland[ldi][ruj] != 0) {
		console.log("ldi,ruj");
		console.log(ldi, ruj);
		return false;
	}
	if (this.bulletland[ldi][ldj] != 0) {
		console.log("ldi,ldj");
		console.log(ldi, ldj);
		return false;
	}
	return true;
}
修改坦克移动函数

tankObj.prototype.movement = function() {
	if (this.boomtime != 0)
		return;
	if (this.ctrlary[0] == true) {
		if (this.now.y - this.speed > 0)
			this.now.y = (this.y - this.speed);
		else
			this.now.y = this.y;
		this.now.x = this.x;
	}
	if (this.ctrlary[1] == true) {
		if (this.now.y + this.speed < canvas_height - 60)
			this.now.y = (this.y + this.speed);
		else
			this.now.y = this.y;
		this.now.x = this.x;
	}
	if (this.ctrlary[2] == true) {
		if (this.now.x - this.speed > 0)
			this.now.x = (this.x - this.speed);
		else
			this.now.x = this.x;
		this.now.y = this.y;
	}
	if (this.ctrlary[3] == true) {
		if (this.now.x + this.speed < canvas_width - 60)
			this.now.x = (this.x + this.speed);
		else
			this.now.x = this.x;
		this.now.y = this.y;
	}
	if (landform.tankJudge(this.now.x, this.now.y) == false) {
		this.now.x = this.x;
		this.now.y = this.y;
	} else {
		this.x = this.now.x;
		this.y = this.now.y;
	}
}
每次完成移动后,不刷新而是进入tankJudge函数判断新的坐标是否处于可通行的位置,如果不可则返回原来的坐标,可通行则刷新。

修改炮弹移动函数

bulletObj.prototype.movement = function(i) {
	this.bullet.x += this.faceX;
	this.bullet.y += this.faceY;
	if (bullet[i].bullet.x < 0 || bullet[i].bullet.y < 0 || bullet[i].bullet.x > canvas_width || bullet[i].bullet.y > canvas_height || landform.bulletJudge(bullet[i].bullet.x, bullet[i].bullet.y) == false) {
		stage2.removeChild(bullet[i].bullet);
		bullet.splice(i, 1);
	}
}
出界或遇到不可通行地形时皆消失。

附目前运行截图


7.31晚

跟媳妇儿闲聊的时候有了新的想法,只要定义一个函数就可以进行完成坦克碰撞判断,其他地方都不需要修改,下面是新定义的坦克碰撞判断函数covertank

covertank函数

tankObj.prototype.covertank = function(x, y) {
	for (var i = 0; i < entanks.length; i++) {
		if (entanks[i] == this)
			continue;
		if (entanks[i].x >= x + 50)
			continue;
		if (entanks[i].x + 50 <= x)
			continue;
		if (entanks[i].y >= y + 50)
			continue;
		if (entanks[i].y + 50 <= y)
			continue;
		return false;
	}
	if (this != tank) {
		if (tank.x >= x + 50)
			return true;
		if (tank.x + 50 <= x)
			return true;
		if (tank.y >= y + 50)
			return true;
		if (tank.y + 50 <= y)
			return true;
		return false;
	}
	return true;
}
这个地形通行判断也可以用这个算法,可以提高判断精度,不过地形的数组比较大会影响效率。

然后在坦克移动函数movement里调用这个函数就好了,方式和坦克通行判断函数tankJudge一样。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
代码来源:http://xxling.com/blog/article/75.aspx 我只是将其代码中asp实例改成了php,转载及使用必须注明原作者。 请遵循原作者开放分享的方式,请勿用来赚取积分!!! 代码做的非常简单,只是用于演示,没有加入任何过滤函数。请务必修改(加入过滤函数)后使用,【坚决不能】直接用于网站!! 之前没怎么接触过js,也是随手做一个。如果不满意请各位多包含,毕竟我不是骗分,也请您高抬贵手。 目前网上看到最好的一个HTML5批量上传程序,它使用纯html+js进行批量上传,不需要flash、jquery等额外组件,大小只有10KB左右。 主要是我想研究一下html5批量上传,但发现纯html5在php中会出现超时、没有进度等问题,于是这网上找了一圈。发现目前的代码,要不就是传统的flash,要不就是调用臃肿的jquery,要不就是代码动辄几百K,根本没法分析。而且CSDN上资源骗分居多,找了一圈花了几十分,还是没下载到一个真正满意的代码。 于是根据这位博主的分享,把原程序精简,并改为了php脚本。因为我php也是初学,之前一直出现只上传1个文件的问题。后来发现是由于定义秒为文件名,本地速度过快将前面的函数覆盖了。多亏了php的sleep,才将这个问题解决。 于是这个简单的批量上传组件就这样做好了,欢迎各位测试和修改。 最后再次提醒各位务必牢记原作者xiaolingzi和其博客地址地址: http://xxling.com/blog/article/75.aspx 转载请注明原作者,修改和使用也不要去掉js的作者标记。 毕竟那标记就一行,人家写个程序很不容易,请各位尊重作者的劳动。谢谢各位配合!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值