[СТАТЬЯ] Как сделать мини-игру?

HunterGaming

Активный участник
Пользователь
Баллы
96
Имя в Minecraft
sqdFendy
МИНИ-ИГРА

Привет форумчане, думаю все хотят научится писать мини-игры(по крайней мере я хотел, и научился уже на 75%), и писал недавно о том, кто бы создал тему по созданию мини-игры, вот сам я и создаю).

Что же нужно для создания мини-игры? Как минимум знание основ Java, а также Bukkit API.

В этой теме я расскажу и покажу вам основной код мини-игры, логику и эвенты дописать думаю сами сумеете. У нас будет 5 классов:
- Arena(в этом классе мы будем описывать свойства и методы),
- ArenaManager(Менеджер всех арен),
- ArenaState(Статус арены: LOBBY, GAME),
- Utils(Класс с утилитой),
- Main(Главный класс).

Начнем мы с класса Arena:

Java:
package me.hunterplay.spleef.arena;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.*********ventory.ItemStack;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Score;
import org.bukkit.scoreboard.Scoreboard;

import me.hunterplay.spleef.Main;
import me.hunterplay.spleef.config.MessageConfig;
import me.hunterplay.spleef.utils.Utils;

public class Arena extends ArenaManager {

    private Arena arena;

    private String arenaName; //Имя арены
    private List<String> arenaPlayers; //Лист игроков
    private int arenaTimeToStart; //Время до старта игры
    private int arenaTime; //Время игры
    private int arenaMinPlayers; //Минимальное кол-во игроков
    private int arenaMaxPlayers; //Максимальное кол-во игроков
    private ArenaState arenaState; //Статус арены
    private Location arenaSpawnPoint; //Локация, куда будет телепортироваться игрок на игру
    private Location arenaLobby; //Лобби арены
    private Location arenaPos1; //1 позиция арены
    private Location arenaPos2; //2 позиция арены
    private boolean lobbyCountdown; //Булевское значение - таймер лобби
    private boolean arenaCountdown; //Булевское значение - таймер арены
    private int lobbyScheduler; //Шедулер лобби
    private int arenaScheduler; //Шедулер арены

    public Arena(String arenaName) { //Конструктор для создания арены, для того что бы создать арену нужно написать Arena arena = new Arena("Arena1"), но так мы писать не будем, для этого есть отдельный класс ArenaManager, в нем будет метод
        this.arenaName = arenaName;
        arenaPlayers = new ArrayList<String>();
        arenaState = ArenaState.LOBBY;
        arena = this;
    }

    public void addPlayer(String pName) { //Добавление игрока на арену
        Player p = Bukkit.getPlayer(pName); //Создаем объект игрока с именем pName

        if (arenaLobby == null || arenaPos1 == null || arenaPos2 == null) { //Если локации равняются null, то пишем сообщение о том что арена не настроена и выходим из метода
            p.sendMessage("Арена не настроена!");
            return;
        }

        if (arenaIsFull()) { //Если арена заполнена, то пишем сообщение о том что она заполнена и выходим из метода
            p.sendMessage("Арена заполнена!");
            return;
        }

        if (arenaState != ArenaState.LOBBY) { //Если статус арены не лобби, то пишем сообщение о том что арена находится в игре и выходим из метода
            p.sendMessage("Арена находится в игре!");
            return;
        }

        p.getInventory().clear(); //Очищаем весь инвентарь игрока
        p.setHealth(p.getMaxHealth()); //Лечим игрока
        p.setFoodLevel(20); //Кормим игрока
        p.setFireTicks(0); //Тушим игрока от огня
        p.setGameMode(GameMode.SURVIVAL); //Ставим режим выживания
        p.teleport(arenaLobby); //Телепортируем в лобби арены
        arenaPlayers.add(pName); //Добавляем игрока в лист игроков
        sendMessageToArena(p.getName() + " присоединился к игре. Игроков " + arenaPlayers.size() + "/" + arenaMaxPlayers + "."); //Отправляем сообщение всем учащимся арены, о том что присоединился новый игрок

        Scoreboard scoreBoard = Bukkit.getScoreboardManager().getNewScoreboard(); //Создаем скорборд
        Objective objective = scoreBoard.registerNewObjective(arenaName, "dummy"); //Создаем обжектив с именем арены
        objective.setDisplayName("Lobby"); //Указываем тайтл нашего скорборда
        objective.setDisplaySlot(DisplaySlot.SIDEBAR); //Задаем displayslot, чтоб скорборд находился справа экрана
        for (int i = 0; i < 3; i++) { //Цикл для создания пустых ячеек в скорборде, сделано для красоты
            String[] str = { "", " ", "  " };
            Score score = objective.getScore(str[I]);
            score.setScore(i + 1);
        }
        Score messagePlayers = objective.getScore("Игроков " + arenaPlayers.size() + "/" + arenaMaxPlayers); //Показываем кол-во игроков и максимальное кол-во арены в скорборде
        messagePlayers.setScore(0);
        p.setScoreboard(scoreBoard); //Присваиваем скорборд игроку

        if (arenaPlayers.size() >= arenaMinPlayers) { //Если кол-во игроков в листе больше минимального значения, то запускаем таймер
            startCountdown(); //Запуск таймера
        }
    }

