PDA

Показать полную графическую версию : Змейка. Написание игры


DaRiYs
22-04-2010, 23:01
Передомной появилась такая проблемма. Нада написать игру "Змейка" на Borland C++ 3.11 с использованием ООП и в графическом режиме. Помогите пожалуста разобратся с такими вопросами:
1. Как правильно спроэктировать самц игру, классы и тп?
2. Как реализовать движение змеи и изменение направлений при нажатии клавиш.

Вообщем помогите хто чем может, кодом, советами, теорией, буду благодарен за любую помощь.

lxa85
23-04-2010, 08:57
DaRiYs, 1. Как правильно спроэктировать самц игру, классы и тп?
2. Как реализовать движение змеи и изменение направлений при нажатии клавиш. »
Рассуждай вслух, а дальше будет видно. Если можно будет на их основе что-нибудь конструктивное выделить, то запросто.
В противном случае это будет чужое решение, а не собственное.

DaRiYs
23-04-2010, 10:22
Бы ло бы еще о чем рассуждать, я незнаю с какой стороны приступить... Хоть теорию реализации игры для начала скажите.

lxa85
23-04-2010, 10:38
DaRiYs, теория реализации игры - это следующий шаг. А сейчас рассуждай о том, чего ты хочешь видеть на экране. Реализаций разновидностей много, а цель должна быть одна.
Начни рассказ со слов "Я хочу чтобы ...".
Чтобы змейка двигалась так-то и так-то. Для управления использовались кнопки такие-то и такие-то.
Змейка характеризуется так-то и так-то. Нямки появляются так-то.
Вопрос будет в том, в каком виде у тебя будет хранится поле и в каком виде будет представлена змейка. Но я этого не говорил! :)
Когда этап "Я хочу" будет пройден, будем думать над реализацией.
Не торопись, запрограммировать плевое дело, было бы что. :)
Т.ч. рассуждай, рисуй схемки, а о программировании пока не думай. (Рассуждения терминами С/С++ сейчас не нужны)

Drongo
23-04-2010, 11:14
Я когда-то решал аналогичную задачку "траектория черепахи", но если честно, до конца не дорешал. Парочка мыслей:

1. Нужно поле по которому змейка будет двигаться - двухмерный массив
const int x = 10;
const int y = 10;

int boarb[x][y] = {0};
2. Нужен массив ходов (поскольку шаг у нас одна клетка то и значение будет 1 или -1) -
const int step = 2;

int step[step] = {1, -1};

3. Варианты ходов 4 варианта, вверх вниз, вправо, влево
4. переменная хода - currentStep = 0;
...
const int x = 10;
const int y = 10;
const int step = 2;

int boarb[x][y] = {0};
int step[step] = {1, -1};

int currentStep = 0, move = 0;

cout<<"\n Введите шаг змейки от '0' или '4': ";
cin>>move ;

