Технологическая часть
2.1 Системные требования.
Данное приложение разработано в среде выполнения .NET Framework 3.5. Поэтому на компьютере пользователя должна быть установлена такая же среда выполнения. По умолчанию она идет в таких Windows как Windows 7, Windows Server 2008 R2.
Системные требования для установки Microsoft .NET Framework 3.5
Поддерживаемые операционные системы: Windows Server 2003; Windows Server 2008; Windows Vista; Windows XP
Процессор: Pentium с тактовой частотой 400 MГц или аналогичный процессор (рекомендуется Pentium с тактовой частотой 1ГГц или аналогичный процессор)
ОЗУ: не менее 96 МБ (рекомендуется 256 МБ)
Жесткий диск: может потребоваться до 500 МБ доступного дискового пространства
Дисковод для компакт-дисков или DVD-дисков: не требуется
Экран: разрешение 800x600, 256 цветов (рекомендуется разрешение 1024x768, 32-разрядный)
2.2 Инструкция пользования
Приложение открывается двойным щелчком по иконке программы. После запуска программы загружается основное окно программы (Рисунок – 1)
Рисунок 1 – Стартовая картинка
Далее нажав кнопку «Начать игру» происходит смена картинки, где визуализировано игровое поле:
Рисунок 2 – Игровое поле приложения
Теперь пользователь может поиграть в игру нажав кнопку «Play». После этого происходит запуск игры, начинается движение вражеских сущностей. Движение колобка, происходит с помощью кнопок на клавиатуре пользователем. Основная задача пользователя, играя игру, собрать все шарики на игровом поле, при этом не пересекаясь с врагами, которые двигаются произвольно, мешая пакману победить.
В верхней части окна приложения, находится меню, с помощью которого возможно начать новую игру, включить/выключить звуки приложения, изменять скорости игры.
Рисунок 3 – Меню «игра» Рисунок 4 – Меню «Настройки»
Заключение
При разработке игрового приложения были реализованы следующие задачи:
Удобный интерфейс
Возможность осуществлять управление движения колобка с помощью клавиатуры
Осуществление анимации колобка
Создание вражеских сущностей, которые двигаются произвольно
Добавление звуковых эффектов в игре
Поедание пакманом шариков на игровом поле
«Прозрачные стены» для игрового поля – т.е. когда сущность подходит к границе поля, она не отходит в сторону, а выходит с противоположной стороны поля.
Объекты при движении смещаются на пиксель для создания эффекта
плавного перемещения.
В рамках данной работы была разработана компьютерная игра, в которую можно поиграть в свободное время, приукрасить свой досуг. Так же при создании проекта были изучены новые элементы управления и свойства языка C#.
Список литературы
1. Фролов А. В., Фролов Г. В. Язык C#. Самоучитель – M.: ДИАЛОГ-МИФИ, 2003. – 560 с.
2. Лабор В.В. Си Шарп: создание приложений для Windows – Мн.: Харвест, 2003. – 384 с.
3. Разработка Windows-приложений на Microsoft Visual Basic и Microsoft Visual C# 2003 /Пер. с англ. – M.: Издательско-торговый дом <Русская Редакция>, 2003. – 512 с.
4. Коннолли Томас, Бегг Карелин. Базы данных. Проектирование, реализация и сопровождение. Теория и практика. 3-е издание. : Пер. с англ. — М. : Издательский дом "Вильяме", 2003. — 1440 с. : ил. — Парал. тит. англ.
Приложение 1. Исходный код класса GameLogic
class GameLogic
{
int sizeField;
int kol_vo_vragov;
int kol_vo_aple;
public int gameSpeed;
public bool status_sound = true;
SoundPlayer sound_Start;
SoundPlayer sound_eate;
SoundPlayer sound_Loozer;
SoundPlayer sound_Winner;
public bool newgame = false;
public bool Win = false;
Random rnd = null;
int value_Animation = 0;
public GameStatus gameStatus;
public Pacman pacman;
public Enemy enemy;
public Enemy enemy_2;
public Enemy enemy_3;
public double GameSpeed = 1;
public System.Timers.Timer timer = new System.Timers.Timer();
public List<Point> Walls = null;
public int[,] pole_mass = {
{1,1,1,1,1,1,1,1,-1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{-1,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,-1},
{1,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,1,1,1,0,0,0,-1,0,0,0,1,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
{1,0,1,1,0,0,0,0,1,0,0,0,0,1,1,0,1},
{-1,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,-1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,-1,1,1,1,1,1,1,1,1}
};
public List<Point> Shariki = null;
public List<Point> Shariki_New = null;
public GameLogic(int sizeField, int kol_vo_vragov, int kol_vo_aple, int gamespeed)
{
this.sizeField = sizeField;
this.kol_vo_vragov = kol_vo_vragov;
this.kol_vo_aple = kol_vo_aple;
this.gameSpeed = gamespeed;
Shariki_New = new List<Point>();
NewGame();
}
public void Play() // Запуск игры
{
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer.Stop();
sound_eate = new SoundPlayer(Properties.Resources.Eat);
sound_Loozer = new SoundPlayer(Properties.Resources.Loozer_sound);
sound_Winner = new SoundPlayer(Properties.Resources.Winner_sound);
switch (gameStatus)
{
case GameStatus.playing:
Run();
rnd_RunEmemy();
rnd_RunEnemy_2();
rnd_RunEnemy_3();
OnRedrawNeeded();
timer.Start();
break;
case GameStatus.stoping:
break;
case GameStatus.loozer:
if (status_sound)
{
sound_Loozer.Load();
sound_Loozer.Play();
}
System.Windows.Forms.MessageBox.Show("Вы проиграли!!!");
stop_all_run();
break;
case GameStatus.winner:
if (status_sound)
{
sound_Winner.Load();
sound_Winner.Play();
}
System.Windows.Forms.MessageBox.Show("Вы выиграли!!!");
stop_all_run();
break;
default:
break;
}
}
private void rnd_RunEmemy()
{
rnd_Direction(enemy);
enemy.LocationEnemy1 = RunEnemy(enemy, enemy.LocationEnemy1);
}
private void rnd_RunEnemy_2()
{
rnd_Direction(enemy_2);
enemy_2.LocationEnemy2 = RunEnemy(enemy_2, enemy_2.LocationEnemy2);
}
private void rnd_RunEnemy_3()
{
rnd_Direction(enemy_3);
enemy_3.LocationEnemy3 = RunEnemy(enemy_3, enemy_3.LocationEnemy3);
}
public delegate void RedrawNeededEventHandler();
public event RedrawNeededEventHandler RedrawNeeded;
private void OnRedrawNeeded()
{
if (RedrawNeeded != null)
{
RedrawNeeded();
}
}
private Point zerkl_otbr(Point Location)
{
if (Location.X >= 400)
{
Location.X = 0;
}
if (Location.Y >= 300)
{
Location.Y = 0;
}
if (Location.X < 0)
{
Location.X = 400;
}
if (Location.Y < 0)
{
Location.Y = 300;
}
return new Point(Location.X, Location.Y);
}
private void Run()
{
#region проверем надо ли повернуть
switch (pacman.NextDirection)
{
case MoveDirections.Right:
{
if (pacman.Location.Y % 25 == 0)
{
if (Walls.Contains(new Point(pacman.Location.X + 25, pacman.Location.Y)))
{
pacman.CurrentDirection = MoveDirections.Stop_X_plus;
}
else
{
pacman.CurrentDirection = pacman.NextDirection;
}
}
break;
}
case MoveDirections.Left:
{
if (pacman.Location.Y % 25 == 0)
{
if (Walls.Contains(new Point(pacman.Location.X - 25, pacman.Location.Y)))
{
pacman.CurrentDirection = MoveDirections.Stop_X_minus;
}
else
{
pacman.CurrentDirection = pacman.NextDirection;
}
}
break;
}
case MoveDirections.Up:
{
if (pacman.Location.X % 25 == 0)
{
if (Walls.Contains(new Point(pacman.Location.X, pacman.Location.Y - 25)))
{
pacman.CurrentDirection = MoveDirections.Stop_Y_minus;
}
else
{
pacman.CurrentDirection = pacman.NextDirection;
}
}
break;
}
case MoveDirections.Down:
{
if (pacman.Location.X % 25 == 0)
{
if (Walls.Contains(new Point(pacman.Location.X, pacman.Location.Y + 25)))
{
pacman.CurrentDirection = MoveDirections.Stop_Y_plus;
}
else
{
pacman.CurrentDirection = pacman.NextDirection;
}
}
break;
}
default:
break;
}
#endregion
#region делаем шаг
switch (pacman.CurrentDirection)
{
case MoveDirections.Right:
{
if (pacman.CurrentDirection != MoveDirections.Stop_X_plus)
{
pacman.Location.X++;
if (value_Animation == 8)
{
value_Animation = 0;
}
if(pacman.Location.X % 5 == 0)
{
pacman.img = pacman.img_mass_Right[value_Animation];
value_Animation++;
}
}
break;
}
case MoveDirections.Left:
{
if (pacman.CurrentDirection != MoveDirections.Stop_X_minus)
{
pacman.Location.X--;
if (value_Animation == 8)
{
value_Animation = 0;
}
if (pacman.Location.X % 5 == 0)
{
pacman.img = pacman.img_mass_Left[value_Animation];
value_Animation++;
}
}
break;
}
case MoveDirections.Up:
{
if (pacman.CurrentDirection != MoveDirections.Stop_Y_minus)
{
pacman.Location.Y--;
if (value_Animation == 8)
{
value_Animation = 0;
}
if (pacman.Location.Y % 5 == 0)
{
pacman.img = pacman.img_mass_Up[value_Animation];
value_Animation++;
}
}
break;
}
case MoveDirections.Down:
{
if (pacman.CurrentDirection != MoveDirections.Stop_Y_plus)
{
pacman.Location.Y++;
if (value_Animation == 8)
{
value_Animation = 0;
}
if (pacman.Location.Y % 5 == 0)
{
pacman.img = pacman.img_mass_Down[value_Animation];
value_Animation++;
}
}
break;
}
default:
break;
}
#endregion
pacman_loozer(enemy.LocationEnemy1);
pacman_loozer(enemy_2.LocationEnemy2);
pacman_loozer(enemy_3.LocationEnemy3);
CheckAppleEate();
pacman.Location = zerkl_otbr(pacman.Location);
}
private void pacman_loozer(Point Location) //Пересечение координаты пакмэна и врага
{
if (
(Math.Abs(Location.X - pacman.Location.X) <= 20 && (Location.Y == pacman.Location.Y))
||
(Math.Abs(Location.Y - pacman.Location.Y) <= 20 && (Location.X == pacman.Location.X))
||
(Math.Abs(Location.X - pacman.Location.X) <= 20 && Math.Abs(Location.Y - pacman.Location.Y) <= 20)
)
{
gameStatus = GameStatus.loozer;
}
}
private Point RunEnemy(Enemy enemy_1, Point Location)
{
#region// Проверяем, можно ли повернуть врагу
switch (enemy_1.NextDirection_enemy)
{
case MoveDirections.Right:
{
if (Location.Y % 25 == 0 && Location.X % 25 == 0)
{
if (Walls.Contains(new Point(Location.X + 25, Location.Y)))
{
enemy_1.CurrentDirection_enemy = MoveDirections.Stop_X_plus;
}
else
{
enemy_1.CurrentDirection_enemy = enemy_1.NextDirection_enemy;
}
}
break;
}
case MoveDirections.Left:
{
if (Location.Y % 25 == 0 && Location.X % 25 == 0)
{
if (Walls.Contains(new Point(Location.X - 25, Location.Y)))
{
enemy_1.CurrentDirection_enemy = MoveDirections.Stop_X_minus;
}
else
{
enemy_1.CurrentDirection_enemy = enemy_1.NextDirection_enemy;
}
}
break;
}
case MoveDirections.Up:
{
if (Location.X % 25 == 0 && Location.Y % 25 == 0)
{
if (Walls.Contains(new Point(Location.X, Location.Y - 25)))
{
enemy_1.CurrentDirection_enemy = MoveDirections.Stop_Y_minus;
}
else
{
enemy_1.CurrentDirection_enemy = enemy_1.NextDirection_enemy;
}
}
break;
}
case MoveDirections.Down:
{
if (Location.X % 25 == 0 && Location.Y % 25 == 0)
{
if (Walls.Contains(new Point(Location.X, Location.Y + 25)))
{
enemy_1.CurrentDirection_enemy = MoveDirections.Stop_Y_plus;
}
else
{
enemy_1.CurrentDirection_enemy = enemy_1.NextDirection_enemy;
}
}
break;
}
}
#endregion
if ((int)enemy_1.CurrentDirection_enemy > 4)
{
ChangeDirection(enemy_1);
}
#region делаем шаг врагом
switch (enemy_1.CurrentDirection_enemy)
{
case MoveDirections.Right:
{
if (enemy_1.CurrentDirection_enemy != MoveDirections.Stop_X_plus)
{
Location.X++;
}
break;
}
case MoveDirections.Left:
{
if (enemy_1.CurrentDirection_enemy != MoveDirections.Stop_X_minus)
{
Location.X--;
}
break;
}
case MoveDirections.Up:
{
if (enemy_1.CurrentDirection_enemy != MoveDirections.Stop_Y_minus)
{
Location.Y--;
}
break;
}
case MoveDirections.Down:
{
if (enemy_1.CurrentDirection_enemy != MoveDirections.Stop_Y_plus)
{
Location.Y++;
}
break;
}
default:
break;
}
#endregion
Location = zerkl_otbr(Location);
return Location;
}
private void rnd_Direction(Enemy enemy)
{
if (rnd.Next(100) < 5)
{
ChangeDirection(enemy);
}
}
private void ChangeDirection(Enemy enemy)
{
int direction = rnd.Next(1, 5);
enemy.NextDirection_enemy = (MoveDirections)direction;
}
private void CheckAppleEate()
{
//проверка того что в данной ячейке поля есть яблоко
bool isSharik = false;
Point sharik = new Point(-1, -1);
foreach (Point item in Shariki)
{
if (pacman.Location.X == item.X && pacman.Location.Y == item.Y)
{
isSharik = true;
sharik = item;
break;
}
}
//если есть, то увеличить количество очков и стереть яблоко
if (isSharik)
{
Shariki.Remove(sharik);
OnSharikRemoved(sharik);
Shariki_New.Add(sharik);
OnScore();
if (status_sound)
{
sound_eate.Load();
sound_eate.Play();
}
}
//если стерли последнее яблоко то уровень закончен
if (Shariki.Count == 0)
{
gameStatus = GameStatus.winner;
}
}
public delegate void SharikRemovedEventHandler(Point sharik);
public event SharikRemovedEventHandler SharikRemoved;
private void OnSharikRemoved(Point sharik)
{
if (SharikRemoved != null)
{
SharikRemoved(sharik);
}
}
public delegate void New_Game();
public event New_Game New_game;
private void OnNew_game()
{
if (New_game != null)
{
New_game();
}
}
public delegate void Score();
public event Score Score_och;
private void OnScore()
{
if (Score_och != null)
{
Score_och();
}
}
void stop_all_run()
{
pacman.NextDirection = MoveDirections.Stop_X_plus;
pacman.CurrentDirection = MoveDirections.Stop_X_plus;
enemy.CurrentDirection_enemy = MoveDirections.Stop_X_plus;
enemy.NextDirection_enemy = MoveDirections.Stop_X_plus;
enemy_2.CurrentDirection_enemy = MoveDirections.Stop_X_plus;
enemy_2.NextDirection_enemy = MoveDirections.Stop_X_plus;
enemy_3.CurrentDirection_enemy = MoveDirections.Stop_X_plus;
enemy_3.NextDirection_enemy = MoveDirections.Stop_X_plus;
}
internal void NewGame()
{
pacman = new Pacman();
sound_Start = new SoundPlayer(Properties.Resources.start_song);
if (status_sound)
{
sound_Start.Load();
sound_Start.Play();
}
gameStatus = GameStatus.stoping;
Shariki = new List<Point>();
//Размещение всех шариков на поле
for (int i = 0; i < 13; i++)
{
for (int j = 0; j < 17; j++)
{
if (pole_mass[i, j] == 0)
{
Shariki.Add(new Point(j * 25, i * 25));
}
}
}
//Размещение всех шариков на поле
OnNew_game();
timer.Interval = 1;
timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
enemy = new Enemy();
enemy_2 = new Enemy();
enemy_3 = new Enemy();
rnd = new Random(DateTime.Now.Millisecond);
Walls = new List<Point>();
//разместить координаты стенок
for (int i = 0; i < 13; i++)
{
for (int j = 0; j < 17; j++)
{
if (pole_mass[i, j] == 1)
{
Walls.Add(new Point(j * 25, i * 25));
}
}
}
Shariki_New = new List<Point>();
//вызов события новой игры
}
}
}