    public void startArena() { //Старт арены
        if (arenaCountdown) //Если arenaCountdown = true, то выходим из метода
            return;

        arenaCountdown = true; //Ставим значение true для arenaCountdown

        for (String pName : arenaPlayers) { //Перебираем всех игроков арены
            if (Bukkit.getPlayer(pName) == null) { //Если игрок вышел, то убираем его из листа
                arenaPlayers.remove(pName);
            }

            if (arenaPlayers.size() < arenaMinPlayers) { //Если кол-во игроков меньше чем минимальное, выполняем следующие действия и выходим из метода
                sendMessageToArena("Недостаточно игроков для старта игры!"); //Уведомляем игроков, о том что кол-во игроков меньше чем минимальное кол-во игроков
                Scoreboard scoreBoard = Bukkit.getScoreboardManager().getNewScoreboard(); //Создаем новый скорборд
                Objective objective = scoreBoard.registerNewObjective(arenaName, "dummy"); //Создаем новый обжектив с именем арены
                objective.setDisplayName("Lobby"); //Указываем тайтл нашего скорборда
                objective.setDisplaySlot(DisplaySlot.SIDEBAR); //Задаем displayslot, чтоб скорборд находился справа экрана
                for (int i = 0; i < 3; i++) { //Цикл для создания пустых ячеек в скорборде, сделано для красоты
                    String[] str = { "", " ", "  " };
                    Score score = objective.getScore(str[I]);
                    score.setScore(i + 1);
                }
                Score messagePlayers = objective.getScore("Игроков " + arenaPlayers.size() + "/" + arenaMaxPlayers); //Показываем кол-во игроков и максимальное кол-во арены в скорборде
                messagePlayers.setScore(0);
                Bukkit.getPlayer(pName).setScoreboard(scoreBoard); //Присваиваем скорборд игроку
                return;
            }
        }

        arenaState = ArenaState.GAME; //Задаем статус арены
        arenaCountdown = true; //Задаем arenaCountdown
        sendMessageToArena("Игра началась..."); //Уведомляем всех игроков арены, о том что игра началась

        for (String pName : arenaPlayers) {
            Player p = Bukkit.getPlayer(pName);

            //TODO: если надо выдаем предметы, думаю сделаете сами

            p.teleport(arenaSpawnPoint); //Телепортируем всех игроков арены на локацию арены
        }

        arenaScheduler = Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.getInstance(), new Runnable() { //Создаем шедулер и присваиваем его значение нашей переменной arenaScheduler
            int arenaT = arenaTime; //Время игры

            [USER=79777]@Override[/USER]
            public void run() {
                Scoreboard scoreBoard = Bukkit.getScoreboardManager().getNewScoreboard();
                Objective objective = scoreBoard.registerNewObjective(arenaName, "dummy");
                objective.setDisplayName("Game");
                objective.setDisplaySlot(DisplaySlot.SIDEBAR);
                Score messageToStart = objective.getScore("До конца осталось:");
                messageToStart.setScore(1);
                Score timeToStart = objective.getScore(Utils.getUtils().formatTime(arenaT));
                timeToStart.setScore(0);

                Iterator<String> players = arenaPlayers.iterator(); //Итератор - почти тоже самое, что у оператор for, но только если здесь вы используете for, и начнете чистить список играющих, то у вас вылетит ConcurrentModificationException, поэтому здесь используем Iterator

                while(players.hasNext()) { // Пока у итератора не кончились ячейки
                    Player p = Bukkit.getPlayer(players.next());

                    p.setScoreboard(scoreBoard); //Присваиваем игрокам скорборд
                }

                if (arenaT <= 0) { //Если время меньше или равно 0, то заканчиваем игру
                    endArena(); //Конец игры
                }
                arenaT--;
            }
        }, 20L, 20L);
    }

    public void endArena() { //Конец

        //TODO: если надо, то ресетим площадку арены, либо загружаем схематик
     
        if (arenaPlayers != null) { //Если лист не пустой
            broadcastMessage(arenaPlayers.get(0) + " победил на арене " + arena.getArenaName());
            arenaState = ArenaState.LOBBY;

            Iterator<String> endPlayers = arenaPlayers.iterator();
            while(endPlayers.hasNext()) {
                Player p = Bukkit.getPlayer(endPlayers.next());
                endPlayers.remove();

                if (p != null) {
                    p.teleport(ArenaManager.getArenaManager().getMainLobby()); // Телепортируем игрока главное лобби
                    p.setHealth(p.getMaxHealth());
                    p.setFireTicks(0);
                    p.getInventory().clear();
                }
                stopArenaCountdown(p); //Останавливаем шедулер арены, и ставим стандартный скорборд игроку
            }
        }
    }

    public void startCountdown() { //Старт таймера в лобби
        if (lobbyCountdown) //Если lobbyCountdown = true, выходим из метода
            return;

        lobbyCountdown = true; //Ставим значение true

        lobbyScheduler = Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.getInstance(), new Runnable() { //Создаем шедулер и присваиваем его нашей переменной lobbyScheduler
            int arenaTTS = arenaTimeToStart; //Время до старта игры

            [USER=79777]@Override[/USER]
            public void run() {
                Scoreboard scoreBoard = Bukkit.getScoreboardManager().getNewScoreboard();
                Objective objective = scoreBoard.registerNewObjective(arenaName, "dummy");
                objective.setDisplayName("Lobby");
                objective.setDisplaySlot(DisplaySlot.SIDEBAR);
                Score messageToStart = objective.getScore("До начала осталось:");
                messageToStart.setScore(3);
                Score timeToStart = objective.getScore(Utils.getUtils().formatTime(arenaTTS));
                timeToStart.setScore(2);
                Score none = objective.getScore("");
                none.setScore(1);
                Score players = objective.getScore("Игроков " + arenaPlayers.size() + "/" + arenaMaxPlayers);
                players.setScore(0);

                if (arenaPlayers.size() == 0) { //Если кол-во игроков в листе равно 0, то
                    Bukkit.getScheduler().cancelTask(lobbyScheduler); //Останавливаем шедулер лобби
                    lobbyCountdown = false; //Ставим значение false
                }

                for (String pName : arenaPlayers) {
                    Player p = Bukkit.getPlayer(pName);

                    p.setScoreboard(scoreBoard);

                    if (arenaTTS <= 0) { //Если arenaTTS меньше или равно 0, то
                        stopLobbyCountdown(p); //Останавливаем шедулер лобби и задаем стандартный скорборд
                        startArena(); //Начинаем игру
                    }
                }
                arenaTTS--;
            }
        }, 20L, 20L);
    }

    public void stopLobbyCountdown(Player p) { //Метод для удаления шедура лобби и установки стандартного скорборда
        Bukkit.getScheduler().cancelTask(lobbyScheduler);
        lobbyCountdown = false;
        p.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
    }

    public void stopArenaCountdown(Player p) { //Метод для удалиния шедулера арены и установки стандартного скорборда
        Bukkit.getScheduler().cancelTask(arenaScheduler);
        arenaCountdown = false;
        p.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard());
    }

    public void sendMessageToArena(String msg) { //Отправка сообщения всем игрокам арены
        if (arenaPlayers.size() == 0) {
            return;
        }

        for (String pName : arenaPlayers)
            if (Bukkit.getPlayer(pName) != null)
                Bukkit.getPlayer(pName).sendMessage(msg);
    }
}
 
