Войти
ПрограммированиеФорумОбщее

Смена экранов игры (комментарии) (5 стр)

Страницы: 14 5 6 710 Следующая »
#60
11:55, 26 янв. 2013

Wraith
> Вопрос правильно поставлен: почему "больше кода" == "лучше"?
Люди просто не разбирались в том, какие преимущества может дать метод описанный в этой статье. В итоге я как раз таки напишу меньше кода чем они своими свитчами или конечными автоматами.

Вообщем опишу где это можно применить.

1) переходы между главным меню и игрой - банально и описано в статье

2) большое число экранов что хорошо например для РПГ, в которой начало игры может состоять из нескольких экранов - меню, создания партии, создания героя которое в свою очередь также может состоять из экранов и т.д. Описано в предыдущем посте.

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

4) дебаг. Вот допустим у вас уже почти готовая игра. Интро, главное меню, игра. И вот вы тестируете, пытаетесь найти какой-то баг который невозможно поймать из дебагера, а только из игры. Сколько времени вы затрачиваете на переход "Интро-Игра"? Раздражает? Меня да. Хорошее решение - убрать интро и главное меню, и запускать сразу игру. Сколько строчек кода вам надо закоментировать или изменить? Мне всего одну. А когда вы найдете баг и надо будет все вернуть, сколько строк? Мне также одну?

5) инструментарий из игры. Я вот для двух своих трешевых игр (у меня в резюме ссылки) писал редакторы, при этом эти игры были не теми, для которых надо писать отдельный редактор. Я его писал в виде отдельного модуля. И как видите модули хорошо мне в этом помогли. Мне не надо писать тяжелый парсер разпознования входных параметров. Я не боюсь что какой-нибудь хакер сможет подобрать нужный ключ для запуска потому что у меня невозможно никаким обрабом в конечной версии запустить редактор (только через перекомпиляцию). Мне не надо комментировать огромные куски кода отвечающие за редактор

6) Подмодули. никто не обратил на это внимание, а зря. Давайте посмотрим на скайрим. В игре вы можете вызвать окно инвентаря, окно квестов, окно навыков, карту. При этом нельзя открыть сразу два окна. Мои модули позволяют такое сделать. В модуле "Игра", создаем новый экземпляр менеджера модулей. Затем создаем наследников IModule для каждого из этих окон. Программируем логику. Все, Теперь просто через менеджер, указываем в нужный момент нужный активный модуль. Все остальное сделает за вас код. Сколько строк кода вам над будет написать только для того чтобы корректно осуществлять переходы в эти окна? Мне все 4 и все они являются вызовом метода SetActiveModule(). Вам надо будет звать всякие Init/Close/Frame/Input, следить за тем чтобы не было вызвано сразу два окна, следить за тем чтобы из окна можно было вызвать только некоторые окна а не все. Мне ничего этого писать не надо - все уже написано

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


#61
12:07, 26 янв. 2013

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

И еще момент - я перерос то время когда ООП - это было круто (точнее я его обошел стороной). Сейчас я понял две вещь - код должен быть не красивым, не следовать всем законам какой-то парадигмы - он должен просто работать и все. Не важно - говнокод или идеал, если он решает свою задачу - это хороший код. Второе - чем меньше я вожусь с кодом, тем больше я могу сделать. Данная система модулей написана один раз год назад (с правками конечно). И теперь мне не надо начиная новый проект строчить сотни строк переходов. Да даже банально - мне не надо напрягать мозг тем как сделать этот переход, тупо копипаста достаточно чтобы все работало.

#62
12:12, 26 янв. 2013

war_zes и что ты так не любишь switch?

if (getch()==49)  // нажал на 1
      m_mgr->SetActiveModule(GAME);// переключаем на следующий модуль
    else if (getch()==50)  // нажал на 2
      return false;  // выходим
Это уже switch.
// если пользователь нажмет Esc, вернемся в главное меню
  if (kbhit() && getch() == 27)
    m_mgr->SetActiveModule(MAINMENU);
Это почти switch.
Заметь, это твой код, а не мой.
#63
12:24, 26 янв. 2013

HumanAPI
> и что ты так не любишь switch?
ты не понял. я не против свитча. Я против архитектурного решения в виде свитча - из-за которого весь код связывается в узел. Я избавлен от такого узла.

HumanAPI
> Это почти switch.
где? две строчки кода - это не кейс свитча

И ты не ответил на мой вопрос. Сделай свитчем (или каким другим способом то что я тебя просил пару постов ранее), просто сравним количество кода которое надо написать (я сделаю после тебя, потому что устал приводить листинги кода в пустую в местных спорах, когда люди не хотят доказывать свою точку зрения а переходят на личности)

#64
13:22, 26 янв. 2013

