Суббота, 20 Апреля 2024, 00:12

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Форум игроделов » Программирование » C/C++ » Помогите с элементарной механикой игры!!!
Помогите с элементарной механикой игры!!!
RenusДата: Вторник, 24 Августа 2010, 05:59 | Сообщение # 1
почетный гость
Сейчас нет на сайте
Есть вопрос по элементарной механике игры, не знаю как сделать хоть в стену головой бейся(((
А научить очень хочется... Хотя бы что-то простое, вот и выбрал 2д...
Игры я не программировал никогда, учил в школе паскаль, писал на нем я много и всяко разно, даже мультики)
Две недели назад начал учить С++, прочитал много литературы и уроков, вроде бы все понятно...
Пока что остановился на WindMill'е и на OMEG'е, как на самых простых 2д движках.

С движками вроде бы все понятно))
Делаю примитивную космическую леталку, корабль сделал, привязал к управлению все работает... И вот тут стена)
КАК НАУЧИТЬ ЕГО СТРЕЛЯТЬ???
Точнее как сделать что бы при каждом нажатии на пробел появлялась и летела пуля...

Ну создать класс для пули можно:

class Bullet {
public:
float x, y;
float speed;
void move(float speed)
{
y += speed;
}
};

А как создать ее объектом и заставить лететь?
Я так понимаю через конструктор для класса?

Пожалуйста объясните как это все делается((((
Второй день мозги ломаю, уже не варят...

ezhickovichДата: Вторник, 24 Августа 2010, 15:33 | Сообщение # 2
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Quote (Renus)
А как создать ее объектом и заставить лететь?

А что конкретно не понятно?

Есть бесконечное количество способов сделать это...

если я правильно понял, то можно так:

Code
class Bullet
{
private:
      
     Bullet (void) {} // - определяем конструктор по умолчанию закрытым
     // Дабы запретить его использование!!!
      
     // -- остальная реализация
      
public:

     Bullet (const Vector2i &pos, Sprite &sprite); // основной конструктор ( pos - позиция; sprite - спрайт булета )
     Bullet (const Bullet &rhs); // конструктор копирования
      
     void Render (void); // здесь код прорисовывающий объект
      
     // -- остальная реализация
};

Конструктор по умолчанию закрыт т.к. нет смысла создавать пустые булеты...
Следовательно все булеты должны создаваться динамически...



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
RenusДата: Вторник, 24 Августа 2010, 20:42 | Сообщение # 3
почетный гость
Сейчас нет на сайте
Я имел ввиду общую организацию игрового цикла.
Как я понимаю, для того что-бы обьект бегал по экрану и выполнял свои функции, он должен иметь одно обращение к функции поведения и одно к функции отрисовки(ну или функция рендер должна перебирать все обьекты, что не сомненно лучше...)

Слышал что такое делается с помощью связанных списков или массивов...
Объясните как реализуется этот механизм, какие есть варианты...

Добавлено (24.08.2010, 20:42)
---------------------------------------------
Неужели никто ничего не знает? Или всем влом ответить?
Вообщем создал я лист объектов и итератор с помощью vector:

Code
std::vector <CObject> ObjectsList;
std::vector <CObject>::iterator ObjectsListInterator;

Основной класс у меня CObject, собственно ObjectsList это по сути массив объектов класса. Сделал в основном цикле игры перебор всех объектов таким вот макаром:

Code
for (ObjectsListInterator = ObjectsList.begin(); ObjectsListInterator < ObjectsList.end(); ObjectsListInterator++)
{???}

Объясните мне дураку, что нужно вписать в скобки выше, а самое главное, что нужно добавить в код который ниже, что бы при нажатии на пробел появлялся объект класса (какая нибудь там пуля) и дальше уже обрабатывался в верхнем кода.

Code
if (Key_Down(K_SPACE))
{
     ?????????
}
ezhickovichДата: Вторник, 24 Августа 2010, 21:00 | Сообщение # 4
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Quote (Renus)
что бы при нажатии на пробел появлялся объект класса (какая нибудь там пуля) и дальше уже обрабатывался в верхнем кода.

Просто создавай объект ( с нужными параметрами ) и добавляй его в список...

Quote (Renus)
Объясните мне дураку, что нужно вписать в скобки выше

Рендерь каждый объект ( или по какому нить алгоритму хз как у тя... )...

Я не могу понять что ты не понимаешь... =(



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
RenusДата: Вторник, 24 Августа 2010, 21:33 | Сообщение # 5
почетный гость
Сейчас нет на сайте
Ну если конкретно то как создать объект с помощью конструктора???
Именно написать код, что бы я мог вставить и посмотреть.

Потому что я с ООП познакомился всего пару недель назад...
Так понятно?)))

ezhickovichДата: Вторник, 24 Августа 2010, 22:59 | Сообщение # 6
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Renus, Ща будет жестокий пример =)

SomeClass someObj; // Здесь вызывается конструктор по умолчанию без аргументов...
То есть это равносильно записи:
SomeClass someObj(); // если так понятей

мы можем описать свой конструктор... ( это и ослу понятно... )

Bullet (const Vector2i &pos, Sprite &sprite); // К примеру...

И использовать его...

Bullet bullet(pos, sprite); // Что тут непонятного...

Однако если ты опишешь булет так как предлагаю я:

Quote
class Bullet
{
private:

Bullet (void) {} // - определяем конструктор по умолчанию закрытым
// Дабы запретить его использование!!!

// -- остальная реализация

public:

Bullet (const Vector2i &pos, Sprite &sprite); // основной конструктор ( pos - позиция; sprite - спрайт булета )
Bullet (const Bullet &rhs); // конструктор копирования

void Render (void); // здесь код прорисовывающий объект

// -- остальная реализация
};

То ты не сможешь вызвать конструктор по умолчанию т.к. он закрыт...

В общем тут много ещё можно говорить лучше почитать умные книжки...

Quote (Renus)
Именно написать код, что бы я мог вставить и посмотреть.

Я не юзаю
Quote (Renus)
WindMill'е и на OMEG'е

???
И никогда их не видел... ( точнее видел, но совсем краем глаза... )

Quote (ezhickovich)
В общем тут много ещё можно говорить лучше почитать умные книжки...

=)



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
ArtesДата: Вторник, 24 Августа 2010, 23:24 | Сообщение # 7
постоянный участник
Сейчас нет на сайте
ОГО!!!Я пока только учу С++..........буду пробывать(может в будущем тетрис напишу)


