ブロック崩しについての質問 への返答
投稿で使用できる特殊コードの説明。(別タブで開きます。)
以下の返答は逆順(新しい順)に並んでいます。
投稿者 YAS  (社会人)
投稿日時
2010/8/26 23:28:26
>Timerコントロールの作成文が変だな。
>だから、不具合がでるんだよ。
私のコードに不具合がありましか?
一応動作確認はしているのですが。
>だから、不具合がでるんだよ。
私のコードに不具合がありましか?
一応動作確認はしているのですが。
投稿者 中島省吾  (社会人)
投稿日時
2010/8/26 21:59:03
Timerコントロールの作成文が変だな。
だから、不具合がでるんだよ。
だから、不具合がでるんだよ。
投稿者 YAS  (社会人)
投稿日時
2010/8/25 08:00:18
今まで話の流れだと下のような感じでしょうか。(コピー&ペーストで動きます。)
もしかすると「Me.KeyPreview = True」が必要なのかもしれません。
Public Class Form1
Dim Paddle As New PictureBox
Dim Ball As New PictureBox
Dim Balldx As Integer = 5
Dim Balldy As Integer = 5
Dim Paddledx As Integer
Dim Key As Keys
Dim WithEvents Timer As New Timer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DoubleBuffered = True
Me.BackColor = Color.Black
Me.Ball.Size = New Size(14, 14)
Me.Ball.Image = New Bitmap(Me.Ball.Size.Width, Me.Ball.Size.Height)
Using g As Graphics = Graphics.FromImage(Me.Ball.Image)
g.FillEllipse(Brushes.White, g.VisibleClipBounds)
End Using
Me.Paddle.Size = New Size(50, 14)
Me.Paddle.Image = New Bitmap(Me.Paddle.Size.Width, Me.Paddle.Size.Height)
Using g As Graphics = Graphics.FromImage(Me.Paddle.Image)
g.FillRectangle(Brushes.White, g.VisibleClipBounds)
End Using
Me.Paddle.Location = New Point((Me.ClientSize.Width - Me.Paddle.Width) / 2, Me.ClientSize.Height - Me.Paddle.Height)
Me.KeyPreview = True
Me.Timer.Interval = 10
Me.Timer.Start()
End Sub
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Key = e.KeyCode
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If Me.Paddle.Image IsNot Nothing AndAlso Me.Ball.Image IsNot Nothing Then
e.Graphics.DrawImage(Me.Paddle.Image, Me.Paddle.Location)
e.Graphics.DrawImage(Me.Ball.Image, Me.Ball.Location)
End If
End Sub
Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick
If Me.Ball.Location.X + Me.Ball.Size.Width > Me.ClientSize.Width OrElse Me.Ball.Location.X < 0 Then
Me.Balldx *= -1
End If
If Me.Ball.Location.Y + Me.Ball.Size.Height > Me.ClientSize.Height OrElse Me.Ball.Location.Y < 0 Then
Me.Balldy *= -1
End If
Me.Ball.Location += New Point(Me.Balldx, Me.Balldy)
If Key = Keys.Right Then
Me.Paddledx = DirectCast(IIf(Me.Paddle.Location.X + Me.Paddle.Size.Width >= Me.ClientSize.Width, 0, 3), Integer)
ElseIf Key = Keys.Left Then
Me.Paddledx = DirectCast(IIf(Me.Paddle.Location.X <= 0, 0, -3), Integer)
End If
Me.Paddle.Location += New Point(Me.Paddledx, 0)
Me.Invalidate()
End Sub
End Class
もしかすると「Me.KeyPreview = True」が必要なのかもしれません。
Public Class Form1
Dim Paddle As New PictureBox
Dim Ball As New PictureBox
Dim Balldx As Integer = 5
Dim Balldy As Integer = 5
Dim Paddledx As Integer
Dim Key As Keys
Dim WithEvents Timer As New Timer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DoubleBuffered = True
Me.BackColor = Color.Black
Me.Ball.Size = New Size(14, 14)
Me.Ball.Image = New Bitmap(Me.Ball.Size.Width, Me.Ball.Size.Height)
Using g As Graphics = Graphics.FromImage(Me.Ball.Image)
g.FillEllipse(Brushes.White, g.VisibleClipBounds)
End Using
Me.Paddle.Size = New Size(50, 14)
Me.Paddle.Image = New Bitmap(Me.Paddle.Size.Width, Me.Paddle.Size.Height)
Using g As Graphics = Graphics.FromImage(Me.Paddle.Image)
g.FillRectangle(Brushes.White, g.VisibleClipBounds)
End Using
Me.Paddle.Location = New Point((Me.ClientSize.Width - Me.Paddle.Width) / 2, Me.ClientSize.Height - Me.Paddle.Height)
Me.KeyPreview = True
Me.Timer.Interval = 10
Me.Timer.Start()
End Sub
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Key = e.KeyCode
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If Me.Paddle.Image IsNot Nothing AndAlso Me.Ball.Image IsNot Nothing Then
e.Graphics.DrawImage(Me.Paddle.Image, Me.Paddle.Location)
e.Graphics.DrawImage(Me.Ball.Image, Me.Ball.Location)
End If
End Sub
Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick
If Me.Ball.Location.X + Me.Ball.Size.Width > Me.ClientSize.Width OrElse Me.Ball.Location.X < 0 Then
Me.Balldx *= -1
End If
If Me.Ball.Location.Y + Me.Ball.Size.Height > Me.ClientSize.Height OrElse Me.Ball.Location.Y < 0 Then
Me.Balldy *= -1
End If
Me.Ball.Location += New Point(Me.Balldx, Me.Balldy)
If Key = Keys.Right Then
Me.Paddledx = DirectCast(IIf(Me.Paddle.Location.X + Me.Paddle.Size.Width >= Me.ClientSize.Width, 0, 3), Integer)
ElseIf Key = Keys.Left Then
Me.Paddledx = DirectCast(IIf(Me.Paddle.Location.X <= 0, 0, -3), Integer)
End If
Me.Paddle.Location += New Point(Me.Paddledx, 0)
Me.Invalidate()
End Sub
End Class
投稿者 TAKASI  (学生)
投稿日時
2010/8/23 11:56:04
お二方返答ありがとうございます。
るきおさんの方法を試させて貰ったのですが、変わらずkeydownイベントは動いていないようです。
そこでボタンを2つ作りそのボタンを押すと自機のx、y座標に3ずつ足す方法にしたところ、動いたのでそれで行こうと思います。
ただその方法だと自機がボールのスピードに追いつかないのでボタンを長押しして動くようにしたいのですがどんな方法がありますか?
るきおさんの方法を試させて貰ったのですが、変わらずkeydownイベントは動いていないようです。
そこでボタンを2つ作りそのボタンを押すと自機のx、y座標に3ずつ足す方法にしたところ、動いたのでそれで行こうと思います。
ただその方法だと自機がボールのスピードに追いつかないのでボタンを長押しして動くようにしたいのですがどんな方法がありますか?
投稿者 よねKEN  (社会人)
投稿日時
2010/8/22 23:34:22
PictureBoxを使うならImageプロパティを使うと便利ですよ。
■FormのLoadイベントで以下の処理を記述
Pic1.Image = New Bitmap(Pic1.ClientSize.Width, Pic1.ClientSize.Height)
■Graphicsオブジェクトが必要な場面では以下の取得
Dim g As Graphics = Graphics.FromImage(Pic1.Image)
■何か描画処理を行った後は以下のような記述をしてPictureBoxの描画を更新しておく
Pic1.Invalidate()
■FormのLoadイベントで以下の処理を記述
Pic1.Image = New Bitmap(Pic1.ClientSize.Width, Pic1.ClientSize.Height)
■Graphicsオブジェクトが必要な場面では以下の取得
Dim g As Graphics = Graphics.FromImage(Pic1.Image)
■何か描画処理を行った後は以下のような記述をしてPictureBoxの描画を更新しておく
Pic1.Invalidate()
投稿者 るきお  (社会人)
投稿日時
2010/8/22 10:21:27
推測で申し訳ないですが、複数の場所でCreateGraphicsしているので結果が合成されていないのだと思います。
ゲームのような描画処理が必要な場合は、Pic1のPaintイベントで描画してください。
KeyDownイベントやballmoveメソッドから描画を行いたい場合はPic1.Invalidateを呼び出します。
Invalidateを呼び出すとPaintイベントが呼び出されます。
Paintイベント内ではe.Graphicsに対して描画を命令します。
このようにすることで描画が一か所に集約されうまくつじつまがあいます。
なお、さらに一歩進めると描画処理はKeyDownやballmoveからは行わずTimer1_Timerイベント内でのみPic1.Invalidateを呼び出すようにすることをお勧めします。
KeyDownは押されたキーを記憶しておくだけ、ballmoveは新しい座標を計算しておくだけで、
それを描画するのはPic1_Paintイベント、描画を呼び出すのPic.Invalidate)はTimer1_Timerイベントだけという仕組みです。
このような基本的な枠組み(=フレームワーク)はゲーム作りでは最重要です。この枠組み次第では簡単なゲームもやけに難しいプログラムになったりどうしても作れくなったりしますが、枠組みがしっかりしていればある程度複雑なゲームでも驚くほど簡単に作成できることもあります。
具体例はサンプルで公開しているシューティングゲームを参考にしてください。
http://homepage1.nifty.com/rucio/main/DownLoad/Index_dl.htm
追加で質問などあればいつでもどうぞ。
ゲーム作りがんばってください!
…完成したらコンテストに応募してもらえるんですよね…??
ゲームのような描画処理が必要な場合は、Pic1のPaintイベントで描画してください。
KeyDownイベントやballmoveメソッドから描画を行いたい場合はPic1.Invalidateを呼び出します。
Invalidateを呼び出すとPaintイベントが呼び出されます。
Paintイベント内ではe.Graphicsに対して描画を命令します。
このようにすることで描画が一か所に集約されうまくつじつまがあいます。
なお、さらに一歩進めると描画処理はKeyDownやballmoveからは行わずTimer1_Timerイベント内でのみPic1.Invalidateを呼び出すようにすることをお勧めします。
KeyDownは押されたキーを記憶しておくだけ、ballmoveは新しい座標を計算しておくだけで、
それを描画するのはPic1_Paintイベント、描画を呼び出すのPic.Invalidate)はTimer1_Timerイベントだけという仕組みです。
このような基本的な枠組み(=フレームワーク)はゲーム作りでは最重要です。この枠組み次第では簡単なゲームもやけに難しいプログラムになったりどうしても作れくなったりしますが、枠組みがしっかりしていればある程度複雑なゲームでも驚くほど簡単に作成できることもあります。
具体例はサンプルで公開しているシューティングゲームを参考にしてください。
http://homepage1.nifty.com/rucio/main/DownLoad/Index_dl.htm
追加で質問などあればいつでもどうぞ。
ゲーム作りがんばってください!
…完成したらコンテストに応募してもらえるんですよね…??
投稿者 TAKASI  (学生)
投稿日時
2010/8/22 00:14:46
VB2008でブロック崩しを作っているのですが、玉は動くようになり次に自機を動かそうと思いやってみたのですが動きません。
もう一つプロジェクトを作って自機を動かす文だけでやってみるときちんと動きます。
あと、keydownイベント内にブレークポイントを作ってみたのですが反応はありませんでした。
長くなってしまうのでballmoveとkeydownイベントだけにしました。簡単に言うとボタン1が押されるとタイマーが動き出し、タイマーが刻むたびにballmove()関数がうごきます。
何が問題だと思われますか?何でもいいのでアドバイスお願いします
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Dim g As Graphics = Pic1.CreateGraphics()
g.DrawImage(picback, zikiX, zikiY, rect, GraphicsUnit.Pixel)
Select Case e.KeyCode
Case Keys.Left : zikiX -= 3
Case Keys.Right : zikiX += 3
End Select
g.DrawImage(ziki, zikiX, zikiY)
g.Dispose()
End Sub
Private Sub ballmove()
Dim g As Graphics = Pic1.CreateGraphics()
rec.X = x : rec.Y = y : rec.Width = 28 : rec.Height = 28
g.DrawImage(picback, x, y, rec, GraphicsUnit.Pixel)
g.DrawImage(ziki, zikiX, zikiY)
If x + 28 >= Pic1.Width Then
flag_x = False
ElseIf x < 1 And flag_x = False Then
flag_x = True
End If
If y + 28 >= Pic1.Height Then
flag_y = False
ElseIf y < 1 And flag_y = False Then
flag_y = True
End If
If flag_x = True The
x = x + 3
Else
x = x - 3
End If
If flag_y = True Then
y = y + 3
Else
y = y - 3
End If
g.DrawImage(tama, x, y)
g.Dispose()
End Sub
もう一つプロジェクトを作って自機を動かす文だけでやってみるときちんと動きます。
あと、keydownイベント内にブレークポイントを作ってみたのですが反応はありませんでした。
長くなってしまうのでballmoveとkeydownイベントだけにしました。簡単に言うとボタン1が押されるとタイマーが動き出し、タイマーが刻むたびにballmove()関数がうごきます。
何が問題だと思われますか?何でもいいのでアドバイスお願いします
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Dim g As Graphics = Pic1.CreateGraphics()
g.DrawImage(picback, zikiX, zikiY, rect, GraphicsUnit.Pixel)
Select Case e.KeyCode
Case Keys.Left : zikiX -= 3
Case Keys.Right : zikiX += 3
End Select
g.DrawImage(ziki, zikiX, zikiY)
g.Dispose()
End Sub
Private Sub ballmove()
Dim g As Graphics = Pic1.CreateGraphics()
rec.X = x : rec.Y = y : rec.Width = 28 : rec.Height = 28
g.DrawImage(picback, x, y, rec, GraphicsUnit.Pixel)
g.DrawImage(ziki, zikiX, zikiY)
If x + 28 >= Pic1.Width Then
flag_x = False
ElseIf x < 1 And flag_x = False Then
flag_x = True
End If
If y + 28 >= Pic1.Height Then
flag_y = False
ElseIf y < 1 And flag_y = False Then
flag_y = True
End If
If flag_x = True The
x = x + 3
Else
x = x - 3
End If
If flag_y = True Then
y = y + 3
Else
y = y - 3
End If
g.DrawImage(tama, x, y)
g.Dispose()
End Sub
失敗。