Пожалуйста, добавил экран для создания персонажа.

Game.h

#pragma once

#include "IModule.h"
#include <string>


class Game : public IModule
{
 private:
  std::string m_text;
  std::string m_name;
  long m_i;

  static int st_init (IModule* module);
  static int st_menu (IModule* module);
  static int st_game (IModule* module);
  static int st_close (IModule* module);
  static int st_person (IModule* module);
 public:
  Game() {do_update = st_init;}
  ~Game() {}
};

Game.cpp

#include "Game.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <conio.h>

int Game::st_init (IModule* module)
 {
   Game* gm = (Game*)module;
   gm->m_text = "Hello World";
   gm->m_name = "war_zes";
   gm->m_i = 0;

   system("CLS");  // очищаем экран
   std::cout << gm->m_text << std::endl;
   system("PAUSE");

   gm->do_update = st_game;
   return 1;
 }

int Game::st_menu (IModule* module)
 {
  Game* gm = (Game*)module;
  int key;
  system("CLS");  // очищаем экран

  std::cout << "Main Menu\n\n";
  std::cout << "Select:\n";
  std::cout << "1 - New Game\n";
  std::cout << "2 - Exit Game\n";
  std::cout << "3 - Set name person\n";

  if (kbhit())
  {
    key = getch();
    switch(key)
     {
      case 49: gm->do_update = st_game; break;
      case 50: gm->do_update = st_close; break;
      case 51: gm->do_update = st_person; break;
     }
  }
  return 1;
 }

int Game::st_game (IModule* module)
 {
   Game* gm = (Game*)module;
   int key;
   system("CLS");  // очищаем экран

   gm->m_i++;
   if (gm->m_i >= LONG_MAX)
    gm->m_i = 0;

  std::cout << gm->m_name << " " << gm->m_i;

  if (kbhit())
  {
    key = getch();
    switch(key)
     {
      case 27: gm->do_update = st_menu; break; // если пользователь нажмет Esc, вернемся в главное меню
      case 51: gm->do_update = st_person; break;
     }

  }
  if (kbhit() && getch() == 27)
   gm->do_update = st_menu;

  return 1;
 }

int Game::st_close (IModule* module)
 {
  Game* gm = (Game*)module;
  gm->m_text.clear();
  gm->m_name.clear();
   return 0;
 }

int Game::st_person (IModule* module)
 {
  Game* gm = (Game*)module;
  system("CLS");  // очищаем экран

  std::cout << "Create person \n\n";
  std::cout << "New name - ";

  if (kbhit())
  {
    std::cin >> gm->m_name;
    gm->do_update = st_game;
  }
  return 1;
 }
Если так дело пойдет к вечеру будет консольный скайрим :))


>> где? две строчки кода - это не кейс свитча

Это пока ты отлавливаешь одно нажатие кнопки, а если несколько то привет switch.

#65
13:46, 26 янв. 2013

HumanAPI
щас тоже напишу, будет короче, понятей и более расширяемей

#66
14:42, 26 янв. 2013

ModuleName.h

#pragma once

#define HELLOSCREEN "Hello"
#define MAINMENU "Menu"
#define GAME "Game"
#define HEROCREATE "Hero"

HelloScreen.h

#pragma once

#include "IModule.h"

class HelloScreen : public IModule
{
public:
  virtual void doInit();
  virtual bool doRun();
  virtual void doClose();
};

HelloScreen.cpp

#include "HelloScreen.h"
#include "ModuleName.h"
#include "ModuleMgr.h"

void HelloScreen::doInit()
{
}

bool HelloScreen::doRun()
{
  m_mgr->SetActiveModule(MAINMENU);
  return true;
}

void HelloScreen::doClose()
{
}

MainMenu.h

#pragma once

#include "IModule.h"
#include <string>

class MainMenu : public IModule
{
public:
  virtual void doInit();
  virtual bool doRun();
  virtual void doClose();
};

MainMenu.cpp

#include "MainMenu.h"
#include "ModuleName.h"
#include "ModuleMgr.h"

void MainMenu::doInit()
{
}

bool MainMenu::doRun()
{
  system("CLS");

  std::cout << "Main Menu\n\n";
  std::cout << "Select:\n";
  std::cout << "1 - New Game\n";
  std::cout << "2 - Exit Game\n";

  if (kbhit())
  {
    if (getch()==49)
      m_mgr->SetActiveModule(HEROCREATE);
    else if (getch()==50)
      Exit();
  }

  return true;
}

void MainMenu::doClose()
{
}

HeroCreate.h

#pragma once

#include "IModule.h"

class HeroCreate : public IModule
{
public:
  virtual void doInit();
  virtual bool doRun();
  virtual void doClose();
};

HeroCreate.cpp

#include "HeroCreate.h"
#include "ModuleName.h"
#include "ModuleMgr.h"

