AS3如何从另一个类调用按钮?

时间:2016-02-23 20:14:49

标签: actionscript-3

我正在尝试创建一个按钮,当您点击它时,船会发射激光,但按钮不起作用。我的意思是我在调试时没有收到任何错误,但它不允许我点击按钮,但它允许我点击我的船来开火。非常感谢任何帮助,谢谢!

我的Fire.as

package control {

import flash.events.Event;
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.events.Event;

import objects.Ship;

public class Fire extends MovieClip {
    private var my_x: Number;
    private var my_y: Number;

    private var ourShip: Ship;

    var mouseDown: Boolean;

    public function Fire(margin_left: Number, margin_bottom: Number,     ourShip_mc: Ship) {
        my_x = margin_left;
        my_y = margin_bottom;
        ourShip = ourShip_mc;

        if (stage) {
            init();
        } else {
            addEventListener(Event.ADDED_TO_STAGE, init);
        }
    }

    private function init(e: Event = null): void {
        if (hasEventListener(Event.ADDED_TO_STAGE)) {
            removeEventListener(Event.ADDED_TO_STAGE, init);
        }

        this.x = my_x + this.width / 2;
        this.y = stage.stageHeight - my_y - this.height / 2;

        this.addEventListener(MouseEvent.CLICK, onClick);
    }

    private function onClick(event: MouseEvent): void {
        //EVENT DISPATCHER
        dispatchEvent(new Event("eventshoot", true));
        trace("Fire clicked");
    }

}
}

我的船。

package objects {

import flash.display.MovieClip;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.utils.Timer;
import flash.display.JointStyle;

import control.Controller;
import control.Joystick;
import control.Fire;

public class Ship extends MovieClip {
    var mouseDown: Boolean;

    private var stageRef: Stage;
    private var key: Controller;

    private var speed: Number = 2.5;
    private var vx: Number = 0;
    private var vy: Number = 0;
    private var friction: Number = 0.93;
    private var maxspeed: Number = 8;

    //fire related variables
    private var fireTimer: Timer; //causes delay between fires
    private var canFire: Boolean = true; //can you fire a laser

    public var move_left: Boolean = false;
    public var move_up: Boolean = false;
    public var move_right: Boolean = false;
    public var move_down: Boolean = false;

    public function Ship(stageRef: Stage): void {
        this.stageRef = stageRef;
        key = new Controller(stageRef);
        this.addEventListener(Event.ENTER_FRAME, ShipMove);
        stage.addEventListener("eventshoot", firenow);

        //setup your fireTimer and attach a listener to it.
        fireTimer = new Timer(250, 1);
        fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);

        addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
    }

    private function ShipMove(event: Event): void {
        if (move_left)
            vx -= speed;
        else if (move_right)
            vx += speed;
        else
            vx *= friction;

        if (move_up)
            vy -= speed;
        else if (move_down)
            vy += speed;
        else
            vy *= friction;
    }

    public function firenow(event: Event) {
        fireLaser();
    }

    public function loop(e: Event): void {

        //update position   
        x += vx;
        y += vy;

        //speed adjustment
        if (vx > maxspeed)
            vx = maxspeed;
        else if (vx < -maxspeed)
            vx = -maxspeed;

        if (vy > maxspeed)
            vy = maxspeed;
        else if (vy < -maxspeed)
            vy = -maxspeed;

        //ship appearance
        rotation = vx;
        scaleX = (maxspeed - Math.abs(vx)) / (maxspeed * 4) + 0.75;

        //stay inside screen
        if (x > stageRef.stageWidth - 30) {
            x = stageRef.stageWidth - 30;
            vx = -vx;
        } else if (x < 30) {
            x = 30;
            vx = -vx;
        }

        if (y > stageRef.stageHeight) {
            y = stageRef.stageHeight;
            vy = -vy;
        } else if (y < 0) {
            y = 0;
            vy = -vy;
        }

    }

    private function fireLaser(): void {
        //if canFire is true, fire a laser
        //set canFire to false and start our timer
        //else do nothing.
        if (canFire) {
            stageRef.addChild(new LaserGreen(stageRef, x + vx, y - 10));
            canFire = false;
            fireTimer.start();
        }
    }

    //HANDLERS      
    private function fireTimerHandler(e: TimerEvent): void {
        //Timer ran, fire again.
        canFire = true;
    }

    public function takeHit(): void {
        dispatchEvent(new Event("hit"));
    }
}

}

更新了,这是Engine.as,很抱歉没有回复你的评论,如果我这样做,结构就搞砸了。

