至急、解決策を求めます。
Q&A
解決したいこと
加速度センサを用いて端末上でバーを操作しブロック崩しのゲームを作成することです。また、3回ボールを落とすとバーの色が赤に変わり5回目になるとゲームオーバーとなります。
ブロックをボールがすり抜けたり、まったく別のあたっていないブロックが消えたり、ボールとバーが反射していないことが発覚しました。
画像ではスタートすると勝手にブロックが消されております
解決方法を教えて下さい。
発生している問題・エラー
出ているエラーメッセージを入力
```なし
```


### 該当するソースコード
```言語名 C# visualstudio2022
ソースコードを入力
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
using System.Net.Sockets;
namespace adbClient2
{
public partial class Form1 : Form
{
MyTcpClient client = new MyTcpClient("127.0.0.1", 7654);
readonly System.Windows.Forms.Timer timer;
Rectangle ballPos;
Vector ballSpeed;
const int ballRadius = 10;
Rectangle paddlePos;
int ballSpeedX = 5, ballSpeedY = 5;
int ballWidth = 20;
int ballHeight = 20;
int paddleWidth = 100;
int paddleHeight = 20;
int paddleX = 150;
int paddleY;
int count = 0;
Brush paddleColor = Brushes.Blue;
Rectangle paddle;
Rectangle ball;
List<Rectangle> blocks = new List<Rectangle>();
private static readonly Brush blue = Brushes.Blue;
Brush blockColor = Brushes.Green;
TcpListener tcpListener;
Thread tcpThread;
float accelX = 0f; // 加速度センサ値
List<Rectangle> blockPos;
public Form1()
{
InitializeComponent();
client.Connected += new EventHandler(client_Connected);
client.Disconnected += new EventHandler(client_Disconnected);
client.DataRead += new EventHandler<DataReadEventArgs>(client_DataRead);
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(Draw);
this.DoubleBuffered = true;
this.Width = 600;
this.Height = 600;
paddle = new Rectangle(this.ClientSize.Width / 2 - paddleWidth / 2, this.ClientSize.Height - 50, paddleWidth, paddleHeight);
ball = new Rectangle(this.ClientSize.Width / 2, this.ClientSize.Height / 2, ballWidth, ballHeight);
this.ballPos = new Rectangle(200, 200, ballRadius * 2, ballRadius * 2);
this.paddlePos = new Rectangle(100, this.Height - 50, 100, 5);
this.blockPos = new List<Rectangle>();
for (int x = 0; x <= this.Height; x += 100)
{
for (int y = 0; y <= 150; y += 40)
{
this.blockPos.Add(new Rectangle(25 + x, y, 80, 25));
}
}
timer = new System.Windows.Forms.Timer();
timer.Interval = 33;
timer.Tick += new EventHandler(Update);
timer.Start();
ballPos = new Rectangle(pictureBox1.Width / 2 - ballRadius, pictureBox1.Height / 2 - ballRadius, ballRadius * 2, ballRadius * 2);
ballSpeed = new Vector(1, 1);
this.paddlePos = new Rectangle(100, this.Height - 50, 100, 5);
paddlePos = new Rectangle(pictureBox1.Width / 2 - 50, pictureBox1.Height - 30, 100, 10);
}
// 接続したときの処理
void client_Connected(object sender, EventArgs e)
{
;
// 別のスレッドから呼び出されるのでDelegate(委譲)を経由してSetTextを実行する
this.Invoke((MethodInvoker)delegate
{
SetText("Connected to Android Device\r\n");
});
}
// 切断した時の処理
void client_Disconnected(object sender, EventArgs e)
{
// 別のスレッドから呼び出されるのでDelegate(委譲)を経由してSetTextを実行する
this.Invoke((MethodInvoker)delegate
{
SetText("Disconnected\r\n");
});
}
// データを受信したときの処理
void client_DataRead(object sender, DataReadEventArgs e)
{
string str;
short accX, accY, accZ;
accX = (short)((e.Data[0] << 8) | e.Data[1]);
accY = (short)((e.Data[2] << 8) | e.Data[3]);
accZ = (short)((e.Data[4] << 8) | e.Data[5]);
str = "加速度センサの値\r\n";
str += "x成分:" + ((float)accX / 100.0).ToString();
str += "\r\n";
str += "Y成分:" + ((float)accY / 100.0).ToString();
str += "\r\n";
str += "Z成分:" + ((float)accZ / 100.0).ToString();
this.Invoke((MethodInvoker)delegate
{
SetText(str);
});
byte[] sendData = new byte[3];
sendData[1] = 100;
sendData[2] = 255;
try
{
client.Write(sendData);
}
catch (Exception ex)
{
SetText(ex.Message);
}
if (accX > 100)
{
paddlePos.Offset(5, 0);
}
else if (accX < -100)
{
paddlePos.Offset(-5, 0);
}
if (paddlePos.Left < 0)
{
paddlePos.X = 0;
}
else if (paddlePos.Right > pictureBox1.Width)
{
paddlePos.X = pictureBox1.Width - paddlePos.Width;
}
pictureBox1.Invalidate();
}
private void CreateBlocks()
{
int blockWidth = 60;
int blockHeight = 20;
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 8; x++)
{
blocks.Add(new Rectangle(10 + x * (blockWidth + 10), 50 + y * (blockHeight + 10), blockWidth, blockHeight));
}
}
}
private void Draw(object sender, PaintEventArgs e)
{
using (var grayBrush = new SolidBrush(Color.DimGray))
using (var pinkBrush = new SolidBrush(Color.HotPink))
using (var blueBrush = new SolidBrush(Color.LightBlue))
{
float px = (float)this.ballPos.X - ballRadius;
float py = (float)this.ballPos.Y - ballRadius;
e.Graphics.FillEllipse(pinkBrush, px, py, ballRadius * 2, ballRadius * 2);
e.Graphics.FillRectangle(grayBrush, paddlePos);
for (int i = 0; i < this.blockPos.Count; i++)
{
int collision = BlockVsCircle(blockPos[i], new Vector(ballPos.X / 2 - ballRadius, ballPos.Y / 2 - ballRadius));
e.Graphics.FillRectangle(blueBrush, blockPos[i]);
}
}
ballPos.Offset((int)ballSpeed.X, (int)ballSpeed.Y);
}
double DotProduct(Vector a, Vector b)
{
return a.X * b.X + a.Y * b.Y; // 内積計算
}
bool LineVsCircle(Vector p1, Vector p2, Vector center, float radius)
{
Vector lineDir = (p2 - p1); // パドルの方向ベクトル
Vector n = new Vector(lineDir.Y, -lineDir.X); // パドルの法線
n.Normalize();
Vector dir1 = center - p1;
Vector dir2 = center - p2;
double dist = Math.Abs(DotProduct(dir1, n));
double a1 = DotProduct(dir1, lineDir);
double a2 = DotProduct(dir2, lineDir);
return (a1 * a2 < 0 && dist < radius) ? true : false;
}
int BlockVsCircle(Rectangle block, Vector ball)
{
if (LineVsCircle(new Vector(block.Left, block.Top),
new Vector(block.Right, block.Top), ball, ballRadius))
return 1;
if (LineVsCircle(new Vector(block.Left, block.Bottom),
new Vector(block.Right, block.Bottom), ball, ballRadius))
return 2;
if (LineVsCircle(new Vector(block.Right, block.Top),
new Vector(block.Right, block.Bottom), ball, ballRadius))
return 3;
if (LineVsCircle(new Vector(block.Left, block.Top),
new Vector(block.Left, block.Bottom), ball, ballRadius))
return 4;
return -1;
}
private void Update(object sender, EventArgs e)
{
ballPos.Offset((int)ballSpeed.X, (int)ballSpeed.Y);
// ボールの移動;
// 壁バウンド処理
if (ballPos.Left <= 0 || ballPos.Right >= pictureBox1.Width)
{
ballSpeed.X *= -1;
}
if (ballPos.Top <= 0)
{
ballSpeed.Y *= -1;
}
if (ballPos.Bottom >= pictureBox1.Height)
{
// ボールが下に落ちた
ballPos.Y = pictureBox1.Height / 2;
ballPos.X = pictureBox1.Width / 2;
ballSpeed.Y *= -1;
}
// パドルとの衝突
if (ballPos.IntersectsWith(paddlePos))
{
ballSpeed.Y *= -1;
ballPos.Y = paddlePos.Top - ballRadius * 2;
}
// 左右の壁でのバウンド
if (ballPos.X + ballRadius > this.Bounds.Width || ballPos.X - ballRadius < 0)
{
ballSpeed.X *= -1;
}
// 上の壁でバウンド
if (ballPos.Y - ballRadius < 0)
{
ballSpeed.Y *= -1;
}
//パドルの当たり判定
if (LineVsCircle(new Vector(this.paddlePos.Left, this.paddlePos.Top),
new Vector(this.paddlePos.Right, this.paddlePos.Top),
new Vector(ballPos.X / 2 - ballRadius, ballPos.Y / 2 - ballRadius),
ballRadius))
{
ballSpeed.Y *= -1;
}
for (int i = 0; i < this.blockPos.Count; i++)
{
int collision = BlockVsCircle(blockPos[i], new Vector(ballPos.X / 2 - ballRadius, ballPos.Y / 2 - ballRadius));
if (collision == 1 || collision == 2)
{
ballSpeed.Y *= -1;
this.blockPos.Remove(blockPos[i]); // 追加
}
else if (collision == 3 || collision == 4)
{
ballSpeed.X *= -1;
this.blockPos.Remove(blockPos[i]); // 追加
}
}
}
// テキストボックス内の文字列を設定
public void SetText(string s)
{
pictureBox1.Text = s;
}
// フォームが出現した時の処理
private void Form1_Load(object sender, EventArgs e)
{
// 接続ボタンを有効にする
btnStart.Enabled = true;
}
// フォームを閉じるときの処理
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// 通信を開始していたら通信用オブジェクトを破棄する
if (client != null)
{
client = null;
}
}
// 接続ボタンを押したときの処理
private void btnStart_Click(object sender, EventArgs e)
{
Process proc; // 別アプリとの連携処理オブジェクト(窓口)を生成
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = System.AppDomain.CurrentDomain.BaseDirectory + "\\adb.exe", // 起動するアプリ名(同じフォルダにある)
Arguments = "forward tcp:7654 tcp:4567", // 引数
CreateNoWindow = true, // ウィンドウは開かない
UseShellExecute = false // シェル機能は使わない
}; // 別アプリを起動する時の設定用の変数
proc = Process.Start(psi); // 別アプリ(adb.exe)の実行を開始
proc.WaitForExit(); // 終了するまで待つ
proc.Close(); // 連携機能を終了
proc.Dispose(); // 連携機能の窓口を破棄
// コマンドプロンプト上で adb forward tcp:7654 tcp:4567 と実行したのと同じ
// PC上の7654番ポートとAndroid端末の4567番ポートを接続
try
{
client.Connect(); // Android端末との通信を開始
}
catch (Exception ex)
{
SetText(ex.Message); // エラー(例外)が発生した場合はエラーメッセージを表示
}
btnStart.Enabled = false; // 接続ボタンを無効にする
}
// 色データ送信ボタンを押したときの処理
private void button1_Click(object sender, EventArgs e)
{
// 色データ(RGB)を格納するための配列(3バイト分)を用意
byte[] colorData = new byte[3];
colorData[0] = Convert.ToByte(textBoxRed.Text); // 第1要素(赤色のデータ)にtextBoxRed.Text(文字列)をバイトに変換してから格納
colorData[1] = Convert.ToByte(textBoxGreen.Text); // 第2要素(緑色のデータ)にtextBoxGreen.Text(文字列)をバイトに変換してから格納
colorData[2] = Convert.ToByte(textBoxBlue.Text); // 第3要素(青色のデータ)にtextBoxBlue.Text(文字列)をバイトに変換してから格納
try
{
client.Write(colorData); // Android端末へ色データを送信
}
catch (Exception ex)
{
SetText(ex.Message); // エラー(例外)が発生した場合はエラーメッセージを表示
}
}
private void timer_Tick(object sender, EventArgs e)
{
// パドル移動(加速度に応じて)
paddle.X += (int)(accelX * 10);
if (paddle.X < 0) paddle.X = 0;
if (paddle.X + paddleWidth > this.ClientSize.Width) paddle.X = this.ClientSize.Width - paddleWidth;
// ボール移動
ball.X += ballSpeedX;
ball.Y += ballSpeedY;
// 壁との衝突
if (ball.Left < 0 || ball.Right > this.ClientSize.Width)
ballSpeedX = -ballSpeedX;
if (ball.Top < 0)
ballSpeedY = -ballSpeedY;
// 落下処理
if (ball.Bottom > pictureBox1.Height)
{
count++; // ミス回数を増やす
ball.X = pictureBox1.Width / 2;
ball.Y = pictureBox1.Height / 2;
ballSpeedY = -ballSpeedY; // ボールを上に戻す
}
// パドルの色をミス回数に応じて変更
if (count >= 3)
paddleColor = Brushes.Red;
else
paddleColor = Brushes.Gray;
// パドル衝突
if (ball.IntersectsWith(paddle))
{
ballSpeedY = -ballSpeedY;
ball.Y = paddle.Top - ballHeight;
}
// ブロック衝突
for (int i = 0; i < blocks.Count; i++)
{
if (ball.IntersectsWith(blocks[i]))
{
blocks.RemoveAt(i);
ballSpeedY = -ballSpeedY;
break;
}
}
paddleColor = count > 2 ? Brushes.Red : Brushes.Blue;
// 終了条件
if (count >= 5)
{
MessageBox.Show("Game Over");
Application.Exit();
}
this.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
// パドルを paddleColor で描画
g.FillRectangle(paddleColor, paddle);
// ボールを黒で描画
g.FillEllipse(Brushes.Black, ball);
// ブロック(必要であれば)もここで描画
foreach (Rectangle b in blocks)
{
g.FillRectangle(Brushes.Green, b);
}
}
}
}
0 likes