/** 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.particle; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.entity.Entity; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import zeldaswordskills.ref.ModInfo; /** * Base class for particles. Provides custom options, such as fade-in/out, glow * and animation. * * @author Hunternif */ public class ModParticle extends EntityFX { /** This sprite sheet must be strictly 16 by 16 icons, any resolution. */ public static final ResourceLocation modParticles = new ResourceLocation(ModInfo.ID, "textures/particles.png"); public static final ResourceLocation minecraftParticles = new ResourceLocation("textures/particle/particles.png"); /** Total number of frames in the sequence. */ protected int iconStages; /** Index of the first frame of the sequence. */ protected int iconStartIndex; /** Index of the actual first frame, if selected at random. */ private int initialIconIndex; /** The number of frames between initialIconIndex and the last frame index. */ private int remainingIconStages; /** Whether to animate through stages. */ private boolean animated = false; private float fadeInTime = 0; private float baseAlpha = 1; private float fadeOutTime = 0.8f; private boolean glowing = false; public ModParticle(World world, double x, double y, double z) { this(world, x, y, z, 0, 0, 0); } public ModParticle(World world, double x, double y, double z, double velX, double velY, double velZ) { super(world, x, y, z, velX, velY, velZ); this.motionX = velX; this.motionY = velY; this.motionZ = velZ; } @Override public void setAlphaF(float value) { setBaseAlpha(value); } protected void setBaseAlpha(float value) { baseAlpha = value; this.particleAlpha = value; } protected void setRandomScale(float min, float max) { particleScale = rand.nextFloat()*(max-min) + min; } protected void setRandomMaxAge(int min, int max) { particleMaxAge = MathHelper.floor_float(rand.nextFloat()*(float)(max-min)) + min; } protected void randomizeVelocity(double maximum) { this.motionX += (rand.nextDouble()*2-1) * maximum; this.motionY += (rand.nextDouble()*2-1) * maximum; this.motionZ += (rand.nextDouble()*2-1) * maximum; } protected void setTexturePositions(int x, int y) { setTexturePositions(x, y, 1, false); } /** * When the particle's icon has multiple stages (frames), it will "play" * the sequence until particle's death at a steady frame rate. Use the * method setAnimated to enable animation sequence (default is false). * @param x horizontal coordinate on the texture. * @param y vertical coordinate on the texture. * @param stages total number of frames. * @param randomStart if true, the initial frame will be selected at * random. The remaining frames will be displayed for equal durations. */ protected void setTexturePositions(int x, int y, int stages, boolean randomStart) { remainingIconStages = iconStages = stages; initialIconIndex = iconStartIndex = y * 16 + x; if (randomStart) { int firstStage = rand.nextInt(stages-1); initialIconIndex += firstStage; remainingIconStages -= firstStage; } setParticleTextureIndex(initialIconIndex); } protected void setAnimated(boolean value) { this.animated = value; } protected void setFade(float fadeInTime, float fadeOutTime) { this.fadeInTime = fadeInTime; this.fadeOutTime = fadeOutTime; } protected void setGlowing() { glowing = true; } @Override public void renderParticle(WorldRenderer renderer, Entity entity, float partialTick, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { /* renderer.finishDrawing(); Minecraft.getMinecraft().renderEngine.bindTexture(modParticles); renderer.startDrawingQuads(); renderer.setBrightness(getBrightnessForRender(partialTick)); super.renderParticle(renderer, entity, partialTick, rotX, rotXZ, rotZ, rotYZ, rotXY); renderer.finishDrawing(); renderer.startDrawingQuads(); */ Minecraft.getMinecraft().renderEngine.bindTexture(minecraftParticles); } @Override public void onUpdate() { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; float ageFraq = ((float)this.particleAge) / (float)this.particleMaxAge; this.particleAlpha = alphaAtAge(ageFraq); particleScale = scaleAtAge(ageFraq); // Animation: if (animated && remainingIconStages > 1) { int stage = MathHelper.floor_float(ageFraq * (float) remainingIconStages); setParticleTextureIndex(initialIconIndex + stage); } if (this.particleAge++ >= this.particleMaxAge) { this.setDead(); } this.moveEntity(this.motionX, this.motionY, this.motionZ); } @Override public int getBrightnessForRender(float partialTick) { return glowing ? 0xf000f0 : super.getBrightnessForRender(partialTick); } /** Particle alpha as function of particle age (from 0 to 1). */ protected float alphaAtAge(float ageFraq) { if (ageFraq <= fadeInTime) { return baseAlpha * ageFraq / fadeInTime; } else if (ageFraq >= fadeOutTime) { return baseAlpha * (1f - (ageFraq - fadeOutTime) / (1f-fadeOutTime) ); } else { return baseAlpha; } } /** Particle scale as function of particle age (from 0 to 1). */ protected float scaleAtAge(float ageFraq) { return particleScale; } protected void setColor(int color) { float r = (float)((color >> 16) & 0xff) / (float)0xff; float g = (float)((color >> 8) & 0xff) / (float)0xff; float b = (float)(color & 0xff) / (float)0xff; setRBGColorF(r, g, b); } }