package objects {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.display.StageScaleMode;
import flash.display.StageAlign;

import control.Joystick;
import control.Fire;

public class Engine extends MovieClip {
    private var preloader: ThePreloader;

    public function Engine() {

        preloader = new ThePreloader(474, this.loaderInfo);
        stage.addChild(preloader);
        preloader.addEventListener("loadComplete", loadAssets);
        preloader.addEventListener("preloaderFinished", showSponsors);
        stage.addEventListener("gameSTART", fGameStart);
    }

    private function loadAssets(e: Event): void {
        this.play();
    }

    private function showSponsors(e: Event): void {
        stage.removeChild(preloader);
        var ps: PrerollSponsors = new PrerollSponsors(stage);
        ps.addEventListener("prerollComplete", showMenu);
        ps.preroll();
    }

    private function showMenu(e: Event): void {
        new MainMenu(stage).load();
    }

    public static var enemyList: Array = new Array();
    private var ourShip: Ship;
    private var joystick: Joystick;
    private var fire: Fire;
    private var scoreHUD: ScoreHUD;

    public function fGameStart(evt: Event): void {

        ourShip = new Ship(stage);
        ourShip.x = stage.stageWidth / 2;
        ourShip.y = stage.stageHeight / 2;
        ourShip.addEventListener("hit", shipHit, false, 0, true);
        stage.addChild(ourShip);

        joystick = new Joystick(120, 70, ourShip);
        addChild(joystick);

        fire = new Fire(420, 70, ourShip);
        addChild(fire);

        scoreHUD = new ScoreHUD(stage);
        stage.addChild(scoreHUD);

        addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
    }

    private function loop(e: Event): void {

        if (Math.floor(Math.random() * 20) == 5) {
            var enemy: E1 = new E1(stage, ourShip);
            enemy.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
            enemy.addEventListener("killed", enemyKilled, false, 0, true);
            enemyList.push(enemy);
            stage.addChild(enemy);
        } else if (Math.floor(Math.random() * 80) == 5) {
            var enemy2: E2 = new E2(stage, ourShip);
            enemy2.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
            enemy2.addEventListener("killed", enemyKilled, false, 0, true);
            enemyList.push(enemy2);
            stage.addChild(enemy2);
        }

    }

    private function enemyKilled(e: Event) {
        scoreHUD.updateKills(1);
        scoreHUD.updateScore(e.currentTarget.points);
    }

    private function removeEnemy(e: Event) {
        enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
    }

    private function shipHit(e: Event) {
        scoreHUD.updateHits(1);
    }

}

}

因此,每次点击开火按钮(Fire.as)时,它都会调度一个事件“eventshoot”,而船只(Ship.as)会将其取出。当船接收它时,船本身会发射激光,这就是这个想法。但是因为有预卷,菜单...这样的东西会在开始游戏之前加载,我不能简单地将火按钮拖到舞台上。当游戏开始时,引擎会将船,火按钮,敌人,得分......加载到舞台上。在调试“TypeError:错误#1009:无法访问空对象引用的属性或方法时,我收到错误1009。”,它来自:

stage.addEventListener(“eventshoot”,现在开火);

在Ship.as中

据我所知,我收到此错误是因为舞台上没有开火按钮,所以我的船无法接收“eventshoot”事件,有没有办法可以让我的船只在确认之后接收该事件按钮被加载到舞台以避免错误?

1 个答案:

答案 0 :(得分:1)

虽然您当然可以为按钮创建一个类,但是使用该对象激发激光的功能不应该在按钮中。

给定Ship类看起来像这样:

package 
{
    import flash.display.MovieClip; 

    public class Ship extends MovieClip
    {
        public function fireLaser():void
        {   
            trace("pew pew");
        }
    }
}

您可以使用以下代码实例化此类并将其添加到主时间轴:

var ship:Ship = new Ship();
addChild(ship);

如果您手动放置符号,则无需执行此操作,只需要为其指定实例名称ship

要使可点击的内容,请向其添加事件侦听器。例如,要使船舶本身可以点击:

var ship:Ship = new Ship();
addChild(ship);

ship.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

function onMouseDown(event:MouseEvent):void
{
    trace("ship clicked");
}

如果主时间线上有一个实例名称为fire的按钮,您可以轻松地将侦听器添加到该按钮:

var ship:Ship = new Ship();
addChild(ship);

// v---this changed
fire.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

function onMouseDown(event:MouseEvent):void
{
    trace("fire button clicked");
}

最后但并非最不重要的一点是,如果你想在一个对象上调用方法而不是使用trace(),你也可以这样做:

var ship:Ship = new Ship();
addChild(ship);

fire.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

function onMouseDown(event:MouseEvent):void
{
    ship.fireLaser();  // this changed, laser fired "pew pew"
}

tl,dr;

按钮本身不应该做任何事情。如果按钮直接对船做任何事情,那就必须知道船。 该按钮不应该知道该船。所有按钮都是&#34;我点击了&#34;通过派遣一个事件,其他一切都应该在外面处理。

你知道,就像你在这里写下你的问题一样,并不是整个互联网(包括我)坐在电脑的键盘按钮上听取你的意见。你所有的键盘按钮都说'#34;我点击了#34;。其他一切都是通过您的操作系统,浏览器等在外部处理的。