while(move != 9999){ // 9999 ходов
if(move == 1){
currentStep += 1; // Вверх
}
else if(move == 2){
currentStep += 1; // Вправо
}
else if(move == 3){
currentStep += -1; // Вниз
}
else if(move == 4){
currentStep += -1; // Влево
}
...В общем я сейчас запутался, но скидываю пример ходов шахматного коня, возможно пригодится

// Задачи главы 4. Задача 4.24
//Программа реализации хода шахматного коня
#include <vcl.h>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <cstdlib>

const int row=8;
const int column=8;

void print(int [][column], int, int);

int main()
{
int board[row][column]={0},
horisontal[8]={2, 1, -1, -2,
-2, -1, 1, 2},
vertical[8]={-1, -2, -2, -1,
1, 2, 2, 1};
int curentRow=0,
curentColumn=0,
moveNumber,
controlRow=0,
controlColumn=0,
counter=0,
z;

cout<<" PROGRAMMA SHACHMATNOGO KONYA ";
cout<<"\n ENTER '0' START FINISH '-1': ";
cout<<"\n ENTER NUMBER CHODA KONYA OT '0' DO '7': ";
cin>>moveNumber;
while(moveNumber != 9999){

curentRow += vertical[moveNumber];
curentColumn += horisontal[moveNumber];
if((curentRow >= 0 && curentRow <= 7) && (curentColumn >= 0 && curentColumn <= 7)){
controlRow=curentRow;
controlColumn=curentColumn;
board[curentRow][curentColumn]=1;
print(board, row, column);
}
else{
cout<<"\n ENTER PRAVILNIY CHOSD";
curentRow=controlRow;
curentColumn=controlColumn;
}
cout<<"\n ENTER NUMBER CHODA KONYA OT '0' DO '7': ";
cin>>moveNumber;
}

print(board, row, column);

cin>>z;
return 0;
}
//Функция печати массива
void print(int boarde[][column], int rowe, int columne)
{
for(int i=0; i<rowe; i++){
for(int j=0; j<columne; j++)
cout<<boarde[i][j];
cout<<endl;
}
}
//---------------------------------------------------------------------------

Awejk
23-04-2010, 11:20
Это у тебя лабораторная работа/курсовая/диплом или ты просто ради фана хочешь разобраться в игростроении? Если учёба тогда какие сроки, если ради фана то, можешь начать примерно со следующего.

Какие ключевые понятия в игре Змейка (да и вообще в любой игре)? Есть карта или просто поле по которому ползает червяк в области ограниченного пространства. На этом поле он собирает объекты (бонусы) которые по разному влияют на червяка. Исходя из этого у нас будет один общий базовый класс для объектов. К объекту можно также отнести и самого червяка, а что он разве не объект? Ещё какой объект только со своим набором атрибутов, поэтому для начало возьмём базовый объект, некий
СBaseObject
{
...
};

Какие общие черты у каждого объекта, пусть это бонус, червяк или его враги (другой червяк который ползает по полю и стреляет):
1. координаты на сетке (x,y)
2. скорость (velocity)
3. тип объекта (type) (мы же должны как-то узнавать в игре что это или кто это, бонус или враг или просто камень в который нужно врезаться и отнять пару поинтов жизни у червяка)
4. Угол (angle) - в ту сторону будет идти червяк меняется угол меняется и направления червяка.
5. ширина и высота объекта (width and height)

а теперь имеем
CBaseObject
{
private:
int x,y;
float velocity;
ETypeObject type;
float angle;
int width, height;
};

ETypeObject
{
BONUS,
ENEMY,
USER
};

Это я взял самые основные свойства объекта, которые будут у любого объекта в игре. Разумеется что в зависимости от сложности игры количество свойств в базовом объекте может меняться. Теперь тебе надо будет наследоваться от этого базового объекта и расширять функционал для каждого отдельного объекта. Например, ты решил добавить бонус для увеличениятела червяка,

СDecreaseBody : public CBaseObject
{

}

А что собственно расширять, спросишь ты. Ну давай подумаем, что должен делать этот бонус увеличивать тело червяка, значит вывод напрашивается сам на себя
СDecreaseBody : public CBaseObject
{
private:
int enlarge;
}
вот такой вот простой бонус будет, он очень примитивный поэтому пока в голову больше ничего не приходит что сюда ещё добавить, но поверь что на протяжении написания игры будет постепенно разрастаться этот класс. На самом деле ещё нужно было в базовый объект кроме свойств добавить базовые методы такие как
render();
logic();
init();
ну и ещё что-нибудь. А у наследника CDecreaseBody реализовать метод logic(); а может и ещё что-нибудь.

Теперь тебе есть от чего оталкиваться.

currentStep += 1; »
нужно расчитывать скорость передвижения на основе делта времени, иначе в игру можно будет играть только на 400 пентиумах. Т.е. она будет слишком быстро работать.

Drongo
23-04-2010, 12:04
нужно расчитывать скорость передвижения на основе делта времени, иначе в игру можно будет играть только на 400 пентиумах. Т.е. она будет слишком быстро работать. »Скорость шага в моём примере неиспользуется, т.е. пока один ход, одно нажатие клавиши.

Awejk
23-04-2010, 12:07
Скорость шага в моём примере неиспользуется, т.е. пока один ход, одно нажатие клавиши. »
но змейка же идёт непрерывно и управлять нужно только поворотом. А не хотьбой. Хотя возможно Вы просто общий случай написали.

Drongo
23-04-2010, 13:11
Хотя возможно Вы просто общий случай написали. »Конечно, отталкиваясь от задачки
траектория черепахи »

DaRiYs
26-04-2010, 00:16
Спсиб всем за помощь и идеи, разобрался наконец то, написал

Awejk
26-04-2010, 10:04
ну тогда выкладывай исходники на все общее обозрение и критику, нам же интересно узнать как ты разобрался :)

