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


9

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

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

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

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

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

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

Ответы:


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.
}

Вау, спасибо. Мне понравилось, как ты это объяснил. Это одно объяснение освещает всю концепцию для меня.
семаджан

@semajhan: Просто спросите, есть ли у вас проблемы. :)

Вот что у меня в голове: класс GameEngine, который действует как «ссылка» или «ссылка» на все другие классы с панелью. Активность> Панель> GameEngine> все остальные классы.
семаджан

@semajhan: Точно. Только для вашего знания: если вы решили пойти с OpenGL ESвами, вы должны знать, что у рендерера OpenGL ESуже есть свой собственный поток, и в этом случае вам не нужно вручную создавать и запускать новую Threadи Runnableдля этой системы.

Игнорировать этот комментарий.
Семаджан

3

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

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

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


3

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

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

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

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

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


Этот учебник немецкого языка хорош, но он был примерно переведен на vai google, поэтому его трудно понять.
семаджан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.