2014-07-03 3 views
3

Я разрабатываю игру для компании. Я буду развивать эту игру только 2 месяца. Моя компания просит меня сделать мой код чистым и расширяемым, чтобы они могли нанять другого программиста, когда им нужно добавить дополнительные функции. Я прочитал «Чистый код» дяди Боба. Мне было очень сложно воплотить концепцию на практике. Это один из моего классаДизайн классов в программировании игр

public class MenuScreen extends ScreenAdapter { 

private final Game game; 

private Stage stage; 
private Actor groundActor; 
private Actor skyActor; 
private Actor titleActor; 
private Actor playbtnActor; 
private Actor optionbtnActor; 

public MenuScreen(Game _game) { 
    this.game = _game; 
} 

@Override 
public void show() { 

    this.stage = new Stage(new ScreenViewport()); 

    createGround(); 
    createSky(); 
    createTitle(); 
    createPlayButton(); 
    createOptionButton(); 
    setupStage(); 

    Gdx.input.setInputProcessor(this.stage); 

} 

public void createGround() { 
    TextureRegion groundTextureRegion = Assets.instance 
      .getTextureRegionByName("bg-ground"); 
    this.groundActor = new SRActor(groundTextureRegion); 
    this.groundActor.setPosition(0, 0); 
} 

public void createSky() { 
    TextureRegion skyTextureRegion = Assets.instance 
      .getTextureRegionByName("bg-sky"); 
    this.skyActor = new SRActor(skyTextureRegion); 
    this.skyActor.setPosition(0, 0); 
} 

public void createTitle() { 
    TextureRegion titleTextureRegion = 
      Assets.instance.getTextureRegionByName("etc-gametitlebanner"); 
    this.titleActor = new SRActor(titleTextureRegion); 

    int bottomLeftX = (int) ((Gdx.graphics.getWidth() - this.titleActor 
      .getWidth())/2); 
    int bottomLeftY = (int) Math.floor(0.6 * this.groundActor.getHeight()); 
    this.titleActor.setPosition(bottomLeftX, bottomLeftY); 
} 

public void createPlayButton() { 

    TextureRegion playbtnTextureRegion = 
      Assets.instance.getTextureRegionByName("etc-playbtn"); 
    this.playbtnActor = new SRActor(playbtnTextureRegion); 

    int bottomLeftX = (int) (0.01 * this.playbtnActor.getWidth()) 
      + (Gdx.graphics.getWidth() - (int) this.playbtnActor.getWidth()) 
      /2; 
    int bottomLeftY = (int) (this.titleActor.getY() + 0.25 * this.titleActor 
      .getHeight()); 
    this.playbtnActor.setPosition(bottomLeftX, bottomLeftY); 
} 

public void createOptionButton() { 
    TextureRegion optionbtnTextureRegion = Assets.instance 
      .getTextureRegionByName("etc-optionbtn"); 
    this.optionbtnActor = new SRActor(optionbtnTextureRegion); 

    int bottomLeftX = (int) (0.01 * this.optionbtnActor.getWidth()) 
      + (Gdx.graphics.getWidth() - (int) this.optionbtnActor 
        .getWidth())/2; 
    int bottomLeftY = (int) (this.titleActor.getY() + 0.05 * this.titleActor 
      .getHeight()); 
    this.optionbtnActor.setPosition(bottomLeftX, bottomLeftY); 

} 

public void setupStage() { 

    this.stage.addActor(this.skyActor); 
    this.stage.addActor(this.groundActor); 
    this.stage.addActor(this.titleActor); 
    this.stage.addActor(this.playbtnActor); 
    this.stage.addActor(this.optionbtnActor); 

} 

@Override 
public void render(float delta) { 
    this.stage.act(Gdx.graphics.getDeltaTime()); 
    this.stage.draw(); 
} 

@Override 
public void resize(int width, int height) { 
    this.stage.getViewport().update(width, height, true); 
} 

@Override 
public void hide() { 
    dispose(); 
} 

@Override 
public void dispose() { 
    this.stage.dispose(); 
} 

}

Мой вопрос делает этот класс нарушает Single Ответственность Принцип? Нужно ли разделять каждого актера на свой класс? И если да, то как мне реорганизовать мой код?

+0