btf
17-11-2010, 19:46
Всем доброго времени суток!
Мне вот тоже стало интересно написать земйку.
Я начал делать все по мануалу: придумал что я хочу и вроде составил 2 класса.

Червяк должен ползать сам. Пользователь лишь выбирает направление червя с помощью клавиатуры.
Яблоки будут появлятся в случайных кооодинатах и через некоторое время исчезать. Съев одно яблоко червяк становится длинее на еденицу.
Скорость червя увеличивается по мере увеличения его длины.
Камни так же будут появляться в случайных местах. Если червь врежется в камень - игра закончена.
Если червяк врежется в границы поля - игра закончена.
За всю игру появляется N яблок.
Игра считается успешно законченной, если длина червяк собрал M яблок (M<N).

Поле - массив[40][40]

Характеристики червя:
Х координата, У координата, длина червя, скорость червя, количество собранных яблок.

Характеристики объекта:
Х коррдината, У координата, время жизни, тип объекта(яблоко или камень).


class Worm
{
int xPos, yPos, length, speed, apples;
public:
Worm();
~Worm();
void SetX(int X) {xPos=X;}
int GetX() const {return xPos;}
void SetY(int Y) {yPos=Y;}
int GetY() const {return yPos;}
void SetLength(int len) {length=len;}
int GetLength() const {return length;}
void SetSpeed(int spd) {speed=spd;}
int GetSpeed() const {return speed;}
void SetApples(int apls) {apples=apls;}
int GetApples() const {return apples;}
}

class Obj
{
int xPos, yPos, existTime, objType;
public:
Obj();
~Obj();
void SetX(int X) {xPos=X;}
int GetX() const {return xPos;}
void SetY(int Y) {yPos=Y;}
int GetY() const {return yPos;}
void SetTime(int time) {existTime=time;}
int GetTime() const {return existTime;}
void SetType(int type) {objTye=type;}
int GetType() const {return objType;}
}


Что делать дальше - я не знаю. Подскажите как сделать управление червем с помощью клавиатуры и как реализовать все это на экране? И еще хотелось бы наследование задействовать, но я не придумал как.

Подскажите, пожалуйста.

pva
17-11-2010, 21:58
Вот червяк:

.........
..x......
..x......
..xxxx...
.....x...
.....X...
.........
.........

можно узнать его координаты GetX(), GetY()? Или я на другую игру подумал?

btf
17-11-2010, 23:02
Я не знаю, про какую игру ты подумал. Я имею ввиду обычную змейку, как на старых моделях телефона nokia. Я хочу использовать не псевдографику, а какие-нибудь стандартные графические функции с++.
Перед тем как узнать координаты их надо установить...

Admiral
17-11-2010, 23:51
Btf если проект под Win32, то в событии WM_CHAR оконной функции обрабатывать нажатия клавиш. В той же функции, но в другом событии (WM_PAINT), реализовать вывод на экран.
Для данной задачи, если требуется что было задействовано наследование, можно наследовать яблоко и камень от одного класса (того же Obj), или же все классы (включая Worm) наследовать от одного интерфейсного класса. Второй вариант упрощает менеджмент объектов.
Если идти по пути ООП далее, то для решения данной задачи стоит создать ещё один класс, который будет управлять всеми игровыми процессами. Он же будет хранить все объекты, характеристики игрового поля, условия игры в своих полях.

В стандарте С++ не заложено графических функций. Графический вывод осуществляют дополнительные библиотеки. Под Win32 такие как GDI, GdiPlus, Direct3D, OpenGL и прочие.

btf
18-11-2010, 01:28
Блин, как-то трудно. А если делать с помощью псевдографики? Как это реализовать?

DaRiYs
18-11-2010, 03:15
И еще хотелось бы наследование задействовать, но я не придумал как. »
Есть одна замечательная фраза "Если в архитектуре приложения ненужно использовать наследование то ненада его придумывать" Тоесть если логически это там ненада то незачем это привинчивать ибо реализация избыточна

Sashochok
20-01-2012, 13:22
а можите дать исходник, интересно)




© OSzone.net 2001-2012