冒險游戲的界面如上圖所示,就是簡單的闖關游戲,一共有5種道具和3種怪物
道具分別為:劍、弓箭、錘子、藍藥水和紅藥水
怪物分別為:蝙蝠、幽靈、食屍鬼
類圖視圖如下所示,怪物類、道具類和玩家類繼承於移動類。
代碼實現如下:
[csharp]
?namespace 冒險游戲
{
public partial class Form1 : Form
{
private Game game;
private Random random = new Random();
public Form1()
{
InitializeComponent();
}
public void UpdateCharacters()
{
Player.Visible = true;
Player.Location = game.PlayerLocation;
lbPlayer.Text = game.PlayerHitPoints.ToString();
//顯示和隱藏生成的敵人
#region Enemy
int enemiesShown = game.Enemies.Count;
foreach (Enemy enemy in game.Enemies)
{
if (enemy is Bat)
{
bat.Location = enemy.Location;
lbBat.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
bat.Visible = true;
}
else
{
enemiesShown--;
bat.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
if (enemy is Ghost)
{
ghost.Location = enemy.Location;
lbGhost.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
ghost.Visible = true;
}
else
{
enemiesShown--;
ghost.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
if (enemy is Ghoul)
{
ghoul.Location = enemy.Location;
lbGhoul.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
ghoul.Visible = true;
}
else
{
enemiesShown--;
ghoul.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
}
#endregion
//顯示和隱藏道具
#region inventory
Control weaponControl = null;
switch (game.WeaponInRoom.Name)
{
case "Sword":
weaponControl = sword;
break;
case "BluePotion":
weaponControl = bluePotion;
break;
case "RedPotion":
weaponControl = redPotion;
break;
case "Bow":
weaponControl = bow;
break;
case "Mac":
weaponControl=mac;
break;
default: break;
}
if (weaponControl != null)
{
weaponControl.Visible = true;
weaponControl.Location = game.WeaponInRoom.Location;
}
if (game.WeaponInRoom.PickedUp)
{
weaponControl.Visible = false;
}
foreach (string weapon in game.PlayerWeapons)
{
switch (weapon)
{
case "Sword":
picSword.Visible = true;
break;
case "BluePotion":
picBluePotion.Visible = true;
break;
case "RedPotion":
picRedPotion.Visible = true;
break;
case "Bow":
picBow.Visible = true;
break;
case "Mac":
picMac.Visible = true;
break;
default: break;
}
}
if (!game.CheckPlayerInventory("BluePotion"))
{
picBluePotion.Visible = false;
}
if (!game.CheckPlayerInventory("RedPotion"))
{
picRedPotion.Visible = false;
}
#endregion
//自己血量不足游戲結束
if (game.PlayerHitPoints <= 0)
{
MessageBox.Show("You died");
Application.Exit();
}
//沒有敵人到下一關
if (enemiesShown < 1)
{
MessageBox.Show("You have defeatead the enemies on this level");
lbBat.Text = "";
lbGhost.Text = "";
lbGhoul.Text = "";
if (!game.NewLevel(random))
{
Application.Exit();
return;
}
weaponControl.Visible = false;
UpdateCharacters();
}
}
private void Form1_Load(object sender, EventArgs e)
{
game = new Game(new Rectangle(78, 57, 420, 155));
game.NewLevel(random);
UpdateCharacters();
}
/// <summary>
/// 向下移動
/// </summary>
private void btnM_Right_Click(object sender, EventArgs e)
{
game.Move(Direction.Right,random);
UpdateCharacters();
}
/// <summary>
/// 向下移動
/// </summary>
private void btnM_Down_Click(object sender, EventArgs e)
{
game.Move(Direction.Down,random);
UpdateCharacters();
}
/// <summary>
/// 向左移動
/// </summary>
private void btnM_Left_Click(object sender, EventArgs e)
{
game.Move(Direction.Left,random);
UpdateCharacters();
}
/// <summary>
/// 向上移動
/// </summary>
private void btnM_Up_Click(object sender, EventArgs e)
{
game.Move(Direction.Up,random);
UpdateCharacters();
}
/// <summary>
/// 裝備物品
/// </summary>
private void picSword_Click(object sender, EventArgs e)
{
foreach (Control pic in this.Controls)
{
if (pic is PictureBox)
{
((PictureBox)pic).BorderStyle = BorderStyle.None;
game.Equip(((PictureBox)sender).Tag.ToString());
if (((PictureBox)sender).Tag.ToString().Contains("Potion"))
{
panelAttrack.Visible = false;
btnDrink.Visible = true;
}
else
{
panelAttrack.Visible = true;
btnDrink.Visible = false;
}
}
}
((PictureBox)sender).BorderStyle = BorderStyle.FixedSingle;
}
/// <summary>
/// 用上下左右鍵盤移動
/// </summary>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData)
{
case Keys.Up:
btnM_Up_Click(null, null);
break;
case Keys.Left:
btnM_Left_Click(null, null);
break;
case Keys.Right:
btnM_Right_Click(null, null);
break;
case Keys.Down:
btnM_Down_Click(null,null);
break;
default:
break;
}
return true;
}
/// <summary>
/// 向上攻擊
/// </summary>
private void btnA_Up_Click(object sender, EventArgs e)
{
game.Attack(Direction.Up,random);
UpdateCharacters();
}
/// <summary>
/// 向左攻擊
/// </summary>
private void btnA_Left_Click(object sender, EventArgs e)
{
game.Attack(Direction.Left, random);
UpdateCharacters();
}
/// <summary>
/// 向左攻擊
/// </summary>
private void btnA_Down_Click(object sender, EventArgs e)
{
game.Attack(Direction.Down, random);
UpdateCharacters();
}
/// <summary>
/// 向右攻擊
/// </summary>
private void btnA_Right_Click(object sender, EventArgs e)
{
game.Attack(Direction.Right, random);
UpdateCharacters();
}
/// <summary>
/// 吃藥
/// </summary>
private void btnDrink_Click(object sender, EventArgs e)
{
game.Attack(Direction.Right, random);
game.Equip(null);
UpdateCharacters();
btnDrink.Visible = false;
panelAttrack.Visible = true;
}
}
/// <summary>
/// 方向
/// </summary>
public enum Direction
{
Up, Left, Right, Down
}
/// <summary>
/// 游戲類
/// </summary>
public class Game
{
public List<Enemy> Enemies;
public Weapon WeaponInRoom;
private Player player;
public Point PlayerLocation { get { return player.Location; } }
public int PlayerHitPoints { get { return player.HitPoints; } }
public List<string> PlayerWeapons { get { return player.Weapons; } }
private int level = 0;
public int Level { get { return level; } }
private Rectangle boundaries;
public Rectangle Boundaries { get { return boundaries; } }
public Game(Rectangle boundaries)
{
this.boundaries = boundaries;
player = new Player(this,new Point(boundaries.Left+10,boundaries.Top+70),boundaries);
}
public void Move(Direction direction,Random random)
{
player.Move(direction);
foreach (Enemy enemy in Enemies)
enemy.Move(random);
}
public void Equip(string weaponName)
{
player.Equip(weaponName);
}
/// <summary>
/// 玩家道具欄裡是否有某武器
/// </summary>
public bool CheckPlayerInventory(string weaponName)
{
return player.Weapons.Contains(weaponName);
}
public void HitPlayer(int maxDamage,Random random)
{
player.Hit(maxDamage,random);
}
public void IncreasePlayerHealth(int health,Random random)
{
player.IncreaseHeath(health,random);
}
public void Attack(Direction direction,Random random)
{
player.Attract(direction,random);
foreach (Enemy enemy in Enemies)
enemy.Move(random);
}
private Point GetRandomLocation(Random random)
{
return new Point(boundaries.Left + random.Next(boundaries.Right / 10 - boundaries.Left / 10) * 10,
boundaries.Top +
random.Next(boundaries.Bottom / 10 - boundaries.Top / 10) * 10);
}
public bool NewLevel(Random random)
{
level++;
switch (level)
{
case 1:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this,GetRandomLocation(random),boundaries));
WeaponInRoom = new Sword(this,GetRandomLocation(random));
break;
case 2:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new BluePotion(this, GetRandomLocation(random));
break;
case 3:
Enemies = new List<Enemy>();
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new Bow(this,GetRandomLocation(random));
break;
case 4:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
if(!CheckPlayerInventory("Bow"))
WeaponInRoom = new Bow(this, GetRandomLocation(random));
else
WeaponInRoom = new BluePotion(this, GetRandomLocation(random));
break;
case 5:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new RedPotion(this, GetRandomLocation(random));
break;
case 6:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new Mace(this, GetRandomLocation(random));
break;
case 7:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
if (!CheckPlayerInventory("Mac"))
WeaponInRoom = new Mace(this, GetRandomLocation(random));
else
WeaponInRoom = new RedPotion(this, GetRandomLocation(random));
break;
case 8:
MessageBox.Show("恭喜你通關了");
return false;
}
return true;
}
}
/// <summary>
/// 移動類,敵人和自己的移動都繼承這個類
/// </summary>
public abstract class Mover
{
private const int MoveInterval = 10;
protected Point location;
public Point Location { get { return location; } }
protected Game game;
public Mover(Game game, Point location)
{
this.game = game;
this.location = location;
}
/// <summary>
/// 用弓箭看是否在一條直線上並且在射程內
/// </summary>
public bool Nearby(Direction direnction,Point locationToCheck, int distance)
{
switch (direnction)
{
case Direction.Down:
if (game.PlayerLocation.X == locationToCheck.X && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) < distance && game.PlayerLocation.Y < locationToCheck.Y)
return true;
break;
case Direction.Up:
if (game.PlayerLocation.X == locationToCheck.X && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) < distance && game.PlayerLocation.Y > locationToCheck.Y)
return true;
break;
case Direction.Left:
if (game.PlayerLocation.Y == locationToCheck.Y && Math.Abs(game.PlayerLocation.X - locationToCheck.X) < distance && game.PlayerLocation.X > locationToCheck.X)
return true;
break;
case Direction.Right:
if (game.PlayerLocation.Y == locationToCheck.Y && Math.Abs(game.PlayerLocation.X - locationToCheck.X) < distance && game.PlayerLocation.X < locationToCheck.X)
return true;
break;
}
return false;
}
/// <summary>
/// 劍和錘判斷怪物是否在武器攻擊半徑內
/// </summary>
public bool Nearby(Point location, Point locationToCheck, int radius)
{
if (Math.Sqrt(Math.Abs(location.X - locationToCheck.X) * Math.Abs(location.X - locationToCheck.X) +
Math.Abs(location.Y - locationToCheck.Y) * Math.Abs(location.Y - locationToCheck.Y)) <= radius)
return true;
else
return false;
}
public Point Move(Direction direction, Rectangle boundaries)
{
Point newLocation = location;
switch (direction)
{
case Direction.Up:
if(newLocation.Y-MoveInterval>=boundaries.Top)
newLocation.Y-=MoveInterval;
break;
case Direction.Down:
if (newLocation.Y + MoveInterval <= boundaries.Bottom)
newLocation.Y += MoveInterval;
break;
case Direction.Left:
if (newLocation.X - MoveInterval >= boundaries.Left)
newLocation.X -= MoveInterval;
break;
case Direction.Right:
if (newLocation.X + MoveInterval <= boundaries.Right)
newLocation.X += MoveInterval;
break;
default: break;
}
return newLocation;
}
}
public class Player : Mover
{
private Weapon equippedWeapon;
private int hitPoints;
public int HitPoints { get { return hitPoints; } }
private List<Weapon> inventory = new List<Weapon>();
public List<string> Weapons
{
get
{
List<string> names = new List<string>();
foreach (Weapon weapon in inventory)
names.Add(weapon.Name);
return names;
}
}
public Player(Game game, Point location, Rectangle boundaries)
: base(game, location)
{ hitPoints = 10; }
public void IncreaseHeath(int health,Random random)
{
hitPoints += random.Next(1,health);
}
public void Hit(int maxDamage,Random random)
{
hitPoints -= random.Next(1,maxDamage);
}
public void Equip(string weaponName)
{
if (weaponName == null)
{
equippedWeapon = null;
return;
}
foreach (Weapon weapon in inventory)
{
if (weapon.Name == weaponName)
equippedWeapon = weapon;
}
}
public void Move(Direction direction)
{
base.location = Move(direction, game.Boundaries);
if (!game.WeaponInRoom.PickedUp)
{
if (game.WeaponInRoom.Location == base.location)
{
game.WeaponInRoom.PickUpWeapon();
inventory.Add(game.WeaponInRoom);
}
}
}
public void Attract(Direction direction,Random random)
{
if (equippedWeapon != null)
{
equippedWeapon.Attack(direction,random);
//如果裝備物品是藥品,接口就是區別裝備和藥品的方法
if (equippedWeapon is IPotion)
inventory.Remove(equippedWeapon);
}
}
}
#region Enemy
public abstract class Enemy : Mover
{
private const int NearPlayerDistance = 30;
private int hitPoints;
public int HitPoints { get { return hitPoints; } }
public bool Dead()
{
if (hitPoints <= 0)
return true;
else
return false;
}
public Enemy(Game game, Point location, Rectangle boundaries, int hitPoints)
: base(game, location)
{ this.hitPoints = hitPoints; }
public abstract void Move(Random random);
protected bool NearPlayer()
{
return (Nearby(location, game.PlayerLocation, NearPlayerDistance));
}
public void Hit(int maxDamage,Random random)
{
hitPoints -= random.Next(1, maxDamage);
}
protected Direction FindPlayerDirection(Point playerLocation)
{
Direction directionToMove;
if (playerLocation.X > Location.X + 10)
directionToMove = Direction.Right;
else if (playerLocation.X < Location.X - 10)
directionToMove = Direction.Left;
else if (playerLocation.Y < Location.Y - 10)
directionToMove = Direction.Up;
else
directionToMove = Direction.Down;
return directionToMove;
}
}
public class Bat : Enemy
{
//蝙蝠起始點數為6,有50%的幾率朝著玩家飛,而另外50%的情況會隨機的飛
public Bat(Game game,Point location,Rectangle boundaries)
: base(game, location, boundaries, 6)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(3, random);
return;
}
if (random.Next(2) == 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location = Move(direction, game.Boundaries);
}
else
{
Direction direction = (Direction)random.Next(4);
this.location = Move(direction, game.Boundaries);
}
}
}
public class Ghost:Enemy
{
//幽靈起始點數為8,有1/3幾率朝著玩家移動,另外情況原地不動
public Ghost(Game game,Point location,Rectangle boundaries)
: base(game, location, boundaries, 8)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(4, random);
return;
}
if (random.Next(3) == 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location = Move(direction, game.Boundaries);
}
}
}
public class Ghoul : Enemy
{
//食屍鬼起始點數為10,有2/3幾率朝著玩家移動,另外情況原地不動
public Ghoul(Game game, Point location, Rectangle boundaries)
: base(game, location, boundaries, 10)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(5, random);
return;
}
if (random.Next(3) != 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location=Move(direction,game.Boundaries);
}
}
}
#endregion
#region Weapon
/// <summary>
/// 武器類
/// </summary>
public abstract class Weapon:Mover
{
public abstract string Name { get; }
public abstract void Attack(Direction direction,Random random);
private bool pickedUp;
public bool PickedUp { get { return pickedUp; } }
public Weapon(Game game, Point location):base(game,location)
{
pickedUp = false;
}
public void PickUpWeapon() { pickedUp = true; }
/// <summary>
/// 弓箭
/// </summary>
protected bool DamageEnemy(Direction direction, int distance, int damage,Random random)
{
Point target = game.PlayerLocation;
foreach (Enemy enemy in game.Enemies)
{
if (Nearby(direction,enemy.Location,distance))
{
enemy.Hit(damage,random);
return true;
}
}
return false;
}
/// <summary>
/// 劍和錘
/// </summary>
protected bool DamageEnemy(int radius, int damage, Random random)
{
Point target = game.PlayerLocation;
foreach (Enemy enemy in game.Enemies)
{
if (Nearby(enemy.Location, target, radius))
{
enemy.Hit(damage, random);
return true;
}
}
return false;
}
}
/// <summary>
/// 藥品接口
/// </summary>
public interface IPotion
{
bool Used { get; }
}
/// <summary>
/// 劍
/// </summary>
public class Sword : Weapon
{
public Sword(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get
{
return "Sword";
}
}
public override void Attack(Direction direction,Random random)
{
DamageEnemy(60, 4,random);
}
}
/// <summary>
/// 弓箭
/// </summary>
public class Bow : Weapon
{
public Bow(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get
{
return "Bow";
}
}
public override void Attack(Direction direction, Random random)
{
DamageEnemy(direction, 90, 2, random);
}
}
/// <summary>
/// 錘
/// </summary>
public class Mace : Weapon
{
public Mace(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "Mac"; }
}
public override void Attack(Direction direction, Random random)
{
DamageEnemy(50, 7, random);
}
}
/// <summary>
/// 藍色藥水
/// </summary>
public class BluePotion : Weapon, IPotion
{
private bool used=false;
public BluePotion(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "BluePotion"; }
}
public override void Attack(Direction direction, Random random)
{
game.IncreasePlayerHealth(6,random);
used=true;
}
public bool Used
{
get { return used; }
}
}
/// <summary>
/// 紅色藥水
/// </summary>
public class RedPotion : Weapon, IPotion
{
private bool used = false;
public RedPotion(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "RedPotion"; }
}
public override void Attack(Direction direction, Random random)
{
game.IncreasePlayerHealth(11, random);
used = true;
}
public bool Used
{
get { return used; }
}
}
#endregion
}
namespace 冒險游戲
{
public partial class Form1 : Form
{
private Game game;
private Random random = new Random();
public Form1()
{
InitializeComponent();
}
public void UpdateCharacters()
{
Player.Visible = true;
Player.Location = game.PlayerLocation;
lbPlayer.Text = game.PlayerHitPoints.ToString();
//顯示和隱藏生成的敵人
#region Enemy
int enemiesShown = game.Enemies.Count;
foreach (Enemy enemy in game.Enemies)
{
if (enemy is Bat)
{
bat.Location = enemy.Location;
lbBat.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
bat.Visible = true;
}
else
{
enemiesShown--;
bat.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
if (enemy is Ghost)
{
ghost.Location = enemy.Location;
lbGhost.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
ghost.Visible = true;
}
else
{
enemiesShown--;
ghost.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
if (enemy is Ghoul)
{
ghoul.Location = enemy.Location;
lbGhoul.Text = enemy.HitPoints.ToString();
if (enemy.HitPoints > 0)
{
ghoul.Visible = true;
}
else
{
enemiesShown--;
ghoul.Visible = false;
game.Enemies.Remove(enemy);
break;
}
}
}
#endregion
//顯示和隱藏道具
#region inventory
Control weaponControl = null;
switch (game.WeaponInRoom.Name)
{
case "Sword":
weaponControl = sword;
break;
case "BluePotion":
weaponControl = bluePotion;
break;
case "RedPotion":
weaponControl = redPotion;
break;
case "Bow":
weaponControl = bow;
break;
case "Mac":
weaponControl=mac;
break;
default: break;
}
if (weaponControl != null)
{
weaponControl.Visible = true;
weaponControl.Location = game.WeaponInRoom.Location;
}
if (game.WeaponInRoom.PickedUp)
{
weaponControl.Visible = false;
}
foreach (string weapon in game.PlayerWeapons)
{
switch (weapon)
{
case "Sword":
picSword.Visible = true;
break;
case "BluePotion":
picBluePotion.Visible = true;
break;
case "RedPotion":
picRedPotion.Visible = true;
break;
case "Bow":
picBow.Visible = true;
break;
case "Mac":
picMac.Visible = true;
break;
default: break;
}
}
if (!game.CheckPlayerInventory("BluePotion"))
{
picBluePotion.Visible = false;
}
if (!game.CheckPlayerInventory("RedPotion"))
{
picRedPotion.Visible = false;
}
#endregion
//自己血量不足游戲結束
if (game.PlayerHitPoints <= 0)
{
MessageBox.Show("You died");
Application.Exit();
}
//沒有敵人到下一關
if (enemiesShown < 1)
{
MessageBox.Show("You have defeatead the enemies on this level");
lbBat.Text = "";
lbGhost.Text = "";
lbGhoul.Text = "";
if (!game.NewLevel(random))
{
Application.Exit();
return;
}
weaponControl.Visible = false;
UpdateCharacters();
}
}
private void Form1_Load(object sender, EventArgs e)
{
game = new Game(new Rectangle(78, 57, 420, 155));
game.NewLevel(random);
UpdateCharacters();
}
/// <summary>
/// 向下移動
/// </summary>
private void btnM_Right_Click(object sender, EventArgs e)
{
game.Move(Direction.Right,random);
UpdateCharacters();
}
/// <summary>
/// 向下移動
/// </summary>
private void btnM_Down_Click(object sender, EventArgs e)
{
game.Move(Direction.Down,random);
UpdateCharacters();
}
/// <summary>
/// 向左移動
/// </summary>
private void btnM_Left_Click(object sender, EventArgs e)
{
game.Move(Direction.Left,random);
UpdateCharacters();
}
/// <summary>
/// 向上移動
/// </summary>
private void btnM_Up_Click(object sender, EventArgs e)
{
game.Move(Direction.Up,random);
UpdateCharacters();
}
/// <summary>
/// 裝備物品
/// </summary>
private void picSword_Click(object sender, EventArgs e)
{
foreach (Control pic in this.Controls)
{
if (pic is PictureBox)
{
((PictureBox)pic).BorderStyle = BorderStyle.None;
game.Equip(((PictureBox)sender).Tag.ToString());
if (((PictureBox)sender).Tag.ToString().Contains("Potion"))
{
panelAttrack.Visible = false;
btnDrink.Visible = true;
}
else
{
panelAttrack.Visible = true;
btnDrink.Visible = false;
}
}
}
((PictureBox)sender).BorderStyle = BorderStyle.FixedSingle;
}
/// <summary>
/// 用上下左右鍵盤移動
/// </summary>
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData)
{
case Keys.Up:
btnM_Up_Click(null, null);
break;
case Keys.Left:
btnM_Left_Click(null, null);
break;
case Keys.Right:
btnM_Right_Click(null, null);
break;
case Keys.Down:
btnM_Down_Click(null,null);
break;
default:
break;
}
return true;
}
/// <summary>
/// 向上攻擊
/// </summary>
private void btnA_Up_Click(object sender, EventArgs e)
{
game.Attack(Direction.Up,random);
UpdateCharacters();
}
/// <summary>
/// 向左攻擊
/// </summary>
private void btnA_Left_Click(object sender, EventArgs e)
{
game.Attack(Direction.Left, random);
UpdateCharacters();
}
/// <summary>
/// 向左攻擊
/// </summary>
private void btnA_Down_Click(object sender, EventArgs e)
{
game.Attack(Direction.Down, random);
UpdateCharacters();
}
/// <summary>
/// 向右攻擊
/// </summary>
private void btnA_Right_Click(object sender, EventArgs e)
{
game.Attack(Direction.Right, random);
UpdateCharacters();
}
/// <summary>
/// 吃藥
/// </summary>
private void btnDrink_Click(object sender, EventArgs e)
{
game.Attack(Direction.Right, random);
game.Equip(null);
UpdateCharacters();
btnDrink.Visible = false;
panelAttrack.Visible = true;
}
}
/// <summary>
/// 方向
/// </summary>
public enum Direction
{
Up, Left, Right, Down
}
/// <summary>
/// 游戲類
/// </summary>
public class Game
{
public List<Enemy> Enemies;
public Weapon WeaponInRoom;
private Player player;
public Point PlayerLocation { get { return player.Location; } }
public int PlayerHitPoints { get { return player.HitPoints; } }
public List<string> PlayerWeapons { get { return player.Weapons; } }
private int level = 0;
public int Level { get { return level; } }
private Rectangle boundaries;
public Rectangle Boundaries { get { return boundaries; } }
public Game(Rectangle boundaries)
{
this.boundaries = boundaries;
player = new Player(this,new Point(boundaries.Left+10,boundaries.Top+70),boundaries);
}
public void Move(Direction direction,Random random)
{
player.Move(direction);
foreach (Enemy enemy in Enemies)
enemy.Move(random);
}
public void Equip(string weaponName)
{
player.Equip(weaponName);
}
/// <summary>
/// 玩家道具欄裡是否有某武器
/// </summary>
public bool CheckPlayerInventory(string weaponName)
{
return player.Weapons.Contains(weaponName);
}
public void HitPlayer(int maxDamage,Random random)
{
player.Hit(maxDamage,random);
}
public void IncreasePlayerHealth(int health,Random random)
{
player.IncreaseHeath(health,random);
}
public void Attack(Direction direction,Random random)
{
player.Attract(direction,random);
foreach (Enemy enemy in Enemies)
enemy.Move(random);
}
private Point GetRandomLocation(Random random)
{
return new Point(boundaries.Left + random.Next(boundaries.Right / 10 - boundaries.Left / 10) * 10,
boundaries.Top +
random.Next(boundaries.Bottom / 10 - boundaries.Top / 10) * 10);
}
public bool NewLevel(Random random)
{
level++;
switch (level)
{
case 1:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this,GetRandomLocation(random),boundaries));
WeaponInRoom = new Sword(this,GetRandomLocation(random));
break;
case 2:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new BluePotion(this, GetRandomLocation(random));
break;
case 3:
Enemies = new List<Enemy>();
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new Bow(this,GetRandomLocation(random));
break;
case 4:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
if(!CheckPlayerInventory("Bow"))
WeaponInRoom = new Bow(this, GetRandomLocation(random));
else
WeaponInRoom = new BluePotion(this, GetRandomLocation(random));
break;
case 5:
Enemies = new List<Enemy>();
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new RedPotion(this, GetRandomLocation(random));
break;
case 6:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
WeaponInRoom = new Mace(this, GetRandomLocation(random));
break;
case 7:
Enemies = new List<Enemy>();
Enemies.Add(new Ghost(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Ghoul(this, GetRandomLocation(random), boundaries));
Enemies.Add(new Bat(this, GetRandomLocation(random), boundaries));
if (!CheckPlayerInventory("Mac"))
WeaponInRoom = new Mace(this, GetRandomLocation(random));
else
WeaponInRoom = new RedPotion(this, GetRandomLocation(random));
break;
case 8:
MessageBox.Show("恭喜你通關了");
return false;
}
return true;
}
}
/// <summary>
/// 移動類,敵人和自己的移動都繼承這個類
/// </summary>
public abstract class Mover
{
private const int MoveInterval = 10;
protected Point location;
public Point Location { get { return location; } }
protected Game game;
public Mover(Game game, Point location)
{
this.game = game;
this.location = location;
}
/// <summary>
/// 用弓箭看是否在一條直線上並且在射程內
/// </summary>
public bool Nearby(Direction direnction,Point locationToCheck, int distance)
{
switch (direnction)
{
case Direction.Down:
if (game.PlayerLocation.X == locationToCheck.X && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) < distance && game.PlayerLocation.Y < locationToCheck.Y)
return true;
break;
case Direction.Up:
if (game.PlayerLocation.X == locationToCheck.X && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) < distance && game.PlayerLocation.Y > locationToCheck.Y)
return true;
break;
case Direction.Left:
if (game.PlayerLocation.Y == locationToCheck.Y && Math.Abs(game.PlayerLocation.X - locationToCheck.X) < distance && game.PlayerLocation.X > locationToCheck.X)
return true;
break;
case Direction.Right:
if (game.PlayerLocation.Y == locationToCheck.Y && Math.Abs(game.PlayerLocation.X - locationToCheck.X) < distance && game.PlayerLocation.X < locationToCheck.X)
return true;
break;
}
return false;
}
/// <summary>
/// 劍和錘判斷怪物是否在武器攻擊半徑內
/// </summary>
public bool Nearby(Point location, Point locationToCheck, int radius)
{
if (Math.Sqrt(Math.Abs(location.X - locationToCheck.X) * Math.Abs(location.X - locationToCheck.X) +
Math.Abs(location.Y - locationToCheck.Y) * Math.Abs(location.Y - locationToCheck.Y)) <= radius)
return true;
else
return false;
}
public Point Move(Direction direction, Rectangle boundaries)
{
Point newLocation = location;
switch (direction)
{
case Direction.Up:
if(newLocation.Y-MoveInterval>=boundaries.Top)
newLocation.Y-=MoveInterval;
break;
case Direction.Down:
if (newLocation.Y + MoveInterval <= boundaries.Bottom)
newLocation.Y += MoveInterval;
break;
case Direction.Left:
if (newLocation.X - MoveInterval >= boundaries.Left)
newLocation.X -= MoveInterval;
break;
case Direction.Right:
if (newLocation.X + MoveInterval <= boundaries.Right)
newLocation.X += MoveInterval;
break;
default: break;
}
return newLocation;
}
}
public class Player : Mover
{
private Weapon equippedWeapon;
private int hitPoints;
public int HitPoints { get { return hitPoints; } }
private List<Weapon> inventory = new List<Weapon>();
public List<string> Weapons
{
get
{
List<string> names = new List<string>();
foreach (Weapon weapon in inventory)
names.Add(weapon.Name);
return names;
}
}
public Player(Game game, Point location, Rectangle boundaries)
: base(game, location)
{ hitPoints = 10; }
public void IncreaseHeath(int health,Random random)
{
hitPoints += random.Next(1,health);
}
public void Hit(int maxDamage,Random random)
{
hitPoints -= random.Next(1,maxDamage);
}
public void Equip(string weaponName)
{
if (weaponName == null)
{
equippedWeapon = null;
return;
}
foreach (Weapon weapon in inventory)
{
if (weapon.Name == weaponName)
equippedWeapon = weapon;
}
}
public void Move(Direction direction)
{
base.location = Move(direction, game.Boundaries);
if (!game.WeaponInRoom.PickedUp)
{
if (game.WeaponInRoom.Location == base.location)
{
game.WeaponInRoom.PickUpWeapon();
inventory.Add(game.WeaponInRoom);
}
}
}
public void Attract(Direction direction,Random random)
{
if (equippedWeapon != null)
{
equippedWeapon.Attack(direction,random);
//如果裝備物品是藥品,接口就是區別裝備和藥品的方法
if (equippedWeapon is IPotion)
inventory.Remove(equippedWeapon);
}
}
}
#region Enemy
public abstract class Enemy : Mover
{
private const int NearPlayerDistance = 30;
private int hitPoints;
public int HitPoints { get { return hitPoints; } }
public bool Dead()
{
if (hitPoints <= 0)
return true;
else
return false;
}
public Enemy(Game game, Point location, Rectangle boundaries, int hitPoints)
: base(game, location)
{ this.hitPoints = hitPoints; }
public abstract void Move(Random random);
protected bool NearPlayer()
{
return (Nearby(location, game.PlayerLocation, NearPlayerDistance));
}
public void Hit(int maxDamage,Random random)
{
hitPoints -= random.Next(1, maxDamage);
}
protected Direction FindPlayerDirection(Point playerLocation)
{
Direction directionToMove;
if (playerLocation.X > Location.X + 10)
directionToMove = Direction.Right;
else if (playerLocation.X < Location.X - 10)
directionToMove = Direction.Left;
else if (playerLocation.Y < Location.Y - 10)
directionToMove = Direction.Up;
else
directionToMove = Direction.Down;
return directionToMove;
}
}
public class Bat : Enemy
{
//蝙蝠起始點數為6,有50%的幾率朝著玩家飛,而另外50%的情況會隨機的飛
public Bat(Game game,Point location,Rectangle boundaries)
: base(game, location, boundaries, 6)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(3, random);
return;
}
if (random.Next(2) == 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location = Move(direction, game.Boundaries);
}
else
{
Direction direction = (Direction)random.Next(4);
this.location = Move(direction, game.Boundaries);
}
}
}
public class Ghost:Enemy
{
//幽靈起始點數為8,有1/3幾率朝著玩家移動,另外情況原地不動
public Ghost(Game game,Point location,Rectangle boundaries)
: base(game, location, boundaries, 8)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(4, random);
return;
}
if (random.Next(3) == 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location = Move(direction, game.Boundaries);
}
}
}
public class Ghoul : Enemy
{
//食屍鬼起始點數為10,有2/3幾率朝著玩家移動,另外情況原地不動
public Ghoul(Game game, Point location, Rectangle boundaries)
: base(game, location, boundaries, 10)
{ }
public override void Move(Random random)
{
if (NearPlayer())
{
game.HitPlayer(5, random);
return;
}
if (random.Next(3) != 0)
{
Direction direction = FindPlayerDirection(game.PlayerLocation);
this.location=Move(direction,game.Boundaries);
}
}
}
#endregion
#region Weapon
/// <summary>
/// 武器類
/// </summary>
public abstract class Weapon:Mover
{
public abstract string Name { get; }
public abstract void Attack(Direction direction,Random random);
private bool pickedUp;
public bool PickedUp { get { return pickedUp; } }
public Weapon(Game game, Point location):base(game,location)
{
pickedUp = false;
}
public void PickUpWeapon() { pickedUp = true; }
/// <summary>
/// 弓箭
/// </summary>
protected bool DamageEnemy(Direction direction, int distance, int damage,Random random)
{
Point target = game.PlayerLocation;
foreach (Enemy enemy in game.Enemies)
{
if (Nearby(direction,enemy.Location,distance))
{
enemy.Hit(damage,random);
return true;
}
}
return false;
}
/// <summary>
/// 劍和錘
/// </summary>
protected bool DamageEnemy(int radius, int damage, Random random)
{
Point target = game.PlayerLocation;
foreach (Enemy enemy in game.Enemies)
{
if (Nearby(enemy.Location, target, radius))
{
enemy.Hit(damage, random);
return true;
}
}
return false;
}
}
/// <summary>
/// 藥品接口
/// </summary>
public interface IPotion
{
bool Used { get; }
}
/// <summary>
/// 劍
/// </summary>
public class Sword : Weapon
{
public Sword(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get
{
return "Sword";
}
}
public override void Attack(Direction direction,Random random)
{
DamageEnemy(60, 4,random);
}
}
/// <summary>
/// 弓箭
/// </summary>
public class Bow : Weapon
{
public Bow(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get
{
return "Bow";
}
}
public override void Attack(Direction direction, Random random)
{
DamageEnemy(direction, 90, 2, random);
}
}
/// <summary>
/// 錘
/// </summary>
public class Mace : Weapon
{
public Mace(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "Mac"; }
}
public override void Attack(Direction direction, Random random)
{
DamageEnemy(50, 7, random);
}
}
/// <summary>
/// 藍色藥水
/// </summary>
public class BluePotion : Weapon, IPotion
{
private bool used=false;
public BluePotion(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "BluePotion"; }
}
public override void Attack(Direction direction, Random random)
{
game.IncreasePlayerHealth(6,random);
used=true;
}
public bool Used
{
get { return used; }
}
}
/// <summary>
/// 紅色藥水
/// </summary>
public class RedPotion : Weapon, IPotion
{
private bool used = false;
public RedPotion(Game game, Point location)
: base(game, location)
{ }
public override string Name
{
get { return "RedPotion"; }
}
public override void Attack(Direction direction, Random random)
{
game.IncreasePlayerHealth(11, random);
used = true;
}
public bool Used
{
get { return used; }
}
}
#endregion
}