我正试图通过击中班级wall
孩子的任何一方来避免玩家朝某个方向移动。
如果我添加了多个wall
的子项,它将被添加到舞台上,但只有一个孩子会获得类命令块(代码)。
我在做什么...
时间轴
var canplayerMoveToTop = true;
var canplayerMoveToBottom = true;
var canplayerMoveToLeft = true;
var canplayerToRight = true;
function addPlayerToStage(playerX, playerY) {
var addingPlayerTo:player = new player(playerX, playerY);
addChild(addingPlayerTo);
return addingPlayerTo;
}
var playerOn = addPlayerToStage(25, 35);
function addWall(XChoosen, YChoosen) {
var addingWall:testWall = new testWall();
addingWall.x = XChoosen; addingWall.y = YChoosen;
addChild(addingWall);
return addingWall;
}
var myNewWall = addWall(155, 55);
var anotherWall = addWall(355, 55);
墙
package {
import flash.display.MovieClip;
import flash.events.Event;
public class testWall extends MovieClip {
public function testWall() {
addEventListener(Event.ADDED_TO_STAGE, whenWasThisWallAdded);
}
public function whenWasThisWallAdded(e:Event):void {
addEventListener(Event.ENTER_FRAME, checkAndUpdateGround);
}
public function checkAndUpdateGround(e:Event):void {
if (this.bottomC.hitTestObject(MovieClip(root).playerOn)) {
parent['canplayerMoveToTop'] = false;
}
else if (this.topC.hitTestObject(MovieClip(root).playerOn)) {
parent['canplayerMoveToBottom'] = false;
}
else if (this.leftC.hitTestObject(MovieClip(root).playerOn)) {
parent['canplayerToRight'] = false;
}
else if (this.rightC.hitTestObject(MovieClip(root).playerOn)) {
parent['canplayerMoveToLeft'] = false;
}
else {
parent['canplayerMoveToTop'] = true;
parent['canplayerMoveToBottom'] = true;
parent['canplayerMoveToLeft'] = true;
parent['canplayerToRight'] = true;
}
}
}
}
答案 0 :(得分:2)
两面墙最有可能获得该功能,但由于它们都修改了父(canplayerMoveToTop
,canplayerMoveToBottom
等)中的相同属性,因此您只能看到最后一面墙的结果运行checkAndUpdateGround
功能(它会覆盖其他墙壁设置的值。
您应该能够使用一些跟踪语句验证这一点。
答案 1 :(得分:2)
问题的原因是关注点分离不良和缺乏封装。
你的班级Wall
(testWall
对于一个班级来说是一个坏名字,他们应该从一个大写名称开始,并且在考试之前进行考试"有点无意义,因为在开发过程中,你总是在测试)做得太多(关注点分离)。
它不仅可以hitTest
,还可以设置其他对象的一些变量,即canplayerMoveToLeft
等。它不应该这样做。这是您设计中的问题。
以这种方式思考:常规hitTestObject
仅返回true或false。它不会将任何变量设置为true或false。这使它非常灵活,更具普遍性。
你打破了这一点,不是简单地返回一个值,而是设置变量。提供某些东西并强迫他们接受它之间的区别。你在做后者。为了做到这一点,Wall类必须处理它不应该处理的变量。
使用动态属性访问来获取变量通常是个坏主意。
在您的情况下,两个对象都访问相同的变量,这会导致混乱,因为它们会覆盖彼此的结果。
这4个变量显然与Player
相关(正如我所说,类应以大写字母开头)。这就是为什么他们应该成为该类的一部分而不是作为个体变量浮出水面。
添加所有4个变量,用于定义玩家是否可以向Player
类的方向移动。下面的示例代码显示了1个这样的变量。请注意,这使得不必将玩家包含在变量名称中
package
{
import flash.display.Sprite;
private movableTop:Boolean = true;
public class Player extends Sprite
{
public function set canMoveToTop(value:Boolean):void
{
movableTop = value;
}
}
}
不,不建议使用x
和y
等参数来膨胀构造函数。如果要设置这些属性,请像使用Wall
类一样进行操作:单独设置这些属性。
此外,为方便起见,添加方法reset
,将所有4个变量设置为true;
Wall
类应仅提供hitTest
Player
的功能。再看一下内置的As3 API是如何工作的,hitTestObject
不会自己运行一些任意对象。相反,您必须显式调用该函数并将该对象作为参数传递。简化的Wall
看起来像这样:
package
{
import flash.display.Sprite;
public class Wall extends Sprite
{
public function hitTestPlayer(player:Player):void
{
if(bottomC.hitTestObject(player))
{
player.canMoveToTop = false;
}
else if(topC.hitTestObject(player))
{
player.canMoveToBottom = false;
}
else if(leftC.hitTestObject(player)
{
player.canMoveToRight = false;
}
else if(rightC.hitTestObject(player)
{
player.canMoveToLeft = false;
}
}
}
}
因为播放器对象被传递给函数,所以改变hitTest
函数中的变量是有效的。作为替代方案,您可以返回一个值,该值表示所有hitTest
ing
不要在时间轴上放置代码。使用文档类,我称之为Main
。这就是重复调用hitTests和其他函数的逻辑所在。
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
private var player:Player;
private var walls:Array = [];
public function Main():void
{
player = addPlayerAt(25, 35);
addWallAt(155, 55);
addWallAt(355, 55);
addEventListener(Event.ENTER_FRAME, loop);
}
public function loop(e:Event):void
{
player.reset();
for each(var wall:Wall in walls)
{
wall.hitTestPlayer(player);
}
}
private function addPlayerAt(x:Number, y:Number):Player
{
var player:Player = new Player();
player.x = x;
player.y = y;
addChild(player);
return player;
}
private function addWallAt(x:Number, y:Number):Wall
{
var wall:Wall = new Wall();
wall.x = x;
wall.y = y;
addChild(wall);
walls.push(wall);
return wall;
}
}
}
代码未经测试,您明白了。