Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > хочу создать компьютерную игру


Автор: vcxz 30.1.2011, 23:11
хочу создать компьютерную игру

простую
например, змейка или что еще попроще

без программирования уж точно не обойтись
поэтому решил изучить хотя бы основы языка Си
но ещё не начал:

перед тем как что-либо учить хотелось бы увидеть весь, так сказать, фронт работы,
то есть, что еще, кроме ЯП, придётся изучить?

немного погуглив выяснил следующее:
большинство программ-приложений работают так:
- ввод неких данных
- вычисления с полученными данными
- вывод результатов вычислений


похоже, что в целом этот алгоритм верен для программ, которые работают в каком-то смысле пошагово.

это не очень хорошо, так как игры чаще бывают реал-таймовыми

Как же тогда работают реал-тайм программы (игры)???
сколько ни думал, могу предположить следующее:
способ тот же, только всё пихается в цикл:
цикл() {
   - ввод неких данных //клава, мышь
   - вычисления с полученными данными //логика игры
   - вывод результатов вычислений //визуализация, звук
}

подумал ещё немного и что-то мне мои умозаключения не понравились

поэтому решил, что изобретать велосипед не надо, а лучше спросить (собственно вопросы я уже напечатал)

Автор: bsa 30.1.2011, 23:58
твой второй велосипед верен не только для игр, но и для обычных программ. Так как очень мало удачных программ завершают свою работы сразу после вывода информации. Обычно, они это делают по требованию пользователя.

Цитата(vcxz @  31.1.2011,  00:11 Найти цитируемый пост)
перед тем как что-либо учить хотелось бы увидеть весь, так сказать, фронт работы,
то есть, что еще, кроме ЯП, придётся изучить?
кроме знаний языка, нужен еще и опыт владения им. Представь себе молоток. Это инструмент. Держать его надо за деревянную ручку так, чтобы при вытянутой руке вперед "тупая" его сторона смотрела вниз. Теперь сгибаешь руку в локте, направляешь молоток на гвоздь и резко разгибаешь локоть одновременно уводя чуть-чуть назад плечо... Теперь ты знаешь инструмент "молоток". Но я уверен на 100%, что не имея опыта работы им, ты себе все пальцы отобьешь. Так же и с языком программирования. Вот только подводных камней у него значительно больше. И если удар по пальцу или загнутый гвоздь обнаруживаются моментально, то ошибки программирования не могут найти годами.

Чтобы написать программу, сначала нужно написать (ну или хотя бы представить) алгоритм ее работы. Делается это сверху вниз - от общего к частному. Для этого даже специальный язык придуман - UML.


Короче, откладываешь свою игру, идешь в "Часто задаваемые вопросы" (тема прикреплена), там есть "С чего начать учиться"... А через пол годика, в качестве практики, уже сможешь написать свою "змейку".

Автор: vcxz 31.1.2011, 00:36
Цитата(bsa @  30.1.2011,  23:58 Найти цитируемый пост)
твой второй велосипед верен не только для игр

посмотрел прилепленные темы - нашел там ссылку на курс по OpenGL

возникли следующие разногласия с моим велосипедом:
если использовать GLUT так как в примере с красным квадратом на черном фоне,
то, как я понял, цикл будет внутри glutMainLoop();

точно не разобрался - похоже есть такое понятие как "событие" например нажатие на клавиш

как же так?
а куда мне писать саму логику игры?

вернёмся к змейке - сама змейка движется постоянно, даже если пользователь ничего не нажимал на клаве
то есть может и не быть ввода данных, который есть в моём велосипеде

значит и не будет события, которое обработает glutMainLoop();
или этот пример с квадратом не подходит для игр?

Автор: vcxz 31.1.2011, 13:17
Цитата(vcxz @  31.1.2011,  00:36 Найти цитируемый пост)
или этот пример с квадратом не подходит для игр? 

сам себе отвечу
первый http://www.rsdn.ru/article/opengl/ogltut2.xml#E1G, о котором идёт речь - действительно предназначен для статичного изображения

там далее по тексту подробнее объясняется GLUT - я просто невнимательно посмотрел  smile 
glutIdleFunc() - похоже оно

Автор: RastaDja 31.1.2011, 13:21
Цитата

вернёмся к змейке - сама змейка движется постоянно, даже если пользователь ничего не нажимал на клаве
то есть может и не быть ввода данных, который есть в моём велосипеде


в этом случае ввод данных совершает сама программа используя таймер.

Автор: baldina 31.1.2011, 14:26
Цитата(vcxz @  31.1.2011,  00:36 Найти цитируемый пост)
куда мне писать саму логику игры?

glutMainLoop() реализует цикл приложения. в цикле вызывается функция, установленная вызовом glutDisplayFunc(). в случае возникновения событий от мыши и клавиатуры вызываются соответствующие функции-обработчики, установленные вызовами glutKeyboardFunc(), glutMouseFunc() и др.
В glutDisplayFunc() надо передать функцию, которая занимается отрисовкой кадра.

Например, логика может быть такой (упрощенно):

Код

