2

在 Scene2d 中,当一个动作完成时,它会从 Actor 中移除,但不会放回池中。

动作类

/** 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() 方法(这是发送到池的唯一位置)(1)当 Actor 的操作数组被清除时,它永远不会被调用,并且随后不会发生对池的备份。 ..

(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

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

@Override
public void reset () {

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

顺便说一句,在 TimelineAction 完成 (2) 后,Timeline 及其 Tweens 对象已成功发送到各自的池:

(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)

4

1 回答 1

1

你还有问题吗。我是 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;
        }

}

LibGDX 的 0.9.6 版本已被更改,以确保对已标记为删除的 Actor 的所有关联操作调用“完成”方法。如果一个动作在演员被标记为移除之前终止,它的'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。

于 2012-09-01T17:36:22.520 回答