Желаю всем добра и успехов в разработке ваших игр!
RenusДата: Среда, 25 Августа 2010, 02:17 | Сообщение # 8
почетный гость
Сейчас нет на сайте
Ну хорошо попробую я поколдовать твоими способами)
подскажи тогда книжки которые тебе помогли в программирование игр...
Если есть кинь какой нибудь исходник простой игры я хоть гляну как это люди делаеют)
ezhickovichДата: Среда, 25 Августа 2010, 10:17 | Сообщение # 9
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Quote (Renus)
Ну хорошо попробую я поколдовать твоими способами)

Лучше подумай и придумай так как те будет удобней, а не слушай чужие советы...
cool

Quote (Renus)
подскажи тогда книжки которые тебе помогли в программирование игр...

Их много...

Вообще советую такие:
"Совершенный код" ( Стив Макконнелл ) - там много внимания уделяется общим вопросам...
"Эффективное использование C++" ( Скотт Майерс ) - крайне полезная книга...
"OpenGL. Суперкнига" ( Райт Ричард С., мл., Липчак Бенджамин ) - чётко и понятно изложены основы OpenGL...
"Современное проектирование на C++" ( Андрей Александреску ) - тоже отличная книга...
"Программирование на C++ глазами хакера" (М.Е. Фленов) - нечего комментировать...
"Графика трехмерной компьютерной игры на OpenGL" (А. В. Боресков) - тоже в особых комментариях не нуждается...

Quote (Renus)
Если есть кинь какой нибудь исходник простой игры я хоть гляну как это люди делаеют)

Разве с этими движками нет примеров?

Должно прояснить некоторые моменты...



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
RenusДата: Четверг, 26 Августа 2010, 04:12 | Сообщение # 10
почетный гость
Сейчас нет на сайте
Фу... Методом перечитки глав об классах, указателях и векторах... Заставил всю эту гадость работать)))
Скоро будет новая тема в проэктах tongue

Как раз тут еще вопросик назрел небольшой...
Я пишу на DEV C++, скажите каким образом можно разбить мой главный файл (main.cpp) на несколько, к примеры классы и игровой цикл вынести в другие файлы, а то тяжко много страничный код писать...

Сообщение отредактировал Renus - Четверг, 26 Августа 2010, 04:17
ezhickovichДата: Четверг, 26 Августа 2010, 10:17 | Сообщение # 11
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Quote (Renus)
Я пишу на DEV C++, скажите каким образом можно разбить мой главный файл (main.cpp) на несколько, к примеры классы и игровой цикл вынести в другие файлы, а то тяжко много страничный код писать...