Последнее редактирование:
А зачем ты тут объявил приватный конструктор если он по дефолту приватный?
Б****, а тебе какое дело, занять пару ячеек памяти не такая большая проблема, не*** придираться к КАЖДОЙ ошибке ТС
 
Б****, а тебе какое дело, занять пару ячеек памяти не такая большая проблема, не*** придираться к КАЖДОЙ ошибке ТС
Чего ты так бомбишь? Зачем засорять код? Давай интерфейс и все методы в нем будем объявлять абстрактными, ну а че?
 
Чего ты так бомбишь? Зачем засорять код? Давай интерфейс и все методы в нем будем объявлять абстрактными, ну а че?
А что по твоему в играх делают сначала оптимизацию и только потом игру или наоборот... КОНСТРУКТИВНЕЕ и лучше будет сначала написать говно, а потом оптимизировать, не обезьяны же!
 
А что по твоему в играх делают сначала оптимизацию и только потом игру или наоборот... КОНСТРУКТИВНЕЕ и лучше будет сначала написать говно, а потом оптимизировать, не обезьяны же!
Если эта статья претендует на руководство новичку (а на другой уровень данная статья не может), то она должна объяснять что происходит в коде, если же руководство содержит архитектурные решения, то необходимо пояснять почему выбор был в пользу данной, а также хотя бы беглое описание других и чем в конкретной ситуации они были плохи(наличие альтернативы важно ).

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

Из конструктивной критики, хотел бы посоветовать автору сначала научиться писать плагины на 100%, прочитать о SOLID принципах и продолжить написание статей с новыми знаниями, опытом, силами и полной логикой.
 
Назад
Верх