2

タイトルが示すように、私が作ったゲームについて質問しています。これをスピードアップしたいと思います。それはかなり一般的な質問です。だからここにあります:私はあなたが円であり、敵があなたに向かってくる正方形であるプログラムを作りました。スペースを押して撮影すると、矢印キーを使用して移動したり、ピックアップがあったりするなど、ヒットするたびにポイントを獲得できます。

ただし、次のように描画されるプレースホルダー円は使用しなくなりました。

e.Graphics.FillEllipse(Brushes.Orange,Player)

ここでのプレーヤーは、プレーヤーを定義する長方形です。そこで、グラフィックを置き換えるために、地球(プレーヤー)と宇宙船(敵)のJPEG画像をダウンロードしました。私はそれを使って描いた:

e.Graphics.DrawImage(ImgEarth,Player.X,Player.Y,Player.Width,Player.Height)

敵を描くための同じテクニック。

しかし、結果は非常に動きの遅いエイリアンです。それは遅いタイマーか何かではありませんが(私はそこに約2つ同時に動作しています)、FPSは貧弱です。それは私のシステムかもしれませんが、私がチェックしたとき、それは〜10MBのメモリしか必要としませんでした。VB.NETは、他のいくつかの言語(C ++、C#)ほど高速ではないため、ゲーム作成にはあまり適していませんが、FPSを犠牲にすることなくこれらを描画できる方法はありますか?

それが役に立ったら、私はGeForce8400MGSを搭載した1.66GHzプロセッサを持っています。(私の意見では、これと同じくらい単純なことにはかなりの能力があります)

編集:私はダブルバッファリングを使用しています。Me.DoubleBuffered = True。ImgEarthは310x310の画像です。フォーム上では50x50として描画されるため、縮小してみます。これは良い点です。

さて、これがForm1.Paintの手順全体です。その後、すべて説明します。

e.Graphics.DrawImage(ImageEarth, Player.x,Player.y,Player.Width,Player.Height)

        'Projectiles
        Dim i As Integer = 0
        Do
            If Current_Projectile(i).IsEmpty = False Then e.Graphics.FillRectangle(Brushes.Red, Current_Projectile(i))
            i += 1
        Loop Until i = UBound(Current_Projectile)

        i = 0

        Do
            If Advanced_Projectiles(i).IsEmpty = False Then e.Graphics.FillRectangle(Brushes.Green, Advanced_Projectiles(i))
            i += 1
        Loop Until i = UBound(Advanced_Projectiles)


        i = 0
        Do
            If Pickups(i).IsEmpty = False Then
                If PickUpType = 0 Then e.Graphics.FillEllipse(Brushes.Green, Pickups(i))
                If PickUpType = 1 Then e.Graphics.FillEllipse(Brushes.Red, Pickups(i))
                If PickUpType = 2 Then e.Graphics.FillEllipse(Brushes.Yellow, Pickups(i))
            End If
            i += 1
        Loop Until i = UBound(Pickups)
        'Objects
        i = 0


        Do
            If Objects(i).IsEmpty = False Then e.Graphics.FillRectangle(Brushes.Blue, Objects(i))
            i += 1
        Loop Until i = UBound(Objects)

わかった。Current_Projectileは、プレーヤーによって発射された発射体(弾丸)に関するデータを格納する配列です。次に、高度な発射体は、前者のより「強力な」バージョンを発射することを除いて、同じです。Pickupsは、プレーヤーに向けて発射されているピックアップに関するデータを格納する配列です。その色は別のサブルーチンで決定されます。最後に、objects(i)は、発射された敵の長方形に関するデータを格納する配列です。

編集2:さて、あなたたちがTimer.Tick手順を必要とするかもしれないと考えました。

タイマーはTmr_Mainと呼ばれ、ゲーム中に発生するすべての約90%を処理します。ほとんどの作業を個々のサブルーチンに委任しますが、一部はタイマー自体で実行されます。これは、フォーム全体で2番目に洗練されたコードブロックです。ここにあります:

Dim i As Integer = 0

CollisionDetect()
CheckForDead()

If ReadyToReset = True Then ResetInt += 1
If ResetInt = 80 Then
    ResetPowerUps()
    ReadyToReset = False
    ResetInt = 0
End If
'Projectiles(Bullets)
i = 0
Do
    If Current_Projectile(i).IsEmpty = False Then
        Current_Projectile(i).X += Projectile_Speed

        If Current_Projectile(i).X > Me.Width Then

            Current_Projectile(i) = Nothing
            No_Of_Projectiles -= 1
        End If

    End If

    i += 1

Loop Until i = UBound(Current_Projectile)
'Advanced Projectiles
i = 0

Do
    If Advanced_Projectiles(i).IsEmpty = False Then
        Advanced_Projectiles(i).X += AdvProjectile_Speed
    End If
    If Advanced_Projectiles(i).X >= Me.Width Then
        Advanced_Projectiles(i) = Nothing
    End If
    i += 1
Loop Until i = UBound(Advanced_Projectiles)

'Pickups
GeneratePickups()

i = 0
Do
    If Pickups(i).IsEmpty = False Then
        Pickups(i).X -= Pickup_Speed
    End If
    If Pickups(i).X < 0 Then
        Pickups(i) = Nothing
    End If
    i += 1
Loop Until i = UBound(Pickups)


LblScore.Text = "Score: " & Score
CheckForWin()



Me.Invalidate()

さて、もう一度、上からすべてを説明します。CollisionDetect()ゲーム全体で何が何にヒットしたかを評価するためのロジックが含まれています。これには、プレーヤーとピックアップ、プレーヤーとオブジェクト、オブジェクトと発射物、オブジェクトと高度な発射物、オブジェクトとプレーヤーが含まれます。次に、ピックアップが使用されているかどうかを評価します。プレーヤーがピックアップをヒットすると、ブール値がtrueに設定されます。これは、このタイマーが繰り返されるたびに、変数に1つ追加されることを意味しますResetInt。これが80、または4秒(50msタイマー)に達すると、ピックアップの効果がリセットされます。さらに、ブール値はfalseであるため、同じことは二度と行われません。

次に、フォーム上のすべてのオブジェクトを移動します。これらには、オブジェクト、発射物、ピックアップが含まれます。また、「パス」の終わりに到達したかどうかもチェックします(つまり、発射物が右に十分に移動した場合、ゲームから削除されます)。

最後に、プレイヤーが勝ったかどうかをチェックし、スコアについてプレイヤーに知らせるラベルを更新します。その後、再描画します。

アイデア?

4

2 に答える 2

4

試してみるべきいくつかのアイデア...

(1)Option Strict On少なくとも、非効率的な自動型変換を回避するための which を使用します。

Do ... Loop Until i = UBound( ... )(2)使用する代わりにFor i = 0 To UBound( ... ) - 1(ループ中に配列が要素を追加または失う可能性があると本当に予想している場合を除きます)。ForUBound一度だけDo呼び出しますが、繰り返しごとに呼び出します。Lengthさらに良いことに、代わりに配列のメンバーを使用しないのはなぜUBoundですか?

(3) これらのIfステートメントのテストについてPickUpTypeは、If-ElseIf はしごを使用します。

If PickUpType = 0 Then 
    e.Graphics.FillEllipse(Brushes.Green, Pickups(i)) 
ElseIf PickUpType = 1 Then 
    e.Graphics.FillEllipse(Brushes.Red, Pickups(i)) 
ElseIf PickUpType = 2 Then 
    e.Graphics.FillEllipse(Brushes.Yellow, Pickups(i)) 
End If

結局のところ、 とPickUpType = 0で時間を無駄にする必要はPickUpType = 1ありPickUpType = 2ません。

With(4) ( http://msdn.microsoft.com/en-us/library/wc500chb(v=vs.100).aspx )を試してください。それ以外の:

If Advanced_Projectiles(i).IsEmpty = False Then 
    Advanced_Projectiles(i).X += AdvProjectile_Speed 
End If 

試す:

With Advanced_Projectiles(i)
    If Not .IsEmpty Then 
        .X += AdvProjectile_Speed 
    End If 
End With

(5) Microsoft.VisualBasic 名前空間 (UBound など) から何か (定数ではない) を使用している場合は、フレームワークのより「標準的な」部分で同じことを達成する方法を見つけてみてください。Microsoft.VisualBasic には、おそらく必要のない追加のレイヤーまたは VB6 癖がある場合があります。

于 2012-04-19T19:05:30.213 に答える
1

ダブルバッファリングを使用する必要があります。これは、ゲーム イベントなどに応答して、メモリ内のビットマップに対してすべてのペイントと描画を実行する場所です。次に、OnPaint で、そのバック バッファの画面に対して単一のブリットを実行します。

于 2012-04-19T12:05:48.450 に答える