Ты всё в одном файле держишь? surprised surprised surprised

Если ты об автоматическом разбивании - то его нет...
Придётсо ручками...



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
WXZRWДата: Четверг, 26 Августа 2010, 12:46 | Сообщение # 12
Thousand faces conspiration
Сейчас нет на сайте
Quote (Renus)
Объясните мне дураку, что нужно вписать в скобки выше

Зависит от реализации, если например класс CObject имеет функцию для рендера данного обьекта или например функции для работы с данным обьектом, допустим, инициализацию обьекта (задать хотя бы начальную позицию), тогда эти функции и вызываешь. То есть делаешь в цикле все то что нужно проделать с каждым обьектом. Например рендер каждого из обьектов (при условии что функция Render существует) , итератор я не стал использовать:

Code
for(int i = 0; i < ObjectsList.size(); i++)
{
ObjectList[i].Render();
}

Quote (Renus)
а самое главное, что нужно добавить в код который ниже

Ниже у тебя виртуальная клавиатура, впрочем неважно, здесь нужно просто создать обьект и закинуть его в массив обьектов. Есть одно но - надо бы сделать проверку чтобы создавать только один обьект, потому что при нажатии кнопки у тебя будут создаваться обьекты не один раз, а до тех пор пока ты кнопку пробел не отпустишь (пробел это в данном случае)... Решается это либо вызовом return; после создания обьекта, либо делается переменная типа bool (можно также int)...

Code
// все равно Key_Down обычно в реалтаймовом цикле, поэтому каждый раз отмечаем что кнопка не нажата, используем int
int item_ready;

// нажат пробел   
if (Key_Down(K_SPACE) && item_ready != 1)
{   
// отметим что нажат пробел
item_ready = 1;

CObject new_item;

// можно использовать тут функции класса CObject, например для инициализации и т.д.

//закидываем в массив
ObjectList.push_back(new_item);

}

теперь надо отметить что кнопка отпущена для этого делаем так

Code
if (Key_Up(K_SPACE) )
{
item_ready = 0;
}

Можно использовать тип bool вместо int для отмечания состояния нажатия кнопок.

Сообщение отредактировал WXZRW - Четверг, 26 Августа 2010, 12:47
bumДата: Четверг, 26 Августа 2010, 14:01 | Сообщение # 13
почетный гость
Сейчас нет на сайте
Quote (Renus)
Я пишу на DEV C++, скажите каким образом можно разбить мой главный файл (main.cpp) на несколько, к примеры классы и игровой цикл вынести в другие файлы, а то тяжко много страничный код писать...

Если возникают такие вопросы, то о чем здесь вообще речь идет? Спуститесь на землю. По ходу раз уж так хочется въехать в C++:

1. Изучать документацию по GCC (раз используеш DevC++, то как раз используеш MinGW, что является виндовым портом GCC). Разбираемся с нуля в том, что такое компилятор и линковщик, и вообще всю теорию о том как из исходников собирается бинарник:
http://www.network-theory.co.uk/docs/gccintro/index.html
2. Берем книгу Кернигана и Риччи о языке C, делаем тамошние упражнения пока не придет понимание особенностей чистого C лежащего в основе C++
http://cgip.inf.unideb.hu/eng/rtornai/Kernighan_Ritchie_Language_C.pdf
3. Штудируем уже сам C++. Впринципе названия книг выше приводились, но в интернете также всяких ресурсов до фига.
4. Паралельно проникаемся идеями объектно-ориентированного программирования. Неплохая книга - Айра Пол. Объектно-ориентированное программирование на C++. Выучить просто синтаксис описания класов - это все до одного места, ООП - это отдельная философия которую нужно понять (реализация ООП в C++ - это только один из вариантов, в других языках часто используются другие реализации, поэтому важно уловить саму идею).

PS: да и почему всех так тянет сразу в C++, может стоит сначала научиться программировать? Выберите что-то попроще, выработайте алгоритмическое мышление, научитесь описывать простенькие алгоритмы теми средствами которые предоставляет вам язык программирования, а потом уже беритесь за сложные вещи.

RenusДата: Четверг, 26 Августа 2010, 18:10 | Сообщение # 14
почетный гость
Сейчас нет на сайте
Ну пряма по полкам разложил... biggrin

