Где контекст живет в игре ООП Javascript Pong? - PullRequest
7 голосов
/ 15 июня 2011

Чтобы применить свои знания ООП, я делаю игру в понг на javascript (я знаю, я знаю, это все равно что играть в Stairway to Heaven в магазине гитар). У меня было несколько функционирующих версий игры, в которых реализовано несколько различных техник, включая ООП на основе прототипа и функциональный стиль. Однако я не делаю это, чтобы получить функциональную игру, я делаю это, чтобы учиться.

Я использую html5 canvas и обычный старый javascript, без фреймворков (хорошо, немного jQuery для захвата клавиатуры). У меня был объект Pong, который представлял мою игру. Понг имел атрибут ctx, который содержал ссылку на контекст canvas.getContext("2d"). Он также имел атрибуты player1, player2 и ball для хранения, вы знаете что. Когда был создан экземпляр мяча и двух игроков, контекст был передан их конструктору, чтобы они тоже могли содержать ссылку на контекст для использования в своих draw(ctx) методах. У Понга был метод draw(), который вызывался с использованием setInterval(this.draw, 10). Метод ничьей Понга вызвал бы метод ничьих двух игроков и мяча.

Мне не нравится, что оба игрока и мяч имеют контекст в качестве атрибута. Им не принадлежит контекст, и поэтому он не должен быть атрибутом. Однако природа использования javascript и canvas заключается в том, что это лучший способ. Кто или что должно владеть контекстом в этой ситуации? В идеале я бы не хотел, чтобы у игроков и мячей вообще был объект для рисования. Я чувствую, что у них должны быть атрибуты, которые описывают их геометрию и положение, и отдельный объект должен быть поставлен перед их отображением на экране. Таким образом, если бы в будущем я решил, что хочу использовать

вместо canvas, я мог бы просто изменить объект рендеринга, и все остальное было бы забыто.

Я знаю, что делаю игру Pong на javascript более сложной, чем должна быть, но я хочу практиковать приемы и действительно впитывать концепцию ООП, но каждый раз, как мне кажется, я решаю ее совершенно новую проблему, созданную мое «решение» представляет себя.

РЕДАКТИРОВАТЬ: Если это помогло бы, если бы вы любопытный на мой код, вот (почти) полностью рабочая версия:

library.js - http://mikemccabe.me/tests/pong.archive.14.06.11/library.js

pong.js - http://mikemccabe.me/tests/pong.archive.14.06.11/pong.js

Попробуйте - из http://mikemccabe.me/tests/pong.archive.14.06.11/

Ответы [ 4 ]

1 голос
/ 16 июня 2011

Я не вижу проблемы с использованием вами контекста.Для достижения цели проектирования, позволяющей сделать рендеринг независимым от технологии, необходимо написать универсальный интерфейс для необходимых вам методов рендеринга и создать объект, который вместо этого использует context для реализации этого интерфейса.Затем вы можете заменить другую версию этого объекта, например, чтобы он работал в Internet Explorer <9. </p>

В Javascript, я думаю, часто бывает удобно использовать область действия, чтобы позволить объектам в вашем приложении получать доступ к общим ресурсам.непосредственно.Хотя это не совсем хороший ОО дизайн, думайте об этом как о синглтоне.Например:

var Pong = (function() {
   var Graphics, graphics, Ball, ball1, ball2, play;
   Graphics = function() {
      this.context = ...
   };
   graphics = new Graphics();
   Ball = function() {
     // do something with graphics
   };
   ball1 = new Ball();
   ball2 = new Ball();
   // ball1 and ball2 will both be able to access graphics

   play =function() {
       // play the game!
   };
   return {
       play: play
   }
}());

Чтобы обобщить это, вы можете просто заставить объект Graphics иметь методы общего назначения вместо прямого доступа к context и иметь более одной его версии, создавая правильную копиюодин в зависимости от браузера.Нет никаких недостатков по сравнению с явным присвоением graphics обоим ball1 и ball2, кроме пуризма.Достоинства становятся существенными, когда вы имеете дело с сотнями объектов (например, представляющих элементы DOM), а не только с несколькими.

1 голос
/ 15 июня 2011

Не относится к понг, но эта онлайн книга

http://eloquentjavascript.net/chapter8.html

Имеет пример построения маленькой игры. Он немного отличается, но он показывает, как использовать объектно-ориентированные принципы.

Вы можете кодировать вещи разными способами, и с шаблонами проектирования легко пойти немного дальше. Как и во всем, используйте модерацию. Я всегда использовал Nibbles / Snake в качестве своей игры при работе на новом языке.

1 голос
/ 15 июня 2011

Это может быть хорошим примером применения принципов MVC ( model-view-controller ).

У вас может быть модель для отслеживания состояния каждого игрового элемента.Это могут быть такие вещи, как Player, Paddle, Ball и т. Д. Затем у вас могут быть средства визуализации (представления), которые содержат только логику для рисования текущего состояния.Представления могут быть названы как-нибудь как BallCanvasRenderer и PaddleCanvasRenderer.

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

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

Обратите внимание, что этот шаблон также дает вам возможность поддерживать несколько средств визуализации для любоготип модели.У вас также могут быть средства визуализации, которые выводят текст, ASCII-изображение или OpenGL.

1 голос
/ 15 июня 2011

Вы делаете вещи более сложными, чем они того стоят.

Задача выделенного объекта должна быть передана на экран ...

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

Кто или что должен владеть контекстом в этой ситуации?

Ничто не «владеет» контекстом.Или, если хотите, холст владеет контекстом, но я не знаю, почему вы взяли бы контекст и поместили его куда-нибудь;Я ожидал бы, что это будет более запутанным, чем просто передать его.

РЕДАКТИРОВАТЬ: Взглянув на свой код, вы сделали закрытие Pong "собственным" (имейте в виду, что это) контекст, которыйкажется достаточно разумным.Я действительно не понимаю, какие проблемы вы ожидаете с таким подходом.Однако я не согласен с тем, что вы должны передать его в конструктор Ball и т. Д. Я думаю, что гораздо проще передать его различным draw() методам.

...