基于HTML5的简单游戏动画Demo_update3

本次更新介绍了HTML5游戏动画的改进,包括物体的匀加速运动(抛物运动)、圆周运动的几何实现以及简单的边界碰撞减速效果。通过源码展示了如何实现这些功能,并预告后续将不再另开新文章,所有更新将在同一文章整理,同时会发布基于html5的游戏物理引擎教程。
摘要由CSDN通过智能技术生成

demo运动的小球

update1添加多个角色

update2碰撞检测

==========================~O(∩_∩)O~==========卖萌的分割线===========================================

5月结束前最后一次更新。

和update2相比,这次的新增点包括:

1、匀加速运动。包括两个方向(x和y),程序将给出“y方向的匀加速和x方向的匀速”合运动示例,也就是常见的抛物运动。

2、圆周运动。圆周运动的模型和原来的运动模型不匹配,如果从物理的角度看,圆周运动是由于物体受到向心力而产生的,其中涉及到向心加速度、角速度等问题,过于复杂。这里区别于原来的位移、速度、加速度模型,另外设置了运动圆心、角度、半径模型,从而从纯几何的角度实现圆周运动。当然,边界检测对这个模型就不适用了。

3、模拟碰撞(仅边界检测)使物体减速的效果。在实际场景中,一个物体掉到地上再弹起不可能再回到原来的高度,因为碰到地面后由于形变和阻力等原因导致物体的能量减小,也就是速度变慢。这里采用最简单的方法模拟物体速度变慢的效果。

先来看效果:



动态截图跳帧很厉害,如果想看原来的效果,自己复制粘贴源码到html文件和js文件用浏览器运行一下吧!

另外,碰撞检测的解决方法还没想好,所以干脆先不要碰撞检测了,原来的代码还在,只是暂时没有用到。

下面是这次的源码:

javascript文件

/**	碰撞检测方法
 *	关于碰撞检测的具体方法在写物理引擎的时候再继续完善
 */
function CollisionDetect(spriteA, spriteB) {
	var length = Math.sqrt((spriteA.x-spriteB.x)*(spriteA.x-spriteB.x) + (spriteA.y-spriteB.y)*(spriteA.y-spriteB.y));
	var minLength = spriteA.radius+spriteB.radius;
	if(length <= minLength) {		// 如果碰撞了,停止
		spriteA.speed.x = 0;
		spriteA.speed.y = 0;
		spriteB.speed.x = 0;
		spriteB.speed.y = 0;
	}
};
/**	边界检测
 *	边界检测方法:当前只对MoveXY运动的物体有效
 */
function BoundDetect(sprite) {
	if(sprite.x > 1000-sprite.radius || sprite.x < sprite.radius) {
		sprite.velocity.vx *= (-1);			// 反向
		sprite.velocity.vx += sprite.ax;	// 速度调整
	}
	if(sprite.y > 500-sprite.radius || sprite.y < sprite.radius) {
		sprite.velocity.vy *= (-1);			// 反向
		sprite.velocity.vy += sprite.ay;	// 速度调整
	}
};
function BoundDetect2(sprite) {					// 添加了阻力的碰撞检测
	if(sprite.x > 300-sprite.radius || sprite.x < sprite.radius) {
		sprite.velocity.vx *= (-1);			// 反向
		sprite.velocity.vx += 3*sprite.ax;	// 速度调整
		if(sprite.velocity.vx < 0 && sprite.velocity.vx > -1) {
			sprite.velocity.vx = 0;
			sprite.ax = 0;
		}
	}
	if(sprite.y > 500-sprite.radius || sprite.y < sprite.radius) {
		sprite.velocity.vy *= (-1);			// 反向
		sprite.velocity.vy += 3*sprite.ay;	// 速度调整
		if(sprite.velocity.vy < 0 && sprite.velocity.vy > -1) {
			sprite.velocity.vy = 0;
			sprite.ay = 0;
		}
	}
};
/**	帧频
 */
var ifps = 1000/60;							// 帧频为60fps
/**	帧对象
 */
var Frame = function(ctx) {
	this.sprites = new Array();				// 当前画布中的角色集合
	this.ctx = ctx;							// 帧维护的画布(可以不止一个,这里只用一个)
};
Frame.prototype = {
	refresh : function() {					// refresh方法把当前帧的内容画到画布上,就是更新整个画布
		this.ctx.clearRect(0,0,1000,500);	// 清空画布
		var num = this.sprites.length;
		for(var i = 0; i < num; ++i) {		// 遍历全部内容
			this.sprites[i].draw();			// 调用各自的draw方法
		}
	}
}
/**	角色类设计
 */
var Sprite = function() {
	this.ax = 0;				// 初始加速度ax
	this.ay = 0;				// 初始加速度ay
	this.velocity = {
		vx : 1,					// 初始横向速度
		vy : 1					// 初始纵向速度
	};
	this.round = {				// 圆周运动相关参数
		angularVelocity : -1,	// 角速度
		roundRadius : 0,		// 圆周运动半径
		angle : 0,				// 初始角
		centerX : 0,			// 圆心x
		centerY : 0				// 圆心y
	}
};
Sprite.prototype = {
	draw : function() {	
	},
	moveXY : function() {
		this.x += this.velocity.vx;
		this.y += this.velocity.vy;
		this.velocity.vx += this.ax;
		this.velocity.vy += this.ay;
	},
	moveRound : function() {
		var rm = this.round;
		rm.angle += rm.angularVelocity;
		rm.angle = rm.angle >= 360 ? 0 : rm.angle;
		this.x = rm.centerX + rm.roundRadius * Math.cos(rm.angle*(Math.PI/180));
		this.y = rm.centerY + rm.roundRadius * Math.sin(rm.angle*(Math.PI/180));
	}
};
/**	圆类:继承角色类
 */
