static bool Particle_PhysicsTick(Particle* p, Real32 gravity, bool throughLiquids, Real64 delta) { p->LastPos = p->NextPos; BlockID cur = Particle_GetBlock((Int32)p->NextPos.X, (Int32)p->NextPos.Y, (Int32)p->NextPos.Z); Real32 minY = Math_Floor(p->NextPos.Y) + Block_MinBB[cur].Y; Real32 maxY = Math_Floor(p->NextPos.Y) + Block_MaxBB[cur].Y; if (!Particle_CanPass(cur, throughLiquids) && p->NextPos.Y >= minY && p->NextPos.Y < maxY && Particle_CollideHor(&p->NextPos, cur)) { return true; } p->Velocity.Y -= gravity * (Real32)delta; Int32 startY = Math_Floor(p->NextPos.Y); Vector3 velocity; Vector3_Mul1(&velocity, &p->Velocity, (Real32)delta * 3.0f); Vector3_Add(&p->NextPos, &p->NextPos, &velocity); Int32 endY = Math_Floor(p->NextPos.Y); Int32 y; if (p->Velocity.Y > 0.0f) { /* don't test block we are already in */ for (y = startY + 1; y <= endY && Particle_TestY(p, y, false, throughLiquids); y++) {} } else { for (y = startY; y >= endY && Particle_TestY(p, y, true, throughLiquids); y--) {} } p->Lifetime -= (Real32)delta; return p->Lifetime < 0.0f; }
static bool Particle_CollideHor(Vector3* nextPos, BlockID block) { Vector3 horPos = Vector3_Create3((Real32)Math_Floor(nextPos->X), 0.0f, (Real32)Math_Floor(nextPos->Z)); Vector3 min, max; Vector3_Add(&min, &Block_MinBB[block], &horPos); Vector3_Add(&max, &Block_MaxBB[block], &horPos); return nextPos->X >= min.X && nextPos->Z >= min.Z && nextPos->X < max.X && nextPos->Z < max.Z; }
static void RainParticle_Render(RainParticle* p, Real32 t, VertexP3fT2fC4b* vertices) { Vector3 pos; Vector3_Lerp(&pos, &p->Base.LastPos, &p->Base.NextPos, t); Vector2 size; size.X = (Real32)p->Base.Size * 0.015625f; size.Y = size.X; Int32 x = Math_Floor(pos.X), y = Math_Floor(pos.Y), z = Math_Floor(pos.Z); PackedCol col = World_IsValidPos(x, y, z) ? Lighting_Col(x, y, z) : Lighting_Outside; Particle_DoRender(&size, &pos, &Rain_Rec, col, vertices); }
static void TerrainParticle_Render(TerrainParticle* p, Real32 t, VertexP3fT2fC4b* vertices) { Vector3 pos; Vector3_Lerp(&pos, &p->Base.LastPos, &p->Base.NextPos, t); Vector2 size; size.X = (Real32)p->Base.Size * 0.015625f; size.Y = size.X; PackedCol col = PACKEDCOL_WHITE; if (!Block_FullBright[p->Block]) { Int32 x = Math_Floor(pos.X), y = Math_Floor(pos.Y), z = Math_Floor(pos.Z); col = World_IsValidPos(x, y, z) ? Lighting_Col_XSide(x, y, z) : Lighting_OutsideXSide; } if (Block_Tinted[p->Block]) { PackedCol tintCol = Block_FogCol[p->Block]; col.R = (UInt8)(col.R * tintCol.R / 255); col.G = (UInt8)(col.G * tintCol.G / 255); col.B = (UInt8)(col.B * tintCol.B / 255); } Particle_DoRender(&size, &pos, &p->Rec, col, vertices); }
/*########################################################################################################################* *-------------------------------------------------------Respawning--------------------------------------------------------* *#########################################################################################################################*/ float Respawn_HighestSolidY(struct AABB* bb) { int minX = Math_Floor(bb->Min.X), maxX = Math_Floor(bb->Max.X); int minY = Math_Floor(bb->Min.Y), maxY = Math_Floor(bb->Max.Y); int minZ = Math_Floor(bb->Min.Z), maxZ = Math_Floor(bb->Max.Z); float highestY = RESPAWN_NOT_FOUND; BlockID block; struct AABB blockBB; Vector3 v; int x, y, z; for (y = minY; y <= maxY; y++) { v.Y = (float)y; for (z = minZ; z <= maxZ; z++) { v.Z = (float)z; for (x = minX; x <= maxX; x++) { v.X = (float)x; block = World_GetPhysicsBlock(x, y, z); Vector3_Add(&blockBB.Min, &v, &Blocks.MinBB[block]); Vector3_Add(&blockBB.Max, &v, &Blocks.MaxBB[block]); if (Blocks.Collide[block] != COLLIDE_SOLID) continue; if (!AABB_Intersects(bb, &blockBB)) continue; if (blockBB.Max.Y > highestY) highestY = blockBB.Max.Y; } } } return highestY; }
/*########################################################################################################################* *-------------------------------------------------------TextAtlas---------------------------------------------------------* *#########################################################################################################################*/ void TextAtlas_Make(struct TextAtlas* atlas, const String* chars, const FontDesc* font, const String* prefix) { struct DrawTextArgs args; Size2D size; Bitmap bmp; int i, width; DrawTextArgs_Make(&args, prefix, font, true); size = Drawer2D_MeasureText(&args); atlas->Offset = size.Width; width = atlas->Offset; for (i = 0; i < chars->length; i++) { args.Text = String_UNSAFE_Substring(chars, i, 1); size = Drawer2D_MeasureText(&args); atlas->Widths[i] = size.Width; atlas->Offsets[i] = width; /* add 1 pixel of padding */ width += size.Width + 1; } Bitmap_AllocateClearedPow2(&bmp, width, size.Height); { args.Text = *prefix; Drawer2D_DrawText(&bmp, &args, 0, 0); for (i = 0; i < chars->length; i++) { args.Text = String_UNSAFE_Substring(chars, i, 1); Drawer2D_DrawText(&bmp, &args, atlas->Offsets[i], 0); } Drawer2D_Make2DTexture(&atlas->Tex, &bmp, size, 0, 0); } Mem_Free(bmp.Scan0); Drawer2D_ReducePadding_Tex(&atlas->Tex, Math_Floor(font->Size), 4); atlas->uScale = 1.0f / (float)bmp.Width; atlas->Tex.uv.U2 = atlas->Offset * atlas->uScale; atlas->Tex.Width = atlas->Offset; }