【问题标题】:Animation in XPCE/prolog not smooth enoughXPCE/prolog 中的动画不够流畅
【发布时间】:2014-02-03 17:46:37
【问题描述】:

我正在尝试用XPCE/Prolog为一个项目写一个简单的动画,但是不够流畅;它出现闪烁或闪烁。 我在配备 Intel i7(四核,2.4 Ghz+)的 ASUS N550jv 笔记本电脑上运行它,所以这应该不是问题。 移动的物体总是一样的(只是在不同的位置绘制),双缓冲是明确启用的,我使用的是 40 FPS。

可以做些什么来提高平滑度?

这是我正在使用的代码:

sm:-   %run this
    sm(600,4,40). %runs animation over 600 pixels, 4 seconds long, with 40 FPS

sm(Length,Duration,FPS):-
    (object( @window),!,free(@window);true), %check is window exists; if it does, delete it 
    (object( @floor), !, free( @floor); true), %check is floor exists; if it does, delete it 
    (object( @box), !, free( @box); true), %%check if box exists; if it does, delete it
    new( @window,picture('Window',size(900,300))), %create window
    send( @window,open), %display window
    send(@window,buffered_update,true), %make sure to use double-buffering
    new( @floor,box(800,10)), %create floor
    send( @floor,fill_pattern,colour(green)), %colour floor
    send( @window,display,@floor,point(50,70)),  %show floor
    new( @box,box(50,50)), %creates box
    send( @box,fill_pattern,colour(yellow)), %colours box yellow
    Frames is Duration*FPS, %how many frames are to be drawn
    Step is Length/Frames, %what's the distance between steps
    Delay is 1/FPS, %what is the delay between steps
    send( @window,display,@box,point(50,20)), %shows Object
    send( @window,flush), %flushes window
    ani(Step,Delay,Frames,point(50,20)), %actual animation
    sleep(1), %wait 1 second, and then
    free( @box), %delete box
    free( @floor), %delete floor
    free( @window). %delete window (and exit)


ani(_,_,0,_).
ani(Step,Delay,Frames,point(X,Y)):-
    send( @box,x(X+Step)), %moves box to the right
    send( @window,flush), %flushes
    repeat,
    sleep(Delay),
    FramesLeft is Frames - 1,
    NewX is X + Step,
    ani(Step,Delay,FramesLeft,point(NewX,Y)).

【问题讨论】:

    标签: animation prolog swi-prolog xpce


    【解决方案1】:

    你应该使用计时器,它可以避免睡眠:

    sm:-   %run this
        sm(600,4,40). %runs animation over 600 pixels, 4 seconds long, with 40 FPS
    
    sm(Length,Duration,FPS):-
        (object( @window),!,free(@window);true), %check is window exists; if it does, delete it
        (object( @floor), !, free( @floor); true), %check is floor exists; if it does, delete it
        (object( @box), !, free( @box); true), %%check if box exists; if it does, delete it
        (object( @my_timer), !, free( @my_timer); true), %%check if box exists; if it does, del
        new( @window,picture('Window',size(900,300))), %create window
        send( @window,open), %display window
         send(@window,buffered_update,true), %make sure to use double-buffering
        new( @floor,box(800,10)), %create floor
        send( @floor,fill_pattern,colour(green)), %colour floor
        send( @window,display,@floor,point(50,70)),  %show floor
        new( @box,box(50,50)), %creates box
        send( @box,fill_pattern,colour(yellow)), %colours box yellow
        Frames is Duration*FPS, %how many frames are to be drawn
        Step is Length/Frames, %what's the distance between steps
        Delay is 1/FPS, %what is the delay between steps
        send( @window,display,@box,point(50,20)), %shows Object
        send( @window,flush), %flushes window
        ani(Step,Delay,Frames,point(50,20)).
    
    ani(Step,Delay,Frames,point(X,Y)) :-
        send( @box,x(X+Step)), %moves box to the right
        send( @window,flush), %flushes
        new(@my_timer, my_timer(Step, Delay, Frames, X)).
    
    :- pce_begin_class(my_timer, object).
    variable(mytimer,   timer,  both, "timer lançant l'animation fréquence 20 fois par seconde").
    variable(step, number, both, "delta x").
    variable(frames, number, both, "number of moves").
    variable(posX, number, both, "xpos of the box").
    
    % initialisation of the tmer
    initialise(P, Step, Delay, Frames, PosX) :->
        send(P, slot, step, Step),
        send(P, slot, frames, Frames),
        send(P, slot, posX, PosX),
        send(P, mytimer, new(_, timer(Delay,message(P, my_message)))),
        send(P?mytimer, start).
    
    % must be called before destruction
    % avoid any problem of non-freed resources
    unlink(F) :->
        send(F?mytimer, stop),
        send(F, send_super, unlink).
    
    
    my_message(P) :->
        get(P, slot, frames, Frame),
        (   get(Frame, value, 0)
        ->  send(P?mytimer, stop),
            free( @box), %delete box
            free( @floor), %delete floor
            free( @window), %delete window (and exit)
            free(@my_timer)
        ;   get(P, slot, step, Step),
            get(P, slot, posX, PosX),
            send( @box,x(PosX+Step)), %moves box to the right
            send( @window,flush), %flushes
            send(PosX, plus, Step),
            send(Frame, minus, 1)).
    :- pce_end_class.
    

    【讨论】:

    • 对不起我在 Prolog 中的无知,但是当我尝试编译它时,swipl 找不到 timer 类。你知道我在哪里可以找到它吗?谢谢!
    • 我使用的是 Windows 7 64 位,我的 swi-prolog 版本是 6.5.3。关于Linux版本我不能说什么。当我在 Linux 上使用 swiprolog 时,我编译了源代码并且它可以工作。
    • 哦,对不起,它现在也对我有用。我使用的是较旧的 swipl。谢谢!
    • 感谢提示,4 秒动画的实际动画时间从 4.73 秒缩短到 4.06 秒,但我没有看到动画在视觉上更流畅,这就是我的想法问。
    • 阅读我答案的第一行,我只是建议使用计时器而不是“睡眠”来制作动画,仅此而已。也许你可以玩定时器的持续时间(延迟)来改善它。
    猜你喜欢
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 2014-10-30
    • 2010-11-07
    • 2017-07-01
    • 1970-01-01
    相关资源
    最近更新 更多