Заскучал на работе и решил отвлечься, набросал мини игрушку sokoban. Картинки нашел в интернете и вперед, вот что получилось:
Главное окно |
Игровое окно |
Конструктор уровней |
Основной класс уровня:
public const int indentLeft = 15; public const int indentUp = 15; #region Private private int currManPosX = -1; private int currManPosY = -1; private bool finished = false; Timer secondsCounterTimer; #endregion #region Fields private int width; private int heigth; private List<item>[,] levelItems; private int movesCnt; private int secondsCnt = 0; public int Width { get { return width; } } public int Heigth { get { return heigth; } } private List<item>[,] LevelItems { get { return levelItems; } } public int MovesCnt { get { return movesCnt; } } public int SecondsCnt { get { return secondsCnt; } } #endregion
Конструкторы класса, первый позволяет создать уровень из сущ. файла в режиме игры или в режиме изменения, второй используется для создания нового уровня:
#region Constructors public Level(string fName, bool constructorMode) { if (!constructorMode) { secondsCounterTimer = new Timer(1000); secondsCounterTimer.Elapsed += new ElapsedEventHandler(secondsCounterTimer_Elapsed); } ReadFromFile(fName); } public Level(int _width, int _heigth) { width = _width; heigth = _heigth; levelItems = List<item>[_width, _heigth]; } #endregionМетод отрисовки уровня:
public void DrawLevel(Graphics g, bool ConstructorMode) { Brush b = Brushes.White; g.FillRegion(b, g.Clip); Pen p = new Pen(Brushes.Black); for (int i = 0; i < width; i++) for (int j = 0; j < heigth; j++) { List<Item> itm = GetItem(i, j); if (itm == null) { g.FillRectangle(b, new Rectangle(new Point(i * 35 + indentLeft, j * 35 + indentUp), new Size(35, 35))); if (ConstructorMode) g.DrawRectangle(p, new Rectangle(new Point(i * 35 + indentLeft, j * 35 + indentUp), new Size(35, 35))); } else foreach (Item item in itm) if (item != null) { if (item.ItemImage is Bitmap) ((Bitmap)item.ItemImage).MakeTransparent(Color.FromArgb(255, 0, 0, 0)); g.DrawImage(item.ItemImage, new Point(i * 35 + indentLeft, j * 35 + indentUp)); if (ConstructorMode) g.DrawRectangle(p, new Rectangle(new Point(i * 35 + indentLeft, j * 35 + indentUp), new Size(35, 35))); } } }Обработчик движения человечка:
public void MoveAction(Graphics g, MoveDirections moveDirections) { if (finished) return; if (secondsCounterTimer.Enabled == false) secondsCounterTimer.Enabled = true; // проверяем есть ли кого двигать if (currManPosX == -1 || currManPosY == -1) { bool founded = false; // выполняем проход по элементам и ищем человечка for (int i = 0; i < width; i++) for (int j = 0; j < heigth; j++) if (levelItems[i, j] != null) foreach (Item itm in levelItems[i, j]) if (itm.ItemType == ItemType.Man) { founded = true; currManPosX = itm.XPos; currManPosY = itm.YPos; } if (!founded) throw new Exception("Некого двигать!"); } int offsetX = 0, offsetY = 0; switch (moveDirections) { case MoveDirections.Rigth: offsetX = 1; if (currManPosX + offsetX >= width) return; break; case MoveDirections.Left: offsetX = -1; if (currManPosX + offsetX < 0) return; break; case MoveDirections.Up: offsetY = -1; if (currManPosY + offsetY < 0) return; break; case MoveDirections.Down: offsetY = 1; if (currManPosY + offsetY >= heigth) return; break; } if (levelItems[currManPosX + offsetX, currManPosY + offsetY] != null) { foreach (Item item in levelItems[currManPosX + offsetX, currManPosY + offsetY]) { if (item.ItemType == ItemType.Wall) // стенка? return; if (item.ItemType == ItemType.Package) // коробка и ее необходимо сдвинуть... { bool move = false; switch (moveDirections) { case MoveDirections.Rigth: offsetX = 1; if (currManPosX + (offsetX * 2) >= width) return; break; case MoveDirections.Left: offsetX = -1; if (currManPosX + (offsetX * 2) < 0) return; break; case MoveDirections.Up: offsetY = -1; if (currManPosY + (offsetY * 2) < 0) return; break; case MoveDirections.Down: offsetY = 1; if (currManPosY + (offsetY * 2) >= heigth) return; break; } //проверяем возможность движения коробки вправо // если коробку не куда двигать, отменяем действие if (levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)] != null) { foreach (Item itm in levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)]) { if (itm.ItemType == ItemType.Wall) // стенка? return; if (itm.ItemType == ItemType.Package) // другая коробка? return; } move = true; } if (move) // двигаем! { Item PckgToDel = null; // у старой позиции удаляем коробку foreach (Item itm in levelItems[currManPosX + offsetX, currManPosY + offsetY]) if (item.ItemType == ItemType.Package) PckgToDel = item; if (PckgToDel != null) levelItems[currManPosX + offsetX, currManPosY + offsetY].Remove(PckgToDel); // добавляем коробку в новое положение // проверяем есть ли во всех элементах goal, если есть то вид коробки нужно изменить // создаем новый вид человечка в соответствии с направлением движения Item newBoxItem; switch (item.Code) { case 4: case 6: newBoxItem = new Item(ItemsCollection.GetItemByCode(4)); foreach (Item itm in levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)]) if (itm.Code == 5) newBoxItem = new Item(ItemsCollection.GetItemByCode(6)); break; case 27: case 29: newBoxItem = new Item(ItemsCollection.GetItemByCode(27)); foreach (Item itm in levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)]) if (itm.Code == 28) newBoxItem = new Item(ItemsCollection.GetItemByCode(29)); break; case 30: case 32: newBoxItem = new Item(ItemsCollection.GetItemByCode(30)); foreach (Item itm in levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)]) if (itm.Code == 31) newBoxItem = new Item(ItemsCollection.GetItemByCode(32)); break; default: return; } newBoxItem.XPos = currManPosX + (offsetX * 2); newBoxItem.YPos = currManPosY + (offsetY * 2); levelItems[currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)].Add(newBoxItem); RedrawItemAtCoords(g, currManPosX + (offsetX * 2), currManPosY + (offsetY * 2)); break; } else return; } } Item ManToDel = null; // у старой позиции удаляем человечка foreach (Item item in levelItems[currManPosX, currManPosY]) if (item.ItemType == ItemType.Man) ManToDel = item; if (ManToDel != null) levelItems[currManPosX, currManPosY].Remove(ManToDel); RedrawItemAtCoords(g, currManPosX, currManPosY); // перерисовывает старую позицию уже без человечка // создаем новый вид человечка в соответствии с направлением движения Item newManItem = null; switch (moveDirections) { case MoveDirections.Rigth: newManItem = new Item(ItemsCollection.GetItemByCode(23)); break; case MoveDirections.Left: newManItem = new Item(ItemsCollection.GetItemByCode(24)); break; case MoveDirections.Up: newManItem = new Item(ItemsCollection.GetItemByCode(22)); break; case MoveDirections.Down: newManItem = new Item(ItemsCollection.GetItemByCode(25)); break; } currManPosX = currManPosX + offsetX; currManPosY = currManPosY + offsetY; newManItem.XPos = currManPosX; newManItem.YPos = currManPosY; // добавляем человечка на новой позиции levelItems[currManPosX, currManPosY].Add(newManItem); RedrawItemAtCoords(g, currManPosX, currManPosY); movesCnt++; isFinished(); } }
Комментариев нет:
Отправить комментарий