Code.org GameLab碰撞检测异常问题求助
问题分析与解决方案
核心问题
你的碰撞检测只有约1/3概率生效,根源在于每次生成新香蕉/篮球时,都用新创建的精灵覆盖了全局变量,但场景中旧的精灵仍然存在,而碰撞检测只针对最后一个生成的精灵。
比如每次执行banana = createSprite(randomNumber(30,370)),旧的香蕉并没有被删除,只是全局变量banana指向了新的精灵。你的pleasegodwork函数只检查这个最新的banana和玩家/地面的碰撞,之前生成的香蕉即使碰到玩家也不会触发逻辑,导致大部分碰撞被忽略,看起来只有偶尔(刚好碰到最新的那个)才会生效。
修复步骤
1. 改用数组管理多个精灵
把香蕉和篮球改成数组,用来存储所有生成的精灵,这样就能遍历所有精灵进行碰撞检测:
// 替换原有的单个精灵变量 var bananas = []; var basketballs = [];
2. 修改生成逻辑,添加到数组中
在game函数里,创建新精灵时添加到数组,而不是覆盖变量:
// 香蕉生成部分替换为: if (bananatime > 100){ var newBanana = createSprite(randomNumber(30,370)); newBanana.setAnimation("bannana"); newBanana.velocityY = bananaspeed; newBanana.scale = 0.2; bananas.push(newBanana); // 添加到数组 bananatime = randomNumber(0,75); } // 篮球生成部分替换为: if (ballstime > 100){ var newBall = createSprite(randomNumber(30,370)); newBall.setAnimation("basketball"); newBall.velocityY = basketballspeed; newBall.scale = 0.17; basketballs.push(newBall); // 添加到数组 ballstime = randomNumber(0,75); }
3. 修改碰撞检测函数,遍历数组处理所有精灵
重写pleasegodwork和pleasegodwork2,遍历所有香蕉/篮球进行检测:
///Checks collisions banana x guy function pleasegodwork(){ // 倒序遍历数组,避免删除元素时索引混乱 for(var i = bananas.length - 1; i >= 0; i--){ var banana = bananas[i]; if (banana.isTouching(ground)){ banana.remove(); // 从场景删除精灵 bananas.splice(i, 1); // 从数组移除引用 console.log('help'); } if (banana.isTouching(guy)){ bananatime = randomNumber(0,75); score = score + 1; banana.remove(); // 从场景删除精灵 bananas.splice(i, 1); // 从数组移除引用 } } } //Checks collisions basketball x guy function pleasegodwork2(){ // 倒序遍历数组,避免删除元素时索引混乱 for(var i = basketballs.length - 1; i >= 0; i--){ var ball = basketballs[i]; if (ball.isTouching(ground)){ ball.remove(); // 从场景删除精灵 basketballs.splice(i, 1); // 从数组移除引用 } if (ball.isTouching(guy)){ lives = lives - 1; ball.remove(); // 从场景删除精灵 basketballs.splice(i, 1); // 从数组移除引用 console.log('what') } } }
4. 清理初始代码中的冗余精灵
删除原来的单个香蕉和篮球变量定义,因为现在用数组管理了:
// 删除以下代码块: // var banana = createSprite(690,420); // banana.setAnimation("bannana"); // banana.scale = 0.25; // var basketball = createSprite(690,690); // basketball.setAnimation("basketball"); // basketball.scale = 0.15;
5. 修复其他小问题
reset函数里不需要再处理单个香蕉/篮球,改为清空数组:
function reset(){ // ... 保留原有其他代码 ... // 清空香蕉数组并删除所有精灵 for(var i = bananas.length - 1; i >=0; i--){ bananas[i].remove(); } bananas = []; // 清空篮球数组并删除所有精灵 for(var i = basketballs.length - 1; i >=0; i--){ basketballs[i].remove(); } basketballs = []; }
- 注意
drawSprites()只需要在draw函数末尾调用一次,不要在pleasegodwork里重复调用,否则会导致渲染异常。把pleasegodwork里的drawSprites()删掉,放到draw函数最后:
function draw() { // ... 原有屏幕判断代码 ... pleasegodwork(); pleasegodwork2(); pleasegodwork3(); drawSprites(); // 只在这里调用一次 }
为什么这样能解决问题
通过数组管理所有生成的精灵,每次碰撞检测都会检查场景中存在的每一个香蕉和篮球,而不是只检查最后一个生成的。这样所有精灵的碰撞都会被正确触发,不会再出现“概率性生效”的问题。
内容的提问来源于stack exchange,提问作者24bit
相关产品推荐
相关产品推荐

