/** * THIS IS CREATED BY tom_mai78101. PLEASE GIVE CREDIT FOR WORKING ON A CLONE. * * ALL WORKS COPYRIGHTED TO The Pokémon Company and Nintendo. I REPEAT, THIS IS A CLONE. * * YOU MAY NOT SELL COMMERCIALLY, OR YOU WILL BE PROSECUTED BY The Pokémon Company AND Nintendo. * * THE CREATOR IS NOT LIABLE FOR ANY DAMAGES DONE. FOLLOW LOCAL LAWS, BE RESPECTFUL, AND HAVE A GOOD DAY! * */ package main; import item.ActionItem; import java.awt.Graphics; import java.util.ArrayList; import java.util.List; import java.util.Map; import level.OverWorld; import level.WorldConstants; import resources.Mod; import saving.GameSave; import screen.BaseScreen; import submenu.Save; import abstracts.SubMenu; import abstracts.World; import dialogue.StartMenu; import entity.Player; public class Game { private static final String SAVE_FILE_NAME = "data.sav"; private final BaseScreen screen; private final List<World> worlds; private StartMenu startMenu; private SubMenu subMenu; private World overworld; private final Player player; private ActionItem registeredItem; public enum State { GAME, PAUSED, INVENTORY, SAVE }; private State state; /** * Creates the core component of the game. * * All future game components are to be placed here. * * @param BaseScreen * Takes in a BaseScreen that displays all rendered graphics to the screen. * @param Keys * Takes the Keys object the input handler receives from the player for the game to handle. The input handler must control this Keys object. * @see BaseScreen * @see NewInputHandler * */ public Game(MainComponent main, Keys input) { Mod.loadModdedResources(); WorldConstants.checkForMods(); this.screen = main.getBaseScreen(); this.player = new Player(input); this.player.setCenterCamPosition(this.screen); this.overworld = new OverWorld(player, this); this.worlds = new ArrayList<World>(); this.worlds.add(this.overworld); this.startMenu = new StartMenu(this).initialize(); this.subMenu = null; this.state = State.GAME; GameSave.load(this, SAVE_FILE_NAME); this.screen.reload(); this.player.reload(); } /** * Handles rendered objects. * * <p> * All render() methods must be placed in here to render to the screen. * * <p> * Methods placed in here are to be separated by game states, and depending on the game states, they are to be called when necessary. * * @return Nothing. * */ public void render(Graphics graphics) { switch (this.state) { case GAME: { screen.clear(0xA4E767); overworld.render(screen, player.getX(), player.getY()); break; } case INVENTORY: { if (screen.getRenderingEffectTick() < (byte) 0x7) { screen.flashing(); } else { if (this.subMenu.equals(this.startMenu.getInventory())) this.subMenu = this.startMenu.getInventory(); else this.subMenu = this.startMenu.getSubMenu(); if (this.subMenu != null) { this.subMenu.render(screen, graphics); } } break; } case PAUSED: { if (screen.getRenderingEffectTick() < (byte) 0x7) { screen.flashing(); } else { screen.clear(0xA4E767); overworld.render(screen, player.getX(), player.getY()); if (startMenu.isActivated()) { startMenu.render(screen, graphics); } } break; } case SAVE: { screen.clear(0xA4E767); overworld.render(screen, player.getX(), player.getY()); if (this.subMenu != null) { this.subMenu.render(screen, graphics); } break; } } graphics.drawImage(MainComponent.createCompatibleBufferedImage(screen.getBufferedImage()), 0, 0, MainComponent.COMPONENT_WIDTH, MainComponent.COMPONENT_HEIGHT, null); } /** * Updates the game. * * All tick() methods must be placed in here, in order to correctly update the game. * * @return Nothing. * */ public void tick() { // Debugging purposes if (this.player.keys.F1.keyStateDown && !(this.player.keys.F1.lastKeyState)) { this.player.keys.F1.lastKeyState = true; Mod.resetLoading(); this.load(); } // End debugging purposes switch (this.state) { case GAME: { overworld.tick(); checkPausing(); break; } case INVENTORY: { if (!this.subMenu.isActivated()) { this.state = State.PAUSED; screen.setRenderingEffectTick((byte) 0x0); break; } this.subMenu = this.startMenu.getSubMenu(); if (!this.subMenu.isActivated()) this.subMenu.enableSubMenu(); this.subMenu.tick(); break; } case PAUSED: { if (startMenu.isActivated()) startMenu.tick(); else startMenu.openMenu(); checkUnpausing(); if (startMenu.isActionEventAvailable()) handleActionEvent(startMenu.getActionEvent()); break; } case SAVE: { if (!this.subMenu.isActivated()) { final Save saveSubMenu = (Save) this.subMenu; if (saveSubMenu.getState() == Save.State.SAVED || saveSubMenu.getState() == Save.State.ERROR) { saveSubMenu.setState(Save.State.ASK); this.startMenu.closeMenu(); this.state = State.GAME; break; } this.state = State.PAUSED; break; } if (this.subMenu != null) { this.subMenu.tick(); } break; } } } /** * Saves the game. * */ public void save() { GameSave.save(this, SAVE_FILE_NAME); } /** * Checks for any previous saved data. * * @return True, if it detects previous saved data. False, otherwise. * */ public boolean checkSaveData() { return GameSave.check(SAVE_FILE_NAME); } /** * <p>Loads the game.</p> * * <p>Currently used for debugging purposes only. Press F1 to re-load.</p> * */ private void load() { // TODO: Load data. this.screen.reload(); Mod.loadModdedResources(); if (WorldConstants.isModsEnabled == null) WorldConstants.isModsEnabled = Boolean.FALSE; player.reload(); this.overworld = new OverWorld(player, this); this.state = State.GAME; GameSave.load(this, SAVE_FILE_NAME); } /** * Currently unused. * */ public void setScrollOffset(int xCamCenter, int yCamCenter) { // CamCenter: the coordinates of the center of camera. // this.xScroll = xCamCenter; // this.yScroll = yCamCenter; } /** * Currently unused. However, this is executed in the render() code. * */ public void setCameraRelativeToArea(int areaXPos, int areaYPos) { // Not used at the moment. // cam(x,y) = area(cam.x * -1 + xConstantOffset, cam.y * -1 + yConstantOffset) // this.xCamera = (-areaXPos + this.xScroll) / Tile.WIDTH; // this.yCamera = (-areaYPos + this.yScroll) / Tile.HEIGHT; } public Player getPlayer() { return this.player; } public StartMenu getStartMenu() { return this.startMenu; } public void setState(State state) { this.state = state; } public BaseScreen getBaseScreen() { return this.screen; } public void setRegisteredItem(ActionItem item) { this.registeredItem = item; // TODO: Continue to handle registered item's action event. } public boolean itemHasBeenRegistered(ActionItem item) { if (this.registeredItem == null) return false; return this.registeredItem.equals(item); } public World getWorld() { return this.overworld; } // ---------------------------------------------- PRIVATE METHODS ------------------------------------------------- private void handleActionEvent(Map.Entry<Integer, SubMenu> entry) { String str = entry.getValue().getName(); if (str.equals(StartMenu.ITEM_NAME_INVENTORY)) { if (this.state != State.INVENTORY) this.state = State.INVENTORY; this.subMenu = entry.getValue(); if (!this.subMenu.isActivated()) this.subMenu.enableSubMenu(); screen.setRenderingEffectTick((byte) 0x0); } else if (str.equals(StartMenu.ITEM_NAME_EXIT)) { if (this.state != State.GAME) this.state = State.GAME; if (this.subMenu != null) this.subMenu.disableSubMenu(); this.subMenu = null; } else if (str.equals(StartMenu.ITEM_NAME_SAVE)) { if (this.state != State.SAVE) this.state = State.SAVE; this.subMenu = entry.getValue(); if (!this.subMenu.isActivated()) this.subMenu.enableSubMenu(); } this.startMenu.clearActionEvent(); this.startMenu.closeMenu(); } private void checkPausing() { Keys keys = this.player.keys; if (!keys.START.lastKeyState && keys.START.keyStateDown) { switch (this.state) { case GAME: if (this.player.isLockedWalking() || this.player.isLockedJumping()) { break; } this.state = State.PAUSED; if (!this.startMenu.isActivated()) this.startMenu.openMenu(); if (!Player.isMovementsLocked()) Player.lockMovements(); break; default: break; } keys.START.lastKeyState = true; } } private void checkUnpausing() { Keys keys = this.player.keys; switch (this.state) { case PAUSED: if ((!keys.START.lastKeyState && keys.START.keyStateDown) || ((keys.X.keyStateDown || keys.PERIOD.keyStateDown) && (!keys.X.lastKeyState || !keys.PERIOD.lastKeyState))) { this.state = State.GAME; if (Player.isMovementsLocked()) Player.unlockMovements(); keys.START.lastKeyState = true; } break; default: break; } } }