181 lines
5.8 KiB
C#
181 lines
5.8 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Drawing;
|
|||
|
using System.Linq;
|
|||
|
using System.Media;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
using Microsoft.Xna.Framework;
|
|||
|
using Microsoft.Xna.Framework.Audio;
|
|||
|
using Microsoft.Xna.Framework.Graphics;
|
|||
|
using ICSharpCode.SharpZipLib.Zip;
|
|||
|
using System.IO;
|
|||
|
using System.Xml;
|
|||
|
using Microsoft.Xna.Framework.Media;
|
|||
|
using Microsoft.Xna.Framework.Content;
|
|||
|
using SpacePew.Models;
|
|||
|
using Rectangle = System.Drawing.Rectangle;
|
|||
|
|
|||
|
namespace SpacePew
|
|||
|
{
|
|||
|
static class LevelLoader
|
|||
|
{
|
|||
|
public static Level LoadLevel(string filePath, ContentManager cm, GraphicsDevice device)
|
|||
|
{
|
|||
|
var levelResources = GetResourceList(filePath);
|
|||
|
if (!levelResources.ContainsKey("leveldata.xml"))
|
|||
|
throw new InvalidOperationException("Level: " + filePath + " doesnt contain any leveldata.xml");
|
|||
|
|
|||
|
var levelData = GetXmlFile(levelResources["leveldata.xml"]);
|
|||
|
string baseTexture = levelData.SelectSingleNode("//baseTexture").InnerText.ToLower();
|
|||
|
string indestructibleTexture = levelData.SelectSingleNode("//indestructibleTexture").InnerText.ToLower();
|
|||
|
|
|||
|
var spriteBatch = new SpriteBatch(device);
|
|||
|
var level = new Level();
|
|||
|
level.FilePath = filePath;
|
|||
|
level.Texture = LoadTextureTiles(levelResources[baseTexture], device, spriteBatch);
|
|||
|
level.IndestructibleTexture = LoadTextureTiles(levelResources[indestructibleTexture], device, spriteBatch);
|
|||
|
level.DeformedTexture = new TiledTexture
|
|||
|
{
|
|||
|
Width = level.Texture.Width,
|
|||
|
Height = level.Texture.Height,
|
|||
|
TileHeight = level.Texture.TileHeight,
|
|||
|
TileWidth = level.Texture.TileWidth,
|
|||
|
XTiles = level.Texture.XTiles,
|
|||
|
YTiles = level.Texture.YTiles
|
|||
|
};
|
|||
|
|
|||
|
level.Texture.ForEach(t => level.DeformedTexture.Add(new Tile(
|
|||
|
new RenderTarget2D(device, level.Texture.TileWidth, level.Texture.TileHeight, false,
|
|||
|
SurfaceFormat.Color, DepthFormat.Depth24,
|
|||
|
device.PresentationParameters.MultiSampleCount,
|
|||
|
RenderTargetUsage.PreserveContents
|
|||
|
),
|
|||
|
t.Position)));
|
|||
|
|
|||
|
if (levelData.SelectSingleNode("//song") != null)
|
|||
|
{
|
|||
|
string songName = levelData.SelectSingleNode("//song").InnerText.ToLower();
|
|||
|
level.OggVorbisSong = levelResources[songName];
|
|||
|
}
|
|||
|
|
|||
|
level.Initialize();
|
|||
|
return level;
|
|||
|
}
|
|||
|
|
|||
|
private static XmlDocument GetXmlFile(byte[] rawData)
|
|||
|
{
|
|||
|
var d = new XmlDocument();
|
|||
|
d.LoadXml(System.Text.Encoding.UTF8.GetString(rawData));
|
|||
|
return d;
|
|||
|
}
|
|||
|
|
|||
|
public static TiledTexture LoadTextureTiles(Byte[] bitmapData, GraphicsDevice device, SpriteBatch spriteBatch, int tileWidth = 0, int tileHeight = 0)
|
|||
|
{
|
|||
|
using (var ms = new MemoryStream(bitmapData))
|
|||
|
{
|
|||
|
ms.Seek(0, SeekOrigin.Begin);
|
|||
|
using (var image = Image.FromStream(ms))
|
|||
|
{
|
|||
|
return LoadTextureTiles(image, device, spriteBatch, tileWidth, tileHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static TiledTexture LoadTextureTiles(string fileName, GraphicsDevice device, SpriteBatch spriteBatch, int tileWidth = 0, int tileHeight = 0)
|
|||
|
{
|
|||
|
using (var image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + fileName.Replace("/", "\\")))
|
|||
|
{
|
|||
|
return LoadTextureTiles(image, device, spriteBatch, tileWidth, tileHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static TiledTexture LoadTextureTiles(Image image, GraphicsDevice device, SpriteBatch spriteBatch, int tileWidth = 0, int tileHeight = 0)
|
|||
|
{
|
|||
|
//OBS!!! S<>tt kartans bredd el h<>jd till ett primtal o det <20>r k<>rt iom att d<> kan man inte hitta en j<>mn multiple och en oj<6F>mn kommer att anv<6E>ndas
|
|||
|
//och det kommer att pricka i framtiden.
|
|||
|
if (tileWidth == 0)
|
|||
|
tileWidth = FindNearbyMultiple(image.Width, 1000);
|
|||
|
if (tileHeight == 0)
|
|||
|
tileHeight = FindNearbyMultiple(image.Height, 1000);
|
|||
|
|
|||
|
|
|||
|
int tilesX = (image.Width % tileWidth == 0)
|
|||
|
? (int)Math.Floor(image.Width / (double)tileWidth)
|
|||
|
: (int)Math.Ceiling(image.Width / (double)tileWidth);
|
|||
|
|
|||
|
int tilesY = (image.Height % tileHeight == 0)
|
|||
|
? (int)Math.Floor(image.Height / (double)tileHeight)
|
|||
|
: (int)Math.Ceiling(image.Height / (double)tileHeight);
|
|||
|
|
|||
|
var ret = new TiledTexture
|
|||
|
{
|
|||
|
TileWidth = tileWidth,
|
|||
|
TileHeight = tileHeight,
|
|||
|
XTiles = tilesX,
|
|||
|
YTiles = tilesY,
|
|||
|
Width = image.Width,
|
|||
|
Height = image.Height
|
|||
|
};
|
|||
|
for (var j = 0; j < tilesX; j++)
|
|||
|
{
|
|||
|
for (var i = 0; i < tilesY; i++)
|
|||
|
{
|
|||
|
var part = new Bitmap(tileWidth, tileHeight, image.PixelFormat);
|
|||
|
var graphics = Graphics.FromImage(part);
|
|||
|
var srcRect = new Rectangle(j * tileWidth, i * tileHeight, tileWidth, tileHeight);
|
|||
|
graphics.DrawImage(image, 0, 0, srcRect, GraphicsUnit.Pixel);
|
|||
|
using (var ms = new MemoryStream())
|
|||
|
{
|
|||
|
//TODO: n<>got vettigare <20>n s<> h<>r f<>r att f<> fram bytesen... tar ju <20>r och dagar att ladda nu.
|
|||
|
part.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
|
|||
|
ms.Seek(0, SeekOrigin.Begin);
|
|||
|
|
|||
|
ret.Add(new Tile(Texture2D.FromStream(device, ms), new Microsoft.Xna.Framework.Point(j * tileWidth, i * tileHeight)));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
private static int FindNearbyMultiple(int totLen, int chunkLen)
|
|||
|
{
|
|||
|
chunkLen = totLen / (int)Math.Ceiling(totLen / (double)chunkLen);
|
|||
|
|
|||
|
var step = 0;
|
|||
|
while (step < 100)
|
|||
|
{
|
|||
|
var t = chunkLen - step;
|
|||
|
if ((totLen % t) == 0)
|
|||
|
return t;
|
|||
|
t = chunkLen + step;
|
|||
|
if ((totLen % t) == 0)
|
|||
|
return t;
|
|||
|
step++;
|
|||
|
}
|
|||
|
return FindNearbyMultiple(totLen - 1, chunkLen);
|
|||
|
}
|
|||
|
|
|||
|
private static Dictionary<string, byte[]> GetResourceList(string file)
|
|||
|
{
|
|||
|
var resources = new Dictionary<string, byte[]>();
|
|||
|
using (var stream = new ZipInputStream(File.OpenRead(file)))
|
|||
|
{
|
|||
|
ZipEntry entry = null;
|
|||
|
while ((entry = stream.GetNextEntry()) != null)
|
|||
|
{
|
|||
|
if (entry.Name.Length > 0)
|
|||
|
{
|
|||
|
var buf = new byte[(int)entry.Size];
|
|||
|
stream.Read(buf, 0, buf.Length);
|
|||
|
resources.Add(entry.Name.ToLower().Trim(), buf);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return resources;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|