io.piotrjastrzebski.sfg.screen.CustomDifficultyScreen.java Source code

Java tutorial

Introduction

Here is the source code for io.piotrjastrzebski.sfg.screen.CustomDifficultyScreen.java

Source

/*
 * Super Flying Gentlemen
 * Copyright (C) 2014  Piotr Jastrzbski <me@piotrjastrzebski.io>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package io.piotrjastrzebski.sfg.screen;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Stack;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.ArrayMap;

import io.piotrjastrzebski.sfg.game.objects.Background;
import io.piotrjastrzebski.sfg.screen.inputhandlers.CustomDifficultyInputHandler;
import io.piotrjastrzebski.sfg.utils.Assets;
import io.piotrjastrzebski.sfg.utils.ClampedRangeFloat;
import io.piotrjastrzebski.sfg.utils.ClampedRangeInt;
import io.piotrjastrzebski.sfg.utils.ClampedValueFloat;
import io.piotrjastrzebski.sfg.utils.ClampedValueInt;
import io.piotrjastrzebski.sfg.utils.Config;
import io.piotrjastrzebski.sfg.utils.ConfigData;
import io.piotrjastrzebski.sfg.utils.Locator;

public class CustomDifficultyScreen extends DefaultScreen {
    private final Background background;

    public CustomDifficultyScreen() {
        super();
        Gdx.input.setInputProcessor(new CustomDifficultyInputHandler(this).getIM());
        Gdx.input.setCatchBackKey(true);
        background = new Background();
        initUI();
    }

    private void initUI() {
        Table root = new Table();
        root.setFillParent(true);
        final Label screenLabel = new Label(assets.getText(Assets.CUSTOM_DIFFICULTY), assets.getSkin(),
                "default-large");
        screenLabel.setAlignment(Align.center);
        root.add(screenLabel).pad(10).top().expandX();
        root.row();
        root.add(createTabs()).expand().fill();
        root.row();
        TextButton back = new TextButton(assets.getText(Assets.BACK), assets.getSkin(), "small");
        back.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                handleBack();
                playButtonPressSound();
            }
        });
        TextButton go = new TextButton(assets.getText(Assets.START_GAME), assets.getSkin(), "small");
        go.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                newGame(currentTab.getDifficulty());
                playButtonPressSound();
            }
        });
        final Table bottomContainer = new Table();
        bottomContainer.add(back);
        bottomContainer.add().expandX();
        bottomContainer.add(go);
        root.add(bottomContainer).pad(20).bottom().expandX().fillX();
        stage.addActor(root);
    }

    private Stack stack;
    private ButtonGroup buttonGroup;
    private Table buttons;
    private ArrayMap<String, Tab> tabs;
    private Tab currentTab;
    private final static String TAB_1 = "1";
    private final static String TAB_2 = "2";
    private final static String TAB_3 = "3";

    private Table createTabs() {
        buttons = new Table();
        buttonGroup = new ButtonGroup();
        stack = new Stack();
        tabs = new ArrayMap<String, Tab>();

        addTab(TAB_1, Config.Difficulty.CUSTOM_1);
        addTab(TAB_2, Config.Difficulty.CUSTOM_2);
        addTab(TAB_3, Config.Difficulty.CUSTOM_3);
        showTab(TAB_1);

        final Table table = new Table();
        table.add(buttons).pad(0, 10, 10, 10);
        table.row();
        final ScrollPane scrollPane = new ScrollPane(stack);
        // so sliders sort of work
        scrollPane.setCancelTouchFocus(false);
        scrollPane.setScrollingDisabled(true, false);
        table.add(scrollPane).expand().fill();
        //        table.debug();
        return table;
    }

    private void addTab(final String name, Config.Difficulty difficulty) {
        final TextButton buttonTab = new TextButton(name, assets.getSkin(), "toggle-small");
        final Tab tab = new Tab(difficulty);
        buttonTab.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event, float x, float y) {
                super.clicked(event, x, y);
                showTab(name);
                currentTab = tab;
            }
        });
        buttonGroup.add(buttonTab);
        buttons.add(buttonTab).pad(10);
        stack.add(tab);
        tabs.put(name, tab);
    }

    private void showTab(String tab) {
        if (currentTab != null)
            currentTab.setVisible(false);
        currentTab = tabs.get(tab);
        currentTab.setVisible(true);
    }

    private void newGame(Config.Difficulty difficulty) {
        Locator.getConfig().setDifficulty(difficulty);
        Locator.getConfig().saveCustomConfigs();
        Locator.getApp().setScreen(new GameScreen());
    }

    @Override
    public void draw() {
        super.draw();
        background.draw(batch);
        stage.draw();
        Table.drawDebug(stage);
    }

    @Override
    public void resize(int width, int height) {
        super.resize(width, height);
        background.updateViewport(width, height);
    }

    @Override
    public void update(float delta) {
        super.update(delta);
        background.update(delta);
    }

    public void handleBack() {
        Locator.getApp().setScreen(new DifficultySelectScreen());
    }

    public void handleEnter() {
        newGame(Config.Difficulty.CUSTOM_1);
    }

    InputListener stopTouchDown = new InputListener() {
        public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
            event.stop();
            return false;
        }
    };

    public Table createIntValueContainer(Skin skin, String text, final ClampedValueInt value) {
        final Table topContainer = new Table();
        final Table container = new Table();
        final Label nameLabel = new Label(assets.getText(text), skin);
        final Label valueLabel = new Label("0", assets.getSkin());

        final Slider slider = new Slider(value.min(), value.max(), value.step(), false, skin);
        slider.setValue(value.value());
        valueLabel.setText(String.valueOf((int) slider.getValue()));

        slider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                final int val = (int) slider.getValue();
                value.set(val);
                valueLabel.setText(String.valueOf(val));
            }
        });
        slider.addListener(stopTouchDown);

        container.add(nameLabel);
        container.add().expandX();
        container.add(valueLabel);
        topContainer.add(container).expandX().fillX().pad(10);
        topContainer.row();
        topContainer.add(slider).expandX().fillX().pad(10);
        return topContainer;
    }

    public Table createFloatValueContainer(Skin skin, String text, final ClampedValueFloat value) {
        final Table topContainer = new Table();
        final Table container = new Table();
        final Label nameLabel = new Label(assets.getText(text), skin);
        final Label valueLabel = new Label("0", assets.getSkin());
        final Slider slider = new Slider(value.min(), value.max(), value.step(), false, skin);
        slider.setValue(value.value());
        valueLabel.setText(String.format("%.2f", slider.getValue()));

        slider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                value.set(slider.getValue());
                valueLabel.setText(String.format("%.2f", slider.getValue()));
            }
        });
        slider.addListener(stopTouchDown);

        container.add(nameLabel);
        container.add().expandX();
        container.add(valueLabel);
        topContainer.add(container).expandX().fillX().pad(10);
        topContainer.row();
        topContainer.add(slider).expandX().fillX().pad(10);
        return topContainer;
    }

    private Table createIntRangeContainer(final ClampedRangeInt range, Skin skin, String labelMin,
            String labelMax) {
        final Table container = new Table();

        final Table topContainer = new Table();
        final Label minLabel = new Label(assets.getText(labelMin), skin);
        final Label valueMinLabel = new Label("0", assets.getSkin());
        final Slider minSlider = new Slider(range.min(), range.max(), range.step(), false, skin);
        minSlider.setValue(range.low());

        final Slider maxSlider = new Slider(range.min(), range.max(), range.step(), false, skin);
        maxSlider.setValue(range.high());

        valueMinLabel.setText(String.valueOf(range.low()));

        minSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                range.low((int) minSlider.getValue());
                valueMinLabel.setText(String.valueOf((int) minSlider.getValue()));
                if (maxSlider.getValue() < range.low()) {
                    maxSlider.setValue(range.low());
                }
            }
        });
        minSlider.addListener(stopTouchDown);

        topContainer.add(minLabel);
        topContainer.add().expandX();
        topContainer.add(valueMinLabel);
        container.add(topContainer).expandX().fillX().pad(10);
        container.row();
        container.add(minSlider).expandX().fillX().pad(10);
        container.row();

        final Table botContainer = new Table();
        final Label maxLabel = new Label(assets.getText(labelMax), skin);
        final Label valueMaxLabel = new Label("0", assets.getSkin());

        valueMaxLabel.setText(String.valueOf(range.high()));

        maxSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                range.high((int) maxSlider.getValue());
                valueMaxLabel.setText(String.valueOf((int) maxSlider.getValue()));
                if (minSlider.getValue() > range.high()) {
                    minSlider.setValue(range.high());
                }
            }
        });
        maxSlider.addListener(stopTouchDown);

        botContainer.add(maxLabel);
        botContainer.add().expandX();
        botContainer.add(valueMaxLabel);
        container.add(botContainer).expandX().fillX().pad(10);
        container.row();
        container.add(maxSlider).expandX().fillX().pad(10);

        return container;
    }

    private Table createFloatRangeContainer(final ClampedRangeFloat range, Skin skin, String labelMin,
            String labelMax) {
        final Table container = new Table();

        final Table topContainer = new Table();
        final Label minLabel = new Label(assets.getText(labelMin), skin);
        final Label valueMinLabel = new Label("0", assets.getSkin());
        final Slider minSlider = new Slider(range.min(), range.max(), range.step(), false, skin);
        minSlider.setValue(range.low());

        final Slider maxSlider = new Slider(range.min(), range.max(), range.step(), false, skin);
        maxSlider.setValue(range.high());

        valueMinLabel.setText(String.format("%.2f", range.low()));

        minSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                range.low(minSlider.getValue());
                valueMinLabel.setText(String.format("%.2f", minSlider.getValue()));
                if (maxSlider.getValue() < range.low()) {
                    maxSlider.setValue(range.low());
                }
            }
        });
        minSlider.addListener(stopTouchDown);

        topContainer.add(minLabel);
        topContainer.add().expandX();
        topContainer.add(valueMinLabel);
        container.add(topContainer).expandX().fillX().pad(10);
        container.row();
        container.add(minSlider).expandX().fillX().pad(10);
        container.row();

        final Table botContainer = new Table();
        final Label maxLabel = new Label(assets.getText(labelMax), skin);
        final Label valueMaxLabel = new Label("0", assets.getSkin());
        valueMaxLabel.setText(String.format("%.2f", range.high()));

        maxSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                range.high(maxSlider.getValue());
                valueMaxLabel.setText(String.format("%.2f", maxSlider.getValue()));
                if (minSlider.getValue() > range.high()) {
                    minSlider.setValue(range.high());
                }
            }
        });
        maxSlider.addListener(stopTouchDown);

        botContainer.add(maxLabel);
        botContainer.add().expandX();
        botContainer.add(valueMaxLabel);
        container.add(botContainer).expandX().fillX().pad(10);
        container.row();
        container.add(maxSlider).expandX().fillX().pad(10);

        return container;
    }

    private class Tab extends Table {
        private ConfigData configData;
        private Skin skin;
        private Config config;
        private ButtonGroup group;
        private Table buttons;

        public Tab(Config.Difficulty difficulty) {
            super();
            config = Locator.getConfig();
            configData = config.getConfigData(difficulty);
            skin = assets.getSkin();
            initUI();
        }

        private void initUI() {
            setVisible(false);
            createSelectBase();
            initSliders();
        }

        private void reInitSliders() {
            // suboptimal since we create all the things from scratch
            clearChildren();
            add(buttons).expandX().fillX().pad(20);
            row();
            initSliders();
        }

        private void initSliders() {
            createPickupSettings();
            createObstacleSettings();
            createPlayerSettings();
            createWorldSettings();
        }

        private TextButton createTB(String text, final Config.Difficulty difficulty) {
            final TextButton button = new TextButton(assets.getText(text), skin, "toggle-small");
            button.addListener(new ClickListener() {
                @Override
                public void clicked(InputEvent event, float x, float y) {
                    final Dialog dialog = new Dialog("", skin) {
                        @Override
                        protected void result(Object object) {
                            if (object.equals("YES")) {
                                config.setCustomBase(configData.getDifficulty(), difficulty);
                                reInitSliders();
                            }
                            setCheckedButton();
                        }
                    };
                    dialog.getButtonTable().defaults().pad(20);
                    dialog.getContentTable().defaults().pad(20);
                    dialog.text(assets.getText(Assets.RESET_DIFFICULTY));
                    final TextButton.TextButtonStyle style = skin.get("small", TextButton.TextButtonStyle.class);
                    dialog.button(assets.getText(Assets.OK), "YES", style);
                    dialog.button(assets.getText(Assets.CANCEL), "NO", style);
                    dialog.show(stage);
                }
            });
            if (configData.getBaseDifficulty().equals(difficulty)) {
                button.setChecked(true);
            }
            group.add(button);
            return button;
        }

        private void setCheckedButton() {
            switch (configData.getBaseDifficulty()) {
            case BRUTAL:
                group.setChecked(assets.getText(Assets.DIFFICULTY_BRUTAL));
                break;
            case VERY_HARD:
                group.setChecked(assets.getText(Assets.DIFFICULTY_VERY_HARD));
                break;
            case HARD:
                group.setChecked(assets.getText(Assets.DIFFICULTY_HARD));
                break;
            }
        }

        private void createSelectBase() {
            buttons = new Table();
            final Label sectionLabel = new Label(assets.getText(Assets.CUSTOM_BASE_SELECT), skin);
            buttons.add(sectionLabel).colspan(3).pad(0, 10, 10, 10);
            buttons.row();
            group = new ButtonGroup();

            buttons.add(createTB(Assets.DIFFICULTY_BRUTAL, Config.Difficulty.BRUTAL)).pad(10);
            buttons.add(createTB(Assets.DIFFICULTY_VERY_HARD, Config.Difficulty.VERY_HARD)).pad(10);
            buttons.add(createTB(Assets.DIFFICULTY_HARD, Config.Difficulty.HARD)).pad(10);

            add(buttons).expandX().fillX().pad(20);
            row();
        }

        private void createPickupSettings() {
            final Table container = new Table();
            final Label sectionLabel = new Label(assets.getText(Assets.PICKUP_SETTINGS), skin);
            container.add(sectionLabel);
            container.row();

            final Table pickupSpawnDist = createIntValueContainer(skin, Assets.PICKUP_SPAWN_DISTANCE,
                    configData.getPickupMinSpawnDistance());
            container.add(pickupSpawnDist).expandX().fillX();
            container.row();

            final Table pickupSpawnChance = createFloatValueContainer(skin, Assets.PICKUP_SPAWN_CHANCE,
                    configData.getPickupSpawnChance());
            container.add(pickupSpawnChance).expandX().fillX();
            container.row();

            container.add(createIntRangeContainer(configData.getPickupLives(), skin, Assets.PICKUP_LIVES_MIN,
                    Assets.PICKUP_LIVES_MAX)).expandX().fillX();
            container.row();

            container.add(createIntRangeContainer(configData.getPickupShield(), skin, Assets.PICKUP_SHIELDS_MIN,
                    Assets.PICKUP_SHIELDS_MAX)).expandX().fillX();
            container.row();

            container.add(createIntRangeContainer(configData.getPickupBoost(), skin, Assets.PICKUP_BOOST_MIN,
                    Assets.PICKUP_BOOST_MAX)).expandX().fillX();
            container.row();

            container.add(createIntRangeContainer(configData.getPickupToxic(), skin, Assets.PICKUP_TOXIC_MIN,
                    Assets.PICKUP_TOXIC_MAX)).expandX().fillX();
            container.row();

            add(container).expandX().fillX().pad(20);
            row();
        }

        private void createObstacleSettings() {
            final Table container = new Table();
            final Label sectionLabel = new Label(assets.getText(Assets.OBSTACLE_SETTINGS), skin);
            container.add(sectionLabel);
            container.row();
            container.add(createFloatRangeContainer(configData.getObstacleDistance(), skin,
                    Assets.OBSTACLE_DISTANCE_MIN, Assets.OBSTACLE_DISTANCE_MAX)).expandX().fillX();
            container.row();

            container.add(createFloatRangeContainer(configData.getObstacleGapSize(), skin, Assets.OBSTACLE_GAP_MIN,
                    Assets.OBSTACLE_GAP_MAX)).expandX().fillX();
            container.row();

            add(container).expandX().fillX().pad(20);
            row();
        }

        private void createPlayerSettings() {
            final Table container = new Table();
            final Label sectionLabel = new Label(assets.getText(Assets.PLAYER_SETTINGS), skin);
            container.add(sectionLabel);
            container.row();

            final Table initLives = createIntValueContainer(skin, Assets.PLAYER_INIT_LIVES,
                    configData.getPlayerInitLives());
            container.add(initLives).expandX().fillX();
            container.row();

            final Table initShields = createIntValueContainer(skin, Assets.PLAYER_INIT_SHIELDS,
                    configData.getPlayerInitShields());
            container.add(initShields).expandX().fillX();
            container.row();

            final Table centreOffset = createFloatValueContainer(skin, Assets.PLAYER_CENTRE_OFFSET,
                    configData.getPlayerCentreOffset());
            container.add(centreOffset).expandX().fillX();
            container.row();

            final Table scale = createFloatValueContainer(skin, Assets.PLAYER_SCALE, configData.getPlayerScale());
            container.add(scale).expandX().fillX();
            container.row();

            final Label warningLabel = new Label(assets.getText(Assets.CUSTOM_WARNING), skin);
            container.add(warningLabel).pad(20);
            container.row();

            final Table jumpImpulse = createFloatValueContainer(skin, Assets.PLAYER_JUMP_IMPULSE,
                    configData.getPlayerJumpImpulse());
            container.add(jumpImpulse).expandX().fillX();
            container.row();

            final Table flySpeed = createFloatValueContainer(skin, Assets.PLAYER_FLY_SPEED,
                    configData.getPlayerFlySpeed());
            container.add(flySpeed).expandX().fillX();
            container.row();

            final Table flyMaxSpeed = createFloatValueContainer(skin, Assets.PLAYER_FLY_MAX_SPEED,
                    configData.getPlayerFlyMaxSpeed());
            container.add(flyMaxSpeed).expandX().fillX();
            container.row();

            final Table flyImpulse = createFloatValueContainer(skin, Assets.PLAYER_FLY_IMPULSE,
                    configData.getPlayerFlyImpulse());
            container.add(flyImpulse).expandX().fillX();
            container.row();

            final Table dashImpulse = createFloatValueContainer(skin, Assets.PLAYER_DASH_IMPULSE,
                    configData.getPlayerDashImpulse());
            container.add(dashImpulse).expandX().fillX();
            container.row();

            final Table dashDelay = createFloatValueContainer(skin, Assets.PLAYER_DASH_DELAY,
                    configData.getPlayerDashDelay());
            container.add(dashDelay).expandX().fillX();
            container.row();

            final Table dashTime = createFloatValueContainer(skin, Assets.PLAYER_DASH_TIME,
                    configData.getPlayerDashTime());
            container.add(dashTime).expandX().fillX();
            container.row();

            add(container).expandX().fillX().pad(20);
            row();
        }

        private void createWorldSettings() {
            final Table container = new Table();
            final Label sectionLabel = new Label(assets.getText(Assets.WORLD_SETTINGS), skin);
            container.add(sectionLabel);
            container.row();

            final Table gravity = createFloatValueContainer(skin, Assets.GRAVITY, configData.getGravity());
            container.add(gravity).expandX().fillX();
            container.row();

            add(container).expandX().fillX().pad(20);
            row();
        }

        public Config.Difficulty getDifficulty() {
            return configData.getDifficulty();
        }
    }
}