| 首页 | 新闻 | 网页 | 设计 | 色彩 | 原创 | 视觉 | 素材 | 动漫 | 酷站 | 策划 | 文案 | 访谈 | 运营 | 编程 | 数据库 | 服务器 | 下载 | 图库 | 
您的位置: 幽幽天空 > 网页 > 网页制作 > Flash教程 > ActionScript教程 > 文章正文 用户登录
新手速建海量软件
物理知识在FLASH世
浅谈应用按钮事件
浅谈AS的绘图功能
浅谈AS与物理运动
利用文本框制作简
初级物理模型的构
初级物理模型的构
初级物理模型的构
初级物理模型的构

初级物理模型的构建(AS)-力学1 基本知识2 碰撞的检测           

初级物理模型的构建(AS)-力学1 基本知识2 碰撞的检测

作者:佚名 来源:闪吧 作者: EmilMatthew 更新:2007-1-13 20:47:27 错误报告 我要投稿

在物理模型,尤其是动量,碰撞类实验中,碰撞的检测方法的优劣无疑决定着整个程序摸拟效果的好坏。碰撞检测函数的构造难度随着碰撞复杂程度的增加而增加。

a) 平面上两个物体的碰撞:

//a)最简单的二物碰撞。

if(mc1.getBounds(_root).xMax>=mc2.getBounds(_root).xMin){//mc1.hitTest(mc2)

例子1:二球动量守恒(速度过大时会出问题,原因在序2中有讲)

UploadFile/2004-8/20048420614911.swf

例子2:三球动量守恒:(速度过大时会出问题,原因在序2中有讲)

UploadFile/2004-8/2004851211341.swf

这个是有方向的,只检测了

//b)框与小物块的碰撞。

//这里参考了FLASH SAMPLE中那个迷宫的源文件,里面的用getBounds来做的碰撞很棒。

function checks(mc1,mc2){//specialize collision detect

if(mc2.hitTest(mc1.getBounds(_root).xMax,mc1._y,true)){

collision(mc1,mc2);

}

else if(mc2.hitTest(mc1.getBounds(_root).xMin,mc1._y,true)){

collision(mc2,mc1);

}

}

例子:框与木块(速度过大时会出问题,原因在序2中有讲)

UploadFile/2004-8/200482021202779.swf

//c)两个小球的碰撞,半径法:

if(Math.sqrt((balla._x-ballb._x)*(balla._x-ballb._x)+(balla._y-ballb._y)*(balla._y-ballb._y))<=(balla.r+ballb.r))

例子1:三球互碰系统:

实现方式:碰撞半径检测法+二维碰撞动量守恒公式(1.d+(Whether really departure detect是否真正分离的检测)

一开始写三球互碰系统时采用的技术只用了“碰撞半径检测法+二维碰撞动量守恒公式”

核心程序清单:



///***Fundamental Function***///

function collisiondetect(mc1, mc2) {

if(Math.sqrt((mc1._x-mc2._x)*(mc1._x-mc2._x)+(mc1._y-mc2._y)*(mc1._y-mc2._y))<=mc1.r+mc2.r) {

collisionx(mc1, mc2);

collisiony(mc1, mc2);

}

}

function collisionx(mc1, mc2) {

var v1temp = mc1.vx;

var v2temp = mc2.vx;

mc1.vx=((mc1.m-e*mc2.m)/(mc1.m+mc2.m))*v1temp+((1+e)*mc2.m/(mc1.m+mc2.m))*v2temp;

mc2.vx = ((1+e)*mc1.m/(mc1.m+mc2.m))*v1temp-((e*mc1.m-mc2.m)/(mc1.m+mc2.m))*v2temp;

}

function collisiony(mc1, mc2) {

var v1temp = mc1.vy;

var v2temp = mc2.vy;

mc1.vy= ((mc1.m-e*mc2.m)/(mc1.m+mc2.m))*v1temp+((1+e)*mc2.m/(mc1.m+mc2.m))*v2temp;

mc2.vy = ((1+e)*mc1.m/(mc1.m+mc2.m))*v1temp-((e*mc1.m-mc2.m)/(mc1.m+mc2.m))*v2temp;

}

MovieClip.prototype.Move = function(vx, vy) {

// 构造专属的move函数。

this._x += vx;

this._y += vy;

};

///**Combine Function*////

function SumCollision() {

collisiondetect(balla, ballb);

collisiondetect(balla, ballc);

collisiondetect(ballb, ballc);

bordercollisiondetect(balla);

bordercollisiondetect(ballb);

bordercollisiondetect(ballc);

}

function SumMove() {

balla.Move(balla.vx, balla.vy);

ballb.Move(ballb.vx, ballb.vy);

ballc.Move(ballc.vx, ballc.vy);

}

_root.onEnterFrame = function() {

SumCollision();

SumMove();

Debugger();

};

但是不足之处是显然的,那就是没有加是否真正分离的判定,结果造成了这个有BUG的碰撞效果:

UploadFile/2004-8/20048520718753.swf

之所以出现两个小球在一起“打架”的情况,是因为两球碰后的速度不足以保证二者分开,于是在下次又进入碰撞判定,刚才的速度还是分离的,现在又相向了,于是就不断的呈现出“粘在一起”的现象。

后来想了一下,给每个球建立一个c属性,用于标识其是否碰撞,碰撞后为1,当检测两个球的距离大于半径之和, c变为0,进入碰撞检测判断,照此不断的在

“碰撞断定”---“碰后检测”----“分开”----“碰撞判定”间进行循环,效果的确不错,

UploadFile/2004-8/20048621362191.swf

例子2

核心算法:

function PreciseCollisionRender(mc1, mc2) {// 确定是否分开

if(Math.sqrt((mc1._x-mc2._x)*(mc1._x-mc2._x)+(mc1._y-mc2._y)*(mc1._y-mc2._y))>mc1.r+mc2.r+1) {

mc1.c = 0;

mc2.c = 0;

}

}

function collisiondetect(mc1, mc2) {

if (mc1.c == 1 && mc2.c == 1) {

PreciseCollisionRender(mc1, mc2); // *****ok,no problem

}

elseif(Math.sqrt((mc1._x-mc2._x)*(mc1._x-mc2._x)+(mc1._y-mc2._y)*(mc1._y-mc2._y))<=mc1.r+mc2.r) {

collisionx(mc1, mc2);

collisiony(mc1, mc2);

mc1.c = 1;

mc2.c = 1;

}

}

其实用这样的两个球之间的c值进行标识的方法在逻辑上还是有些说不过去,如果几个球同时碰时问题似乎就复杂了,但是从效果上来看,由于在碰后的几帧内(即便是在墙角边),两球的分开也是很必然的,所以,这样一个理由不是很充足的写法倒也说得过去,怎样就完配了呢,我想了一下,用一个二维数组来标识一组球的碰撞情况,如ball1ball2就用a[1][2]来标识,这样这两个小球间的“碰撞断定”---“碰后检测”----“分开”----“碰撞判定”的循球,就由这一个二维数组元素来进行唯一的标识,通过数组元素值倒底是1还是0决定每帧里两个小球间进入何种检测,这就是我比较满意的一个七球碰撞系统:

UploadFile/2004-8/200481117051510.swf

例子3

完整的程序清单:

#include "Physics.as"

_root.onLoad = function() {

ball1.CreatePhysicsFeature(1, 0, 0, 8, 6, 15);

ball2.CreatePhysicsFeature(1, 0, 0, -7, 5, 15);

ball3.CreatePhysicsFeature(1, 0, 0, 8, -9, 15);

ball4.CreatePhysicsFeature(1, 0, 0, 5, -5, 15);

ball5.CreatePhysicsFeature(1, 0, 0, 5, -2, 15);

ball6.CreatePhysicsFeature(1, 0, 0, 6, -6, 15);

ball7.CreatePhysicsFeature(1, 0, 0, 7, -6, 15);

for (var i = 1; i<8; i++) {//创建用于标识二球间状况的二维数组

eval("ball"+i).n(i);

}

_global.a = new Array();

for (var i = 1; i<7; i++) {

a[i] = new Array();

for (var j = i+1; j<8; j++) {

a[i][j] = 0;

}

}

};

///***Fundamental Function***///

function PreciseCollisionRender(mc1, mc2) {// 确定是否分开

if(Math.sqrt((mc1._x-mc2._x)*(mc1._x-mc2._x)+(mc1._y-mc2._y)*(mc1._y-mc2._y))>mc1.r+mc2.r+1) {

a[mc1.n][mc2.n] = 0;

}

}

function collisionx(mc1, mc2) {

var v1temp = mc1.vx;

var v2temp = mc2.vx;

mc1.vx=((mc1.m-e*mc2.m)/(mc1.m+mc2.m))*v1temp+((1+e)*mc2.m/(mc1.m+mc2.m))*v2temp;

mc2.vx = ((1+e)*mc1.m/(mc1.m+mc2.m))*v1temp-((e*mc1.m-mc2.m)/(mc1.m+mc2.m))*v2temp;

}

function collisiony(mc1, mc2) {

var v1temp = mc1.vy;

var v2temp = mc2.vy;

mc1.vy= ((mc1.m-e*mc2.m)/(mc1.m+mc2.m))*v1temp+((1+e)*mc2.m/(mc1.m+mc2.m))*v2temp;

mc2.vy = ((1+e)*mc1.m/(mc1.m+mc2.m))*v1temp-((e*mc1.m-mc2.m)/(mc1.m+mc2.m))*v2temp;

}

MovieClip.prototype.Move = function(vx, vy) {

// 构造专属的move函数。

this._x += vx;

this._y += vy;

};

function bordercollisiondetect(mc) {//碰边检测

if (mc.getBounds(_root).xMin<1) {

mc._x = 1+mc.r;

mc.vx *= -1;

}

if (mc.getBounds(_root).xMax>399) {

mc._x = 399-mc.r;

mc.vx *= -1;

}

if (mc.getBounds(_root).yMin<1) {

mc._y = 1+mc.r;

mc.vy *= -1;

}

if (mc.getBounds(_root).yMax>399) {

mc._y = 399-mc.r;

mc.vy *= -1;

}

}

//**Combine Function**//

function collisiondetect(mc1, mc2) {

if (a[mc1.n][mc2.n] == 1) {

PreciseCollisionRender(mc1, mc2);

}

elseif(Math.sqrt((mc1._x-mc2._x)*(mc1._x-mc2._x)+(mc1._y-mc2._y)*(mc1._y-mc2._y))<=mc1.r+mc.r) {

collisionx(mc1, mc2);

collisiony(mc1, mc2);

a[mc1.n][mc2.n] = 1;

}

}

function SumCollision() {

for (var i = 1; i<7; i++) {

for (var j = i+1; j<8; j++) {

collisiondetect(eval("ball"+i), eval("ball"+j));

}

}

for (var i = 1; i<8; i++) {

bordercollisiondetect(eval("ball"+i));

}

}

function SumMove() {

for (var i = 1; i<8; i++) {

eval("ball"+i).Move(eval("ball"+i).vx, eval("ball"+i).vy);

}

}

_root.onEnterFrame = function() {

SumCollision();

SumMove();

};

文章录入:skyuu    责任编辑:skyuu 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    发表评论:
    姓名:  评 分: 1分 2分 3分 4分 5分
     
  • 严禁发表危害国家安全、政治、黄色淫秽等内容的评论。
  • 用户需对自己在使用幽幽天空服务过程中的行为承担法律责任。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表机友个人观点,与本网站立场无关。