var Circle = function(ctx,x,y,radius,style) {
	this.ctx = ctx;
	this.x = x;
	this.y = y;
	this.radius = radius;
	this.propotity = {
		fillStyle:"#acffac",
		strokeStyle:"#000000",
		lineWidth:"2"
	};
};
Circle.prototype = new Sprite();
Circle.prototype.draw = function() {
	this.ctx.beginPath();
	this.ctx.lineWidth = this.propotity.lineWidth;
	this.ctx.strokeStyle = this.propotity.strokeStyle;
	this.ctx.fillStyle = this.propotity.fillStyle;
	this.ctx.arc(this.x,this.y,this.radius,0,Math.PI*2,true);
	this.ctx.stroke();
	this.ctx.fill();
};
/**	自动控制器
 */
var AutoControler = function(aFrame) {
	this.currentFrame = aFrame;
	this.spriteSet;
};
AutoControler.prototype = {

	addSprite : function(aSprite) {				// 添加角色的方法
		if(!this.spriteSet){
			this.spriteSet = new Array();
		}
		this.spriteSet.push(aSprite);
	},
	
	move : function() {							// 控制角色运动的方法
		var self = this;
		var arr = this.spriteSet;
		var len = arr.length;
		for(var i = 0; i < len; ++i) {
			if(arr[i].round.angularVelocity == -1) {
				arr[i].moveXY();
			}
			else {
				arr[i].moveRound();
			}
		}
		this.currentFrame.refresh();
		for(var i = 0; i < len; ++i) {
			BoundDetect(arr[i]);				// 边界检测:检测每一个角色
			//for(var j = 0; j < len; ++j) {
			//	if(i == j) continue;
			//	CollisionDetect(arr[i], arr[j]);
			//}
		}
		setTimeout(function(){self.move();}, ifps);
	},
	
	move2 : function() {						// 碰撞后速度减小
		var self = this;
		var arr = this.spriteSet;
		var len = arr.length;
		for(var i = 0; i < len; ++i) {
			if(arr[i].round.angularVelocity == -1) {
				arr[i].moveXY();
			}
			else {
				arr[i].moveRound();
			}
		}
		this.currentFrame.refresh();
		for(var i = 0; i < len; ++i) {
			BoundDetect2(arr[i]);				// 边界检测:检测每一个角色
		}
		setTimeout(function(){self.move2();}, ifps);
	}

};

html文件

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Moving Circle</title>
<script src="demo.js"></script>
</head>
<body>
<canvas id="zCanvas" width="1000" height="500" style="border:2px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="small" width="300" height="500" style="border:2px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
// 获取当前绘图区
var can = document.getElementById("zCanvas");
var ctx = can.getContext("2d");
// 创建帧对象
frame = new Frame(ctx);
// 构造7个角色
var ca = new Circle(ctx,80,80,10);
var cb = new Circle(ctx,20,20,10);
var cc = new Circle(ctx,50,300,10);
var cd = new Circle(ctx,800,100,10);
var ce = new Circle(ctx,500,200,10);
// 改变角色cb的属性
cb.propotity.fillStyle = "#ff0000";
cb.velocity = {vx:0, vy:0};
cb.ay = 0.3;
// 改变角色cc的属性
cc.propotity.fillStyle = "#8888aa";
cc.velocity = {vx:5, vy:0};
cc.ay = 1;
// 改变角色cd的属性
cd.propotity.fillStyle = "#0000ff";
cd.velocity = {vx:3,vy:1};
// 改变角色ce的属性
ce.propotity.fillStyle = "#aaff00";
ce.velocity = {vx:1,vy:2};
// 创建做圆周运动的角色
var cr = new Circle(ctx,80,80,10);
var cs = new Circle(ctx,80,80,10);
// 修改cr属性
cr.propotity.fillStyle = "#aa55bb";
cr.round = {angularVelocity : 5, roundRadius : 50, angle : 0, centerX : 200, centerY : 200};
// 修改cs属性
cs.propotity.fillStyle = "#ffcc88";
cs.round = {angularVelocity : 5, roundRadius : 80, angle : 0, centerX : 500, centerY : 200};
// 把角色添加到帧
frame.sprites.push(ca);
frame.sprites.push(cb);
frame.sprites.push(cc);
frame.sprites.push(cd);
frame.sprites.push(ce);
frame.sprites.push(cr);
frame.sprites.push(cs);
// 创建控制器对象
var controler = new AutoControler(frame);
controler.addSprite(ca);
controler.addSprite(cb);
controler.addSprite(cc);
controler.addSprite(cd);
controler.addSprite(ce);
controler.addSprite(cr);
controler.addSprite(cs);
controler.move();

var canr = document.getElementById("small");
var ctxr = canr.getContext("2d");
var framer = new Frame(ctxr);
var cra = new Circle(ctxr,50,50,20);
cra.propotity.fillStyle = "#ff8888";
cra.velocity = {vx:3, vy:0};
cra.ay = 0.5;
framer.sprites.push(cra);
var controlerr = new AutoControler(framer);
controlerr.addSprite(cra);
controlerr.move2();
</script>
</body>
</html>

注意改一下js文件名。

从下一次更新开始,所有的更新将在下一篇文章里面整理,不会再另开新的文章。另外,基于html5的游戏物理引擎的文章将会发布。

物理引擎部分将会以该系列为基础进行讲解。敬请期待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值