void HeroCreate::doInit()
{
}

bool HeroCreate::doRun()
{
  m_mgr->SetActiveModule(GAME);
  return true;
}

void HeroCreate::doClose()
{
}

Game.h

#pragma once

#include "IModule.h"
#include <string>

class Game : public IModule
{
public:
  virtual void doInit();
  virtual bool doRun();
  virtual void doClose();
};

Game.cpp

#include "Game.h"
#include "ModuleName.h"
#include "ModuleMgr.h"

void Game::doInit()
{
}

bool Game::doRun()
{
  if (kbhit())
  {
    if (getch() == 27)
      m_mgr->SetActiveModule(MAINMENU);
    else if(getch() == 51)
      m_mgr->SetActiveModule(HEROCREATE);
  }
  return true;
}

void Game::doClose()
{
}

#67
14:46, 26 янв. 2013

HumanAPI
> static int st_init (IModule* module);
> static int st_menu (IModule* module);
> static int st_game (IModule* module);
> static int st_close (IModule* module);
> static int st_person (IModule* module);
Видишь, ты вставил новую строчку в код. Я в своем примере не изменил ни одной строчки в системе модулей. Вообщем считай как знаешь, но я свою систему написал не ради крутости и не ради лололоООПлололо-я мастер ООП. А ради того чтобы без напряга добавлять новые экраны. Тебе чтобы добавить экран, надо лезть в код, мне надо написать отдельный независимый модуль и прицепить его к менеджеру. А это еще и бонус для командной разработки - я могу писать модуль главного меню, а другой программист модуль создания героя, и мы не будем писать конфликтующий друг с другом код, потому что нет связи.

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

#68
14:51, 26 янв. 2013

war_zes
> А ради того чтобы без напряга добавлять новые экраны.
я всегда удивлялся с людей которые чтобы не писать 1 строчку пишут 3:)

#69
14:52, 26 янв. 2013

war_zes
> . А ради того чтобы без напряга добавлять новые экраны

Это называется повторное использование кода ...

#70
14:53, 26 янв. 2013

Mephistopheles
> я всегда удивлялся с людей которые чтобы не писать 1 строчку пишут 3:)

Эх...  семь раз отмерь - один раз отреж

#71
15:03, 26 янв. 2013

Mephistopheles
> я всегда удивлялся с людей которые чтобы не писать 1 строчку пишут 3:)
Где? Я что, виноват, что в C++, чтобы написать метод класса, надо написать его объявление в объявлении класса, затем строчку с возвращающим типом именем и параметрами (как она зовется?) еще две строчки для фигурных скобок и строчку для ретурна, а из модулей у меня таки одна строчка. И вы никак не поймете, что в реальном проекте напишите те же самые 3 строчки и ваша ранняя экономия вам ровным счетом ничего не даст. Потому что можно сказать вообще так - затем писать 100 тысяч строк кода, если для рабочего приложения достаточно одной строчки: int main(){}
?
Это как раз то что вы и говорите, вы сэкономили 99999 строк но ничего не получили. также и здесь.

#72
15:23, 26 янв. 2013

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

PS Я понял, что бы модуль HeroCreate начал работать его надо связать с модулем Game, но тогда он потеряет свою независимость.

#73
17:56, 26 янв. 2013

А что же еще не опубликована то статья? Напиши модераторам, посмотрят, покажут что поправить, и опубликуется статья.

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

Любая сцена (экран) игры имеет свою логику, в любом случае придется писать под каждый свой класс/код. Тут уж ни как не обойти. Но в данном случае достаточно будет только одной строчки для регистрации сцены. Связь между переходами сцен описывают сами сцены, что и откуда открыть они должны знать, им и назначается эта задача.
Что имеем, если это свитч? Тоже самое, создаем сцену, и после не регистрируем сцену, а правим блок свитча. Устанавливаем новые флаги, новые константы/переменные. В итоге они нагромождаются и становится не ясна логика а как и что работает. Теперь, что бы переключить экран, надо дергать не имя сцены, а знать какие же там были фалги/константы/переменные в свитч навязаны. А если удалить экран? два, три? Править опять свитч, убирать лишние переменные. А кто этим будет заниматься? Оставим на потом, как оно обычно и бывает. В итоге лишнее нагромождение кода.

Примеры приводят здесь которые, единичные они. Опираться не стоит на них.

#74
21:25, 26 янв. 2013

кейс прозрачен и понятен любому нубу и легко правится.
говономенеджер сосет уже в статье
"как это работает" - вот этого пункта не должно быть в принципе. Читаем art of readable code.
новичков которые пишут статьи я бы отстреливал. резиновыми пулями (чтоб больнее и дольше)

Страницы: 14 5 6 710 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.