これまでに作成した壁よけゲームは正面の壁だけしか描画されません。現在位置が大きく上下左右にズレてしまった場合、コースアウトした状態からもとに戻す方法を考えます。
まず上下左右に境界を描画します。そのためにDrawOutsideWalls()メソッドを作成します。
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 55 56 57 58 59 60 61 62 63 |
public partial class Form1 : Form { private void glControlEx1_Paint(object sender, PaintEventArgs e) { GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Lighting(); DrawWalls(); DrawOutsideWalls(); DrawJiki(); glControl.SwapBuffers(); } float WallSize = 6.0f; void DrawOutsideWalls() { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, Color.Brown); GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, Color.Brown); GL.Normal3(-Vector3.UnitY); GL.Begin(BeginMode.Quads); { GL.Vertex3(WallSize/2, WallSize / 2, 0); GL.Vertex3(-WallSize / 2, WallSize / 2, 0); GL.Vertex3(-WallSize / 2, WallSize / 2, -1000); GL.Vertex3(WallSize / 2, WallSize / 2, -1000); } GL.End(); GL.Normal3(Vector3.UnitY); GL.Begin(BeginMode.Quads); { GL.Vertex3(WallSize / 2, -WallSize / 2, 0); GL.Vertex3(-WallSize / 2, -WallSize / 2, 0); GL.Vertex3(-WallSize / 2, -WallSize / 2, -1000); GL.Vertex3(WallSize / 2, -WallSize / 2, -1000); } GL.End(); GL.Normal3(-Vector3.UnitX); GL.Begin(BeginMode.Quads); { GL.Vertex3(WallSize / 2, WallSize / 2, 0); GL.Vertex3(WallSize / 2, -WallSize / 2, 0); GL.Vertex3(WallSize / 2, -WallSize / 2, -1000); GL.Vertex3(WallSize / 2, WallSize / 2, -1000); } GL.End(); GL.Normal3(Vector3.UnitX); GL.Begin(BeginMode.Quads); { GL.Vertex3(-WallSize / 2, WallSize / 2, 0); GL.Vertex3(-WallSize / 2, -WallSize / 2, 0); GL.Vertex3(-WallSize / 2, -WallSize / 2, -1000); GL.Vertex3(-WallSize / 2, WallSize / 2, -1000); } GL.End(); } } |
次に外側の壁に当たったとき、強制的に進路を修正します。
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 |
public partial class Form1 : Form { private void Timer_Tick(object sender, EventArgs e) { // 上下左右 進路変更は30度までとする if(DoesMoveUp && RotateX < 30) RotateUpTarget(3); if(DoesMoveDown && RotateX > -30) RotateDownTarget(3); if(DoesMoveLeft && RotateY < 30) RotateLeftTarget(3); if(DoesMoveRight && RotateY > -30) RotateRightTarget(3); // コースアウトしていたら軌道修正する CourseCorrectionIfOutside(); MoveTargetDirect(0.1f); SetSight(); glControl.Refresh(); } float JikiSize = 0.5f; void CourseCorrectionIfOutside() { if(X < -3 + JikiSize / 2 || X > 3 - JikiSize / 2 || Y < -3 + JikiSize / 2 || Y > 3 - JikiSize / 2) { RotateX = 0; RotateY = 0; DoesMoveUp = false; DoesMoveDown = false; DoesMoveLeft = false; DoesMoveRight = false; if(X < -WallSize / 2 + JikiSize / 2) X = -WallSize / 2 + JikiSize; if(X > WallSize / 2 - JikiSize / 2) X = WallSize / 2 - JikiSize; if(Y < -WallSize / 2 + JikiSize / 2) Y = -WallSize / 2 + JikiSize; if(Y > WallSize / 2 - JikiSize / 2) Y = WallSize / 2 - JikiSize; } } } |
自機の座標によってはこれを撮影するカメラの座標がコースの外になる場合があります。これでは外壁が描画されて自機が見えなくなるので、カメラの座標を修正します。
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 partial class Form1 : Form { void SetSight() { float Distance = 3f; float radY = (float)(2f * Math.PI * RotateY / 360); float radX = (float)(2f * Math.PI * RotateX / 360); float eyeX = Distance * (float)Math.Sin(radY) * (float)Math.Cos(radX) + X; float eyeY = -Distance * (float)Math.Sin(radX) + Y; float eyeZ = Distance * (float)Math.Cos(radY) * (float)Math.Cos(radX) + Z; // カメラの座標が外壁よりも外側にある場合は修正する if(eyeX < -WallSize / 2) eyeX = -WallSize / 2; if(eyeX > WallSize / 2) eyeX = WallSize / 2; if(eyeY < -WallSize / 2) eyeY = -WallSize / 2; if(eyeY > WallSize / 2) eyeY = WallSize / 2; Vector3 eye = new Vector3(eyeX, eyeY, eyeZ); Vector3 target = new Vector3(X, Y, Z); Vector3 up = Vector3.UnitY; Matrix4 look = Matrix4.LookAt(eye, target, up); GL.LoadMatrix(ref look); } } |
壁の数を増やしました。だんだん壁の間隔が狭くなっていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { void CreateWalls() { Walls.Add(new Wall(WallSize, WallSize, -1f, 1f, 2f, 2f, -10f, Color.Yellow)); Walls.Add(new Wall(WallSize, WallSize, 1f, -1f, 2f, 2f, -20f, Color.Orange)); Walls.Add(new Wall(WallSize, WallSize, -1f, 1f, 2f, 2f, -29f, Color.Yellow)); Walls.Add(new Wall(WallSize, WallSize, 1f, -1f, 2f, 2f, -37f, Color.Orange)); Walls.Add(new Wall(WallSize, WallSize, -1f, 1f, 2f, 2f, -44f, Color.Yellow)); Walls.Add(new Wall(WallSize, WallSize, 1f, -1f, 2f, 2f, -50f, Color.Orange)); Walls.Add(new Wall(WallSize, WallSize, -1f, 1f, 2f, 2f, -55f, Color.Yellow)); Walls.Add(new Wall(WallSize, WallSize, 1f, -1f, 2f, 2f, -60f, Color.Orange)); Walls.Add(new Wall(WallSize, WallSize, -1f, 1f, 2f, 2f, -65f, Color.Yellow)); Walls.Add(new Wall(WallSize, WallSize, 1f, -1f, 2f, 2f, -70f, Color.Orange)); } } |
Wonderful, what a website it is! This weblog provides valuable information to us, keep it up. Leonore Ernst Averi
I read a great article with pleasure, I hope it will continue
XXXさん、コメントありがとうございます。不適切なサイトへのリンクがあったので削除させていただきました。笑