AS3游戏开发角色非预期下落 falling布尔值判定异常问题
AS3平台游戏角色穿透下落问题修复
问题描述
- 实现角色未站在物体顶部时自动下落的功能后,布尔变量
falling会在不满足触发条件时持续保持为true - 角色短暂停驻在平台后会穿透平台下落,已确认诱因是
velocity数值增长后超出地板判定范围,在代码其他位置重置velocity后问题仍存在 - 已在
gameEngine函数的if(falling)代码块中标记了临时解决方案的注释,原始代码如下:
// Imports import flash.events.KeyboardEvent; import flash.events.Event; // Constants that can be edited const grav:Number = 0.05; const jumpPow:Number = 15; const walkingDistance = 50; // Variables var jumpVel:Number = jumpPow; var velocity:Number = 0; var dt:Number = 0; var movingCount:Number = 0; var newX:Number = 0; var newY:Number = 0; var charCornerHit:Number = 0; // 0 = TL 1 = TR 2 = BR 3 = BL (clockwise) var jumping:Boolean = false; var falling:Boolean = false; var movingRight:Boolean = false; var movingLeft:Boolean = false; var hitDetVal:Boolean = false; // false var floorHit:Boolean = false; var object1Hit:Boolean = false; var cCnrTL:Array = new Array(char.x, char.y); var cCnrTR:Array = new Array(char.x + char.width, char.y); var cCnrBR:Array = new Array(char.x + char.width, char.y + char.height); var cCnrBL:Array = new Array(char.x, char.y + char.height); var charCorners:Array = new Array(cCnrTL, cCnrTR, cCnrBR, cCnrBL); // Clockwise addEventListener(Event.ENTER_FRAME, gameEngine); function gameEngine(evt:Event):void{ stage.addEventListener(KeyboardEvent.KEY_DOWN, moveCharacter); charCorners[0][0] = char.x; charCorners[0][1] = char.y; charCorners[1][0] = char.x + char.width; charCorners[1][1] = char.y; charCorners[2][0] = char.x + char.width; charCorners[2][1] = char.y + char.height; charCorners[3][0] = char.x; charCorners[3][1] = char.y + char.height; //trace(char.y); // Check if char is standing on something // Supposed to only check when character is not falling if (falling == false) { //trace(char.y + char.height + 1) hitDetection(0, char.y + char.height + 1) if (hitDetVal == false) { falling = true; hitDetVal = false; trace("not standing"); } else {trace("standing on something");} } // Move char loop if (movingRight){ if (movingCount == walkingDistance) { movingCount = 0 movingRight = false; } else { char.x+=1 movingCount += 1; } } else if (movingLeft) { if (movingCount == walkingDistance) { movingCount = 0 movingLeft = false; } else { char.x-=1 movingCount += 1; } } //trace(velocity) if (falling) { dt += 1 velocity = velocity + grav*dt hitDetection(0, velocity) if (hitDetVal) { falling = false; hitDetVal = false; // TEMPORARY SOLUTION - Stopped character from falling past the floor but still ran falling condition //velocity = 0; //dt = 0; if (floorHit) { if (char.y < floor.y){ char.y = floor.y - char.height; floorHit = false; trace("Char Stopped falling") } } else if (object1Hit) { if (char.y - char.height < object1.y){ char.y = object1.y - char.height; object1Hit = false; trace("Char Stopped falling") } } } else { char.y += velocity; } } else { if (jumping) { } velocity = 0; dt = 0; } } function moveCharacter(event:KeyboardEvent):void{ if(event.keyCode == Keyboard.LEFT){ if(movingRight){ movingRight = false; trace("STOPPED") } else { movingCount = 0 movingLeft = true; trace("LEFT"); } } if(event.keyCode == Keyboard.RIGHT){ if(movingLeft){ movingLeft = false; trace("STOPPED") } else { movingCount = 0 movingRight = true; trace("RIGHT"); } } if(event.keyCode == Keyboard.UP){ jumping = true; trace("UP"); } } function hitDetection(distX:Number, distY:Number) { for (var i:uint = 0; i < charCorners.length; i++) { newX = charCorners[i][0] + distX; newY = charCorners[i][1] + distY; if (floor.hitTestPoint(newX, newY, true)){ hitDetVal = true; floorHit = true; charCornerHit = i; break; } else if (object1.hitTestPoint(newX, newY, true)){ hitDetVal = true; object1Hit = true; charCornerHit = i; break; } } }
核心问题点
- 碰撞检测函数状态残留:
hitDetection没有在入口处重置hitDetVal/floorHit/object1Hit三个标记,上次检测的结果会残留到本次,导致判定完全失真。 - 站立检测传参错误:站立检测时把绝对坐标
char.y + char.height +1当成了偏移量传入,检测点直接被甩到角色下方极远位置,根本碰不到脚下的平台,自然会持续判定角色悬空,把falling设为true。 - 落地状态重置被注释:被注释掉的
velocity = 0和dt = 0是必须的逻辑,落地后不重置下落速度和重力累计时间,速度会持续累加,单帧位移过大直接穿过碰撞体。 - 键盘监听重复注册:把键盘监听写在
ENTER_FRAME循环里,每帧都会新增一个监听,按一次键会触发多次移动逻辑,运行越久越卡。 - 跳跃逻辑缺失:按上键只改了
jumping标记,没有给向上的初速度,跳跃功能完全没生效。
修复方案
直接按以下点改代码即可:
- 把
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveCharacter);移到gameEngine函数外面,和ENTER_FRAME监听放在一起,只注册一次。 - 在
hitDetection函数最开头加三行重置状态的代码:hitDetVal = false; floorHit = false; object1Hit = false; - 修正站立检测的传参,把
hitDetection(0, char.y + char.height + 1)改成hitDetection(0, 1),只检测角色脚下1像素位置是否有平台。 - 取消
velocity = 0;和dt = 0;两行的注释,落地时必须重置下落速度和重力累计值。 - 补全跳跃逻辑,在非下落状态检测到
jumping为true时,给velocity赋值为-jumpPow,把falling设为true,再把jumping重置为false。
内容的提问来源于stack exchange,提问作者Goat
相关产品推荐
相关产品推荐

