こんな感じのゲームをつくります。
自分と敵の居場所と砲弾と残されているブロックがわかるようにレーダーを表示させます。
最後にレーダーに戦車、ブロック、砲弾を表示させます。デザイナでパネルを追加してここにレーダーを表示させます。
まずShowRadar()メソッドのなかで以下を実行することでPaintイベントを発生させます。
1 2 3 4 5 6 7 |
public partial class Form1 : Form { void ShowRadar() { panelRadar.Invalidate(); } } |
Paintイベントを処理できるようにPanelRadar_Paintメソッドを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); Tank = new Tank(0, 0, Color.Red, 0, this); ShowLabel(); panelRadar.BackColor = Color.Black; panelRadar.Paint += PanelRadar_Paint; InitTimer(); CreateStage(1); } private void PanelRadar_Paint(object sender, PaintEventArgs e) { // レーダーにブロックを表示 BlocksShowRadar(e.Graphics); // レーダーに自分の戦車を表示 MyTankShowRadar(e.Graphics); // レーダーに砲弾を表示 BulletsShowRadar(e.Graphics); return; } } |
BlocksShowRadar(Graphics g)メソッドでは破壊できないブロックと破壊できるけれども現段階では破壊されていないブロックを集めて座標を取得します。座標はPointのリストに格納しますが、このままではY座標は負数なのでBorderBlocks.Backの最小値の絶対値を調べて、これを加えています。そして16ピクセルで表示させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public partial class Form1 : Form { void BlocksShowRadar(Graphics g) { int size = 16; int leftMargin = 1; int min = (int)BorderBlocks.Min(x => x.Back); min = Math.Abs(min); List<Block> blocks = Blocks.Where(x => !x.IsBroken).ToList(); List<Point> pt1 = new List<Point>(); foreach(Block block in blocks) pt1.Add(new Point((int)block.PositionX, (int)block.PositionZ)); List<Point> pt2 = new List<Point>(); foreach(Block block in BorderBlocks) pt2.Add(new Point((int)block.PositionX, (int)block.PositionZ)); // ブロックは2.0なので2で割っている List<Rectangle> rectangles1 = pt1.Select(x => { return new Rectangle((x.X + leftMargin) * size / 2, (x.Y + min) * size / 2, size, size); }).ToList(); g.FillRectangles(new SolidBrush(Color.Brown), rectangles1.ToArray()); List<Rectangle> rectangles2 = pt2.Select(x => { return new Rectangle((x.X + leftMargin) * size / 2, (x.Y + min) * size / 2, size, size); }).ToList(); int left = rectangles2.Min(x => x.Right); int top = rectangles2.Min(x => x.Bottom); int right = rectangles2.Max(x => x.Left); int bottom = rectangles2.Max(x => x.Top); g.DrawRectangle(new Pen(Color.SaddleBrown, 2), new Rectangle(new Point(left, top), new Size(right- left, bottom-top))); } } |
MyTankShowRadar(Graphics g)メソッドは自分の戦車の位置を表示させるためのものです。ブロックを16ピクセルで表示させているので、表示させる座標はこれをもとに求める必要があります。戦車の位置の表示は12ピクセルにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public partial class Form1 : Form { void MyTankShowRadar(Graphics g) { int size = 16; int leftMargin = 1; int min = (int)BorderBlocks.Min(x1 => x1.Back); min = Math.Abs(min); Point tankPos = new Point((int)Math.Round(Tank.X), (int)Math.Round(Tank.Z)); int x = (tankPos.X + leftMargin) * size / 2 + 2; int y = (tankPos.Y + min) * size / 2 + 2; TankShowRadar(Tank, g, x, y); } void TankShowRadar(Tank tank, Graphics g, int x, int y) { Color color = Color.Empty; if(tank == Tank) color = Color.Yellow; else color = Color.Blue; List<Point> points = new List<Point>(); if(tank.Direct == Direct.North) { points.Add(new Point(x + 6, y)); points.Add(new Point(x, y + 12)); points.Add(new Point(x + 12, y + 12)); g.FillPolygon(new SolidBrush(color), points.ToArray()); } else if(tank.Direct == Direct.South) { points.Add(new Point(x, y)); points.Add(new Point(x + 12, y)); points.Add(new Point(x + 6, y + 12)); g.FillPolygon(new SolidBrush(color), points.ToArray()); } else if(tank.Direct == Direct.East) { points.Add(new Point(x, y)); points.Add(new Point(x, y + 12)); points.Add(new Point(x + 12, y + 6)); g.FillPolygon(new SolidBrush(color), points.ToArray()); } else if(tank.Direct == Direct.West) { points.Add(new Point(x, y + 6)); points.Add(new Point(x + 12, y)); points.Add(new Point(x + 12, y + 12)); g.FillPolygon(new SolidBrush(color), points.ToArray()); } } } |
Tank.Directプロパティは、RotateYプロパティから現在戦車がどちら向きなのかを取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class Tank { public Direct Direct { get { if(RotateY < 0) RotateY += 360; if(RotateY > 360) RotateY -= 360; if((0 <= RotateY && RotateY < 45) || (315 <= RotateY && RotateY <= 360)) return Direct.South; else if(45 <= RotateY && RotateY < 135) return Direct.East; if(135 <= RotateY && RotateY < 225) return Direct.North; else // if(RotateY == 270) return Direct.West; } } } |
BulletsShowRadar(Graphics g)メソッドは砲弾の位置を表示させるためのものです。ブロックを16ピクセルで表示させているので、表示させる座標はこれをもとに求める必要があります。砲弾の位置の表示は6ピクセルにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { void BulletsShowRadar(Graphics g) { int size = 16; int leftMargin = 1; int min = (int)BorderBlocks.Min(x => x.Back); min = Math.Abs(min); List<Point> pt = new List<Point>(); foreach(Bullet bullet in Tank.Bullets) pt.Add(new Point((int)bullet.X, (int)bullet.Z)); List<Rectangle> rectangles = pt.Select(x => new Rectangle((x.X + leftMargin) * size / 2 + 5, (x.Y + min) * size / 2 + 5, 6, 6)).ToList(); if(rectangles.Count > 0) g.FillRectangles(new SolidBrush(Color.White), rectangles.ToArray()); } } |