用200行代码,创造出逼真的人工生命Floy
创始人
2025-09-22 16:06:56
0

本文来自微信公众号:集智俱乐部 (ID:swarma_org),作者:集智百科团队,原文标题:《用200行代码,创造出逼真的人工生命Floy丨集智百科》


导语


“集智百科精选”是一个长期专栏,持续为大家推送复杂性科学相关的基本概念和资源信息。作为集智俱乐部的开源科学项目,集智百科希望打造复杂性科学领域最全面的百科全书,欢迎对复杂性科学感兴趣、热爱知识整理和分享的朋友加入,文末可以扫码报名加入百科志愿者!


目录


1.人工生命Floy模拟程序


2.Floy模拟模型


2.1程序说明


2.2模型的规则


2.3模型的参数


3三维的Floy鸟群模拟模型


3.1程序说明


4相关wiki


1.人工生命Floy模拟程序


根据Floy模拟模型制作的javascript程序:


2.Floy模拟模型


名称:人工生命


作者:Ariel Dolan


源代码:文件:Floy.zip


2.1程序说明


生命是什么?我们能不能造出生命来?看看上面的程序。


你看到了什么?一群苍蝇在飞舞?这是简简单单的动画么?这些家伙是“活”的么?我可以告诉你,这群飞舞的动物叫Floy,它既不是苍蝇也不是蝌蚪,而是人工生命!这就是一段简简单单的程序,而且代码的长度才有200多行!


单击Properties按钮,你可以改变这群Floy的属性,首先我们为了从简单开始把Floy的个数更改为1个看看,点击OK返回以后再按一下Continue按钮,一只Floy在围绕着中心转,也许你会说,这没什么,不就是一个运动的点么?如果更改Floy的个数为2个,那么这两只Floy就会互相追逐着在屏幕上飞行,注意两只Floy的行为就会产生混沌模式了,也就是它们的运动方式几乎是完全不确定的。逐渐增加到15只以上你就会看到一大群生物在那里乱飞了,这很像我们现实世界中的苍蝇行为。点击Strangers按钮,你会看到一只红色的Floy从屏幕的左上角飞进来,注意,它的到来可不寻常,它是一个外来的入侵者!本来相安无事的绿色Floy因为它的到来而变得行为异常起来,它们会突然转过头来进攻红色的入侵者,而红色的Floy会赶忙逃跑。继续点击Strangers按钮,就会有不断的入侵者加入进来,同时原有的Floy群体在减少。你会看到有两群苍蝇在那里追逐。绿色的Floy是本地居民,它会进攻入侵者最后将它杀死。如果幸运,你甚至会看到绿色的Floy们会使用诡计,它们先若无其事的在一起飞即使身边就有一只红色的入侵者,但是突然之间,它会转过头来进攻红色的,让它来不及逃跑。点击Default按钮可以恢复原状。


2.2模型的规则


为什么这一群小点在这么简单的程序之下会有这样复杂的行为?它们是怎么实现的?注意,虽然这也是编程,但我们并不是按照传统的方法对所有Floy的集体行为在每一种可能的情况都编程,而是给每一个个体Floy制定简单的规则,这样Floy集体的复杂行为就会自然而然的涌现出来了!那么个体Floy的规则是什么呢?它是遵循下面的规律:


首先找到和自己最近的几只(邻居数)的Floy作为自己的邻居;


对于每个邻居如果它是自己的同类那么然后分别计算与这些邻居之间的距离;


如果太近(距离小于碰撞距离)就朝向远离这个邻居的方向加速飞翔;


如果较远(距离大于碰撞距离)就朝向靠近这个邻居的方向加速飞翔;


如果邻居是自己的异类;


如果这只Floy是绿色的则以非常快的加速度向对方进攻;


如果这只Floy是红色的陌生者则当小于碰撞距离的时候以非常快的加速度逃离,并且自己的能量减小;当距离不是很大时,停止加速。