1. Программировать я умею, знаю паскаль, ассемблер, немного php...
2. Просто я этим 3 года не занимался, и с ООП не работал, щас вот учу с++
3. За ссылочки спасибо, про компилятор почитаю обязательно...

PS: Не надо делать из меня совсем уж нуба, т.к все не сложные вещи я освоил еще лет 5 назад...
По тому и спрашиваю здесь вещи которые для меня не ясны с данной области...

Добавлено (26.08.2010, 18:10)
---------------------------------------------
Практически все сделал, остался только один существенный вопрос.

Code
ObjectsList[i].Process();

Вызывает функцию Process из базового класса CObject.
Как сделать что бы вызывалась функция Process из под классов, таких как CPlayer например?
Иначе, не получается достучаться до объектов(((
ezhickovichДата: Четверг, 26 Августа 2010, 19:11 | Сообщение # 15
[Великий и могучий хозяинъ]
Сейчас нет на сайте
Renus, Сделай её виртуальной...

допустим так:

Code
class CObject
{
public:
    virtual void ~CObject (void);
    virtual void Process (void);
};

class CPlayer : public CObject
{
public:
    virtual void ~CPlayer(void);
    virtual void Process (void);
};

Тогда автоматически будет вызываться "Process" нужного класса ( наследника в данном случае... )



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
RenusДата: Пятница, 27 Августа 2010, 01:16 | Сообщение # 16
почетный гость
Сейчас нет на сайте
Не получилось(((
Вот, для простоты понимания процесса сократил код до консольного с целью решения этой проблемы:

Code
#include <iostream.h>
#include <vector.h>

class CObject
{
public:
    virtual void Process() {cout << "Общий класс" << endl;}
};

class CPlayer : public CObject
{
public:
    void Process() {cout << "Игрок" << endl;}
};

std::vector <CObject> ObjectsList;

int main()
{
    CObject he;
    ObjectsList.push_back(he);
    CPlayer me;
    ObjectsList.push_back(me);
     
    for(int i = 0; i < ObjectsList.size(); i++)  
    {  
       ObjectsList[i].Process();  
    }
     
    system("pause");
}

Как сделать что бы внутри цикла правильно определялся класс и выполнялось нужное действие?
Неужели ни у кого нет похожей реализации игрового цикла? Опишите какая у вас тогда...

bumДата: Пятница, 27 Августа 2010, 01:38 | Сообщение # 17
почетный гость
Сейчас нет на сайте
Renus, Вот исправленный код, теперь должно работать

Code

#include <iostream>
#include <vector>

using namespace std;

class CObject
{
public:
       CObject() {}
       virtual void Process() {cout << "Общий класс" << endl;}
};

class CPlayer : public CObject
{
public:
       CPlayer() {}
       virtual void Process() {cout << "Игрок" << endl;}
};

std::vector <CObject*> ObjectsList;

int main()
{
       ObjectsList.push_back(new CObject());
       ObjectsList.push_back(new CPlayer());

       for(int i = 0; i < ObjectsList.size(); i++)
       {
          ObjectsList[i]->Process();
       }

}

Два момента:
1. Метод объявленный виртуальным - всегда должен оставаться виртуальным.
2. Перед вызовом виртуального метода должен вызываться конструктор.

PS: Вы выше писали, что знаете Паскаль. Так вот извините, но нифига вы его не знаете, иначе бы не написали, то что написали. В Турбо Паскале еще с пятой версии точно такая же объектная модель, только терминология чуть другая (там до Делфи классы назывались объектами, а объекты - экземплярами объекта, но смысл тот же). Вот только Паскаль в отличие от C++ даже не позволил бы вам скомпилировать ваш код.

Сообщение отредактировал bum - Пятница, 27 Августа 2010, 01:41
RenusДата: Пятница, 27 Августа 2010, 02:21 | Сообщение # 18
почетный гость
Сейчас нет на сайте
Окей, спасибо)
На таком уровне может и не знал, выучим...
Тогда спрошу еще один вопрос.
Почему таким образом работает: ObjectsList.push_back(new CObject());
А таким нет: CObject name;
ObjectsList.push_back(name);

Целый день учу книжку по С++, уже мозги плавяться, благо Мафией 2 разбавляю)))

Добавлено (27.08.2010, 02:21)
---------------------------------------------
Просто в тех источников где я читал вообще нет таких тонкостей, про виртуальные методы вообще почти ничего нету, только что они дают, а реализация только через указатели и то в какой то извращенной форме, а в другой книге вообще совсем другое написали... капец(((

bumДата: Пятница, 27 Августа 2010, 10:06 | Сообщение # 19
почетный гость
Сейчас нет на сайте
Renus, Боюсь непросто будет объяснить, полиморфизм с ходу так просто не дается, но попробую. Смотри, вот два разных куска кода:
Code

         CObject a; // просто создаем объект класса
         a.Process();
         CPlayer b;
         b.Process();
         a=b;
         a.Process();  // вызовется CObject::Process()

         // ---------------         

         CObject* w = new CObject(); // явно вызываем конструктор, получаем адрес объекта и присваеваем его указателю
         w->Process();
         CPlayer* t = new CPlayer();
         t->Process();
         w=t;
         w->Process();  // вызовется CPlayer::Process()

В чем разница? Эти два примера описывают два ключевых подхода - раннее связывание и позднее связывание соответственно. При раннем связывании (первый вариант) привязка действия к объекту происходит на этапе компиляции. При позднем связывании (второй вариант) эта привязка происходит при выполнении программы. Для виртуального метода по определению возможно только позднее связывание, поскольку на этапе компиляции компилятор не обладает необходимой информацией об объекте чтобы вызвать нужный нам метод. Во втором случае при вызове конструктора неявно создается таблица виртуальных методов, которая как раз и дополняет объекты необходимой информацией. Это поведение свойственно конструктору по своей природе, в отличие от обычного метода его функциональность не ограничивается только тем, что вы впишете в его тело. В первом же случае таблица виртуальных методов не создается, поэтому метод вызывается как статический. Правда конструктор там все равно неявно запускается, но он не может дополнить объект новыми данными.

Таким образом, если в твоих классах есть виртуальные методы, то просто используй позднее связывание и все будет нормально. А лучше вообще заведи привычку использовать его всегда. Тогда и париться не будешь.

Сообщение отредактировал bum - Пятница, 27 Августа 2010, 10:36
WXZRWДата: Пятница, 27 Августа 2010, 15:47 | Сообщение # 20
Thousand faces conspiration
Сейчас нет на сайте
Quote (Renus)
Вызывает функцию Process из базового класса CObject.
Как сделать что бы вызывалась функция Process из под классов, таких как CPlayer например?
Иначе, не получается достучаться до объектов(((

Можно сделать без виртуальных функций и наследования вообще...

Если ты хочешь обратиться к функциям одного класса внутри другого класса, можно сделать первый класс глобальным (extern). В таком случае, после создания глобального класса CObject к нему можно обратиться из любой точки программы. Второй вариант - внутри класса CPlayer создать класс CObject, тогда при создании обьекта класса CPlayer этот класс будет иметь в себе также и обьект класса CObject.

Code
class CObject
{
public:
     void ~CObject (void);
     void Process (void);
};

class CPlayer :
{
public:
     void ~CPlayer(void);
     void Process (void);

     CObject object;
};

Если ты хочешь запихивать в один и тот же массив обьекты разных классов, то есть и CPlayer и CObject, опять же ест вариант без наследования и без виртуальных функций.

Делается это так.. Создается общий класс, например CObjectVarying... Потом ты создаешь enum список, там перечисляешь типы обьектов - например Item, Player, Vehicle, и т.д. Также ты создаешь struct с описанием параметров... Допустим, Position, Orientation а также главное не забыть занести туда элемент типа int и назовем его допустим, Type; После всего этого мы в классе CObjectVarying создаем обьект типа struct, который мы описали... А дальше, всякий раз когда мы создаем обьект класса CObjectVarying, мы просто заполняем наш struct и заодно в нашей переменной Type указываем что у нас за обьект... Потом мы создаем все нужные функции для всех этих типов обьектов внутри класса и в цикле при работе с обьектами проверяем переменную Type и опознаем с каким обьектом именно мы работаем... Вот и все, один класс - много разных типов обьектов... никакого наследования... все просто...

Псевдокод :

Code
enum eObjectType
{
ITEM,
PLAYER,
VEHICLE
};

struct OBJECT
{
float position[3];
float orientation[9];

int TYPE;
};

class CObjectVarying
{
public:

     void ~CObject (void);

     void Process (void);

     OBJECT obj;

     void InitializeObjectDefault(int OBJECT_TYPE);
};
Форум игроделов » Программирование » C/C++ » Помогите с элементарной механикой игры!!!
  • Страница 1 из 3
  • 1
  • 2
  • 3
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг