zeldaswordskills.client.gui.GuiMusicBase.java Source code

Java tutorial

Introduction

Here is the source code for zeldaswordskills.client.gui.GuiMusicBase.java

Source

/**
Copyright (C) <2015> <coolAlias>
    
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
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 zeldaswordskills.client.gui;

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

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;

import zeldaswordskills.client.RenderHelperQ;
import zeldaswordskills.client.ZSSKeyHandler;
import zeldaswordskills.ref.Config;
import zeldaswordskills.ref.ModInfo;
import zeldaswordskills.songs.AbstractZeldaSong;
import zeldaswordskills.util.SongNote;
import zeldaswordskills.util.SongNote.PlayableNote;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

/**
 * 
 * Basic Zelda music GUI shows notes on the screen as played, leaving it up to
 * child implementations to determine the song played and effects it should have
 *
 */
@SideOnly(Side.CLIENT)
public abstract class GuiMusicBase extends GuiScreen {
    protected final Minecraft mc;

    /** Maximum number of notes that can display on the GUI at any given time */
    protected static final int MAX_NOTES = 8;

    /** Note texture height and width */
    protected static final int NOTE_SIZE = 12;

    /** Y interval between lines */
    protected static final int INT_Y = 5;

    /** The X size of the window in pixels */
    protected int xSize = 213;

    /** The Y size of the window in pixels */
    protected int ySize = 90;

    /** Full width of texture file, in pixels */
    protected int fullX = 256;

    /** Full height of texture file, in pixels */
    protected int fullY = 128;

    /** Starting X position for the Gui */
    protected int guiLeft;

    /** Starting Y position for the Gui */
    protected int guiTop;

    /** Currently playing song, if any */
    protected AbstractZeldaSong song;

    /** Stores the notes played so far */
    protected final List<SongNote> melody = new ArrayList<SongNote>();

    /** Number of ticks since last note played; after a certain threshold, current melody clears */
    protected int ticksSinceLastNote;

    /** Location of the player when the gui is opened, makes it easier to handle packets and such */
    protected final int x, y, z;

    public GuiMusicBase(int x, int y, int z) {
        mc = Minecraft.getMinecraft();
        this.x = x;
        this.y = y;
        this.z = z;
    }

    @Override
    public void initGui() {
        super.initGui();
        guiLeft = (width - xSize) / 2;
        guiTop = (height - ySize) / 2 + 25;
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    protected abstract ResourceLocation getTexture();

    @Override
    public void drawScreen(int mouseX, int mouseY, float f) {
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        mc.getTextureManager().bindTexture(getTexture());
        GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
        GL11.glDisable(GL11.GL_LIGHTING);
        GL11.glEnable(GL11.GL_ALPHA_TEST);
        GL11.glEnable(GL11.GL_BLEND);
        RenderHelperQ.drawTexturedRect(guiLeft, guiTop, 0, 0, xSize, ySize, fullX, fullY);
        GL11.glPopAttrib();
        int i1 = (melody.size() > MAX_NOTES ? ((melody.size() - 1) / MAX_NOTES) * MAX_NOTES : 0);
        for (int i = 0; (i + i1) < melody.size(); ++i) {
            SongNote note = melody.get(i + i1);
            // j is factor of how far down the screen note should be drawn
            int j = SongNote.Note.values().length - (note.note.ordinal() + 1)
                    + (SongNote.Note.values().length * (2 - note.getOctave()));
            int dy = 6 + (INT_Y * j);
            int dx = 46 + (NOTE_SIZE + 8) * i;
            // draw supplementary line(s) under staff and behind note
            if (j > 10) { // j goes from 0-13, not 1-14
                int dy2 = (10 + INT_Y * 11);
                // given the control scheme, this loop is not really necessary as it's not possible to reach the low A note
                for (int n = 0; n < ((j - 9) / 2); ++n) {
                    // each line segment is 16x5 pixels, using first line in .png file at 8,15
                    RenderHelperQ.drawTexturedRect(guiLeft + (dx - 2), guiTop + dy2 + (n * 2 * INT_Y), 8, 15, 16, 5,
                            fullX, fullY);
                }
            }
            RenderHelperQ.drawTexturedRect(guiLeft + dx, guiTop + dy, xSize,
                    PlayableNote.getOrdinalFromNote(note) * NOTE_SIZE, NOTE_SIZE, NOTE_SIZE, fullX, fullY);
            // draw additional sharp / flat if applicable
            if (note.isSharp() || note.isFlat()) {
                RenderHelperQ.drawTexturedRect(guiLeft + dx + NOTE_SIZE - 2, guiTop + dy, xSize + NOTE_SIZE,
                        (note.isSharp() ? 0 : 5), 5, 5, fullX, fullY);
            }
        }
        if (song != null) {
            String s = song.getDisplayName();
            fontRendererObj.drawString(s, guiLeft + (xSize / 2) - (fontRendererObj.getStringWidth(s) / 2),
                    guiTop + 3, 0xFFFFFF);
        }
        super.drawScreen(mouseX, mouseY, f);
    }

    @Override
    public void updateScreen() {
        ++ticksSinceLastNote;
        if (song != null) {
            if (ticksSinceLastNote > song.getMinDuration()) {
                mc.thePlayer.closeScreen();
            }
        } else if (ticksSinceLastNote > Config.getNoteResetInterval()) {
            ticksSinceLastNote = 0;
            melody.clear();
        }
    }

    /**
     * Returning false prevents further key inputs from affecting the notes played,
     * though Esc will still close the GUI; default allows input as long as song is null
     */
    protected boolean allowKeyInput() {
        return song == null;
    }

    @Override
    protected void keyTyped(char c, int key) {
        if (!allowKeyInput()) {
            super.keyTyped(c, key);
            return;
        }
        PlayableNote playedNote = null;
        // Change to use your own KeyBindings, of course
        if (key == ZSSKeyHandler.keys[ZSSKeyHandler.KEY_ATTACK].getKeyCode()) {
            playedNote = PlayableNote.D2; // high D
        } else if (key == ZSSKeyHandler.keys[ZSSKeyHandler.KEY_DOWN].getKeyCode()) {
            playedNote = PlayableNote.F1; // low F
        } else if (key == ZSSKeyHandler.keys[ZSSKeyHandler.KEY_LEFT].getKeyCode()) {
            playedNote = PlayableNote.B2; // high B
        } else if (key == ZSSKeyHandler.keys[ZSSKeyHandler.KEY_RIGHT].getKeyCode()) {
            playedNote = PlayableNote.A2; // high A
        } else if (key == mc.gameSettings.keyBindJump.getKeyCode()) {
            playedNote = PlayableNote.D1; // low D
        }

        // No note key was pressed, call super and get out
        if (playedNote == null) {
            super.keyTyped(c, key);
        } else {
            int modifier = 0;
            // Half-step modifier keys
            if (Keyboard.isKeyDown(mc.gameSettings.keyBindRight.getKeyCode())) {
                ++modifier;
            } else if (Keyboard.isKeyDown(mc.gameSettings.keyBindLeft.getKeyCode())) {
                --modifier;
            }
            // Whole step modifier keys are in addition to half-step modifiers
            if (Keyboard.isKeyDown(mc.gameSettings.keyBindForward.getKeyCode())) {
                modifier += 2;
            } else if (Keyboard.isKeyDown(mc.gameSettings.keyBindBack.getKeyCode())) {
                modifier -= 2;
            }

            SongNote note = SongNote.getNote(playedNote, modifier);
            if (note != null) {
                onNotePlayed(note);
                onNoteAdded();
            }
        }
    }

    /**
     * Called after each note is added; check if notes match a song here
     */
    protected abstract void onNoteAdded();

    /**
     * Adds the note to the list of notes played, plays the note sound, and spawns particles.
     */
    protected void onNotePlayed(SongNote note) {
        melody.add(note);
        ticksSinceLastNote = 0;
        float f = (float) Math.pow(2.0D, (double) (note.ordinal() - 12) / 12.0D);
        // TODO retrieve note to play from player's held ItemInstrument when gui constructed
        mc.thePlayer.playSound(ModInfo.ID + ":note.ocarina", 3.0F, f);
        Vec3 look = mc.thePlayer.getLookVec();
        mc.theWorld.spawnParticle("note", mc.thePlayer.posX + look.xCoord + mc.theWorld.rand.nextDouble() - 0.5D,
                mc.thePlayer.posY + look.yCoord + mc.thePlayer.getEyeHeight() + mc.theWorld.rand.nextDouble()
                        - 0.5D,
                mc.thePlayer.posZ + look.zCoord + mc.theWorld.rand.nextDouble() - 0.5D,
                (double) note.ordinal() / 24.0D, 0.0D, 0.0D);
    }
}