C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: Application.Idleでゲームのタイマー制御


(過去ログ 95 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■56584 / inTopicNo.1)  Application.Idleでゲームのタイマー制御
  
□投稿者/ えれこぜ (1回)-(2011/01/20(Thu) 18:21:19)

分類:[VB.NET/VB2005 以降] 

VB2005でシューティングゲームのような、リアルタイムで動くゲームを作成しようと考えています。

最初は無限ループを回して、「キー入力」「画像描画」「各種処理」を行おうと考えていましたが、
「キー入力」などの各種イベントを、をApplication.DoEvents で拾うのは良くない処理と思い、
無限ループは捨て、代わりにApplication.Idle イベントを利用しようと考えました。

そこで、試しに1秒ごとに「画像描画」を行うサンプルを作りましたが、
何もしなければApplication.Idleイベントも発生しないようで、結果、描画もされていきません。
(フォーム上でマウスを絶えず動かすなど何かすれば、Application.Idleは発生します)

Public Class Form1
    Private mainGraphics As Graphics
    Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        If mainGraphics Is Nothing Then
            Dim bmp As New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Me.BackgroundImage = bmp
            mainGraphics = Graphics.FromImage(bmp)
        End If

        'MainLoop()  ← こちらであればうまく動作しますが、DoEvents が気になる!
        AddHandler Application.Idle, AddressOf Application_Idle
    End Sub

    Private targetTime As DateTime = DateTime.Now
    Private Sub Application_Idle(ByVal sender As Object, ByVal e As EventArgs)
        If DateTime.Now <= targetTime Then
            Return
        End If
        DrawString() '//描画処理
        targetTime = targetTime.AddMilliseconds(1000) '1秒
    End Sub

    Private Sub MainLoop()
        While True
            While DateTime.Now <= targetTime
                System.Threading.Thread.Sleep(10)
                Application.DoEvents()
            End While
            DrawString() '//描画処理
            targetTime = targetTime.AddMilliseconds(1000) '1秒
        End While
    End Sub

    Private stringValue As String = String.Empty
    Private Sub DrawString()
        stringValue &= "○"
        mainGraphics.DrawString(stringValue, Me.Font, Brushes.Black, 0, 0)
        Me.Invalidate()
    End Sub
End Class

Application.Idleを利用して、タイマーの代わりとなるループ制御を行うには、
どのようにしたら良いでしょうか?
よろしくお願い致します。

引用返信 編集キー/
■56588 / inTopicNo.2)  Re[1]: Application.Idleでゲームのタイマー制御
□投稿者/ YAS (14回)-(2011/01/20(Thu) 22:19:27)
私が問題が何なのか本質を理解していないのかもしれませんが,
タイマー制御はタイマーで行えばよいのではと思います。
引用返信 編集キー/
■56589 / inTopicNo.3)  Re[2]: Application.Idleでゲームのタイマー制御
□投稿者/ YAS (15回)-(2011/01/20(Thu) 22:37:38)
具体的なコードは次のようになると思います。
なお,Timerをデザイナで配置するならばFormClosingのTimer1.Disposeはなくてもかまいません。

Public Class Form1

    Dim WithEvents Timer1 As New Timer()

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Me.Timer1.Interval = 1000
        Me.Timer1.Start()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Me.Timer1.Stop()
        Me.Timer1.Dispose()
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Static StringValue As String = String.Empty
        StringValue &= "○"
        e.Graphics.DrawString(StringValue, Me.Font, Brushes.Black, 0, 0)
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Invalidate()
    End Sub

End Class

引用返信 編集キー/
■56599 / inTopicNo.4)  Re[3]: Application.Idleでゲームのタイマー制御
□投稿者/ shu (378回)-(2011/01/21(Fri) 09:31:04)
No56589 (YAS さん) に返信

> Dim WithEvents Timer1 As New Timer()

これでも大丈夫だけど

Private WithEvents Timer1 As New Timer()

とか

Friend WithEvents Timer1 As New Timer()

の記述の方が分かりやすいかと思います。DimはSub,Function,Propertyなどその記述しか
出来ないところに限定した方が変数のスコープが分かりやすいです。
引用返信 編集キー/
■56602 / inTopicNo.5)  Re[3]: Application.Idleでゲームのタイマー制御
□投稿者/ えれこぜ (2回)-(2011/01/21(Fri) 09:48:32)
今後、1回の処理でIntervalの値(16程度?)を超えて処理するケースが発生すると、
処理のコマ落ちが発生するのではないかと考え、前回時間との差分をとる
方式をとりたいと考えていました。
(Idle状態であれば、遅延していた処理群を一気に取り返してくれる仕組み)

逐次実行型(?)のサンプルを手本に作成していたので、Timerだと割り込めず処理落ちすると思いこんでいましたが、
Timerでイベント自体は発生しているので、次回分以降の処理は待たせておけば良いだけでした。

イベントドリブン方式でゲームプログラミングするなら、やはりTimerですかね。
ありがとうございました。

ただ、Application_Idleを利用する仕組みが楽しくなってきたので、
Timerは、「アプリケーションが処理を完了し、アイドル状態に入ろうとする」状態を作りだすのに利用しようと思います。

とここまで書いてTimerを起動してみたら、「アイドル状態に入ろうとする」状態を作れていました(笑)

'//空っぽでOK
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick

End Sub
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -