public static Vertex FromData(byte[] data, int offset) { var x = BitConverter.ToInt16(data, offset); var y = BitConverter.ToInt16(data, offset + 2); return(new Vertex(Fixed.FromInt(x), Fixed.FromInt(y))); }
/// <summary> /// Spawn blood. /// </summary> public void SpawnBlood(Fixed x, Fixed y, Fixed z, int damage) { var random = this.world.Random; z += new Fixed((random.Next() - random.Next()) << 10); var thing = this.world.ThingAllocation.SpawnMobj(x, y, z, MobjType.Blood); thing.MomZ = Fixed.FromInt(2); thing.Tics -= random.Next() & 3; if (thing.Tics < 1) { thing.Tics = 1; } if (damage <= 12 && damage >= 9) { thing.SetState(MobjState.Blood2); } else if (damage < 9) { thing.SetState(MobjState.Blood3); } }
private void UnArchiveLine(LineDef line) { line.Flags = (LineFlags)this.reader.ReadInt16(); line.Special = (LineSpecial)this.reader.ReadInt16(); line.Tag = this.reader.ReadInt16(); if (line.FrontSide != null) { var side = line.FrontSide; side.TextureOffset = Fixed.FromInt(this.reader.ReadInt16()); side.RowOffset = Fixed.FromInt(this.reader.ReadInt16()); side.TopTexture = this.reader.ReadInt16(); side.BottomTexture = this.reader.ReadInt16(); side.MiddleTexture = this.reader.ReadInt16(); } if (line.BackSide != null) { var side = line.BackSide; side.TextureOffset = Fixed.FromInt(this.reader.ReadInt16()); side.RowOffset = Fixed.FromInt(this.reader.ReadInt16()); side.TopTexture = this.reader.ReadInt16(); side.BottomTexture = this.reader.ReadInt16(); side.MiddleTexture = this.reader.ReadInt16(); } }
public void BFGSpray(Mobj bfgBall) { var hs = this.world.Hitscan; var random = this.world.Random; // Offset angles from its attack angle. for (var i = 0; i < 40; i++) { var an = bfgBall.Angle - Angle.Ang90 / 2 + Angle.Ang90 / 40 * (uint)i; // bfgBall.Target is the originator (player) of the missile. hs.AimLineAttack(bfgBall.Target, an, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { continue; } this.world.ThingAllocation.SpawnMobj(hs.LineTarget.X, hs.LineTarget.Y, hs.LineTarget.Z + (hs.LineTarget.Height >> 2), MobjType.Extrabfg); var damage = 0; for (var j = 0; j < 15; j++) { damage += (random.Next() & 7) + 1; } this.world.ThingInteraction.DamageMobj(hs.LineTarget, bfgBall.Target, bfgBall.Target, damage); } }
private bool SlideTraverse(Intercept intercept) { var mc = this.world.MapCollision; if (intercept.Line == null) { throw new Exception("ThingMovement.SlideTraverse: Not a line?"); } var line = intercept.Line; if ((line.Flags & LineFlags.TwoSided) == 0) { if (Geometry.PointOnLineSide(this.slideThing.X, this.slideThing.Y, line) != 0) { // Don't hit the back side. return(true); } goto isBlocking; } // Set openrange, opentop, openbottom. mc.LineOpening(line); if (mc.OpenRange < this.slideThing.Height) { // Doesn't fit. goto isBlocking; } if (mc.OpenTop - this.slideThing.Z < this.slideThing.Height) { // Mobj is too high. goto isBlocking; } if (mc.OpenBottom - this.slideThing.Z > Fixed.FromInt(24)) { // Too big a step up. goto isBlocking; } // This line doesn't block movement. return(true); // The line does block movement, see if it is closer than best so far. isBlocking: if (intercept.Frac < this.bestSlideFrac) { this.secondSlideFrac = this.bestSlideFrac; this.secondSlideLine = this.bestSlideLine; this.bestSlideFrac = intercept.Frac; this.bestSlideLine = line; } // Stop. return(false); }
/// <summary> /// Find a target on the aiming line. /// Sets LineTaget when a target is aimed at. /// </summary> public Fixed AimLineAttack(Mobj shooter, Angle angle, Fixed range) { this.currentShooter = shooter; this.currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); this.currentRange = range; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); // Can't shoot outside view angles. this.topSlope = Fixed.FromInt(100) / 160; this.bottomSlope = Fixed.FromInt(-100) / 160; this.lineTarget = null; this.world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, this.aimTraverseFunc ); if (this.lineTarget != null) { return(this.currentAimSlope); } return(Fixed.Zero); }
public static Node FromData(byte[] data, int offset) { var x = BitConverter.ToInt16(data, offset); var y = BitConverter.ToInt16(data, offset + 2); var dx = BitConverter.ToInt16(data, offset + 4); var dy = BitConverter.ToInt16(data, offset + 6); var frontBoundingBoxTop = BitConverter.ToInt16(data, offset + 8); var frontBoundingBoxBottom = BitConverter.ToInt16(data, offset + 10); var frontBoundingBoxLeft = BitConverter.ToInt16(data, offset + 12); var frontBoundingBoxRight = BitConverter.ToInt16(data, offset + 14); var backBoundingBoxTop = BitConverter.ToInt16(data, offset + 16); var backBoundingBoxBottom = BitConverter.ToInt16(data, offset + 18); var backBoundingBoxLeft = BitConverter.ToInt16(data, offset + 20); var backBoundingBoxRight = BitConverter.ToInt16(data, offset + 22); var frontChild = BitConverter.ToInt16(data, offset + 24); var backChild = BitConverter.ToInt16(data, offset + 26); return(new Node( Fixed.FromInt(x), Fixed.FromInt(y), Fixed.FromInt(dx), Fixed.FromInt(dy), Fixed.FromInt(frontBoundingBoxTop), Fixed.FromInt(frontBoundingBoxBottom), Fixed.FromInt(frontBoundingBoxLeft), Fixed.FromInt(frontBoundingBoxRight), Fixed.FromInt(backBoundingBoxTop), Fixed.FromInt(backBoundingBoxBottom), Fixed.FromInt(backBoundingBoxLeft), Fixed.FromInt(backBoundingBoxRight), frontChild, backChild )); }
public static MapThing FromData(byte[] data, int offset) { var x = BitConverter.ToInt16(data, offset); var y = BitConverter.ToInt16(data, offset + 2); var angle = BitConverter.ToInt16(data, offset + 4); var type = BitConverter.ToInt16(data, offset + 6); var flags = BitConverter.ToInt16(data, offset + 8); return(new MapThing(Fixed.FromInt(x), Fixed.FromInt(y), new Angle(Angle.Ang45.Data * (uint)(angle / 45)), type, (ThingFlags)flags)); }
public void TestSqrt() { var a = Fixed.FromInt(9); var r = Fixed.FromInt(3); AssertApproximately(r, FMath.Sqrt(a)); a = Fixed.Parse("1546.564654"); r = Fixed.Parse("39.326386"); AssertApproximately(r, FMath.Sqrt(a)); }
/// <summary> /// Fall on your face when dying. /// Decrease POV height to floor height. /// </summary> private void DeathThink(Player player) { this.MovePlayerSprites(player); // Fall to the ground. if (player.ViewHeight > Fixed.FromInt(6)) { player.ViewHeight -= Fixed.One; } if (player.ViewHeight < Fixed.FromInt(6)) { player.ViewHeight = Fixed.FromInt(6); } player.DeltaViewHeight = Fixed.Zero; this.onGround = (player.Mobj.Z <= player.Mobj.FloorZ); this.CalcHeight(player); if (player.Attacker != null && player.Attacker != player.Mobj) { var angle = Geometry.PointToAngle(player.Mobj.X, player.Mobj.Y, player.Attacker.X, player.Attacker.Y); var delta = angle - player.Mobj.Angle; if (delta < PlayerBehavior.ang5 || delta.Data > (-PlayerBehavior.ang5).Data) { // Looking at killer, so fade damage flash down. player.Mobj.Angle = angle; if (player.DamageCount > 0) { player.DamageCount--; } } else if (delta < Angle.Ang180) { player.Mobj.Angle += PlayerBehavior.ang5; } else { player.Mobj.Angle -= PlayerBehavior.ang5; } } else if (player.DamageCount > 0) { player.DamageCount--; } if ((player.Cmd.Buttons & TicCmdButtons.Use) != 0) { player.PlayerState = PlayerState.Reborn; } }
private void UnArchiveSector(Sector sector) { sector.FloorHeight = Fixed.FromInt(this.reader.ReadInt16()); sector.CeilingHeight = Fixed.FromInt(this.reader.ReadInt16()); sector.FloorFlat = this.reader.ReadInt16(); sector.CeilingFlat = this.reader.ReadInt16(); sector.LightLevel = this.reader.ReadInt16(); sector.Special = (SectorSpecial)this.reader.ReadInt16(); sector.Tag = this.reader.ReadInt16(); sector.SpecialData = null; sector.SoundTarget = null; }
/// <summary> /// Looks for lines in the given block that intercept the given trace /// to add to the intercepts list. /// A line is crossed if its endpoints are on opposite sidesof the trace. /// Returns true if earlyOut and a solid line hit. /// </summary> private bool AddLineIntercepts(LineDef line) { int s1; int s2; // Avoid precision problems with two routines. if (this.trace.Dx > Fixed.FromInt(16) || this.trace.Dy > Fixed.FromInt(16) || this.trace.Dx < -Fixed.FromInt(16) || this.trace.Dy < -Fixed.FromInt(16)) { s1 = Geometry.PointOnDivLineSide(line.Vertex1.X, line.Vertex1.Y, this.trace); s2 = Geometry.PointOnDivLineSide(line.Vertex2.X, line.Vertex2.Y, this.trace); } else { s1 = Geometry.PointOnLineSide(this.trace.X, this.trace.Y, line); s2 = Geometry.PointOnLineSide(this.trace.X + this.trace.Dx, this.trace.Y + this.trace.Dy, line); } if (s1 == s2) { // Line isn't crossed. return(true); } // Hit the line. this.target.MakeFrom(line); var frac = this.InterceptVector(this.trace, this.target); if (frac < Fixed.Zero) { // Behind source. return(true); } // Try to early out the check. if (this.earlyOut && frac < Fixed.One && line.BackSector == null) { // Stop checking. return(false); } this.intercepts[this.interceptCount].Make(frac, line); this.interceptCount++; // Continue. return(true); }
public void TestAtan() { var a = Fixed.FromInt(14); var r = Fixed.FromFloat(1.4994888f); AssertApproximately(r, FMath.Atan(a)); a = Fixed.FromFloat(-0.154787f); r = Fixed.FromFloat(-0.153568f); AssertApproximately(r, FMath.Atan(a)); a = Fixed.FromFloat(0.7547870f); r = Fixed.FromFloat(0.6465577f); AssertApproximately(r, FMath.Atan(a)); }
public void TestTan() { var deg2Rad = Fixed.FromFloat((float)(Math.PI / 180)); var a = Fixed.FromInt(45) * deg2Rad; var r = Fixed.FromInt(1); AssertApproximately(r, FMath.Tan(a)); a = Fixed.FromInt(0) * deg2Rad; r = Fixed.FromInt(0); AssertApproximately(r, FMath.Tan(a)); a = Fixed.FromInt(37) * deg2Rad; r = Fixed.Parse("0.75355405"); AssertApproximately(r, FMath.Tan(a)); }
public void TestSin() { var deg2Rad = Fixed.FromFloat((float)(Math.PI / 180)); var a = Fixed.FromInt(90) * deg2Rad; var r = Fixed.FromInt(1); AssertApproximately(r, FMath.Sin(a)); a = Fixed.FromInt(0) * deg2Rad; r = Fixed.FromInt(0); AssertApproximately(r, FMath.Sin(a)); a = Fixed.FromInt(37) * deg2Rad; r = Fixed.Parse("0.60181502"); AssertApproximately(r, FMath.Sin(a)); }
public void TestCos() { var deg2Rad = Fixed.FromFloat((float)(Math.PI / 180)); var a = Fixed.FromInt(90) * deg2Rad; var r = Fixed.FromInt(0); AssertApproximately(r, FMath.Cos(a)); a = Fixed.FromInt(0) * deg2Rad; r = Fixed.FromInt(1); AssertApproximately(r, FMath.Cos(a)); a = Fixed.FromInt(37) * deg2Rad; r = Fixed.Parse("0.79863551"); AssertApproximately(r, FMath.Cos(a)); }
public void Division1() { var random = new Random(666); for (var i = 0; i < 100; i++) { var a = random.Next(66) - 33; var b = (2 * random.Next(2) - 1) * (random.Next(33) + 33); var c = (double)a / b; var fa = Fixed.FromInt(a); var fb = Fixed.FromInt(b); var fc = fa / fb; Assert.AreEqual(c, fc.ToDouble(), delta); } }
public void Addition1() { var random = new Random(666); for (var i = 0; i < 100; i++) { var a = random.Next(666) - 333; var b = random.Next(666) - 333; var c = a + b; var fa = Fixed.FromInt(a); var fb = Fixed.FromInt(b); var fc = fa + fb; Assert.AreEqual(c, fc.ToDouble(), delta); } }
/// <summary> /// Shoot a missile from the source. /// For players. /// </summary> public void SpawnPlayerMissile(Mobj source, MobjType type) { var hs = this.world.Hitscan; // See which target is to be aimed at. var angle = source.Angle; var slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { angle += new Angle(1 << 26); slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); if (hs.LineTarget == null) { angle -= new Angle(2 << 26); slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64)); } if (hs.LineTarget == null) { angle = source.Angle; slope = Fixed.Zero; } } var x = source.X; var y = source.Y; var z = source.Z + Fixed.FromInt(32); var missile = this.SpawnMobj(x, y, z, type); if (missile.Info.SeeSound != 0) { this.world.StartSound(missile, missile.Info.SeeSound, SfxType.Misc); } missile.Target = source; missile.Angle = angle; missile.MomX = new Fixed(missile.Info.Speed) * Trig.Cos(angle); missile.MomY = new Fixed(missile.Info.Speed) * Trig.Sin(angle); missile.MomZ = new Fixed(missile.Info.Speed) * slope; this.CheckMissileSpawn(missile); }
public void TestFactory() { var a = Fixed.FromInt(10); Assert.AreEqual(Fixed.FromInt(10), a); var b = Fixed.FromFloat(3.2f); Assert.AreEqual(Fixed.FromFloat(3.2f), b); var c = Fixed.Parse("6.3"); AssertApproximately(Fixed.FromFraction(63, 10), c); var d = Fixed.FromFraction(3141592, 1000000); AssertApproximately(Fixed.FromFloat(3.141592f), d); }
public void TestParseInt() { var n = Fixed.Parse("0"); Assert.AreEqual(Fixed.Zero, n); n = Fixed.Parse("1"); Assert.AreEqual(Fixed.One, n); n = Fixed.Parse("-1"); Assert.AreEqual(Fixed.FromInt(-1), n); n = Fixed.Parse("16777216"); Assert.AreEqual(Fixed.FromInt(16777216), n); n = Fixed.Parse("-16777216"); Assert.AreEqual(Fixed.FromInt(-16777216), n); }
public static SideDef FromData(byte[] data, int offset, TextureLookup textures, Sector[] sectors) { var textureOffset = BitConverter.ToInt16(data, offset); var rowOffset = BitConverter.ToInt16(data, offset + 2); var topTextureName = DoomInterop.ToString(data, offset + 4, 8); var bottomTextureName = DoomInterop.ToString(data, offset + 12, 8); var middleTextureName = DoomInterop.ToString(data, offset + 20, 8); var sectorNum = BitConverter.ToInt16(data, offset + 28); return(new SideDef( Fixed.FromInt(textureOffset), Fixed.FromInt(rowOffset), textures.GetNumber(topTextureName), textures.GetNumber(bottomTextureName), textures.GetNumber(middleTextureName), sectorNum != -1 ? sectors[sectorNum] : null )); }
/// <summary> /// Shoot a missile from the source to the destination. /// For monsters. /// </summary> public Mobj SpawnMissile(Mobj source, Mobj dest, MobjType type) { var missile = this.SpawnMobj(source.X, source.Y, source.Z + Fixed.FromInt(32), type); if (missile.Info.SeeSound != 0) { this.world.StartSound(missile, missile.Info.SeeSound, SfxType.Misc); } // Where it came from? missile.Target = source; var angle = Geometry.PointToAngle(source.X, source.Y, dest.X, dest.Y); // Fuzzy player. if ((dest.Flags & MobjFlags.Shadow) != 0) { var random = this.world.Random; angle += new Angle((random.Next() - random.Next()) << 20); } var speed = this.GetMissileSpeed(missile.Type); missile.Angle = angle; missile.MomX = new Fixed(speed) * Trig.Cos(angle); missile.MomY = new Fixed(speed) * Trig.Sin(angle); var dist = Geometry.AproxDistance(dest.X - source.X, dest.Y - source.Y); var num = (dest.Z - source.Z).Data; var den = (dist / speed).Data; if (den < 1) { den = 1; } missile.MomZ = new Fixed(num / den); this.CheckMissileSpawn(missile); return(missile); }
private void Run_Add_Int_Int(Random r) { var a = r.Next(-10000, 10000); var b = r.Next(-10000, 10000); var result = a + b; LoopBase(() => result = a + b); var fa = Fixed.FromInt(a); var fb = Fixed.FromInt(b); var fresult = fa + fb; LoopFixed(() => fresult = fa + fb); if (result != fresult) { throw new InvalidOperationException(); } }
private void Run_Add_Int_Float(Random r) { var a = r.Next(-10000, 10000); var b = (float)(r.NextDouble() * r.Next(-10000, 10000)); var result = a + b; LoopBase(() => result = a + b); var fa = Fixed.FromInt(a); var fb = Fixed.FromFloat(b); var fresult = fa + fb; LoopFixed(() => fresult = fa + fb); if (!Fixed.Approximately(fresult, Fixed.FromFloat(result))) { throw new InvalidOperationException(); } }
/// <summary> /// Change the player's weapon sprite. /// </summary> public void SetPlayerSprite(Player player, PlayerSprite position, MobjState state) { var psp = player.PlayerSprites[(int)position]; do { if (state == MobjState.Null) { // Object removed itself. psp.State = null; break; } var stateDef = DoomInfo.States[(int)state]; psp.State = stateDef; psp.Tics = stateDef.Tics; // Could be 0. if (stateDef.Misc1 != 0) { // Coordinate set. psp.Sx = Fixed.FromInt(stateDef.Misc1); psp.Sy = Fixed.FromInt(stateDef.Misc2); } // Call action routine. // Modified handling. if (stateDef.PlayerAction != null) { stateDef.PlayerAction(this.world, player, psp); if (psp.State == null) { break; } } state = psp.State.Next; }while (psp.Tics == 0); // An initial state of 0 could cycle through. }
/// <summary> /// Fire a hitscan bullet. /// If damage == 0, it is just a test trace that will leave linetarget set. /// </summary> public void LineAttack(Mobj shooter, Angle angle, Fixed range, Fixed slope, int damage) { this.currentShooter = shooter; this.currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); this.currentRange = range; this.currentAimSlope = slope; this.currentDamage = damage; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); this.world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, this.shootTraverseFunc ); }
public static BlockMap FromWad(string fileName, LineDef[] lines) { var reader = new BinaryReader(DoomApplication.Instance.FileSystem.Read(fileName)); var data = reader.ReadBytes((int)reader.BaseStream.Length); var table = new short[data.Length / 2]; for (var i = 0; i < table.Length; i++) { var offset = 2 * i; table[i] = BitConverter.ToInt16(data, offset); } var originX = Fixed.FromInt(table[0]); var originY = Fixed.FromInt(table[1]); var width = table[2]; var height = table[3]; return(new BlockMap(originX, originY, width, height, table, lines)); }
public void Comparison() { var random = new Random(666); for (var i = 0; i < 100; i++) { var a = random.Next(5); var b = random.Next(5); var fa = Fixed.FromInt(a); var fb = Fixed.FromInt(b); Assert.AreEqual(a == b, fa == fb); Assert.AreEqual(a != b, fa != fb); Assert.AreEqual(a < b, fa < fb); Assert.AreEqual(a > b, fa > fb); Assert.AreEqual(a <= b, fa <= fb); Assert.AreEqual(a >= b, fa >= fb); } }
public void MinMax() { var random = new Random(666); for (var i = 0; i < 100; i++) { var a = random.Next(5); var b = random.Next(5); var min = Math.Min(a, b); var max = Math.Max(a, b); var fa = Fixed.FromInt(a); var fb = Fixed.FromInt(b); var fmin = Fixed.Min(fa, fb); var fmax = Fixed.Max(fa, fb); Assert.AreEqual(min, fmin.ToDouble(), 1.0E-9); Assert.AreEqual(max, fmax.ToDouble(), 1.0E-9); } }