Есть много рамок игры, которые существуют (JGame хорошо для 2d игр). Попытка дизайна для «расширяемости» в первый раз очень тяжелая - боссы просят об этом, но пока вам действительно не нужно расширяться, и вы знаете, каким образом вы, вероятно, совершаете ошибку и тратите свои усилия. Сначала я предлагаю вам взглянуть на существующие рамки. – Fuhrmanator

ответ

1

Это похоже на меня. Если все ваши разные актеры имеют одинаковое поведение и отличаются только от используемой текстуры, размера, положения и т. Д., То наличие одного SRActor с разными атрибутами кажется подходящим.

Однако я бы посоветовал вам использовать статический заводский шаблон и переместить поколение в другой класс. Таким образом, вы бы сделали только stage.addActor(SRActorFactory.createOptionButton()).

+0

Спасибо за ваш ответ. Я нашел ваш ответ действительно полезным. Что делать, если у меня есть другой экран, который использует тот же фон, что и этот? Мне нужна отдельная фабрика или просто придерживаться одной фабрики. Например, у меня есть MenuObjectFactory, который создает вышеупомянутых актеров, и у меня есть еще одна фабрика «OptionObjectFactory», которая создает одно и то же основание, небо и какой-то отдельный актер, такой как volumeSlider? – kevinyu

+1

Это зависит от того, как сгруппированы создаваемые вами актеры. У вас должен быть Factory для группы вещей, которые принадлежат друг другу, как и все кнопки в вашем главном меню. Но вы здесь довольно свободны, и вы можете также положить все эти статические заводские методы в единую фабрику и использовать ее везде. Если вы можете повторно использовать эти заводы на разных экранах, еще лучше. Всегда старайтесь избегать дублирования кода. – noone

1

Предполагая, что на экране меню есть небо и земля (т. Е. Этот материал не входит в игру), то пока все хорошо. Похоже, у вас есть актеры в отдельных классах, что хорошо. «MenuScreen» - это то, что имеет смысл как отдельная ответственность.

+0

Просто любопытно, не было бы неплохо сохранить createGround в отдельном наземном объекте? то же самое касается Sky, Title и размещения связанных методов в соответствующих классах, Afa MenuScreen касается этого класса, должен быть метод построения, который будет строить экран, и метод show отобразит его? –

+0

Проводя это, чтобы узнать больше о моем мышлении у опытного программиста. :) :) :) –

+2

Это вопрос относительной важности объектов. Если он просто рисует небо и землю на экране меню, то, вероятно, этого недостаточно, чтобы оправдать различные классы. Фактически, в этом случае я просто возьму изображение и нарисую его. Но если объекты имеют специальную логику воспроизведения (например,, у неба есть логика для оживления облаков), тогда да, ваше предложение было бы вполне уместным. –

1

Я работал с libgdx и работал над довольно большой игрой с группой людей. То, что я нашел особенно полезным, - это разделение отображаемых компонентов. Например, у меня есть отдельный класс пользовательского интерфейса для статических элементов. Затем введите класс рендеринга, который содержит все динамические компоненты.

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

(входные мультиплексоры - хорошая вещь для изучения).

Однако, просто сделайте некоторые настройки в своем коде прямо сейчас, почему бы вам не создать отдельный класс «рендеринга» для вашего меню? Просто инициализируйте его сценой, затем добавьте к нему актеров. Это позволит вам добавлять анимационные последовательности без раздувания вашего класса MenuScreen. Сделайте так, чтобы все, что вам нужно сделать, это сделать MenuUI.render();, тогда он просто работает. Ваш ScreenAdapter должен использоваться для переходов на вашем игровом экране, а не для жесткого кодирования вашего пользовательского интерфейса. Затем, если вы хотите изменить пользовательский интерфейс для вашего экрана меню, вы просто подключите новый модуль пользовательского интерфейса.

Надеется, что это помогает: d

+0

Как это принято? Что бы сделал MenuUI.render()? Вызовите stage.render() ... и для этого вам нужен целый класс? – noone

+0

Извините @noone. Я новичок в stackoverflow. Я думаю, что могу дать контрольный список нескольким ответам. Я думаю, что это хорошая альтернативная идея для GameScreen, где гораздо больше Object, чем MenuScreen. Хотя я предпочитаю создавать класс для каждого объекта для GameScreen – kevinyu

+0

@progenhard Спасибо за ваш ответ. Вы имеете в виду, что MenuUI - это класс, который имеет этап как переменную экземпляра? И все createGround(), createSky() и т. Д. Должны быть вызваны при инициализации MenuUI? – kevinyu

Смежные вопросы