質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

653閲覧

ゲームの停止ができない

likuson

総合スコア34

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2020/07/07 03:40

前提・実現したいこと

ゲームをクリアした際にゲームを停止させたいです。

発生している問題・エラーメッセージ

エラーメッセージはありませんでした。

該当のソースコード

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10using System.IO; 11 12namespace blockbreking_v2 13{ 14 public partial class Form1 : Form 15 { 16 Racket racket; 17 Ball ball; 18 static int numOfBlocks = 20; 19 Block[] blocks = new Block[numOfBlocks]; 20 public static int score; 21 22 Random random = new Random(); 23 bool rightKey = false, leftKey = false; 24 25 private void Initialize() 26 { 27 racket = new Racket(new Rectangle(pictureBox1.Width / 2 - 25, pictureBox1.Height - 10, 50, 10), 0, 0, 0, 10); 28 ball = new Ball(new Rectangle(0, 0, 10, 10), 0, 255, 0, new Point(7, 8)); 29 30 int drawX = 10, drawY = 40; 31 for (int i = 0; i < blocks.Length; i++) 32 { 33 blocks[i] = new Block(new Rectangle(drawX, drawY, 25, 10), random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)); 34 drawX += 100; 35 if (drawX >= pictureBox1.Width - 25) 36 { 37 drawX = 10; 38 drawY += 30; 39 } 40 } 41 score = 0; 42 43 } 44 public Form1() 45 { 46 InitializeComponent(); 47 Initialize(); 48 } 49 50 private void timer1_Tick(object sender, EventArgs e) 51 { 52 pictureBox1.Invalidate(); 53 } 54 55 private void Form1_KeyDown(object sender, KeyEventArgs e) 56 { 57 if (e.KeyCode == Keys.Right) 58 rightKey = true; 59 if (e.KeyCode == Keys.Left) 60 leftKey = true; 61 } 62 63 private void Form1_KeyUp(object sender, KeyEventArgs e) 64 { 65 if (e.KeyCode == Keys.Right) 66 rightKey = false; 67 if (e.KeyCode == Keys.Left) 68 leftKey = false; 69 } 70 71 private void startSToolStripMenuItem_Click(object sender, EventArgs e) 72 { 73 timer1.Enabled = true; 74 Initialize(); 75 } 76 77 private void saveSToolStripMenuItem_Click(object sender, EventArgs e) 78 { 79 if (saveFileDialog1.ShowDialog() == DialogResult.OK) 80 { 81 Encoding enc = Encoding.GetEncoding("Shift_JIS"); 82 using (StreamWriter sw = new StreamWriter(saveFileDialog1.FileName, false, enc)) 83 { 84 sw.Write(score); 85 } 86 } 87 } 88 89 private void button1_Click(object sender, EventArgs e) 90 { 91 button1.Visible = false; 92 this.ActiveControl = null; 93 Initialize(); 94 timer1.Enabled = true; 95 } 96 97 private void pictureBox1_Paint(object sender, PaintEventArgs e) 98 { 99 if (rightKey) 100 racket.MoveRight(pictureBox1.Width); 101 if (leftKey) 102 racket.MoveLeft(); 103 racket.DrawImage(e.Graphics); 104 ball.CalcSpeed(new Point(pictureBox1.Width, pictureBox1.Height), racket.GetPosition()); 105 ball.Move(); 106 ball.DrawImage(e.Graphics); 107 foreach (Block b in blocks) 108 { 109 if (!b.Hit(ball.GetPosition())) 110 b.DrawImage(e.Graphics); 111 else 112 { 113 score += 10; 114 toolStripStatusLabel1.Text = score.ToString(); 115 if (score == numOfBlocks*10) 116 { 117 timer1.Enabled = false; 118 float x = 140.0F; 119 float y = 70.0F; 120 float width = 200.0F; 121 float height = 50.0F; 122 RectangleF drawRect = new RectangleF(x, y, width, height); 123 Font drawFont = new Font("Arial", 30); 124 e.Graphics.FillRectangle(Brushes.Gold, x, y, width, height); 125 e.Graphics.DrawString(" Clear", drawFont, Brushes.DeepSkyBlue, drawRect); 126 127 } 128 } 129 } 130 131 132 if (!ball.JudgeFail(new Point(pictureBox1.Width, pictureBox1.Height))) 133 { 134 timer1.Enabled = false; 135 float x = 140.0F; 136 float y = 70.0F; 137 float width = 200.0F; 138 float height = 50.0F; 139 RectangleF drawRect = new RectangleF(x, y, width, height); 140 Font drawFont = new Font("Arial", 30); 141 e.Graphics.FillRectangle(Brushes.Black, x, y, width, height); 142 e.Graphics.DrawString(" Fail!", drawFont, Brushes.Red, drawRect); 143 } 144 145 } 146 147 } 148 class ParentClass 149 { 150 protected Rectangle position; 151 protected SolidBrush brush; 152 protected bool visible = true; 153 154 public ParentClass(Rectangle position, int r, int g, int b) 155 { 156 this.position = position; 157 brush = new SolidBrush(Color.FromArgb(r, g, b)); 158 } 159 public virtual bool Hit(Rectangle obstaclePosition) 160 { 161 if (position.IntersectsWith(obstaclePosition) && visible) 162 { 163 return true; 164 } 165 else 166 167 return false; 168 169 } 170 public Rectangle GetPosition() 171 { 172 return position; 173 } 174 public void SetPosition(Rectangle position) 175 { 176 this.position = position; 177 } 178 public bool GetVisible() 179 { 180 return visible; 181 } 182 public virtual void DrawImage(Graphics g) 183 { 184 if (visible) 185 g.FillRectangle(brush, position); 186 } 187 } 188 class Block : ParentClass 189 { 190 public Block(Rectangle position, int r, int b, int g) : base(position, r, g, b) 191 { 192 } 193 public override bool Hit(Rectangle obstaclePosition) 194 { 195 if (position.IntersectsWith(obstaclePosition) && visible) 196 { 197 visible = false;//ブロックを見えなくする 198 return true; 199 } 200 else 201 { 202 return false; 203 } 204 } 205 } 206 207 class Racket : ParentClass 208 { 209 int speed;//ラケットのスピード 210 public Racket(Rectangle position, int r, int g, int b, int speed) : base(position, r, g, b) 211 { 212 this.speed = speed*3; 213 } 214 public void MoveRight(int width) 215 { 216 if (position.X + speed <= width - position.Width) 217 position.X += speed; 218 else 219 position.X = width - position.Width; 220 } 221 public void MoveLeft() 222 { 223 if (position.X - speed >= 0) 224 position.X -= speed; 225 else 226 position.X = 0; 227 } 228 } 229 230 class Ball : ParentClass 231 { 232 bool preHit; 233 Point speed; 234 235 public Ball(Rectangle position, int r, int g, int b, Point speed) : base(position, r, g, b) 236 { 237 this.position = position; 238 this.speed = speed; 239 preHit = false; 240 } 241 public void CalcSpeed(Point pictureBocSize, Rectangle obstaclePosition) 242 { 243 if (position.IntersectsWith(obstaclePosition) && !preHit) 244 { 245 double degree = Math.Atan2(position.Y + position.Height / 2 - speed.Y - (obstaclePosition.Y + obstaclePosition.Height / 2), position.X + position.Width / 2 - speed.X - (obstaclePosition.X + obstaclePosition.Width / 2)); 246 double racketDegree = Math.Atan2(obstaclePosition.Height, obstaclePosition.Width); 247 if (degree >= racketDegree && degree <= racketDegree) 248 speed.X = -speed.X; 249 else 250 speed.Y = -speed.Y; 251 preHit = true; 252 } 253 else 254 preHit = false; 255 if (position.Y + speed.Y < 0) 256 speed.Y = -speed.Y; 257 if (position.X + speed.X > pictureBocSize.X - position.Width) 258 speed.X = -speed.X; 259 if (position.X + speed.X < 0) 260 speed.X = -speed.X; 261 } 262 public void Move() 263 { 264 int score = Form1.score; 265 if (score >= 0&& score <= 60) 266 { 267 position.X += speed.X ; 268 position.Y += speed.Y ; 269 } 270 else if(score >= 70 && score <= 130) 271 { 272 position.X += speed.X * 1; 273 position.Y += speed.Y * 1; 274 } 275 else 276 { 277 position.X += speed.X * 1; 278 position.Y += speed.Y * 1; 279 } 280 281 } 282 public bool JudgeFail(Point pictureBoxSize) 283 { 284 if (position.Y > pictureBoxSize.Y) 285 return false; 286 else 287 return true; 288 } 289 public override void DrawImage(Graphics g) 290 { 291 g.FillEllipse(brush, position); 292 } 293 } 294 295} 296

試したこと

timer.Enable=falseで停止させているつもりです。Failの場合もtimer.Enable=falseで停止させて、Failの場合はきちんとゲームが停止します。
Clearの場合は一瞬Clearと描画され、すぐにボールが動き出してしまいます。
ブロックは描画されません。

補足情報(FW/ツールのバージョンなど)

visualstudio 2019 consoleapplication

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

  • timer1_Tick()の役目 = ゲームの進行(状態の更新)
  • pictureBox1_Paint()の役目 = ゲームの現状態の描画

とする.
すなわち,現コードでpictureBox1_Paint()内で行っていることを,

  1. ゲームの処理ロジック
  2. ゲームの現状態の描画

の2つにわけ,前者をtimer1_Tick()内に移動させる.

投稿2020/07/07 07:54

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

タイマー以外でもpictureBox1の描画が発生すると動くコードになっていますよ。
あまり手を入れたくなければ、pictureBox1_Paint()の先頭で

C#

1if (!timer1.Enabled) 2{ 3 return; 4}

とでもしておけばよいかと。
DWM無効の環境でゲーム停止時に他ウインドウで隠れた部分は再描画されなくなるでしょうけれど…

投稿2020/07/07 04:37

編集2020/07/07 04:41
SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

likuson

2020/07/07 04:51

ありがとうございます。再描画はされなくなったのですが、クリア及びフェル(fail)の画面が一瞬で消えてしまいます。クリア及びフェルの画面の表示を永久に続行、又は、一定時間クリア及びフェルの画面の表示をする方法はあるのでしょうか。
SHOMI

2020/07/07 05:52 編集

再描画がかかって、その際にはなにも描画していないために消えているのでしょう。 returnにブレークポイントを貼るとfailやclearの後に止まり、ステップ実行してpictureBox1_Paint()を抜けるとpictureBox1の内容が消えていませんか? pictureBox1_Paint()の先頭に入れたコードでreturnの前にfailやclearならその描画を行うようコードを入れてください。
SHOMI

2020/07/07 08:28 編集

「あまり手を入れたくなければ」と前置きしたとおり、簡易対策です。 きちんと対応するなら、fanaさんの回答の通り描画とゲーム進行に分離してください。
fana

2020/07/07 08:48

せっかくの(?) "簡易" なのに, 「止めている時でも,これだけはやりたい」とか言い始めると,結局,現存する処理を if を境にして上下に2つに選り分ける: timer1の状況によらずやる処理; //(1)上側 if (!timer1.Enabled)return; //境界 timer1がEnabledなときだけやる処理; //(2)下側 という形になるので,別の場所に処理を分けるのと比較して,行う作業の規模は変わらなくなってしまう気がしますね.
SHOMI

2020/07/07 09:51

あまり手を入れずにメッセージを出し続けたいなら、PictureBoxに直接書かずにラベルをPictureBoxの上に表示するとかですかね。
SHOMI

2020/07/07 10:02 編集

後々手を入れることを考えると、きちんと分離しておいたほうがよいですね。 それに今のままだと他アプリなどの影響で再描画が掛かってしまうと進行スピードが不安定になりますし。 そういえば昔ゲーム画面上でマウスポインタを動かしまくると進行速度が上がるゲームが有ったな…
fana

2020/07/07 10:22

The word "DWM" is helpful for me, so I press the "+" button.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問