1

私はイメージを動いているように見せようとしています。画面をクリアして画像を元に戻しましたが、画面がちらつきます。あまりちらつきなく動いているように見せる方法はありますか?

「draw_asteroids」は、画像の動きをできるだけ連続的にしたいので、100ミリ秒ごとに呼び出されます。さらに、画面上で移動する他の多くの要素もあります(コードは宇宙船に似ています)。

私のコード:

start->
Wx = wx:new(),
Frame = wxFrame:new(Wx, -1, "Main Game Frame", [{size, {?max_x, ?max_y}}]),    
MenuBar = wxMenuBar:new(),
wxFrame:setMenuBar(Frame, MenuBar),
Panel = wxPanel:new(Frame),
wxFrame:connect(Panel, paint),
Image = wxImage:new("asteroid.png"),
wxFrame:show(Frame),
loop(Panel, {0,0}, Image).



loop(Panel, {X,Y},  Image)->
receive
after 100 ->
{NewX,NewY} =claculateNewPosition({X,Y}),
clearScreen(Frame, Panel),
draw_asteroids(Panel, {NewX,NewY}, Image),
loop(Panel, {NewX,NewY},  Image)
end.



draw_asteroids(Panel, {X, Y}, Image) ->

Pos = {round(X), round(Y)},
ClientDC = wxClientDC:new(Panel),
Bitmap = wxBitmap:new(Image),
wxDC:drawBitmap(ClientDC, Bitmap, Pos),
wxBitmap:destroy(Bitmap),
wxClientDC:destroy(ClientDC).


clearScreen(Frame, Panel)->

NewPanel = wxPanel:new(Frame),
wxWindow:setSize(Frame, {?max_x+1, ?max_y+1}),
wxWindow:setSize(Frame, {?max_x, ?max_y}),
NewPanel.
4

1 に答える 1

1

WindowsとLinuxの両方で次のことを行ってこれを解決しました:

init 関数で: 予想されるサイズのビットマップを作成し、それから memoryDC を作成します。

Bitmap = wxBitmap:new(W,H),
MemoryDC = wxMemoryDC:new(Bitmap),
...

また、ビットマップを配置する領域を定義し、それを何らかのイベント (少なくともペイント) に接続します。

Panel = wxPanel:new(Board, [{size,{W,H}}]),
wxPanel:connect(Panel, paint, [callback]),
wxPanel:connect(Panel, left_up, []),
wxPanel:connect(Panel, right_down, []),
wxPanel:connect(Panel, middle_down, []),

後で処理されるリストに変更リクエストを保存するために使用します。

次に、外部イベントを使用して画面を更新し、ウィンドウの更新をトリガーします オプション {eraseBackground,false} は、ちらつきを避けるために非常に重要です。

do_refresh(Cb,Z,PMa,PFe,PM,BMa,BFe,BM,P,MemoryDC) ->
    wx:batch(fun ()  ->
        Cb1 = lists:reverse(Cb),
        [cell(MemoryDC,PMa,PFe,PM,BMa,BFe,BM,State,Cell,Sex,Z) || {State,Cell,Sex} <- Cb1],
        wxWindow:refresh(P,[{eraseBackground,false}])
    end).

この外部イベントを使用する理由は 2 つあります。

  • 私が習得している定期的なリフレッシュレートを持っている
  • 多くのプロセスが独立してビットマップを更新できるようにする (リクエストをリストに保存する)

他のプロセスから要求された変更のリストを収集し、それらを memoryDC で順番に実行し、window:refresh/2 関数を使用してペイント イベントをトリガーするリフレッシュ関数を呼び出す外部タイマーを使用します。パフォーマンスを向上させるために、関数全体がバッチで実行されます。

そして、再描画イベントでは、パネルを単純に「ブリット」しました (この関数は実行時間を短縮するためにパネルの一部を更新できることに注意してください。最初はこの最適化を使用しませんでしたが、結果は十分に高速でスムーズだったので、私の初期コードを保持しました):

handle_sync_event(#wx{event = #wxPaint{}}, _wxObj, #state{panel=Panel, memoryDC=MDC, w=W, h=H}) ->
    redraw(Panel,MDC,W,H).

redraw(Panel, MemoryDC, W, H) ->
    DC = wxPaintDC:new(Panel),  
    wxDC:blit(DC,{0,0},{W,H},MemoryDC,{0,0}),
    wxPaintDC:destroy(DC).

PaintDC の作成と破棄が必要なようです。

このコードはウィンドウのサイズ変更を管理しません (私のアプリケーションでは意味がありません) が、拡張は簡単なはずです。

于 2014-08-12T19:51:48.130 に答える