スペース・パニックは1980年にユニバーサル(現・ユニバーサルエンターテインメント)によって設計されたアーケードゲームです。上は自分でつくったゲーム、下は本物のスペースパニックの実演動画です。
主人公は敵であるエイリアンを穴を掘って穴から突き落として倒します。またエイリアンのなかには強力なものもあり、2つ以上の穴を垂直に並べて落とさないと死なないものもあります。
スペース・パニックは商業的には失敗との評価ですが、その理由として1983年エレクトロニック・ゲームズ誌はコンセプトの斬新さが観客に受け入れられなかったことを挙げています。「クライミングゲームの最初の作品であるだけでなく、掘るゲームの最初の作品でもあった。新しいゲームをプレイする人にとって、これはかなりの負担だ。しゃれを言うつもりではなく平均的なゲーマーがするには梯子が高すぎた」とのこと。
管理人はゲームセンターで他の人がプレイしているのをみたことはありますが、自分自身でこのゲームをしたことがありません。それから当時は学校の規則でゲームセンターへの立ち入りは禁止されていて・・・こんなことを書くと管理人のだいたいの年齢がバレます。
Contents
ステージをつくる
ではさっそくはじめましょう。ステージをつくるところからはじめます。
画像ファイルを作成してリソースに追加しておきます。
6階建ての建物でところどころにハシゴがあり、上下の階に移動できます。キャラクターサイズを32ピクセル×32ピクセルとして1階の高さをキャラクターサイズの3倍、幅を15倍としましょう。
こんな感じにつくります。X座標はキャラクターサイズの0倍から15倍まで白い直線を、Y座標はキャラクターサイズの3倍ずつ増やして黄色の直線を描画しています。それから上と左に余白をいれています。
ゲームのキャラクターを移動させたり描画するためのGameManagerクラスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public GameManager(Form1 form) { Bitmap LadderImage = Properties.Resources.ladder; Bitmap FloorImage = Properties.Resources.floor; public static int CharctorSize = 32; static int MarginLeft = 40; static int MarginTop = 20; Form1 Form = null; public GameManager(Form1 form) { Form = form; } public static Point GetPointForShow(int x, int y) { return new Point(MarginLeft + x, MarginTop + y); } } |
床を描画する
X座標とY座標はそれぞれキャラクターが移動する座標であり、床はそれよりもキャラクターサイズ分下に存在します。それからキャラクターが移動できる部分よりも広めに描画します。一番下は穴を掘ることができない床なので別の色で描画します。
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 |
public class GameManager { public void DrawFloor(Graphics graphics) { for (int i = 1; i <= 6; i++) { for (int j = -1; j <= 15; j++) { // 床はキャラクターのY座標よりキャラクターの高さだけ下にある int x = CharctorSize * j; int y = GetYFromNumberOfFloors(i) + CharctorSize; Point pt = GetPointForShow(x, y); if (i == 1) { graphics.FillRectangle( new SolidBrush(Color.Aqua), new Rectangle(pt.X, pt.Y, 32, 32)); } else { graphics.DrawImage( FloorImage, new Rectangle(pt.X, pt.Y, 32, 32), new Rectangle(0, 0, 32, 32), GraphicsUnit.Pixel); } } } } // 階数からY座標を求める static int GetYFromNumberOfFloors(int numberOfFloors) { return (18 - numberOfFloors * 3) * CharctorSize; } } |
ハシゴを描画する
次にハシゴを描画します。
ハシゴがある位置は、
全階のX座標がCharctorSizeの0倍と14倍(両端)の位置
1階はX座標がCharctorSizeの4倍と10倍
2階はCharctorSizeの10倍
3階はCharctorSizeの6倍
4階はCharctorSizeの6倍
5階はX座標がCharctorSizeの4倍と10倍の位置
にあるものとします。X座標がこれらの値のときは上の階へ移動することができます。同様に移動先の階とX座標から下の階に移動することもできます。
以下はハシゴの位置を取得するメソッドです。コンストラクタ内で実行して結果をフィールド変数に保存します。
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 class GameManager { public static List<Point> GetLadderPositions() { List<Point> points = new List<Point>(); int y1 = GetYFromNumberOfFloors(1); points.Add(new Point(CharctorSize * 0, y1)); points.Add(new Point(CharctorSize * 4, y1)); points.Add(new Point(CharctorSize * 10, y1)); points.Add(new Point(CharctorSize * 14, y1)); int y2 = GetYFromNumberOfFloors(2); points.Add(new Point(CharctorSize * 0, y2)); points.Add(new Point(CharctorSize * 10, y2)); points.Add(new Point(CharctorSize * 14, y2)); int y3 = GetYFromNumberOfFloors(3); points.Add(new Point(CharctorSize * 0, y3)); points.Add(new Point(CharctorSize * 6, y3)); points.Add(new Point(CharctorSize * 14, y3)); int y4 = GetYFromNumberOfFloors(4); points.Add(new Point(CharctorSize * 0, y4)); points.Add(new Point(CharctorSize * 6, y4)); points.Add(new Point(CharctorSize * 14, y4)); int y5 = GetYFromNumberOfFloors(5); points.Add(new Point(CharctorSize * 0, y5)); points.Add(new Point(CharctorSize * 4, y5)); points.Add(new Point(CharctorSize * 10, y5)); points.Add(new Point(CharctorSize * 14, y5)); return points; } } |
ハシゴを描画する処理を示します。
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 |
public class GameManager { public GameManager(Form1 form) { Form = form; // 最初にハシゴの座標を取得する LadderPositions = GetLadderPositions(); } static List<Point> LadderPositions = new List<Point>(); public void DrawLadders(Graphics graphics) { List<Point> points = new List<Point>(); foreach (Point pt in LadderPositions) { points.Add(new Point(pt.X, pt.Y)); points.Add(new Point(pt.X, pt.Y - CharctorSize * 1)); points.Add(new Point(pt.X, pt.Y - CharctorSize * 2)); points.Add(new Point(pt.X, pt.Y - CharctorSize * 3)); } foreach (Point pt in points) { Point point = GetPointForShow(pt.X, pt.Y); graphics.DrawImage(LadderImage, new Rectangle(point.X, point.Y, 32, 32), new Rectangle(0, 0, 32, 32), GraphicsUnit.Pixel); } } } |
実際に描画の処理をするときは上記のメソッドをForm1クラスから呼び出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { GameManager GameManager; public Form1() { InitializeComponent(); GameManager = new GameManager(this); this.DoubleBuffered = true; this.BackColor = Color.Black; } protected override void OnPaint(PaintEventArgs e) { GameManager.DrawFloor(e.Graphics); GameManager.DrawLadders(e.Graphics); base.OnPaint(e); } } |