void onTimer(int)
{
   // установить новое положение змейки смещением на 1 по горизонтали
   setPos (getPos ()+Point2d(1,0));

   // сообщить, что пора перерисовать содержимое окна
   glutPostRedisplay ();
}

void onDraw()
{
  glClear (GL_COLOR_BUFFER_BIT);
  glLoadIdentity ();

  // получить текущее положение змейки
  Point2d p = getPos ();
  glTranslated(p.x, p.y, 0);
  
  // нарисовать змейку
  //...

  glutSwapBuffers();
}

int main (int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
  glutCreateWindow("Test");

  glutTimerFunc(100, onTimer, 0);
  glutDisplayFunc(onDraw);
  glutMainLoop();
}

Автор: vcxz 31.1.2011, 14:45
несколько лет назад пытался учить MS VB

так вот там на форму приложения можно было ставить 'таймер'

на практике это оказалось ПЛОХИМ решением
- большой код не успевал выполняться за отведённое время тика таймера

может быть это был мой косяк,
но таймеры использовать больше не хочется

Предполагаю вместо таймера нужно сделать просто бесконечный цикл:
- а внутри цикла считать Δt  - то есть шаг времени - период за который выполнилась предыдущая итерация цикла
- и координаты змейки сдвигать по формуле учитывающей Δt

не знаю - можно ли так сделать?

Автор: Modul 31.1.2011, 15:25
Цитата(vcxz @  31.1.2011,  14:45 Найти цитируемый пост)
Предполагаю вместо таймера нужно сделать просто бесконечный цикл...


и получится таймер  smile 


З.Ы. Данные у программы есть всегда, если их нет - они равны нулю.

Автор: baldina 31.1.2011, 15:59
Цитата(vcxz @  31.1.2011,  14:45 Найти цитируемый пост)
так вот там на форму приложения можно было ставить 'таймер'

на практике это оказалось ПЛОХИМ решением
- большой код не успевал выполняться за отведённое время тика таймера

из пистолета можно застрелиться. можно зарезаться пилочкой для ногтей. отравиться шоколадом.
все дело в правильном и неправильном (неумелом, неумеренном) использовании.
в данном случае таймер нужен для того, что бы приложение работало с одинаковой скоростью независимо от производительности ПК. Число срабатываний onDraw() зависит от частоты вызова из glutMainLoop(), которая зависит от текущей производительности комп-а.

Добавлено через 5 минут и 31 секунду
Цитата(vcxz @  31.1.2011,  14:45 Найти цитируемый пост)
Предполагаю вместо таймера нужно сделать просто бесконечный цикл:
- а внутри цикла считать Δt  - то есть шаг времени - период за который выполнилась предыдущая итерация цикла
- и координаты змейки сдвигать по формуле учитывающей Δt

такая программа будет даром проедать процессорное время.
конечно, можно Δt и соответствующие перемещения вычислять внутри onDraw, однако лучше разделить логику приложения: реакция на событие отдельно от отрисовки. событие "пора передвинуть змейку" - тоже событие, ничем не хуже нажатия на клавиатуру.

Добавлено через 7 минут и 55 секунд
кстати, забыл. нужно в onTimer() вставить вызов glutPostRedisplay(); - команду перерисовки окна
ща поправлю

Автор: vcxz 31.1.2011, 16:20
Цитата(baldina @  31.1.2011,  15:59 Найти цитируемый пост)
такая программа будет даром проедать процессорное время.

угу - если код логики обработается быстрее кода визуализации
вот если бы паузы можно было вставлять в код - тогда можно было бы это устранить

кстати, есть большое подозрение, что glutMainLoop может выполниться раньше чем видеокарта отрисует картинку.
Где бы это дело уточнить?

и снова о времени Δt
порылся в гугле и сделал вот это (не смеяться - язык Си изучаю три дня)
Код

#include <stdio.h>
#include <windows.h>

main()
{
    int i = 1;
    long x2 = 0;
    long x1 = GetTickCount();
    for (i = 1; i <= 10000; i++)
    {
        x2 = GetTickCount();
        printf("%d\t", x2 - x1);
        x1 = x2;
    }
    return 0;
}


что-то оно подозрительно работает
выводит кучу нулей (это так и должно быть), и изредка 15 или 16 (а вот это уже странно, так как я ожидал единицу)

Автор: bsa 31.1.2011, 16:22
vcxz, зря ты вот так, без подготовки сразу пытаешься взять быка за рога. Поверь мне, если ты не будешь последователен в изучении программирования, то в голове у тебя образуется каша. Прежде чем строить дом, надо сначала научиться строить и проектировать дома, а потом уже проектировать и строить. А когда учатся проектировать одновременно учась строить при постройке дома, то он очень смешным  получается...

Добавлено через 2 минуты и 22 секунды
Цитата(vcxz @  31.1.2011,  17:20 Найти цитируемый пост)
выводит кучу нулей (это так и должно быть), и изредка 15 или 16 (а вот это уже странно, так как я ожидал единицу) 
С чего это вдруг ты ожидал единицу? Ты не удосужился почитать документацию про GetTickCount?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)