Skip to content

Commit

Permalink
add block particles
Browse files Browse the repository at this point in the history
  • Loading branch information
Pannoniae committed Jul 20, 2024
1 parent 00695c5 commit 1a0a226
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 29 deletions.
2 changes: 2 additions & 0 deletions BlockGame.sln.DotSettings.user
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIView_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F77b6093498874e5590363bcf1d64746ed3a0_003Fa0_003Fefa88011_003FIView_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIWindow_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F77b6093498874e5590363bcf1d64746ed3a0_003F9a_003Fdb64aa0a_003FIWindow_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AList_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F3712a13b205a97fe0e8afddc0cf36f285106f97dd7e3f21a120e9f6bbdd124_003FList_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMathF_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fc7e8693bcd2b99ff1026be64bbccf25616a97d935ce156de9eca6e0523313a3_003FMathF_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMatrix4F_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3cfec35914b54ad8b5a9e578d6e61749ad800_003F39_003F7ad60054_003FMatrix4F_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMatrix4X4_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F2a_003F625192c8_003FMatrix4X4_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMatrix4x4_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F2978e6fd12761c5f515215d431bbe018d4542ea5395e9eb9c28ba4b739155_003FMatrix4x4_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
Expand All @@ -28,6 +29,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APlane_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fd3dcccdc63aac1732584c75613ee3fe953c5cf50c7c3f96a1d999a7e76c4c_003FPlane_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APlane_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F18_003Fe6ee8535_003FPlane_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AScalar_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F56_003Fd747cb09_003FScalar_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F57_003F1d92b6f3_003FVector3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3D_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe445a7db98e64ffc9f5bfeafad0d34d7501a0_003F93_003F3bc9f62f_003FVector3D_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F1ebc76fea7e5a8f5586a1c924dd76440b8f6aeaf045b14419aa2736419e8c5_003FVector3_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AViewImplementationBase_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F77b6093498874e5590363bcf1d64746ed3a0_003F11_003Fedea32f4_003FViewImplementationBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
Expand Down
3 changes: 3 additions & 0 deletions src/main/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public partial class Game {

public static BlendState initialBlendState = BlendState.NonPremultiplied;

public static Random random = new Random(1337 * 1337);
public static Random clientRandom = new Random(1337);

public static Stopwatch stopwatch = new();

/// <summary>
Expand Down
106 changes: 102 additions & 4 deletions src/render/Particle.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Numerics;
using BlockGame.util;
using Silk.NET.Maths;
using TrippyGL;

namespace BlockGame;

Expand All @@ -26,6 +25,11 @@ public class Particle : Entity {
/// </summary>
public double size;

/// <summary>
/// The size of the texture on the particle.
/// </summary>
public double uvsize;

/// <summary>
/// The time-to-live of the particle in ticks.
/// </summary>
Expand All @@ -36,22 +40,116 @@ public class Particle : Entity {
/// </summary>
public bool active;

public Particle(Vector3D<double> position, string texture, float u, float v, double size, int ttl) {
public Particle(World world, Vector3D<double> position, string texture, float u, float v, double size, double uvsize, int ttl) : base(world) {
this.position = position;
this.texture = texture;
this.u = u;
this.v = v;
this.size = size;
this.uvsize = uvsize;
this.ttl = ttl;
active = true;
}

protected override AABB calcAABB(Vector3D<double> pos) {
return new AABB(pos - new Vector3D<double>(size / 2), pos + new Vector3D<double>(size / 2));
}

public virtual void update(double dt) {
prevPosition = position;
if (active) {
// gravity
accel.Y = -5;
velocity.Y -= 6 * dt;
ttl -= 1;
}
// cursed logic?
velocity.X *= Constants.verticalFriction;
velocity.Z *= Constants.verticalFriction;
velocity.Y *= Constants.verticalFriction;
if (onGround) {
velocity.X *= Constants.airFriction;
velocity.Z *= Constants.airFriction;
}
var blockPos = position.toBlockPos();
collisionTargets.Clear();
var currentAABB = world.getAABB(blockPos.X, blockPos.Y, blockPos.Z, world.getBlock(blockPos));
if (currentAABB != null) {
collisionTargets.Add(currentAABB.Value);
}
foreach (var neighbour in world.getBlocksInBox(blockPos + new Vector3D<int>(-1, -1, -1), blockPos + new Vector3D<int>(1, 1, 1))) {
var block = world.getBlock(neighbour);
var blockAABB = world.getAABB(neighbour.X, neighbour.Y, neighbour.Z, block);
if (blockAABB == null) {
continue;
}

collisionTargets.Add(blockAABB.Value);
}

// Y axis resolution
position.Y += velocity.Y * dt;
foreach (var blockAABB in collisionTargets) {
var aabbY = calcAABB(new Vector3D<double>(position.X, position.Y, position.Z));
if (AABB.isCollision(aabbY, blockAABB)) {
// left side
if (velocity.Y > 0 && aabbY.maxY >= blockAABB.minY) {
var diff = blockAABB.minY - aabbY.maxY;
position.Y += diff;
velocity.Y = 0;
}

else if (velocity.Y < 0 && aabbY.minY <= blockAABB.maxY) {
var diff = blockAABB.maxY - aabbY.minY;
position.Y += diff;
velocity.Y = 0;
}
}
}


// X axis resolution
position.X += velocity.X * dt;
foreach (var blockAABB in collisionTargets) {
var aabbX = calcAABB(new Vector3D<double>(position.X, position.Y, position.Z));
var sneakaabbX = calcAABB(new Vector3D<double>(position.X, position.Y - 0.1, position.Z));
if (AABB.isCollision(aabbX, blockAABB)) {
collisionXThisFrame = true;
// left side
if (velocity.X > 0 && aabbX.maxX >= blockAABB.minX) {
var diff = blockAABB.minX - aabbX.maxX;
position.X += diff;
}

else if (velocity.X < 0 && aabbX.minX <= blockAABB.maxX) {
var diff = blockAABB.maxX - aabbX.minX;
position.X += diff;
}
}
}

position.Z += velocity.Z * dt;
foreach (var blockAABB in collisionTargets) {
var aabbZ = calcAABB(new Vector3D<double>(position.X, position.Y, position.Z));
if (AABB.isCollision(aabbZ, blockAABB)) {
collisionZThisFrame = true;
if (velocity.Z > 0 && aabbZ.maxZ >= blockAABB.minZ) {
var diff = blockAABB.minZ - aabbZ.maxZ;
position.Z += diff;
}

else if (velocity.Z < 0 && aabbZ.minZ <= blockAABB.maxZ) {
var diff = blockAABB.maxZ - aabbZ.minZ;
position.Z += diff;
}
}
}
var groundCheck = calcAABB(new Vector3D<double>(position.X, position.Y - Constants.epsilonGroundCheck, position.Z));
onGround = false;
foreach (var blockAABB in collisionTargets) {
if (AABB.isCollision(blockAABB, groundCheck)) {
onGround = true;
}
}
}

public void reset() {
Expand Down
41 changes: 25 additions & 16 deletions src/render/ParticleManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Numerics;
using BlockGame.util;
using Molten;
using Silk.NET.Maths;
using Silk.NET.OpenGL;

Expand All @@ -15,9 +14,6 @@ public class ParticleManager {

public ParticleManager(World world) {
this.world = world;
for (int i = 0; i < 20; i++) {
add(new TerrainParticle(new Vector3D<double>(0, 100, 0), "textures/blocks.png", 0, 0, 0.5, 9_000_000));
}
}

public void add(Particle particle) {
Expand All @@ -30,7 +26,7 @@ public void update(double dt) {
var particle = particles[i];
particle.update(dt);

if (!particle.active) {
if (!particle.active || particle.ttl <= 0) {
particles.RemoveAt(i);
// don't skip the next particle
i--;
Expand All @@ -52,22 +48,35 @@ public void render(double interp) {
Game.GL.ActiveTexture(TextureUnit.Texture0);
Game.GL.BindTexture(TextureTarget.Texture2D, tex.Handle);
}

var billboard = Matrix4F.BillboardLH(particle.position.toVec3F(),
world.player.camera.position.toVec3FM(), world.player.camera.up.toVec3FM(), world.player.camera.forward.toVec3FM());
InstantDraw.instantShader.setUniform(InstantDraw.uMVP, world.player.camera.getViewMatrix(interp) * world.player.camera.getProjectionMatrix());
var vert = new InstantVertex((float)particle.position.X, (float)particle.position.Y, (float)particle.position.Z,
// get interp pos
var pos = Vector3D.Lerp(particle.prevPosition, particle.position, (float)interp);
var right = Vector3.Cross(world.player.camera.up, world.player.camera.forward);
var up = world.player.camera.up;
var ul = pos.toVec3() - right * (float)particle.size / 2 + up * (float)particle.size / 2;
var ll = pos.toVec3() - right * (float)particle.size / 2 - up * (float)particle.size / 2;
var lr = pos.toVec3() + right * (float)particle.size / 2 - up * (float)particle.size / 2;
var ur = pos.toVec3() + right * (float)particle.size / 2 + up * (float)particle.size / 2;
var vert = new InstantVertex(ul.X, ul.Y, ul.Z,
(Half)particle.u, (Half)particle.v, 255, 255, 255, 255);
drawer.addVertex(vert);
vert = new InstantVertex(ll.X, ll.Y, ll.Z,
(Half)particle.u, (Half)(particle.v + particle.uvsize), 255, 255, 255, 255);
drawer.addVertex(vert);
vert = new InstantVertex(lr.X, lr.Y, lr.Z,
(Half)(particle.u + particle.uvsize), (Half)(particle.v + particle.uvsize), 255, 255, 255, 255);
drawer.addVertex(vert);

vert = new InstantVertex(ul.X, ul.Y, ul.Z,
(Half)particle.u, (Half)particle.v, 255, 255, 255, 255);
drawer.addVertex(vert);
vert = new InstantVertex((float)particle.position.X, (float)(particle.position.Y - particle.size), (float)particle.position.Z,
(Half)particle.u, (Half)(particle.v + particle.size), 255, 255, 255, 255);
vert = new InstantVertex(lr.X, lr.Y, lr.Z,
(Half)(particle.u + particle.uvsize), (Half)(particle.v + particle.uvsize), 255, 255, 255, 255);
drawer.addVertex(vert);
vert = new InstantVertex((float)(particle.position.X + particle.size), (float)(particle.position.Y - particle.size), (float)particle.position.Z,
(Half)(particle.u + particle.size), (Half)(particle.v + particle.size), 255, 255, 255, 255);
vert = new InstantVertex(ur.X, ur.Y, ur.Z,
(Half)(particle.u + particle.uvsize), (Half)particle.v, 255, 255, 255, 255);
drawer.addVertex(vert);
//vert = new InstantVertex((float)(particle.position.X + particle.size), (float)particle.position.Y, (float)particle.position.Z,
// (Half)(particle.u + particle.size), (Half)particle.v, 255, 255, 255, 255);
//drawer.addVertex(vert);

}

drawer.finish();
Expand Down
3 changes: 2 additions & 1 deletion src/render/TerrainParticle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace BlockGame;

public class TerrainParticle : Particle {

public TerrainParticle(Vector3D<double> position, string texture, float u, float v, double size, int ttl) : base(position, texture, u, v, size, ttl) {
public TerrainParticle(World world, Vector3D<double> position, string texture, float u, float v, double size, double uvsize, int ttl)
: base(world, position, texture, u, v, size, uvsize, ttl) {
}
}
57 changes: 57 additions & 0 deletions src/util/Blocks.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Silk.NET.Maths;
Expand Down Expand Up @@ -146,6 +147,9 @@ public static bool hasCollision(Block block) {
}

public class Block {

private const int particleCount = 4;

/// <summary>
/// Block ID
/// </summary>
Expand Down Expand Up @@ -352,6 +356,59 @@ public Block tick() {
randomTick = true;
return this;
}

public virtual void crack(World world, int x, int y, int z) {
var factor = 1f / particleCount;
for (var x1 = 0; x1 < particleCount; x1++) {
for (var y1 = 0; y1 < particleCount; y1++) {
for (var z1 = 0; z1 < particleCount; z1++) {
var particleX = x + (x1 + 0.5f) * factor + (Game.clientRandom.NextSingle() - 0.5f) * 0.05f;
var particleY = y + (y1 + 0.5f) * factor + (Game.clientRandom.NextSingle() - 0.5f) * 0.05f;
var particleZ = z + (z1 + 0.5f) * factor + (Game.clientRandom.NextSingle() - 0.5f) * 0.05f;
var particlePosition = new Vector3D<double>(particleX, particleY, particleZ);

var size = Game.clientRandom.NextSingle() * 0.1f + 0.05f;
var ttl = (int)(3f / (Game.clientRandom.NextSingle() + 0.05f));

var randFace = model.faces[Game.clientRandom.Next(0, model.faces.Length)];

var randU = texU(randFace.min.u + Game.clientRandom.NextSingle() * 0.75f);
var randV = texV(randFace.min.v + Game.clientRandom.NextSingle() * 0.75f);

// the closer to the centre, the less the motion
// dx gives a number between -0.5 and 0.5 -> remap to between 0.5 and 3
var dx = (particleX - x - 0.5f);
var dy = (particleY - y - 0.5f);
var dz = (particleZ - z - 0.5f);


// between -0.7 and 0.7
var motion = new Vector3(dx * 3 + (Game.clientRandom.NextSingle() - 0.5f) * 0.2f,
dy * 3 + (Game.clientRandom.NextSingle() - 0.5f) * 0.2f,
dz * 3 + (Game.clientRandom.NextSingle() - 0.5f) * 0.2f);

var speed = (MathF.Pow(Game.clientRandom.NextSingle(), 2) + 1) * 0.8f;

motion *= speed;
motion.Y += 0.15f;

var particle = new Particle(
world,
particlePosition,
"textures/blocks.png",
randU,
randV,
size,
1 / 16f * size,
ttl);
world.particleManager.add(particle);

particle.velocity = motion.toVec3D();
}
}
}
}

}

public class Flower(ushort id, string name, BlockModel uvs) : Block(id, name, uvs) {
Expand Down
3 changes: 3 additions & 0 deletions src/util/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public static Vector3F toVec3F(this Vector3D<float> vec) {
public static Vector3D<float> toVec3F(this Vector3 vec) {
return new Vector3D<float>(vec.X, vec.Y, vec.Z);
}
public static Vector3D<double> toVec3D(this Vector3 vec) {
return new Vector3D<double>(vec.X, vec.Y, vec.Z);
}
public static Vector3F toVec3FM(this Vector3 vec) {
return new Vector3F(vec.X, vec.Y, vec.Z);
}
Expand Down
Loading

0 comments on commit 1a0a226

Please sign in to comment.