总体来说,Floy的规则就是选择自己的加速度,并且这种选择仅仅跟自己的邻居有关,也就是说规则都是局部的。而这个程序的关键是要体现整体行为的涌现,也就是说虽然微观上每个Floy个体的规则都是简单的局部的,但是在集体涌现出来的现象却是复杂的并且是不可预测的。人工生命的精髓就是:其实生命现象本身不过是由微观的简单相互作用规律涌现出来的集体复杂行为。


2.3模型的参数


进一步,你可以探索更改参数对这群Floy的影响。你可以点击Behavior按钮,Floy的个性会改变,有温顺的也有疯狂的。它们的行为完全是由几个简单参数制约的,再次点击Properties按钮,那里面的参数制约了每个Floy个体的行为自然也就制约了Floy整体的涌现规律。其中各个参数的意义:加速度就是指每只苍蝇进行加速靠近或者远离的最小加速度值;中心吸引度是为了让Floy能够围绕屏幕中心旋转而让它们的加速度都有一个指向中心的分量;碰撞距离定义多少像素距离是叫做碰撞,从而Floy们选择远离还是靠近;最大速度是为了Floy们的行为不至于太疯狂也就是速度固定一个上限;反弹速度是当Floy撞击墙壁的时候反弹回来的速度;间隔时间是控制整个程序快慢的参数;初始速度是每只苍蝇在开始的初速度;自由重组邻居的概率:为了让Floy们的行为中有一定的随机不确定性,它们会以自由重组邻居的概率重新随机的选择自己的邻居(正常情况下是选择距离最小的若干Floy作为自己的邻居),如果这个概率指定为0那么Floy的行为就没那么有趣了;邻居数目定义了每只Floy可以有多少邻居。


接下来我们能干什么?也许你觉得这个简单程序太没趣了,应该把它改为三维的动画。没问题,这个要求还算容易满足。你只要点击这里就能看到三维的Floy。但是因为Java本身的限制,动画不如用Maya之类的三维软件作的好看,但是这个程序却反映了规律的本质,有兴趣的朋友完全可以把这个动画用Maya作一遍,这样你可以给每个Floy赋予贴图裁质,那样也许更有趣。


也许三维的Floy仍然不够有趣,我们能不能再想出点疯狂的?


进化!首先让每只Floy都拥有自己的个性,然后让Floy能够进行有性繁殖,并且后代Floy能够继承父母的特性,没问题,请看能够进化的Floy。


3.三维的Floy鸟群模拟模型


名称:3d的Floy


作者:Ariel Dolan


源代码:Floy3d.zip


3.1程序说明


如果二维的Floy还看得不够过瘾,那么请看三维Floy程序,这里,每个Floy遵循的规则和前面叙述的基本Floy的规则一样,其中每只Floy都有两个邻居。


根据3D Floy模拟模型制作的javascript程序:


也许三维的Floy仍然不够有趣,我们能不能再想出点疯狂的?进化!首先让每只Floy都拥有自己的个性,然后让Floy能够进行有性繁殖,并且后代Floy能够继承父母的特性,没问题,请看期待后续进化的Floy。


4.相关wiki


人工生命:


https://wiki.swarma.org/index.php/%E4%BA%BA%E5%B7%A5%E7%94%9F%E5%91%BD


生命游戏:


https://wiki.swarma.org/index.php/%E5%BA%B7%E5%A8%81%E7%9A%84%E7%94%9F%E5%91%BD%E6%B8%B8%E6%88%8F_Conway%27s_Game_of_Life


Boid模型:


https://wiki.swarma.org/index.php/%E9%B8%9F%E7%BE%A4%E7%AE%97%E6%B3%95_Boids


代码(2DFloy代码如下)


//Global configuration for all Floys


