Парадигма 2D-игры

1

Я пытаюсь расширить навыки ООП, пытаясь запрограммировать 2D-графическую игру. Использование утилиты Java swing.

Теперь то, что я до сих пор: 4 общих класса, абстрактный класс, интерфейс и класс KeyListener. (Не волнуйся, это очень маленькая игра на данный момент).

Из 4 общих классов основной класс устанавливает два других класса в качестве объектов внутри него. Этими двумя объектами являются моя графика и мой гаджет. Gamestate, в свою очередь, устанавливает последний оставшийся объект (игрока) внутри него.

Проблема заключается в том, что когда я изначально получил все, чтобы он работал, чтобы игрок мог перемещаться (через keyPressed), как считывается ввод с клавиатуры, игрок слегка дрогнул вперед, а затем бегал в непрерывном движении. Именно так, если вы удерживаете клавишу буквы на клавиатуре, перед тем, как начнется формирование строки, появится буква.

Поэтому я подумал: "О, это так очевидно. Я должен попытаться справиться с этим с помощью булевых элементов, чтобы при смене ключа у меня было" boolean right = true ". И у меня будет некоторый код, где-то уходит в цикле с условными операторами для перемещения игрока ".

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

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

--- РЕДАКТИРОВАТЬ*

Вот все исходные файлы по запросу. https://www.dropbox.com/sh/f4diy7qtzh4xkem/AABUkM415PrRK1hu35TVkBo2a

Общие классы: Main, Window, GameState, Robot. Интерфейсы: Тезисы движения: GameVisualiser Слушатели: ArrowPress

Простите некоторые комментарии.

  • 1
    Нам было бы легче ответить, если вы разместите реализованную часть своего кода.
  • 1
    Ваша идея отслеживать, является ли ключ логическим или нет, является хорошей идеей и часто используется в играх, использующих Swing. Трудно дать совет о том, как справиться с этим, не зная вашей архитектуры, связанной с тем, как вы обновляете состояние своей игры. Есть ли у вас игровой цикл, где на разных этапах вы делаете следующие три вещи? : 1. обновлять анимацию / позиции в зависимости от того, сколько времени прошло с момента последнего обновления, 2. обновлять состояние на основании последнего полученного пользовательского ввода (здесь вы проверяете свои логические значения) и 3. когда вы рисуете.
Показать ещё 7 комментариев
Теги:
multithreading
oop
swing

2 ответа

0
Лучший ответ

Ну, вы не вдавались в подробности, какую игру вы делаете.

Независимо от этого, его легко угадать, какова ваша проблема. Вы только продвигаете свое состояние игр в прямом ответе на какое-то входное событие (вы упомянули KeyListener). Такая архитектура, основанная исключительно на входных событиях, отлично подходит для игр, которые только делают что-то в ответ на ввод пользователей (например, простые карточные или настольные игры).

Но, похоже, вы хотите продвинуть свое игровое состояние в тот момент, когда пользователь не вводит пользователя (например, между KeyDown и событием KeyUp). В этом случае вам понадобится то, что обычно называется игровым циклом, где игра фактически работает, постоянно обновляя состояние игры (обычно с фиксированными интервалами времени).

У вас есть два варианта:

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

b.) Создайте событие искусственно с фиксированной скоростью для продвижения состояния игры (это также будет использовать потоки под капотом, но вам не нужно разбираться с деталями):

Взгляните на класс java.swing.Timer. Вы создаете экземпляр Timer, который запускается с регулярными интервалами (скажем каждые 32 миллисекунды, что составляет примерно 30 раз в секунду). Таймер генерирует событие (вы присоединяете слушателя к таймеру, чтобы получать уведомление о событии) через равные промежутки времени. Теперь вы перемещаете все состояние игры в это событие действия. Это превращает вашу игру из входного события, управляемого в игру, управляемую тиком, давая вам возможность продвигать состояние игры при каждом тике по мере необходимости.

В вашем KeyListener вы просто обновите флаги для "перемещений в направлении", фактическое движение будет сделано в событии галочки с таймера.

Причина, по которой вы получаете отрывистое движение прямо сейчас, вероятно, вы полагаетесь на событие KeyTyped, которое создается искусственно путем swing - одно событие в момент нажатия клавиши, затем задержка, затем, наконец, после этой начальной задержки событие запускается с ключевую частоту повторения (заданную в настройках системы) до тех пор, пока клавиша не будет отпущена. Это не очень подходит для игры, вы лучше обрабатываете события KeyPressed и KeyReleased, которые отражают то, что пользователь действительно делает на клавиатуре.

Подход a.) С потоками по существу делает то же самое, с большей свободой и всем под вашим контролем - но еще много подводных камней, о которых нужно знать, таких как параллелизм и условия гонки.

0

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

  • 0
    Там нет ничего в этом вопросе, чтобы предположить, что это не будет представлять ненужную сложность.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню