p5.js小球碰撞程序:修复重复死亡日志与数组中死亡小球替换问题
p5.js小球碰撞程序:修复重复死亡日志与数组中死亡小球替换问题
我明白你现在遇到两个头疼的问题——一是小球死亡时控制台会同时输出三条日志,二是不知道怎么把数组里的死球换成新的。咱们一步步来解决,先搞定重复日志的问题,再处理数组替换的事儿。
一、修复重复死亡日志问题
你当前的lifeCounter方法里,三个if(this.life <=0)是独立的判断逻辑,只要小球生命值归0,三个条件都会触发,所以三条死亡日志会一起打印出来。而且里面的this.alive = false && new Ball(...)写法也不对,&&在这里起不到创建新球的作用,因为this.alive = false已经是布尔值,后面的代码根本不会执行。
咱们可以给Ball类加一个name属性,在构造函数里根据传入的纹理对应上名字,这样死亡时只输出对应名字的日志,同时把三个判断合并成一个:
class Ball { constructor(pos, vel, r, tex) { this.pos = pos; this.vel = vel; this.r = r; this.tex = tex; this.life = 3; this.alive = true; // 根据纹理绑定对应名字 if(tex === subaruImg) { this.name = "subaru"; } else if(tex === emiliaImg) { this.name = "emilia"; } else if(tex === remImg) { this.name = "Rem"; } } lifeCounter() { this.life -= 1; if (this.life <= 0) { this.alive = false; console.log(`${this.name} has died`); } } }
这样每个小球死亡时只会输出自己对应的那条日志,不会再出现三条重复的情况了。
二、替换数组中的死亡小球
问题的核心在于Ball类本身不知道自己在balls数组里的位置,所以没法自己完成替换操作。咱们可以在draw循环里遍历数组时,主动检查每个球的存活状态,一旦发现死球,就生成新的Ball实例替换掉这个位置的元素:
function draw() { // ... 保留原来的背景、灯光等代码 ... for (let i = 0; i < balls.length; i++) { // 先检查当前球是否死亡,是则替换 if (!balls[i].alive) { let pos = createVector( random(-width / 2 + 20, width / 2 - 20), random(-height / 2 + 20, height / 2 - 20), random(-200, 200) ); let vel = p5.Vector.random3D().mult(random(1, 2)); let r = random(20, 30); let tex = random(ballTextures); // 替换数组中的死球 balls[i] = new Ball(pos, vel, r, tex); // 跳过死球的后续操作,直接处理下一个球 continue; } balls[i].move(); balls[i].edgeCheck(); balls[i].drawBall(); for (let j = i + 1; j < balls.length; j++) { balls[i].checkCollision(balls[j]); } } }
这样每次draw循环都会扫描所有小球,一旦发现死亡的就立刻替换成新的,数组长度始终保持你设置的20个,完美解决了不知道索引的问题。
额外小提示
- 原来
lifeCounter里的new Ball写法是无效的,因为只是创建了一个新对象但没有加入到balls数组中,现在咱们在外部循环里处理替换才是正确的方式。 - 如果担心新生成的小球刚出现就和其他球碰撞,可以在生成位置时加个简单的检查,不过当前的随机位置逻辑已经足够避免大部分情况了。
备注:内容来源于stack exchange,提问作者nouserbruh1
相关产品推荐
相关产品推荐