constDEFAULT_CONFIG={


NF:15,//Number of Floys


REVDIST:200,//Reverse distance


ACC:0.3,//Acceleration


ACCTOMID:0.1,//Acceleration to middle


MAXSPEED:5.0,//Maximum speed


BOUNCESPEED:0.8,//Bounce speed


NUMNB:2,//Number of neighbors to consider


V0:4.0,//Initial velocity


KICK:0.05,//Kick strength


TYPE:0,//Floy type


MARGIN:30,//Margin for initialization


SLEEP:10//Animation sleep time


};


//Floy class implementation


classFloy{


//Static configuration that can be modified at runtime


static config={...DEFAULT_CONFIG};


//Calculate distance between two Floys-matching Java version exactly


getDistance(other){


constdx=this.x-other.x;


constdy=this.y-other.y;


returndx*dx+dy*dy;//Return squared distance like Java version


}


//Randomize velocity-matching Java version


randomize(){


this.vx=(Math.random()*Floy.config.V0*2-Floy.config.V0);


this.vy=(Math.random()*Floy.config.V0*2-Floy.config.V0);


}


constructor(x,y,canvas){


this.x=x;


this.y=y;


this.xtail=x;


this.ytail=y;


this.vx=0;//Changed from dx to vx to match Java version


this.vy=0;//Changed from dy to vy to match Java version


this.canvas=canvas;


this.neighbors=new Array(Floy.config.NUMNB).fill(null);


this.color='#ffffff';


this.type=0;


this.energy=100;


this.xc=x;


this.yc=y;


//Initialize velocity using randomize method


this.randomize();


}


//Get neighbors-improved version matching Java implementation


getNeighbors(allFloys){


//First pass:find closest neighbors


constsortedFloys=allFloys


.filter(floy=>floy!==this)


.sort((a,b)=>this.getDistance(a)-this.getDistance(b));


//Initialize neighbors array if needed


if(!this.neighbors){


this.neighbors=new Array(Floy.config.NUMNB).fill(null);


}


//Set initial neighbors


for(let i=0;i


this.neighbors[i]=sortedFloys[i]||null;


}


//Second pass:check neighbors of neighbors(exact Java implementation)


for(let i=0;i


if(!this.neighbors[i])continue;


constng=this.neighbors[i];


for(let j=0;j


if(!ng.neighbors[j])continue;


//Check if neighbor's neighbor is closer


if(this.getDistance(ng.neighbors[j])


this.neighbors[i]=ng.neighbors[j];


}


//Prioritize aggressive Floys


if(ng.neighbors[j].type===1){


this.neighbors[i]=ng.neighbors[j];


}


//Calculate center of neighbors


let xc=0,yc=0;


let validNeighbors=0;


for(let i=0;i


if(this.neighbors[i]){


//If neighbor is self,replace with first neighbor's neighbor


if(this.neighbors[i]===this&&this.neighbors[0]){


this.neighbors[i]=this.neighbors[0];


}


xc+=this.neighbors[i].x;


yc+=this.neighbors[i].y;


validNeighbors++;


}


//Update center coordinates


if(validNeighbors>0){


this.xc=xc/validNeighbors;


this.yc=yc/validNeighbors;


}else{


this.xc=this.x;


this.yc=this.y;


}


//Process movement-exactly matching Java version's implementation


process(){


this.xtail=this.x;


this.ytail=this.y;


let rev=-1;


for(let i=0;i


if(!this.neighbors[i])continue;


constd=this.getDistance(this.neighbors[i]);


if(d===0){


rev=0;


}elseif(d


if(this.neighbors[i].type!==this.type){


if(this.type===1){


this.energy--;


rev=-30;


}else{


rev=30;


}


}else{


rev=-1;


}


}else{


if(this.type===1){


if(this.neighbors[i].type===1){


rev=1;


}else{


rev=0;


}


}elseif(this.neighbors[i].type===1){


rev=20;


}else{


rev=1;


}


//Apply acceleration exactly as in Java version


if(this.x


this.vx+=Floy.config.ACC*rev;


}else{


this.vx-=Floy.config.ACC*rev;


}


if(this.y


this.vy+=Floy.config.ACC*rev;


}else{


this.vy-=Floy.config.ACC*rev;


}


//Speed limits


if(this.vx>Floy.config.MAXSPEED)this.vx=Floy.config.MAXSPEED;


if(this.vx


if(this.vy>Floy.config.MAXSPEED)this.vy=Floy.config.MAXSPEED;


if(this.vy


//Boundary handling


if(this.x<0){


this.vx=Floy.config.BOUNCESPEED;


if(document.getElementById('joySound')){


document.getElementById('joySound').play().catch(e=>{});


}


if(this.x>this.canvas.width){


this.vx=-Floy.config.BOUNCESPEED;


if(document.getElementById('joySound')){


document.getElementById('joySound').play().catch(e=>{});


}


if(this.y<0){


this.vy=Floy.config.BOUNCESPEED;


if(document.getElementById('joySound')){


document.getElementById('joySound').play().catch(e=>{});


}


if(this.y>this.canvas.height){


this.vy=-Floy.config.BOUNCESPEED;


if(document.getElementById('joySound')){


document.getElementById('joySound').play().catch(e=>{});


}


//Center attraction for normal type


if(this.type===0){


if(this.x


if(this.x>this.canvas.width/2)this.vx-=Floy.config.ACCTOMID;


if(this.y


if(this.y>this.canvas.height/2)this.vy-=Floy.config.ACCTOMID;


}


//Update position


this.x+=this.vx;


this.y+=this.vy;


//Update color


this.updateColor();


}


//Update color


updateColor(){


//Default white


this.color='#ffffff';


//Aggressive Floy is magenta


if(this.type===1){


this.color='#FF00FF';


}


//Energy depletion turns green


if(this.energy<1){


this.color='#00FF00';


this.type=0;


}


//Draw the Floy-enhanced version with tail and energy indicator


draw(ctx){


//设置颜色


ctx.strokeStyle=this.color;


ctx.fillStyle=this.color;


//计算尾巴长度和角度


constdx=this.x-this.xtail;


constdy=this.y-this.ytail;


consttailLength=Math.sqrt(dx*dx+dy*dy);


constextendedTailLength=tailLength*3;//延长尾巴长度


//计算尾巴的起点,使尾巴更长


consttailStartX=this.x-(dx/tailLength)*extendedTailLength;


consttailStartY=this.y-(dy/tailLength)*extendedTailLength;


//绘制尾巴(线段)


ctx.beginPath();


ctx.moveTo(tailStartX,tailStartY);


ctx.lineTo(this.x,this.y);


ctx.lineWidth=1;


ctx.stroke();


//绘制主体(小圆点)


ctx.beginPath();


ctx.arc(this.x,this.y,3,0,Math.PI*2);


ctx.fill();


//对于异类Floy,绘制能量指示器


if(this.type===1){


ctx.beginPath();


ctx.fillStyle=`rgba(255,0,0,${this.energy/100})`;


ctx.arc(this.x,this.y,5,0,Math.PI*2);


ctx.fill();


}


代码可上下滑动查看


作者简介


glider,集智百科重度爱好者


本词条由集智俱乐部众包生产,难免存在纰漏和问题,欢迎大家留言反馈,一经采纳,可以获得对应的积分奖励噢!


加入我们亲爱的社区伙伴与知识探索者:


我们诚挚邀请热爱知识分享的您,加入集智百科词条编写志愿团队!无论您是领域专家,还是对特定主题充满热忱的学习者,这里都有您的舞台。通过编写百科词条,您将为全球读者传递权威知识,同时获得专家指导个人能力跃升的双重成长。


志愿者职责


创作新词条:覆盖复杂系统、人工智能等前沿领域


迭代经典内容:更新现有词条,守护知识的准确性与时效性


质量守护者:参与内容校对审核,共建精品知识库


我们期待您


集智读书会成员(需完成共创任务并获得退费资格)


拥有清晰表达复杂概念的写作能力


对特定领域有深度研究或强烈兴趣


具备信息检索与整合素养


怀揣责任感与协作精神,愿为知识共享赋能


您将收获


百科积分(支持兑换集智俱乐部周边:文化衫、复杂科学知识卡等)


集智俱乐部创始人张江教授亲自指导写作


科研助理晋升通道:表现优异者可加入张江教授科研团队


加入张江组发起的任何一期读书会并完成共创任务即可让我们一起,用知识连接世界!


参考资料


[1]FLOY模型的原始网站:https://mybiosoftware.com/tag/floys


[2]作者网站:http://www.aridolan.com/


[3]动态滑翔机机图片:


https://www.wikiwand.com/en/articles/Glider_(Conway%27s_Game_of_Life)


「大模型时代下的Agent建模与仿真」读书会


集智俱乐部联合山东工商学院副教授高德华、天津大学教授薛霄、北京师范大学教授张江、国防科技大学博士研究生曾利共同发起「大模型时代下的Agent建模与仿真」读书会。读书会自2025年7月8日开始,每周二晚上7:30-9:30进行,预计持续分享8周左右。扫码加入Agent建模与仿真的前沿探索之旅,一起共学、共创、共建、共享「大模型时代下的Agent建模与仿真」社区,共同畅想大模型时代人工社会的未来图景!


核心问题


Agent建模与仿真是什么,核心技术发生了怎样的演变?


大模型时代,Agent建模与仿真会给复杂系统理论带来哪些突破?


大模型如何赋能Agent实现自主思考与动态适应?


大模型驱动的Agent交互会涌现出什么新型的社会现象?


Agent建模与仿真如何改变金融、心理、管理、军事等领域的研究范式?


你将收获


梳理Agent建模与仿真的历史发展脉络与方法论;


掌握一套理解、分析、控制、预测复杂系统的计算实验框架;


掌握基于多主体强化学习的复杂系统优化方法;


领略领域前沿学者的研究体系与科研路径。

相关内容

热门资讯

原创 杜... 近日,据TA记者Will Guillory报道称:“一切迹象表明,凯文-杜兰特很快将与火箭签下一份续...
原创 齐... 9月20日晚8点,青岛青春足球场将上演一场焦点战——齐鲁德比火爆开打!主场作战的青岛海牛将迎战同省劲...
体检查出肝囊肿,是肝癌前兆吗?... 太原龙城中医医院科普:不少人在体检报告中看到 “肝囊肿” 的诊断时,会立刻联想到肝癌,担心这是癌症的...
员工患抑郁症可以辞退吗? 抑郁症是现在最常见的一种心理疾病,以连续且长期的心情低落为主要的临特征,是现代人心理疾病最重要的类型...
原创 医... “饭后一根烟,快活似神仙”的陈旧观念早已淡出人们视野,取而代之的是“饭后百步走,活到九十九”的养生口...
原创 霜... 霜降将至,菜市场的角落里悄悄出现了一群"土疙瘩"——带着新鲜泥土的芋艿,正挤挤挨挨地堆在竹筐里。这其...
我,投资人,打算在港股IPO博... 本文来自微信公众号:数星星的星哥 (ID:gh_e6a9d8423302),作者:singsing2...
国产品牌注意,海外医美修护品牌... 本文来自微信公众号:亿邦动力 (ID:iebrun),作者:张从容,原文标题:《国产品牌注意!海外医...
2025三亚旅行社排名:吉宏道... 2025三亚旅行社排名:吉宏道与远胜游,藏在细节里的三亚游答案 准备去三亚的人,多半会卡在 “选哪家...
原创 韩... 韩国位于东亚地区朝鲜半岛南部,面积约10.3万平方公里,人口约5143万,首都为首尔。首尔原名汉城,...