Проблемы с Android связаны с дизайном

9

У меня проблемы с тем, чтобы обернуть голову вокруг игрового дизайна. На платформе Android у меня есть действие, и я настраиваю его представление контента с помощью пользовательского представления поверхности. Пользовательский вид поверхности выступает в качестве моей панели, и я создаю экземпляры всех классов и выполняю там все чертежи и расчеты.

Вопрос: Должен ли я вместо этого создавать экземпляры других классов в моей деятельности?

Теперь я создаю собственный класс потока, который обрабатывает игровой цикл.

Вопрос: Как я могу использовать этот один класс во всех моих действиях? Или мне нужно каждый раз создавать отдельный экземпляр расширенного класса потока?

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

Я просто хочу знать, является ли метод, который я использую, неэффективным (что, вероятно, так и есть) и как правильно разработать его. Я прочитал много уроков, и у меня все еще много проблем с этой конкретной темой. Может быть, ссылка на некоторые учебники, которые объясняют это? Спасибо.

semajhan
источник

Ответы:

13

Я настоятельно рекомендую иметь нить рендеринга (использование Canvas/ OpenGL ES, Canvasвозможно, немного проще в настройке) и нить игры, в которую вы помещаете свою игровую логику.

Чтобы действительно «загрузить» игру, вы можете создать класс GameEngine и сделать его центральным пунктом вашего приложения. Когда ваш рендерер готов к работе, вы можете создать обратный вызов для экземпляра GameEngine, который создаст и запустит два потока, используя Runnableдля рендеринга один, а другой - Runnableдля игровой логики.

Образец кода:

Запуск приложения

private GameEngine engine;
private CanvasRenderer renderer;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   // Create instances of your two Runnable classes and pass that into
   // the GameEngine constructor.
   // Create an instance of the game engine.
   engine = new GameEngine(canvasRunnable, gamelogicRunnable);
   renderer = new CanvasRenderer(this, engine); 
   setContentView(renderer); 
}

CanvasRenderer

private GameEngine engine;    

// Save your instance from the GameEngine reference in your constrcutor and make
// a global initializion for your GameEngine instance.  

@Override
public void surfaceCreated(SurfaceHolder holder) {  
   // One time setup here.
   // When your view is ready, make this callback to the 
   // GameEngine.
   engine.surfaceIsReady();
}

GameEngine

private Thread canvasThread;
private CanvasRunnable canvasRunnable;
// You should be able to figure out how to create a second thread
// where you should put your game logic. :)

// Constructor stuff like creating instances of your threads
// and passing references as you wish to those.
// Don't start the threads here.
// Remember to set references from your Runnable's into your Thread's 
// instances here!

/**
 * Callback. Now your renderer is ready and you
 * can start your threads.
 */
public void surfaceIsReady() {
   thread.setName("Canvas");
   thread.start();
   // Same for game logic.
}
Wroclai
источник
Вау, спасибо. Мне понравилось, как ты это объяснил. Это одно объяснение освещает всю концепцию для меня.
семаджан
@semajhan: Просто спросите, есть ли у вас проблемы. :)
Вот что у меня в голове: класс GameEngine, который действует как «ссылка» или «ссылка» на все другие классы с панелью. Активность> Панель> GameEngine> все остальные классы.
семаджан
@semajhan: Точно. Только для вашего знания: если вы решили пойти с OpenGL ESвами, вы должны знать, что у рендерера OpenGL ESуже есть свой собственный поток, и в этом случае вам не нужно вручную создавать и запускать новую Threadи Runnableдля этой системы.
Игнорировать этот комментарий.
Семаджан
3

Как правило, ваш игровой цикл самодостаточен внутри одного занятия.

когда вы переключаете активность, вы приостанавливаете / убиваете свой игровой цикл. Отдельные действия должны в любом случае соответствовать приостановке игры (например, потому что вы переключились на действие «отправить письмо друзьям» или «главное меню»)

Для дополнительных уровней вы не должны создавать или уничтожать какие-либо новые темы ... если вы не переключились на "полный уровень, загружая следующий уровень, пожалуйста, подождите" активность, и вам придется перезапустить "основную игру" "Активность в любом случае. Но даже в этом случае вы на самом деле не создаете «лишние» потоки, вы просто создаете один поток в этом одном действии и последовательно убиваете / перезапускаете / убиваете / перезапускаете ... и т.д. этого действия. каждый раз, когда уровень завершен.


источник
3

Если вы понимаете немецкий, этот урок очень хорош.

Для английского языка я могу рекомендовать этот урок

Что касается класса потока: я не знаю, действительно ли необходимо, чтобы вы могли ссылаться на все классы в вашем приложении. В моей игре я решил это так:

Класс, который отвечает за отрисовку основного GUI, имеет переопределенный метод рендеринга. В этом методе вызывается класс потока, который обновляет все элементы графического интерфейса и обрабатывает вводимые пользователем данные.

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

RoflcoptrException
источник
Этот учебник немецкого языка хорош, но он был примерно переведен на vai google, поэтому его трудно понять.
семаджан