Заскучал на работе и решил отвлечься, набросал мини игрушку 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();
}
}
Комментариев нет:
Отправить комментарий