package betazavr.adder.client.particle;
import java.util.Random;
import org.lwjgl.opengl.GL11;
import betazavr.adder.Adder;
import betazavr.adder.api.Metods;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class ParticleStun
extends Particle {
private static final ResourceLocation texture = new ResourceLocation(Adder.MODID, "textures/effect/particles.png");
private static final VertexFormat VERTEX_FORMAT = (new VertexFormat()).addElement(DefaultVertexFormats.POSITION_3F).addElement(DefaultVertexFormats.TEX_2F).addElement(DefaultVertexFormats.COLOR_4UB).addElement(DefaultVertexFormats.TEX_2S).addElement(DefaultVertexFormats.NORMAL_3B).addElement(DefaultVertexFormats.PADDING_1B);
protected int icon = 0;
protected double centerX = 0.0;
protected double centerZ = 0.0;
protected EntityLivingBase target = null;
protected double radius = 0.5;
protected boolean dimension = false;
/*конструктор класса №1*/
public ParticleStun(World world, double x, double y, double z) {
super(world, x, y, z);
prevPosX = x;
prevPosY = y;
prevPosZ = z;
particleRed = 1.0F;
particleGreen = 1.0F;
particleBlue = 1.0F;
particleMaxAge = 50;
particleAge = 0;
particleScale = 1.0F;
particleAngle = (float) Math.round(360.0F * Math.random());
centerX = x;
centerZ = z;
icon = 0;
radius = 0.5D;
}
/*конструктор класса №2*/
public ParticleStun(World world, double x, double y, double z, double xS, double yS, double zS) {
super(world, x, y, z, xS, yS, zS);
prevPosX = x;
prevPosY = y;
prevPosZ = z;
particleRed = (float) xS;
particleGreen = (float) yS;
particleBlue = (float) zS;
particleMaxAge = 50;
particleAge = 0;
particleScale = 1.0F;
particleAngle = (float) Math.round(360.0F * Math.random());
centerX = x;
centerZ = z;
icon = 0;
radius = 0.5D;
}
/*конструктор класса №3*/
public ParticleStun(World world, double x, double y, double z, Entity entity, int delay) {
super(world, x, y, z);
prevPosX = x;
prevPosY = y;
prevPosZ = z;
particleRed = 1.0F;
particleGreen = 1.0F;
particleBlue = 1.0F;
if (delay < 50) {particleMaxAge = delay;} // время существования частицы ограничено
else {particleMaxAge = 50;}
particleAge = 0;
particleScale = 1.0F;
particleAngle = (float) Math.round(360.0F * Math.random()); // начальное положение на окружности (для механики движения)
centerX = x; // положение оси X для центра окружности (для механики движения)
centerZ = z; // положение оси Z для центра окружности (для механики движения)
target = (EntityLivingBase) entity; // частица прикреплена к сущности
icon = 0; // стартовый порядковый номер частицы из текстуры
radius = 0.5D; // радиус окружности вращения (для механики движения)
}
@Override
/*отображение частицы игроку на клиенте:*/
public void renderParticle(BufferBuilder buffer, Entity entity, float partialTicks, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) {
Minecraft.getMinecraft().getTextureManager().bindTexture(this.texture); // подмена карты текстуры на собственную
float minU = 0.0625F * (((float) this.icon) % 16.0F); // базовое имя f - начальное горизонтальное значение положения вершины из текстуры
float maxU = minU + 0.0625f; // базовое имя f1 - конечное горизонтальное значение положения вершины из текстуры
float minV = 0.0625F * ((float) Math.floor(this.icon / 16.0F)); // базовое имя f2 - начальное вертикальное значение положения вершины из текстуры
float maxV = minV + 0.0625f; // базовое имя f3 - конечное горизонтальное значение положения вершины из текстуры
float scale = 0.1F * this.particleScale; // базовое имя f4 - размер частицы в игре
float f5 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f6 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f7 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
/*
* this.prevPos - начальное/предыдущее положение частицы
* this.pos - текущее положение частицы
* interpPos - интерполяция положения изображения (будущее положение частицы)
*/
buffer.begin(7, VERTEX_FORMAT); // своего рода способ форматирования вершин
// создание квадратной частицы:
buffer.pos((double)(f5 - rotX * scale - rotXY * scale), (double)(f6 - rotZ * scale), (double)(f7 - rotYZ * scale - rotXZ * scale)).tex((double)maxU, (double)maxV).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); // нижняя правая вершина
buffer.pos((double)(f5 - rotX * scale + rotXY * scale), (double)(f6 + rotZ * scale), (double)(f7 - rotYZ * scale + rotXZ * scale)).tex((double)maxU, (double)minV).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); // верхняя правая вершина
buffer.pos((double)(f5 + rotX * scale + rotXY * scale), (double)(f6 + rotZ * scale), (double)(f7 + rotYZ * scale + rotXZ * scale)).tex((double)minU, (double)minV).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); // верхняя левая вершина
buffer.pos((double)(f5 + rotX * scale - rotXY * scale), (double)(f6 - rotZ * scale), (double)(f7 + rotYZ * scale - rotXZ * scale)).tex((double)minU, (double)maxV).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); // нижняя левая вершина
/*
* pos - позиция вершины в поле координат игры
* tex - позиция вершины из текстуры
* color - маска RGB цвета, накладываемая поверх изображения
* lightmap - координата из карты освещения (маска затемнения изображения)
* normal - поверхность, образованная через треугольник, ортогонально к вектору (что-то вроде угла обзора (0,1,0) - параллельно экрану)
* endVertex - объявление завершения вершины
* P.S. Для создания прозрачности необходимо добавлять методы OpenGL типа - GL11.glColor4f(1.0F, 1.0F, 1.0F, alpha);
* где alpha - (float) степень не прозрачности от 0 до 1
*/
Tessellator.getInstance().draw(); // отображение частицы на экран
}
@Override
public void onUpdate() { // изменения каждый тик:
// Запомнить текущее положение на будущее
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
// Проверка жизни частицы
if (this.particleAge++ >= this.particleMaxAge)
{
this.setExpired();
}
// Механика частицы в игре:
this.icon = (int) Math.floor((this.particleAge % 20) / 4); // смена иконки частицы от 0 до 4 каждые 0,25 секунды
if (this.dimension) { // изменяет размер частицы (от 30% до 170% за секунду)
this.particleScale += 0.07F;
if (this.particleScale >= 1.7F) {this.dimension = false;}
}
else {
this.particleScale -= 0.07F;
if (this.particleScale <= 0.3F) {this.dimension = true;}
}
// движение частицы по окружности над головой сущности:
this.particleAngle += 25.0F;
if (this.particleAngle > 360.0F) {this.particleAngle -= 360.0F;}
float imp = 0.98F; // своего рода корректировка движения частицы по окружности = 98% от нормального
// получение импульса движения из текущего положения, до необходимого на окружности
double[] motionsXZ = Metods.getMotionOnCircle(centerX, centerZ, this.posX, this.posZ, this.particleAngle, this.radius, imp);
double motY = 0.0D;
if (this.target!=null && this.posY!=this.target.posY + 2) {
motY = this.target.posY + 2 - this.posY; // корректировка оси Y - всегда над головой
}
this.move(motionsXZ[0], motY, motionsXZ[1]); // переместить частицу на приращение
}
public int getFXLayer() {
// текущий слой изображения, что-то вроде использования для плавного перехода от одного изображения к другому
return 3;
}
}