概要
cscの作法、調べてみた。
練習問題やってみた。
練習問題
ブロック崩しに、音を付けよ。
方針
- beep使う。
写真
サンプルコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
namespace Breakout
{
public partial class Form1: Form {
Label label1;
Label label2;
Vector ballPos;
Vector ballSpeed;
int ballRadius;
Rectangle paddlePos;
List<Rectangle> blockPos;
Timer timer = new Timer();
Timer timerCount = new Timer();
int countSize = 200;
int countNo = 3;
double accelSpeed = 1;
public static int blockNum {
get;
set;
}
public static int blockNumMax {
get;
set;
}
public static Stopwatch keikaTime = new Stopwatch();
public Form1() {
Text = "Breakout";
ClientSize = new System.Drawing.Size(600, 400);
label1 = new Label();
label1.Location = new System.Drawing.Point(550, 50);
label1.Text = "test1";
Controls.AddRange(new Control[] {
label1
});
label2 = new Label();
label2.Location = new System.Drawing.Point(550, 150);
label2.Text = "test2";
Controls.AddRange(new Control[] {
label2
});
this.ballSpeed = new Vector(3, 3);
this.ballPos = new Vector(200, 200);
this.ballRadius = 10;
this.paddlePos = new Rectangle(100, this.Height - 50, 100, 5);
this.blockPos = new List<Rectangle>();
blockNum = 0;
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));
blockNum++;
}
}
blockNumMax = blockNum;
label1.BackColor = Color.Transparent;
label2.BackColor = Color.Transparent;
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
timer.Interval = 80;
timerCount.Tick += new EventHandler(countDown);
timerCount.Start();
}
private void countDown(object sender, EventArgs e) {
if (countSize == 0)
{
countNo--;
label1.Text = countNo.ToString();
countSize = 200;
}
if (countSize == 20 && countNo == 1)
{
timerCount.Stop();
countDownAfter();
}
countSize -= 20;
}
private void countDownAfter() {
timer.Interval = 70;
timer.Tick += new EventHandler(Update);
timer.Start();
keikaTime.Start();
}
private void realTime() {
label2.Text = keikaTime.Elapsed.ToString().Substring(6, 6);
}
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) {
realTime();
int x = 1;
if (x / 100 == 1)
{
ballSpeed.X *= accelSpeed;
ballSpeed.Y *= accelSpeed;
ballPos += ballSpeed;
accelSpeed += 0.001;
}
else
{
ballPos += ballSpeed;
}
if (ballPos.X + ballRadius * 3 > this.Bounds.Width || ballPos.X - ballRadius < 0)
{
ballSpeed.X *= -1;
Console.Beep(500, 200);
}
if (ballPos.Y - ballRadius < 0)
{
ballSpeed.Y *= -1;
Console.Beep(500, 200);
}
if (LineVsCircle(new Vector(this.paddlePos.Left, this.paddlePos.Top), new Vector(this.paddlePos.Right, this.paddlePos.Top), ballPos, ballRadius))
{
if (ballPos.Y + 20 > paddlePos.Top)
{
ballSpeed.Y *= -1;
Console.Beep(500, 200);
}
}
for (int i = 0; i < this.blockPos.Count; i++)
{
int collision = BlockVsCircle(blockPos[i], ballPos);
if (collision == 1 || collision == 2)
{
ballSpeed.Y *= -1;
Console.Beep(500, 200);
this.blockPos.Remove(blockPos[i]);
blockNum--;
}
else if (collision == 3 || collision == 4)
{
ballSpeed.X *= -1;
Console.Beep(500, 200);
this.blockPos.Remove(blockPos[i]);
blockNum--;
}
}
if (ballPos.Y > this.Height || blockNum == 0)
{
keikaTime.Stop();
timer.Stop();
MessageBox.Show("game over !!");
Application.Exit();
}
Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
SolidBrush pinkBrush = new SolidBrush(Color.HotPink);
SolidBrush grayBrush = new SolidBrush(Color.DimGray);
SolidBrush 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, this.ballRadius * 2, this.ballRadius * 2);
e.Graphics.FillRectangle(grayBrush, paddlePos);
for (int i = 0; i < this.blockPos.Count; i++)
{
e.Graphics.FillRectangle(blueBrush, blockPos[i]);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e) {
switch(e.KeyData)
{
case Keys.Left:
this.paddlePos.X -= 20;
break;
case Keys.Right:
this.paddlePos.X += 20;
break;
default:
break;
}
}
private void form1_Closing(object sender, FormClosingEventArgs e) {
keikaTime.Stop();
timer.Stop();
timerCount.Stop();
this.Close();
this.Hide();
}
[STAThread]
static void Main(string[] args) {
Application.Run(new Form1());
}
}
}
以上。