public void Deserialize(Stream input) { var header = input.ReadStructure<Level.Header>(); this.Width = header.Width; this.Height = header.Height; this.OffsetX = header.OffsetX; this.OffsetY = header.OffsetY; if (Enumerable.Any(header.Padding, t => t != 0) == true) { throw new FormatException("non-zero data in padding"); } Array.Copy(header.TerrainIds, this.TerrainIds, header.TerrainIds.Length); for (int i = 0; i < this.TerrainIds.Length; i++) { this.TerrainIds[i] %= 16; } if (header.Version >= 4) { this.LightColorWhite = header.LightColorWhite; this.LightColorRed = header.LightColorRed; this.LightColorGreen = header.LightColorGreen; this.LightColorBlue = header.LightColorBlue; Array.Copy(header.PhysicsLow, this.PhysicsLow, header.PhysicsLow.Length); Array.Copy(header.PhysicsHigh, this.PhysicsHigh, header.PhysicsHigh.Length); } else { this.SetDefaults(); } var objects = new Level.BlobReference[header.ObjectCount]; for (int i = 0; i < objects.Length; i++) { if (header.Version >= 6) { objects[i] = input.ReadStructure<Level.BlobReference>(); } else { objects[i] = new Level.BlobReference { FileName = null, Id = string.Format("o{0}.cfs", i), }; } } this.Objects = new List<Level.BlobReference>(); this.Objects.AddRange(objects); var floors = new Level.BlobReference[header.FloorCount]; for (int i = 0; i < floors.Length; i++) { if (header.Version >= 6) { floors[i] = input.ReadStructure<Level.BlobReference>(); } else { floors[i] = new Level.BlobReference { FileName = null, Id = string.Format("f{0}.cfs", i), }; } } this.Floors = new List<Level.BlobReference>(); this.Floors.AddRange(floors); this.Tiles = new Level.Tile[this.Width * this.Height]; var tileData = input.ReadRLE(3, this.Tiles.Length, true); for (int i = 0, j = 0; i < this.Tiles.Length; i++, j += 3) { this.Tiles[i].BitsA = tileData[j + 0]; this.Tiles[i].BitsB = tileData[j + 1]; this.Tiles[i].BitsC = tileData[j + 2]; } if (header.Version < 4) { var magic = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x1A, 0x1B, 0x1C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x08, 0x09, 0x10, 0x1A, 0x1B, 0x1C, 0x1D, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, }; for (int i = 0; i < this.Tiles.Length; i++) { var a = this.Tiles[i].BitsC; var b = (byte)((magic[a & 0x1F] ^ a) & 0x1F); this.Tiles[i].BitsC ^= b; } } var entities = new Level.Entity[header.EntityCount]; if (header.Version >= 3) { for (int i = 0; i < header.EntityCount; i++) { entities[i] = input.ReadStructure<Level.Entity>(); } } else { using (var entityData = new MemoryStream(input.ReadRLE(14, header.EntityCount, true))) { for (int i = 0; i < header.EntityCount; i++) { var oldEntity = entityData.ReadStructure<Level.OldEntity>(); //entities[i] = new Level.Entity(); entities[i].X = oldEntity.X; entities[i].Y = oldEntity.Y; entities[i].BitsA = oldEntity.BitsA & 0x3FFFFFFFu; entities[i].BitsB = oldEntity.BitsB & 0x7FFFFFFFu; entities[i].BitsC = (oldEntity.BitsD & 0x7Fu) << 23; entities[i].BitsD = oldEntity.BitsC; } } } if (header.Version < 5) { for (int i = 0; i < header.EntityCount; i++) { entities[i].BitsC &= 0xBFFFFFFFu; } } this.Entities = new List<Level.Entity>(); this.Entities.AddRange(entities); if (input.Position != input.Length) { throw new FormatException(); } }
public static void Main(string[] args) { bool showHelp = false; int width = 500; int height = 500; var options = new OptionSet() { { "?|help", "show this message and exit", v => showHelp = v != null }, { "w|width=", "set level width", v => width = v != null ? int.Parse(v) : width }, { "h|height=", "set level height", v => height = v != null ? int.Parse(v) : height }, }; List<string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 0 || extras.Count > 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var outputPath = extras.Count > 0 ? extras[0] : "space.map"; var templates = LoadEntities(); int cx = width / 2; int cy = height / 2; // ReSharper disable UnusedVariable var radius = (int)(Math.Min(width, height) / 2.0); // ReSharper restore UnusedVariable var range = Math.Min(width, height) / 2.5; var rng = new MersenneTwister(); var noise = PerlinNoise.Generate( width, height, 0.0325f, 1.0f, 0.5f, 16, rng); var physics = new bool[width,height]; var vision = new bool[width,height]; var entities = new List<Entity>(); for (int x = 8; x < width - 8; x++) { for (int y = 8; y < height - 8; y++) { var distance = GetDistance(cx, cy, x, y); if (distance > range && rng.Next(100) > 2) { continue; } var magic = noise[x, y]; if (magic >= 200) { } else if (magic >= 180) { if (rng.Next(100) >= 60 && (x % 2) == 0 && (y % 2) == 0) { var template = templates .Where(t => t.Category == "asteroid") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithPhysics(x, y, physics, width, height) == true) { var entity = new Entity(x, y, template); int speed = rng.Next(100); if (speed < 60) { entity.AnimationTime = 0; } else if (speed < 70) { entity.AnimationTime = 100; } else if (speed < 80) { entity.AnimationTime = 200; } else if (speed < 85) { entity.AnimationTime = 250; } else if (speed < 90) { entity.AnimationTime = 350; } else if (speed < 95) { entity.AnimationTime = 400; } else { entity.AnimationTime = 450; } template.BlockPhysics(x, y, physics); entities.Add(entity); } } } else if (magic >= 100) { } else if (magic >= 15) { } else { if (rng.Next(100) >= 80) { var template = templates .Where(t => t.Category == "nebula") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithVision(x, y, vision, width, height) == true) { var entity = new Entity(x, y, template) { AnimationTime = 50 }; template.BlockVision(x, y, vision); entities.Add(entity); } } } } } var tiles = new Level.Tile[width,height]; foreach (var entity in entities) { for (int rx = 0; rx < entity.Template.Width; rx++) { for (int ry = 0; ry < entity.Template.Height; ry++) { if (entity.Template.Physics[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Physics = entity.Template.Physics[rx, ry]; } if (entity.Template.Vision[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Vision = entity.Template.Vision[rx, ry]; } } } } var floors = new List<Map.BlobReference> { new Map.BlobReference() { Path = "f_default.blo,default.cfs" }, }; //floors.Add(new Map.BlobReference() { Path = "f_colors.blo,color3.cfs" }); using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = width, Height = height, EntityCount = entities.Count, LightColorWhite = 0xFFFFFF00u, LightColorRed = 0x0000FF00u, LightColorGreen = 0x00FF0000u, LightColorBlue = 0xFF000000u, PhysicsLow = new short[32], PhysicsHigh = new short[32], }; header.PhysicsHigh[0] = 0; header.PhysicsHigh[1] = 1024; header.PhysicsHigh[2] = 1024; header.PhysicsHigh[3] = 1024; header.PhysicsHigh[4] = 1024; header.PhysicsHigh[5] = 1024; header.PhysicsHigh[6] = 16; header.PhysicsHigh[7] = 16; header.PhysicsHigh[8] = 16; header.PhysicsHigh[9] = 16; header.PhysicsHigh[10] = 16; header.PhysicsHigh[11] = 32; header.PhysicsHigh[12] = 32; header.PhysicsHigh[13] = 32; header.PhysicsHigh[14] = 32; header.PhysicsHigh[15] = 32; header.PhysicsHigh[16] = 64; header.PhysicsHigh[17] = 64; header.PhysicsHigh[18] = 64; header.PhysicsHigh[19] = 64; header.PhysicsHigh[20] = 64; header.PhysicsHigh[21] = 128; header.PhysicsHigh[22] = 128; header.PhysicsHigh[23] = 128; header.PhysicsHigh[24] = 128; header.PhysicsHigh[25] = 128; header.PhysicsHigh[26] = 1024; header.PhysicsHigh[27] = 1024; header.PhysicsHigh[29] = 1024; header.PhysicsHigh[28] = 1024; header.PhysicsHigh[30] = 1024; header.PhysicsHigh[31] = 1024; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < 16) { output.WriteValueU8((byte)i); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { if (i < floors.Count) { output.WriteStructure(floors[i]); } else { output.Seek(64, SeekOrigin.Current); } } var buffer = new byte[width * height * 4]; for (int y = 0, offset = 0; y < height; y++) { for (int x = 0; x < width; x++, offset += 4) { buffer[offset + 0] = tiles[x, y].BitsA; buffer[offset + 1] = 0; buffer[offset + 2] = tiles[x, y].BitsC; buffer[offset + 3] = tiles[x, y].BitsB; } } using (var rle = new MemoryStream()) { rle.WriteRLE(buffer, 4, width * height, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var source in entities) { var entity = new Level.Entity { X = (short)((source.X - source.Template.OffsetX) * 16), Y = (short)((source.Y - source.Template.OffsetY) * 16), AnimationTime = source.AnimationTime, }; output.WriteStructure(entity); var reference = new Map.BlobReference { Path = string.Format("{0},{1}", source.Template.BloName, source.Template.CfsName), }; output.WriteStructure(reference); } } }
public void Deserialize(Stream input) { var header = input.ReadStructure <Level.Header>(); this.Width = header.Width; this.Height = header.Height; this.OffsetX = header.OffsetX; this.OffsetY = header.OffsetY; if (Enumerable.Any(header.Padding, t => t != 0) == true) { throw new FormatException("non-zero data in padding"); } Array.Copy(header.TerrainIds, this.TerrainIds, header.TerrainIds.Length); for (int i = 0; i < this.TerrainIds.Length; i++) { this.TerrainIds[i] %= 16; } if (header.Version >= 4) { this.LightColorWhite = header.LightColorWhite; this.LightColorRed = header.LightColorRed; this.LightColorGreen = header.LightColorGreen; this.LightColorBlue = header.LightColorBlue; Array.Copy(header.PhysicsLow, this.PhysicsLow, header.PhysicsLow.Length); Array.Copy(header.PhysicsHigh, this.PhysicsHigh, header.PhysicsHigh.Length); } else { this.SetDefaults(); } var objects = new Level.BlobReference[header.ObjectCount]; for (int i = 0; i < objects.Length; i++) { if (header.Version >= 6) { objects[i] = input.ReadStructure <Level.BlobReference>(); } else { objects[i] = new Level.BlobReference { FileName = null, Id = string.Format("o{0}.cfs", i), }; } } this.Objects = new List <Level.BlobReference>(); this.Objects.AddRange(objects); var floors = new Level.BlobReference[header.FloorCount]; for (int i = 0; i < floors.Length; i++) { if (header.Version >= 6) { floors[i] = input.ReadStructure <Level.BlobReference>(); } else { floors[i] = new Level.BlobReference { FileName = null, Id = string.Format("f{0}.cfs", i), }; } } this.Floors = new List <Level.BlobReference>(); this.Floors.AddRange(floors); this.Tiles = new Level.Tile[this.Width * this.Height]; var tileData = input.ReadRLE(3, this.Tiles.Length, true); for (int i = 0, j = 0; i < this.Tiles.Length; i++, j += 3) { this.Tiles[i].BitsA = tileData[j + 0]; this.Tiles[i].BitsB = tileData[j + 1]; this.Tiles[i].BitsC = tileData[j + 2]; } if (header.Version < 4) { var magic = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x1A, 0x1B, 0x1C, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x08, 0x09, 0x10, 0x1A, 0x1B, 0x1C, 0x1D, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, }; for (int i = 0; i < this.Tiles.Length; i++) { var a = this.Tiles[i].BitsC; var b = (byte)((magic[a & 0x1F] ^ a) & 0x1F); this.Tiles[i].BitsC ^= b; } } var entities = new Level.Entity[header.EntityCount]; if (header.Version >= 3) { for (int i = 0; i < header.EntityCount; i++) { entities[i] = input.ReadStructure <Level.Entity>(); } } else { using (var entityData = new MemoryStream(input.ReadRLE(14, header.EntityCount, true))) { for (int i = 0; i < header.EntityCount; i++) { var oldEntity = entityData.ReadStructure <Level.OldEntity>(); //entities[i] = new Level.Entity(); entities[i].X = oldEntity.X; entities[i].Y = oldEntity.Y; entities[i].BitsA = oldEntity.BitsA & 0x3FFFFFFFu; entities[i].BitsB = oldEntity.BitsB & 0x7FFFFFFFu; entities[i].BitsC = (oldEntity.BitsD & 0x7Fu) << 23; entities[i].BitsD = oldEntity.BitsC; } } } if (header.Version < 5) { for (int i = 0; i < header.EntityCount; i++) { entities[i].BitsC &= 0xBFFFFFFFu; } } this.Entities = new List <Level.Entity>(); this.Entities.AddRange(entities); if (input.Position != input.Length) { throw new FormatException(); } }
public static void Main(string[] args) { bool showHelp = false; int width = 500; int height = 500; var options = new OptionSet() { { "?|help", "show this message and exit", v => showHelp = v != null }, { "w|width=", "set level width", v => width = v != null?int.Parse(v) : width }, { "h|height=", "set level height", v => height = v != null?int.Parse(v) : height }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 0 || extras.Count > 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ [output_map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var outputPath = extras.Count > 0 ? extras[0] : "space.map"; var templates = LoadEntities(); int cx = width / 2; int cy = height / 2; // ReSharper disable UnusedVariable var radius = (int)(Math.Min(width, height) / 2.0); // ReSharper restore UnusedVariable var range = Math.Min(width, height) / 2.5; var rng = new MersenneTwister(); var noise = PerlinNoise.Generate( width, height, 0.0325f, 1.0f, 0.5f, 16, rng); var physics = new bool[width, height]; var vision = new bool[width, height]; var entities = new List <Entity>(); for (int x = 8; x < width - 8; x++) { for (int y = 8; y < height - 8; y++) { var distance = GetDistance(cx, cy, x, y); if (distance > range && rng.Next(100) > 2) { continue; } var magic = noise[x, y]; if (magic >= 200) { } else if (magic >= 180) { if (rng.Next(100) >= 60 && (x % 2) == 0 && (y % 2) == 0) { var template = templates .Where(t => t.Category == "asteroid") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithPhysics(x, y, physics, width, height) == true) { var entity = new Entity(x, y, template); int speed = rng.Next(100); if (speed < 60) { entity.AnimationTime = 0; } else if (speed < 70) { entity.AnimationTime = 100; } else if (speed < 80) { entity.AnimationTime = 200; } else if (speed < 85) { entity.AnimationTime = 250; } else if (speed < 90) { entity.AnimationTime = 350; } else if (speed < 95) { entity.AnimationTime = 400; } else { entity.AnimationTime = 450; } template.BlockPhysics(x, y, physics); entities.Add(entity); } } } else if (magic >= 100) { } else if (magic >= 15) { } else { if (rng.Next(100) >= 80) { var template = templates .Where(t => t.Category == "nebula") .OrderBy(t => rng.Next()) .FirstOrDefault(); if (template != null && template.CanPlaceWithVision(x, y, vision, width, height) == true) { var entity = new Entity(x, y, template) { AnimationTime = 50 }; template.BlockVision(x, y, vision); entities.Add(entity); } } } } } var tiles = new Level.Tile[width, height]; foreach (var entity in entities) { for (int rx = 0; rx < entity.Template.Width; rx++) { for (int ry = 0; ry < entity.Template.Height; ry++) { if (entity.Template.Physics[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Physics = entity.Template.Physics[rx, ry]; } if (entity.Template.Vision[rx, ry] > 0) { tiles[entity.X + rx, entity.Y + ry].Vision = entity.Template.Vision[rx, ry]; } } } } var floors = new List <Map.BlobReference> { new Map.BlobReference() { Path = "f_default.blo,default.cfs" }, }; //floors.Add(new Map.BlobReference() { Path = "f_colors.blo,color3.cfs" }); using (var output = File.Create(outputPath)) { var header = new Map.Header { Version = 9, Width = width, Height = height, EntityCount = entities.Count, LightColorWhite = 0xFFFFFF00u, LightColorRed = 0x0000FF00u, LightColorGreen = 0x00FF0000u, LightColorBlue = 0xFF000000u, PhysicsLow = new short[32], PhysicsHigh = new short[32], }; header.PhysicsHigh[0] = 0; header.PhysicsHigh[1] = 1024; header.PhysicsHigh[2] = 1024; header.PhysicsHigh[3] = 1024; header.PhysicsHigh[4] = 1024; header.PhysicsHigh[5] = 1024; header.PhysicsHigh[6] = 16; header.PhysicsHigh[7] = 16; header.PhysicsHigh[8] = 16; header.PhysicsHigh[9] = 16; header.PhysicsHigh[10] = 16; header.PhysicsHigh[11] = 32; header.PhysicsHigh[12] = 32; header.PhysicsHigh[13] = 32; header.PhysicsHigh[14] = 32; header.PhysicsHigh[15] = 32; header.PhysicsHigh[16] = 64; header.PhysicsHigh[17] = 64; header.PhysicsHigh[18] = 64; header.PhysicsHigh[19] = 64; header.PhysicsHigh[20] = 64; header.PhysicsHigh[21] = 128; header.PhysicsHigh[22] = 128; header.PhysicsHigh[23] = 128; header.PhysicsHigh[24] = 128; header.PhysicsHigh[25] = 128; header.PhysicsHigh[26] = 1024; header.PhysicsHigh[27] = 1024; header.PhysicsHigh[29] = 1024; header.PhysicsHigh[28] = 1024; header.PhysicsHigh[30] = 1024; header.PhysicsHigh[31] = 1024; output.WriteStructure(header); for (int i = 0; i < 8192; i++) { if (i < 16) { output.WriteValueU8((byte)i); } else { output.WriteValueU8(0); } } for (int i = 0; i < 2048; i++) { if (i < floors.Count) { output.WriteStructure(floors[i]); } else { output.Seek(64, SeekOrigin.Current); } } var buffer = new byte[width * height * 4]; for (int y = 0, offset = 0; y < height; y++) { for (int x = 0; x < width; x++, offset += 4) { buffer[offset + 0] = tiles[x, y].BitsA; buffer[offset + 1] = 0; buffer[offset + 2] = tiles[x, y].BitsC; buffer[offset + 3] = tiles[x, y].BitsB; } } using (var rle = new MemoryStream()) { rle.WriteRLE(buffer, 4, width * height, false); rle.Position = 0; output.WriteValueS32((int)rle.Length); output.WriteFromStream(rle, rle.Length); } foreach (var source in entities) { var entity = new Level.Entity { X = (short)((source.X - source.Template.OffsetX) * 16), Y = (short)((source.Y - source.Template.OffsetY) * 16), AnimationTime = source.AnimationTime, }; output.WriteStructure(entity); var reference = new Map.BlobReference { Path = string.Format("{0},{1}", source.Template.BloName, source.Template.CfsName), }; output.WriteStructure(reference); } } }