mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
Better bezier curve, more work on /ctf
This commit is contained in:
parent
282edd2ca3
commit
b48c6d52f1
@ -42,7 +42,7 @@ namespace MCGalaxy.Blocks.Physics {
|
|||||||
args.Type1 = PhysicsArgs.Wait; args.Value1 = 1;
|
args.Type1 = PhysicsArgs.Wait; args.Value1 = 1;
|
||||||
args.Type2 = PhysicsArgs.Dissipate; args.Value2 = 100;
|
args.Type2 = PhysicsArgs.Dissipate; args.Value2 = 100;
|
||||||
|
|
||||||
lvl.AddUpdate(bAbove, Block.Fireworks, false);
|
lvl.AddUpdate(bAbove, Block.Fireworks);
|
||||||
lvl.AddUpdate(C.b, Block.StillLava, false, args);
|
lvl.AddUpdate(C.b, Block.StillLava, false, args);
|
||||||
args.Data = C.data.Data;
|
args.Data = C.data.Data;
|
||||||
C.data = args;
|
C.data = args;
|
||||||
|
@ -19,6 +19,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using MCGalaxy.Games;
|
using MCGalaxy.Games;
|
||||||
|
using MCGalaxy.Maths;
|
||||||
|
|
||||||
namespace MCGalaxy.Commands.Fun {
|
namespace MCGalaxy.Commands.Fun {
|
||||||
public sealed class CmdCTF : Command {
|
public sealed class CmdCTF : Command {
|
||||||
@ -107,11 +108,31 @@ namespace MCGalaxy.Commands.Fun {
|
|||||||
cfg.RedSpawnX = p.Pos.X; cfg.RedSpawnY = p.Pos.Y; cfg.RedSpawnZ = p.Pos.Z;
|
cfg.RedSpawnX = p.Pos.X; cfg.RedSpawnY = p.Pos.Y; cfg.RedSpawnZ = p.Pos.Z;
|
||||||
Player.Message(p, "Set spawn of red team to your position.");
|
Player.Message(p, "Set spawn of red team to your position.");
|
||||||
UpdateConfig(p, cfg);
|
UpdateConfig(p, cfg);
|
||||||
|
} else if (property.CaselessEq("blueflag")) {
|
||||||
|
Player.Message(p, "Place or delete a block to set blue team's flag.");
|
||||||
|
p.MakeSelection(1, null, BlueFlagCallback);
|
||||||
|
} else if (property.CaselessEq("redflag")) {
|
||||||
|
Player.Message(p, "Place or delete a block to set red team's flag.");
|
||||||
|
p.MakeSelection(1, null, RedFlagCallback);
|
||||||
} else {
|
} else {
|
||||||
Help(p, "set");
|
Help(p, "set");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool BlueFlagCallback(Player p, Vec3S32[] marks, object state, ExtBlock block) {
|
||||||
|
CTFConfig cfg = RetrieveConfig(p);
|
||||||
|
cfg.BlueFlagX = marks[0].X; cfg.BlueFlagY = marks[0].Y; cfg.BlueFlagZ = marks[0].Z;
|
||||||
|
UpdateConfig(p, cfg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RedFlagCallback(Player p, Vec3S32[] marks, object state, ExtBlock block) {
|
||||||
|
CTFConfig cfg = RetrieveConfig(p);
|
||||||
|
cfg.RedFlagX = marks[0].X; cfg.RedFlagY = marks[0].Y; cfg.RedFlagZ = marks[0].Z;
|
||||||
|
UpdateConfig(p, cfg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static CTFConfig RetrieveConfig(Player p) {
|
static CTFConfig RetrieveConfig(Player p) {
|
||||||
CTFConfig cfg = new CTFConfig();
|
CTFConfig cfg = new CTFConfig();
|
||||||
cfg.SetDefaults(p.level);
|
cfg.SetDefaults(p.level);
|
||||||
|
@ -23,6 +23,9 @@ namespace MCGalaxy.Commands.Building {
|
|||||||
public override string name { get { return "bezier"; } }
|
public override string name { get { return "bezier"; } }
|
||||||
protected override string PlaceMessage { get { return "Place or break two blocks to determine the endpoints, then another for the control point"; } }
|
protected override string PlaceMessage { get { return "Place or break two blocks to determine the endpoints, then another for the control point"; } }
|
||||||
public override int MarksCount { get { return 3; } }
|
public override int MarksCount { get { return 3; } }
|
||||||
|
public override CommandAlias[] Aliases {
|
||||||
|
get { return new[] { new CommandAlias("curve") }; }
|
||||||
|
}
|
||||||
|
|
||||||
protected override DrawOp GetDrawOp(DrawArgs dArgs) {
|
protected override DrawOp GetDrawOp(DrawArgs dArgs) {
|
||||||
return new BezierDrawOp();
|
return new BezierDrawOp();
|
||||||
|
@ -21,34 +21,68 @@ using MCGalaxy.Drawing.Brushes;
|
|||||||
using MCGalaxy.Maths;
|
using MCGalaxy.Maths;
|
||||||
|
|
||||||
namespace MCGalaxy.Drawing.Ops {
|
namespace MCGalaxy.Drawing.Ops {
|
||||||
public class BezierDrawOp : DrawOp {
|
public class BezierDrawOp : DrawOp {
|
||||||
public override string Name { get { return "Bezier"; } }
|
public override string Name { get { return "Bezier"; } }
|
||||||
public bool WallsMode;
|
public bool WallsMode;
|
||||||
public int MaxLength = int.MaxValue;
|
public int MaxLength = int.MaxValue;
|
||||||
|
|
||||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) {
|
public override long BlocksAffected(Level lvl, Vec3S32[] marks) {
|
||||||
Vec3S32 p0 = marks[0], p2 = marks[1], p1 = marks[2];
|
Vec3S32 p0 = marks[0], p2 = marks[1], p1 = marks[2];
|
||||||
return (long)((p1 - p0).Length + (p1 - p2).Length);
|
return (long)((p1 - p0).Length + (p1 - p2).Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) {
|
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) {
|
||||||
int steps = 20;
|
points.Add(marks[0]);
|
||||||
Vec3F32 p0 = marks[0], p2 = marks[1], p1 = marks[2];
|
TesselateCurve(marks[0], marks[2], marks[1], 0);
|
||||||
steps *= (int)((p1 - p0).Length + (p1 - p2).Length);
|
|
||||||
|
|
||||||
float t = 0, invT = 1, delta = 1.0f / steps;
|
List<Vec3S32> buffer = new List<Vec3S32>();
|
||||||
for (int i = 0; i <= steps; i++) {
|
for (int i = 0; i < points.Count - 1; i++) {
|
||||||
Vec3F32 B = invT * invT * p0 + 2 * invT * t * p1 + t * t * p2;
|
LineDrawOp.DrawLine(points[i].X, points[i].Y, points[i].Z, 1000000,
|
||||||
output(Place(Round(B.X), Round(B.Y), Round(B.Z), brush));
|
points[i+1].X, points[i+1].Y, points[i+1].Z, buffer);
|
||||||
t += delta; invT -= delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static ushort Round(float value) {
|
foreach (Vec3S32 P in buffer) {
|
||||||
int valueI = (int)value;
|
output(Place((ushort)P.X, (ushort)P.Y, (ushort)P.Z, brush));
|
||||||
int floored = value < valueI ? valueI - 1 : valueI;
|
}
|
||||||
float frac = (value % 1.0f);
|
}
|
||||||
return (ushort)(floored + (frac > 0.5f ? 1 : 0));
|
}
|
||||||
}
|
|
||||||
}
|
List<Vec3S32> points = new List<Vec3S32>();
|
||||||
|
const float objspace_flatness_squared = 0.35f * 0.35f;
|
||||||
|
|
||||||
|
// Based off stbtt__tesselate_curve from https://github.com/nothings/stb/blob/master/stb_truetype.h
|
||||||
|
void TesselateCurve(Vec3F32 p0, Vec3F32 p1, Vec3F32 p2, int n) {
|
||||||
|
// midpoint
|
||||||
|
Vec3F32 m;
|
||||||
|
m.X = (p0.X + 2 * p1.X + p2.X) * 0.25f;
|
||||||
|
m.Y = (p0.Y + 2 * p1.Y + p2.Y) * 0.25f;
|
||||||
|
m.Z = (p0.Z + 2 * p1.Z + p2.Z) * 0.25f;
|
||||||
|
|
||||||
|
// versus directly drawn line
|
||||||
|
Vec3F32 d;
|
||||||
|
d.X = (p0.X + p2.X) * 0.5f - m.X;
|
||||||
|
d.Y = (p0.Y + p2.Y) * 0.5f - m.Y;
|
||||||
|
d.Z = (p0.Z + p2.Z) * 0.5f - m.Z;
|
||||||
|
|
||||||
|
if (n > 16) return; // 65536 segments on one curve better be enough!
|
||||||
|
|
||||||
|
// half-pixel error allowed... need to be smaller if AA
|
||||||
|
if (d.X * d.X + d.Y * d.Y + d.Z * d.Z > objspace_flatness_squared) {
|
||||||
|
Vec3F32 p0_p1 = new Vec3F32((p0.X + p1.X) * 0.5f, (p0.Y + p1.Y) * 0.5f, (p0.Z + p1.Z) * 0.5f);
|
||||||
|
TesselateCurve(p0, p0_p1, m, n + 1);
|
||||||
|
|
||||||
|
Vec3F32 p1_p2 = new Vec3F32((p1.X + p2.X) * 0.5f, (p1.Y + p2.Y) * 0.5f, (p1.Z + p2.Z) * 0.5f);
|
||||||
|
TesselateCurve(m, p1_p2, p2, n + 1);
|
||||||
|
} else {
|
||||||
|
// TODO: do we need to round properly here or not
|
||||||
|
points.Add(new Vec3S32((int)p2.X, (int)p2.Y, (int)p2.Z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static ushort Round(float value) {
|
||||||
|
int valueI = (int)value;
|
||||||
|
int floored = value < valueI ? valueI - 1 : valueI;
|
||||||
|
float frac = (value % 1.0f);
|
||||||
|
return (ushort)(floored + (frac > 0.5f ? 1 : 0));
|
||||||
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user