我的敌人电影剪辑没有从碰撞/ hitTestObject中的舞台上移除子弹影片剪辑,但子弹正在被移除,只有敌人不是。感谢所有帮助。谢谢你们,你们这里有一个很棒的社区,尊重你们。
我使用了相同的代码,可以为敌人移除子弹影片剪辑(虽然相应地更改了变量等等)。
我的Main.as和Enemy.as代码在这里:
Main.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
public var player:Player;
public var enemy:Enemy;
public var bulletList:Array = [];
public var mousePressed:Boolean = false; //keeps track of whether the mouse is currently pressed down
public var delayCounter:int = 0; //this adds delay between the shots
public var delayMax:int = 7; //change this number to shoot more or less rapidly
public var enemies:Array = [];
public function Main():void
{
player = new Player(stage, 320, 240);
stage.addChild(player);
//stage.addEventListener(MouseEvent.CLICK, shootBullet, false, 0, true); //remove this
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, 0, true);
stage.addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
for(var numBaddies=0; numBaddies<6;numBaddies++){
var enemy:Enemy = new Enemy(null);
enemy.x = numBaddies*50;
enemy.y = numBaddies*50
stage.addChild(enemy);
enemies.push(enemy);
}
}
public function loop(e:Event):void
{
if(mousePressed) // as long as the mouse is pressed...
{
delayCounter++; //increase the delayCounter by 1
if(delayCounter == delayMax) //if it reaches the max...
{
shootBullet(); //shoot a bullet
delayCounter = 0; //reset the delay counter so there is a pause between bullets
}
}
if(bulletList.length > 0)
{
for(var i:int = bulletList.length-1; i >= 0; i--)
{
bulletList[i].loop();
}
}
for(var h = 0; h<bulletList.length; ++h)
{
if(bulletList[h].hitTestObject(this)){
trace("player hit by baddie " + h);
}
}
for(var u:int=0; u<enemies.length; u++) {
Enemy(enemies[u]).moveTowards(player.x, player.y);
}
}
public function mouseDownHandler(e:MouseEvent):void //add this function
{
mousePressed = true; //set mousePressed to true
}
public function mouseUpHandler(e:MouseEvent):void //add this function
{
mousePressed = false; //reset this to false
}
public function shootBullet():void //delete the "e:MouseEvent" parameter
{
var bullet:Bullet = new Bullet(stage, player.x, player.y, player.rotation, enemies);
bullet.addEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved, false, 0, true);
bulletList.push(bullet);
stage.addChild(bullet);
}
public function bulletRemoved(e:Event):void
{
e.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved);
bulletList.splice(bulletList.indexOf(e.currentTarget),1);
}
}
}
Enemy.as
package {
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Enemy extends MovieClip {
public var bullets:Array;
public var stageRef:Stage;
private var enemyPositionX, enemyPositionY,xDistance,yDistance,myRotation:int;
public function Enemy(bulletList:Array) {
// constructor code
bullets = bulletList;
}
public function moveTowards(playerX:int, playerY:int){
xDistance = this.x - playerX;
yDistance = this.y - playerY;
myRotation = Math.atan2(yDistance, xDistance);
this.x -= 3 * Math.cos(myRotation);
this.y -= 3 * Math.sin(myRotation);
}
public function loop():void{
for(var i=0; i<bullets.length; ++i)
{
if(bullets[i].hitTestObject(this)){
trace("you killed enemy " + i);
removeSelf();
}
}
}
private function removeSelf():void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
作为参考,你可以看到我如何使用相同的代码删除影片剪辑,我也将添加Bullet.as:
Bullet.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Bullet extends MovieClip
{
private var stageRef:Stage; //checks if the bullet leaves the screen borders
private var speed:Number = 10; //speed that the bullet will travel at
private var xVel:Number = 0; //current x velocity
private var yVel:Number = 0; //current y velocity
private var rotationInRadians = 0; //convenient to store our rotation in radians instead of degrees
public var allBaddies:Array;
//our constructor requires: the stage, the position of the bullet, and the direction the bullet should be facing
public function Bullet(stageRef:Stage, X:int, Y:int, rotationInDegrees:Number, enemies:Array):void
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180; //convert degrees to radians, for trigonometry
allBaddies = enemies;
}
public function loop():void //we don't need to include the "e:Event" because we aren't using an EventListener
{
for(var b=0; b<allBaddies.length; ++b)
{
if(allBaddies[b].hitTestObject(this)){
trace("bullet hit baddie " + b);
removeSelf();
}
}
xVel = Math.cos(rotationInRadians) * speed; //uses the cosine to get the xVel from the speed and rotation
yVel = Math.sin(rotationInRadians) * speed; //uses the sine to get the yVel
x += xVel; //updates the position
y += yVel;
//if the bullet goes off the edge of the screen...
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
this.parent.removeChild(this); //remove the bullet
}
}
private function removeSelf():void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
答案 0 :(得分:0)
好的,我会改变一些事情,除了我注意到的几个问题。
首先,就我所知,你的Enemy
类永远不会得到stageRef
变量集。因此,在Enemy
班级removeSelf()
中,您的stageRef
将为空。
您可以通过构造函数传递舞台并设置它(就像在子弹类中一样),也可以在使用enemy.stageRef = stage
在敌人循环中实例化后设置它。或者您可以为Event.ADDED_TO_STAGE
的敌人类添加和事件监听器,当发生这种情况时,您的敌人将会引用继承的阶段。
现在,真正的肉问题。你有2个for循环测试碰撞(除了Main
类中的一个,但我会得到它)。一个是你的子弹课,一个是你的敌人类。如果你开始添加很多子弹和敌人,那就太过分了,并且在表现上很难。你真的只需要一个for循环(就像你的子弹类中的循环),当它检测到碰撞时,它会调用碰撞对象的remove方法。在你的Bullet
类中看起来像这样:
public function loop():void //we don't need to include the "e:Event" because we aren't using an EventListener
{
for(var b=0; b<allBaddies.length; ++b)
{
if(allBaddies[b].hitTestObject(this)){
trace("bullet hit baddie " + b);
removeSelf();
allBaddies[b].removeSelf();
}
}
虽然为了实现这一目标,您需要将removeSelf()
班级中的Enemy
设置为公开访问权限:
public function removeSelf():void
{
//this is removing a listener not even added Enemy...
//removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
然后你甚至可以从loop()
类中删除Enemy
,看看它是如何检测不再需要的碰撞的。
最后为什么会发生这种情况?好吧,它可能是从主要类中的调用中首先运行的子弹hitTest:bulletList[i].loop();
正在检测此hitTest,然后移除子弹离开您的Enemy类而没有对象进行测试。但!你没有在主类的任何地方向敌人调用loop()
,因此命中测试永远不会运行。
最好压缩你的碰撞。您当前正在循环遍历主类中的Bullet
实例,调用它们的loop()
(测试冲突),然后再执行for循环执行碰撞测试。你可以改变这个:
if(bulletList.length > 0)
{
for(var i:int = bulletList.length-1; i >= 0; i--)
{
bulletList[i].loop();
}
}
//this is no longer needed...
/*for(var h = 0; h<bulletList.length; ++h)
{
if(bulletList[h].hitTestObject(this)){
trace("player hit by baddie " + h);
}
}*/
没有理由在Bullet
班级和Main
班级loop(e:Event)
中测试碰撞。
希望这些信息有所帮助!祝你好运:)