在Scene2d中,当Action完成时,它将从Actor中删除,但它不会放回池中

时间:2012-07-30 14:27:57

标签: android libgdx scene2d

在Scene2d中,当一个Action完成后,它将从Actor中移除,但它不会被放回到Pool中。

Action.class

/** Sets the actor this action will be used for. This is called automatically when an action is added to an actor. This is also
     * called with null when an action is removed from an actor. When set to null, {@link #reset()} is called.
     * <p>
     * This method is not typically a good place for a subclass to query the actor's state because the action may not be executed
     * for some time, eg it may be {@link DelayAction delayed}. The actor's state is best queried in the first call to
     * {@link #act(float)}. For a TimedAction, use TimedAction#initialize(). */
    public void setActor (Actor actor) {
        this.actor = actor;

    }

    /** Resets the optional state of this action to as if it were newly created, allowing the action to be pooled and reused. State
     * required to be set for every usage of this action or computed during the action does not need to be reset.
     * <p>
     * The default implementation calls {@link #restart()}. Also, if the action has a {@link #setPool(Pool) pool} then the action is
     * {@link Pool#free(Object) returned} to the pool.
     * <p>
     * If a subclass has optional state, it must override this method, call super, and reset the optional state. */
    public void reset () {
        restart();
        if (pool != null) {
            pool.free(this);
            pool = null;
        }
    }

似乎Action reset()方法(这是发送到Pool的唯一地方)(1)当Actor的actions数组被清除时,它永远不会被调用,并且随后对池的备份没有发生......

(1) - 在以前的版本中,我们可以覆盖finish()方法并将Action发送到池中,但是它不再可用的方法......

当我尝试将Action类扩展到此类时,我遇到了这个问题:

TimelineAction.class

/**
 * Timeline action runs a Timeline (separate from the TweenManager to avoid a second manager/loop cycle)
 * with Scene2d
 */
public class TimelineAction extends Action {

    private static final Pool<TimelineAction> pool = new Pool<TimelineAction>() {

        @Override
        protected TimelineAction newObject() {

            Gdx.app.log("LOG", "TimelineAction action = new TimelineAction();");        
            TimelineAction action = new TimelineAction(); 

            return action;
        }

    };  

    private Timeline timeline;
    private boolean done;

    /**
     * Get instance from pool.
     * 
     * @param timeline
     *            The associated tween.
     * 
     * @return Pooled instance.
     */
    public static TimelineAction createTimelineAction(Timeline _timeline)   {

        TimelineAction action = pool.obtain();

        action.setPool(pool);

        action.setTimeline(_timeline);      

        return action;
    }

    @Override
    public boolean act(float delta) {

        done = timeline.isFinished(); 
        if (!done) {
            timeline.update(delta);
        } else {
            Gdx.app.log("LOG", "timeline.finished()");          
            timeline.free();
            timeline = null;                            
        }
        return done;
    }

    private void setTimeline(Timeline timeline) {

        this.timeline = timeline;
    }

}

来自netthreads

的原创想法

我注意到每次添加一个Action时,它都会创建一个新对象(TimelineAction action = new TimelineAction())而不是返回一个池。 然后我尝试通过覆盖他的reset()方法来追踪Action结尾,以确定它是否被调用过......但事实并非如此。

@Override
public void reset () {

    Gdx.app.log("LOG", "reset()");
    super.reset();
}

顺便说一句,在TimelineAction完成后,时间轴和它的Tweens对象被成功发送到各个池:(2):

(2) - Timeline.getPoolSize()返回1,Tween.getPoolSize()返回2

actor1.addAction(TimelineAction.createTimelineAction(
            Timeline.createSequence()
                    .push( Tween.to(logo_MUTANT, Element2DAccessor.POS_XY, 3f)
                            .waypoint(400, 800)
                            .waypoint(200, 400)
                            .waypoint(100, 200)
                            .target(0,0)
                         )
                    .ease(Quad.INOUT).path(TweenPaths.catmullRom)).push(Tween.call(callback).setCallbackTriggers(TweenCallback.BACK_COMPLETE)).repeatYoyo(1, 0.5f).start()));

所以,我需要一些帮助,拜托! :S

先谢谢,请原谅我可怜的英语。 ;)

Libgdx版本0.9.6(24-07-2012)

1 个答案:

答案 0 :(得分:0)

你还有问题吗?我是TimelineAction的netthreads版本的作者,只要你使用这个版本,我不相信你应该有问题:

    public class TimelineAction extends Action
    {
        private static final ActionResetingPool<TimelineAction> pool = new ActionResetingPool<TimelineAction>(10, 100)
        {
            @Override
            protected TimelineAction newObject()
            {
                TimelineAction action = new TimelineAction();

                return action;
            }
        };

        private Timeline timeline;
        private Actor target;
        protected boolean done;

        /**
         * Get instance from pool.
         * 
         * @param timeline
         *            The action time-line to execute.
         * 
         * @return Pooled instance.
         */
        public static TimelineAction $(Timeline timeline)
        {
            TimelineAction action = pool.obtain();

            action.setTimeline(timeline);

            return action;
        }

        @Override
        public void act(float delta)
        {
            if (!isDone())
            {
                timeline.update((int) (delta * 1000));
            }
            else
            {
                Gdx.app.log("TimelineAction", "!!!Executing finished timeline, " + timeline.getClass().hashCode());
            }

        }

        @Override
        public boolean isDone()
        {
            return timeline.isFinished();
        }

        @Override
        public Action copy()
        {
            return this;
        }

        @Override
        public void setTarget(Actor actor)
        {
            this.target = actor;
        }

        @Override
        public Actor getTarget()
        {
            return target;
        }

        @Override
        public void finish()
        {
            super.finish();

            pool.free(this);

            timeline.free();
        }

        private void setTimeline(Timeline timeline)
        {
            this.timeline = timeline;
        }

        /**
         * Fetch TimeLine reference.
         * 
         * @return The TimeLine reference.
         */
        public Timeline getTimeline()
        {
            return timeline;
        }

        /**
         * Set done status.
         * 
         * @param done
         */
        public void setDone(boolean done)
        {
            this.done = done;
        }

}

已修改了0.9.6版本的LibGDX,以确保在已标记为要删除的Actor的所有相关操作上调用“finish”方法。如果一个动作在演员被标记为删除之前终止,那么它的'done'标志将被设置,演员的'act'方法将在其上调用'finish',即。

public void act (float delta) {
        actions.iter();
        Action action;

        while ((action = actions.next()) != null) {
            action.act(delta);
            if (action.isDone()) {
                action.finish();
                actions.remove();
            }
        }
    }

我正在将我的所有演示更新为0.9.6。