Marshal.Copy() causes System.StackOverflowException - c#
I encountered a System.StackOverflowException problem when I was trying to Marshal.Copy()
Here is the screen shot of the code where exception happens:
Here is the function:
private static void ImageUpdate(IntPtr returnArray, ref int channels)
{
if (_prevTickCount == 0)
{
_sumTickCount = 0;
}
else
{
_sumTickCount = _sumTickCount * .75 + (Environment.TickCount - _prevTickCount) * .25;
}
//only copy to the buffer when pixel data is not being read
if (_pixelDataReady == false)
{
int width = 0;
int height = 0;
if (false == GetImageDimensions(ref width, ref height))
{
return;
}
_dataLength = width * height;
_colorChannels = channels;
if ((_pixelData == null) || (_pixelData.Length != (_dataLength * _colorChannels)))
{
_pixelData = new short[_dataLength * _colorChannels];
//_pixelDataHistogram = new int[_colorChannels][];
_pixelDataHistogram = new int[MAX_CHANNELS][];
if (_colorChannels == 1)
{
_pixelDataByte = new byte[_dataLength];
}
else
{
_pixelDataByte = new byte[_dataLength * 3];
}
//for (int i = 0; i < _colorChannels; i++)
for (int i = 0; i < MAX_CHANNELS; i++)
{
_pixelDataHistogram[i] = new int[PIXEL_DATA_HISTOGRAM_SIZE];
}
}
//2^n == FULL_RANGE_NORMALIZATION_FACTOR
const int SHIFT_VALUE = 6;
switch (_colorChannels)
{
case 1:
{
Marshal.Copy(returnArray, _pixelData, 0, _dataLength * _colorChannels);
//factor is derived by taking CAMERA_MAX_INTENSITY_VALUE/256
//const double FULL_RANGE_NORMALIZATION_FACTOR = 64.0;
//clear the histogram
for (int i = 0; i < PIXEL_DATA_HISTOGRAM_SIZE; i++)
{
_pixelDataHistogram[0][i] = 0;
}
for (int i = 0; i < _dataLength * _colorChannels; i++)
{
double valHist;
if (_pixelData[i] < 0)
{
valHist = (_pixelData[i] + 32768) >> SHIFT_VALUE;
}
else
{
valHist = (_pixelData[i]) >> SHIFT_VALUE;
}
_pixelDataHistogram[0][(byte)valHist]++;
}
}
break;
default:
{
Marshal.Copy(returnArray, _pixelData, 0, _dataLength * _colorChannels);
}
break;
}
_dataWidth = width;
_dataHeight = height;
_pixelDataReady = true;
ThorLog.Instance.TraceEvent(TraceEventType.Verbose, 1, "ImageUpdate pixeldata updated");
}
else
{
ThorLog.Instance.TraceEvent(TraceEventType.Verbose, 1, "ImageUpdate pixeldata not ready");
}
_prevTickCount = Environment.TickCount;
}
The whole idea is to copy image buffer from native code. This exception occurs only when image size is large 4K X 4K, but I dont have a problem processing a size below that.
I have no idea how I should correct this. Anyone care to educate? Thanks!
I traced it down, eventually, if was the returnArray which is not newed large enough to cause this problem.
Related
Unable to detect if two rectangles are colliding C#
I am working on a procedural room generator in c#, I would like the rooms not to overlap and I am having a hard time getting that to work. After #Idle_Mind's comments, I have a new problem. The Image produced by the program has many overlapping rooms. Bellow is the class that should handle the intersection checking and the placement of the rooms onto the tilemap public int XSize, YSize; private Cell[ , ] cells; private List<Room> rooms; public Tilemap(int xSize, int ySize) { XSize = xSize; YSize = ySize; rooms = new List<Room>(); cells = new Cell[XSize, YSize]; for (int y = 0; y < YSize; y++) { for (int x = 0; x < XSize; x++) { cells[x, y].type = CellType.Empty; } } for (int i = 0; i < 10; i++) { GenerateRandomRoomSafe(10); } } private Room GetRoomBounds() { Utils.Int2 min = new Utils.Int2(0, 0); Utils.Int2 max = new Utils.Int2(XSize,YSize); Utils.Int2 q1 = Utils.GetRandomCoords(min, max); max.X = XSize - 1 - q1.X; max.Y = YSize - 1 - q1.Y; Utils.Int2 siz = Utils.GetRandomCoords(min, max); Room check = new Room(q1.X, q1.Y, siz.X, siz.Y); return check; } public void GenerateRandomRoomSafe(int maxTries) { Room check = new Room(0, 0, 0, 0); bool isValid = false; int tries = 0; if (rooms.Count == 0) { isValid = true; check = GetRoomBounds(); tries = 1; } else { while (!isValid && tries < maxTries) { check = GetRoomBounds(); for (int i = 0; i < rooms.Count; i++) { if (!rooms[i].Walls.IntersectsWith(check.Walls)) { isValid = true; break; } } tries++; } } if (isValid) { Console.WriteLine(check + " was placed after " + tries + " tries"); PlaceRoomUnsafe(check); } } public void PlaceRoomUnsafe(Room r) { for (int y = r.Walls.Y; y <= r.Walls.Y + r.Walls.Height; y++) { cells[r.Walls.X, y].type = CellType.Wall; } for (int y = r.Walls.Y; y <= r.Walls.Y + r.Walls.Height; y++) { cells[r.Walls.X + r.Walls.Width, y].type = CellType.Wall; } for (int x = r.Walls.X; x <= r.Walls.X + r.Walls.Width; x++) { cells[x, r.Walls.Y].type = CellType.Wall; } for (int x = r.Walls.X; x <= r.Walls.X + r.Walls.Width; x++) { cells[x, r.Walls.Y + r.Walls.Height].type = CellType.Wall; } for (int y = r.Floor.Y; y < r.Floor.Y + r.Floor.Height; y++) { for (int x = r.Floor.X; x < r.Floor.X + r.Floor.Width; x++) { cells[x, y].type = CellType.Floor; } } rooms.Add(r); } public void GenerateRandomRoomUnsafe() { Room r = GetRoomBounds(); PlaceRoomUnsafe(r); } public int GetCellPixel(int x, int y) { return (int) cells[x, y].type; } public class Room { public Rectangle Walls; public Rectangle Floor; public Room(int q1X, int q1Y, int xSize, int ySize) { Walls.X = q1X; Walls.Y = q1Y; Walls.Width = xSize; Walls.Height = ySize; Floor.X = q1X + 1; Floor.Y = q1Y + 1; Floor.Width = xSize - 1; Floor.Height = ySize - 1; } public override string ToString() { return "[Walls: " + Walls + "\n Floor: " + Floor + "]"; } } } Image below for reference
Your logic in GenerateRandomRoomSafe() is backwards. In this code block: while (!isValid && tries < maxTries) { check = GetRoomBounds(); for (int i = 0; i < rooms.Count; i++) { if (!rooms[i].Walls.IntersectsWith(check.Walls)) { isValid = true; break; } } tries++; } What you're saying is, "If it doesn't intersect with at least one room, then it must be valid". Just because it doesn't intersect with the current room, doesn't mean it won't intersect with a different one! It should look more like: (note the comments) while (!isValid && tries < maxTries) { isValid = true; // assume it's good until proven otherwise check = GetRoomBounds(); for (int i = 0; i < rooms.Count; i++) { if (rooms[i].Walls.IntersectsWith(check.Walls)) // if it DOES intersect... { isValid = false; // .. then set valid to false. break; } } tries++; } So we start by assuming it is valid, then when we encounter a room that DOES intersect, we set valid to false and stop the for loop so another random room can be tried (assuming we haven't exceeded the number of tries). Some of the maps it produced:
Ray/AABB Intersection Incorrect
I've tried to reimplement the Fast Graphics Gems Ray/AABB Intersection Method in C#: // Based on "Fast Ray-Box Intersection" algorithm by Andrew Woo, "Graphics Gems", Academic Press, 1990 public unsafe Vector? IntersectionWith(Cuboid other) { const int NUM_DIMENSIONS = 3; Assure.Equal(NUM_DIMENSIONS, 3); // If that value is ever changed, this algorithm will need some maintenance const byte QUADRANT_MIN = 0; const byte QUADRANT_MAX = 1; const byte QUADRANT_BETWEEN = 2; // Step 1: Work out which direction from the start point to test for intersection for all 3 dimensions, and the distance byte* quadrants = stackalloc byte[NUM_DIMENSIONS]; float* candidatePlanes = stackalloc float[NUM_DIMENSIONS]; float* cuboidMinPoints = stackalloc float[NUM_DIMENSIONS]; float* cuboidMaxPoints = stackalloc float[NUM_DIMENSIONS]; float maxDistance = Single.NegativeInfinity; byte maxDistanceDimension = 0; bool startPointIsInsideCuboid = true; cuboidMinPoints[0] = other.X; cuboidMinPoints[1] = other.Y; cuboidMinPoints[2] = other.Z; cuboidMaxPoints[0] = other.X + other.Width; cuboidMaxPoints[1] = other.Y + other.Height; cuboidMaxPoints[2] = other.Z + other.Depth; for (byte i = 0; i < NUM_DIMENSIONS; ++i) { if (StartPoint[i] < cuboidMinPoints[i]) { quadrants[i] = QUADRANT_MIN; candidatePlanes[i] = cuboidMinPoints[i]; startPointIsInsideCuboid = false; } else if (StartPoint[i] > cuboidMaxPoints[i]) { quadrants[i] = QUADRANT_MAX; candidatePlanes[i] = cuboidMaxPoints[i]; startPointIsInsideCuboid = false; } else { quadrants[i] = QUADRANT_BETWEEN; } } if (startPointIsInsideCuboid) return StartPoint; // Step 2: Find farthest dimension from cuboid for (byte i = 0; i < NUM_DIMENSIONS; ++i) { // ReSharper disable once CompareOfFloatsByEqualityOperator Exact check is desired here: Anything other than 0f is usable if (quadrants[i] != QUADRANT_BETWEEN && Orientation[i] != 0f) { float thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i]; if (thisDimensionDist > maxDistance) { maxDistance = thisDimensionDist; maxDistanceDimension = i; } } } if (maxDistance < 0f) return null; if (maxDistance - Length > MathUtils.FlopsErrorMargin) return null; float* intersectionPoint = stackalloc float[NUM_DIMENSIONS]; for (byte i = 0; i < NUM_DIMENSIONS; ++i) { if (maxDistanceDimension == i) { intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i]; if (cuboidMinPoints[i] - intersectionPoint[i] > MathUtils.FlopsErrorMargin || intersectionPoint[i] - cuboidMaxPoints[i] > MathUtils.FlopsErrorMargin) return null; } else intersectionPoint[i] = candidatePlanes[i]; } Vector result = new Vector(intersectionPoint[0], intersectionPoint[1], intersectionPoint[2]); if (!IsInfiniteLength && Vector.DistanceSquared(StartPoint, result) > Length * Length) return null; else return result; } However, although it sort of works, I'm getting incorrect results on the following part of a unit test: Cuboid cuboid = new Cuboid(frontBottomLeft: new Vector(0f, 7.1f, 0f), width: 0f, height: 5f, depth: 0f); Ray testRayC = new Ray(startPoint: new Vector(30f, 30f, 30f), orientation: new Vector(-1f, -1f, -1f)); Assert.AreEqual( null, testRayC.IntersectionWith(cuboid) ); I am expecting null from the call to testRayC.IntersectionWith(cuboid), but instead it returns a Vector(0, 12.1, 0), which is not a point on the ray at all. So is it just a case of adding a final check that the calculated point is on the ray? Or (and this is what I suspect), have I made an error in transcribing the code? I have double and triple checked but didn't see anything obvious...
The problem in your code is when you do if (maxDistanceDimension == i) {. The original code checks if (whichPlane != i) {. I don't have your data structures, but a fix should look like: for (byte i = 0; i < NUM_DIMENSIONS; ++i) { if (maxDistanceDimension != i) { intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i]; if (intersectionPoint[i] < cuboidMinPoints[i] - MathUtils.FlopsErrorMargin || intersectionPoint[i] > cuboidMaxPoints[i] + MathUtils.FlopsErrorMargin) return null; } else { intersectionPoint[i] = candidatePlanes[i]; } } Next, the following isn't in the original code. What is this for? if (maxDistance - Length > MathUtils.FlopsErrorMargin) return null; If you are trying to check if the hit is within the extent of the ray, this may be a bug. Given that your Orientation does not appear to be normalized, maxDistance is not necessarily in units of length. This may not matter in the original algorithm, but if you are going to check maxDistance against some other length you need to normalize Orientation (make it dimensionless) so that thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i]; will have units of length. Incidentally, in the original I think the following is wrong: if(inside) { coord = origin; return (TRUE); } Assuming this code is c and not c++, this simply sets the the coord pointer to have the same reference as the origin pointer, which will have no effect on the caller. This issue doesn't apply to your version, however. Also, in the course of looking at this, I made a more literal c# transcription of the algorithm here: public static class RayXCuboid { enum HitQuadrant { Right = 0, Left = 1, Middle = 2, } const int Dimension = 3; [Conditional("DEBUG")] static void AssertValidArguments<TDoubleList>(params TDoubleList[] args) where TDoubleList : IList<double> { Debug.Assert(Dimension == 3); foreach (var list in args) Debug.Assert(list != null && list.Count == Dimension); } public static bool HitBoundingBox<TDoubleList>(TDoubleList minB, TDoubleList maxB, TDoubleList origin, TDoubleList dir, TDoubleList coord) where TDoubleList : IList<double> { AssertValidArguments(minB, maxB, origin, dir, coord); HitQuadrant[] quadrant = new HitQuadrant[Dimension]; double[] maxT = new double[Dimension]; double[] candidatePlane = new double[Dimension]; /* Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view) */ bool inside = true; for (int i = 0; i < Dimension; i++) if (origin[i] < minB[i]) { quadrant[i] = HitQuadrant.Left; candidatePlane[i] = minB[i]; inside = false; } else if (origin[i] > maxB[i]) { quadrant[i] = HitQuadrant.Right; candidatePlane[i] = maxB[i]; inside = false; } else { quadrant[i] = HitQuadrant.Middle; } /* Ray origin inside bounding box */ if (inside) { CopyTo(origin, coord); return true; } /* Calculate T distances to candidate planes */ for (int i = 0; i < Dimension; i++) if (quadrant[i] != HitQuadrant.Middle && dir[i] != 0.0) maxT[i] = (candidatePlane[i] - origin[i]) / dir[i]; else maxT[i] = -1.0; /* Get largest of the maxT's for final choice of intersection */ int whichPlane = 0; for (int i = 1; i < Dimension; i++) if (maxT[whichPlane] < maxT[i]) whichPlane = i; /* Check final candidate actually inside box */ if (maxT[whichPlane] < 0.0) { FillWithDefault(coord); return false; } for (int i = 0; i < Dimension; i++) if (whichPlane != i) { coord[i] = origin[i] + maxT[whichPlane] * dir[i]; if (coord[i] < minB[i] || coord[i] > maxB[i]) { FillWithDefault(coord); return false; } } else { coord[i] = candidatePlane[i]; } return true; /* ray hits box */ } static void FillWithDefault<T>(IList<T> list) { for (int i = 0; i < list.Count; i++) list[i] = default(T); } static void CopyTo<T>(IList<T> from, IList<T> to) { int arrayIndex = 0; foreach (var item in from) to[arrayIndex++] = item; } }
The knights tour for 8x8 infinite recurssion
here will be my code for famous Knights Tour for 8x8 deck. So, the main idea of my code is: we will choose from Turns our destination, check it with isPossible and then go recursevly to it, marked this cell to '1'. So, check every cell, and if we will be in 64's cell - return true. But my code goes to infinite recurssion, and I can't debug it, any recommendation will be greatly appreciated. class Class1 { static void Main(string[] args) { int x = 0; int y = 0; Console.WriteLine("Enter X and press enter"); x = Int32.Parse(Console.ReadLine()); Console.WriteLine("Enter Y and press enter"); y = Int32.Parse(Console.ReadLine()); TurnVariation Turns = new TurnVariation(); EmptyBoard Board = new EmptyBoard(); if (TryPut.Put(Board, x, y, Turns, 1, false)) { Console.WriteLine("МОЖНА!!!!"); } else { Console.WriteLine("NET!!"); } } } public class TryPut : EmptyBoard { public static bool Put(EmptyBoard Board, int x, int y, TurnVariation Turns, int count, bool flag) { int tempX = 0; int tempY = 0; if (count >= 64) { Console.WriteLine("yeab"); return true; } for (int i = 0; i <= 7; i++) { tempX = x + Turns.Turns[i,0]; tempY = y + Turns.Turns[i,1]; //Console.WriteLine(count); if (IsPossible(Board, tempX, tempY)) { Board.Array[tempX, tempY] = 1; flag = Put(Board, tempX, tempY, Turns, count+1, flag); if (flag) { break; } Board.Array[tempX, tempY] = 0; } } if (flag) return true; else return false; } public static bool IsPossible(EmptyBoard Board, int x, int y) { if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) return false; if (Board.Array[x, y] == 1) return false; return true; } } public class TurnVariation { public int[,] Turns = new int[8, 2]; public TurnVariation() { Turns[0, 0] = -2; Turns[0, 1] = 1; Turns[1,0] = -2; Turns[1,1] = -1; Turns[2,0] = -1; Turns[2,1] = 2; Turns[3,0] = 1; Turns[3,1] = 2; Turns[4,0] = 2; Turns[4,1] = 1; Turns[5,0] = 2; Turns[5,1] = -1; Turns[6,0] = 1; Turns[6,1] = -2; Turns[7,0] = -1; Turns[7,1] = -2; } } public class EmptyBoard { public const int N = 8; public int[,] Array = new int[N, N]; public EmptyBoard() { for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) Array[i, j] = 0; } }
I think your problem is that your testing for count<64, but you never assign to count. You just pass (by value!) 'Count + 1' to the put method. You are probably thinking that this will bewritten back to the count variable. But that is not the case... Do note that debugging is the first skill you need to learn!
AccessViolationException with VST.NET and NAudio host application in C#
I'm trying to create a VSTstream class based on this thread: http://vstnet.codeplex.com/discussions/228692. To record and playback the sound I'm using the AsioOut object that gives me available to IntPtr[] buffers type in the callback function OnAudioAvailable(). To do this I created the VSTstream class, taking example from the thread linked, appropriately modified to process directly the IntPtr[] buffers. During the various processes of casting, however, it gives me an error of "AccessViolationException", probably due to the casting wrong. I'm testing the VSTstream class opening the Jacobi.Vst.Samples.Delay.dll EDIT: The error occurs on this line: Marshal.Copy(sourceBuffer[1], rightBuf, 0, sampleCount/channels); Does anyone know what I did wrong? If you need additional information or code I'm available. Thanks to all. OnAudioAvailable(): private void OnAudioAvailable(object sender, AsioAudioAvailableEventArgs e) { //No Effect for (int i = 0; i < e.InputBuffers.Length; i++) { MoveMemory(e.OutputBuffers[i], e.InputBuffers[i], e.SamplesPerBuffer * e.InputBuffers.Length * 2); } //Effect if (Parametri.effetto) { //Accendo i plugin for (int i = 0; i < plugins.Count; i++) { plugins[i].MainsChanged(true); plugins[i].StartProcess(); } //Processo i sample vstStream.ProcessSample(e.OutputBuffers, 0, e.SamplesPerBuffer * e.InputBuffers.Length * 2, e.InputBuffers); //Spengo i plugin for (int i = 0; i < plugins.Count; i++) { plugins[i].StopProcess(); plugins[i].MainsChanged(false); } } e.WrittenToOutputBuffers = true; } VSTstream class: class VSTstream { public List<IVstPluginCommandStub> plugins; VstAudioBufferManager vstBufManIn, vstBufManOut; private VstAudioBuffer[] vstBufIn = null; private VstAudioBuffer[] vstBufOut = null; private int sampleRate, channels, blockSize; private float[] leftBuf, rightBuf; public VSTstream(int sampleRate, int channels, int blockSize, List<IVstPluginCommandStub> plugins) { this.plugins = plugins; this.sampleRate = sampleRate; this.channels = channels; this.blockSize = blockSize; plugins[0].SetBlockSize(blockSize); plugins[0].SetSampleRate((float)sampleRate); vstBufManIn = new VstAudioBufferManager(channels, blockSize); //*channels vstBufManOut = new VstAudioBufferManager(channels, blockSize); //vstBufIn = vstBufManIn.ToArray(); //vstBufOut = vstBufManOut.ToArray(); vstBufIn = vstBufManIn.Cast<VstAudioBuffer>().ToArray(); vstBufOut = vstBufManOut.Cast<VstAudioBuffer>().ToArray(); leftBuf = new float[(blockSize * 4)/channels]; rightBuf = new float[(blockSize * 4)/channels]; } public int ProcessSample(IntPtr[] destBuffer, int offset, int sampleCount, IntPtr[] sourceBuffer) { //da IntPtr[L][R] a Lfloat[]+Rfloat[] Marshal.Copy(sourceBuffer[0], leftBuf, 0, sampleCount/channels);// (/channels) Marshal.Copy(sourceBuffer[1], rightBuf, 0, sampleCount/channels); unsafe { fixed (float* Lfloat = &leftBuf[0]) { fixed (float* Rfloat = &rightBuf[0]) { for (int i = 0; i < sampleCount / channels; i++) { vstBufIn[0][i] = *(Lfloat + i); vstBufIn[1][i] = *(Rfloat + i); } } } } //Qui dovrà rimanere solo 'ProcessReplacing();' //plugins[0].MainsChanged(true); //plugins[0].StartProcess(); plugins[0].ProcessReplacing(vstBufIn, vstBufOut); //plugins[0].StopProcess(); //plugins[0].MainsChanged(false); unsafe { float* tmpBufL = ((IDirectBufferAccess32)vstBufOut[0]).Buffer; float* tmpBufR = ((IDirectBufferAccess32)vstBufOut[1]).Buffer; for (int i = 0; i < (sampleCount / channels); i++) { leftBuf[i] = *(tmpBufL + i); rightBuf[i] = *(tmpBufR + i); } } //da Lfloat[]+Rfloat[] a IntPtr[L][R] Marshal.Copy(leftBuf, 0, destBuffer[0], sampleCount/channels); Marshal.Copy(rightBuf, 0, destBuffer[1], sampleCount/channels); return sampleCount; } }
how can i drag a 2d level array from a txt file
i am working on improving this tower defence gtame that i finished from this tutorial http://xnatd.blogspot.com/ i now wish to load the levels from a text file but not quite sure how i would do this using a streamreader, any tips? heres the source code for my level class; public class Level { protected int temperature; protected int levelNo; private Queue<Vector2> waypoints = new Queue<Vector2>(); public Queue<Vector2> Waypoints { get { return waypoints; } } int[,] map = new int[,] { {0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,}, {0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,}, {0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,}, {0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,}, {0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,}, {0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,}, {0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,}, {0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,}, {0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,}, {0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,}, {0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,}, {0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,}, {0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,}, {0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,}, {0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,}, {0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,}, }; public int Temperature // get the width of the level (how many numbers are in a row) { get { return temperature; } } public int LevelNo // get the width of the level (how many numbers are in a row) { get { return levelNo; } set { levelNo = value; } } public int Width // get the width of the level (how many numbers are in a row) { get { return map.GetLength(1); } } public int Height // get the height of our level (how many numbers are there in a column) { get { return map.GetLength(0); } } public int GetIndex(int cellX, int cellY) // return the index of the requested cell. { if (cellX < 0 || cellX > Width - 1 || cellY < 0 || cellY > Height - 1) { return 0; } else { return map[cellY, cellX]; } } public List<Texture2D> tileTextures = new List<Texture2D>(); // list to contain all the textures /// <summary> /// CONSTRUCTOR NEW LEVEL /// </summary> public Level() { SetWayPoints(map); this.temperature = 1000; this.levelNo = 2; } private void SetWayPoints(int[,] map) { int currentPosVal = map[0, 0]; int lPos = 0; int rPos = 0; int uPos = 0; int dPos = 0; int storedXPos = 99; int storedYPos = 99; int endstoredXPos = 99; int endstoredYPos = 99; int lastY = 0; int lastX = 0; //Search top ROW for start for (int i = 0; i < Width; i++) { currentPosVal = map[0, i]; if (currentPosVal == 1) { storedXPos = i; storedYPos = 0; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); lastX = storedXPos; lastY = storedYPos; break; } } //if start not set if (storedXPos == 99 && storedXPos == 99) { //look in 1st coloum for start for (int i = 0; i < Height; i++) { currentPosVal = map[i, 0]; if (currentPosVal == 1) { storedXPos = 0; storedYPos = i; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); lastX = storedXPos; lastY = storedYPos; break; } } } //search end COLOUM for end for (int i = 0; i < Height; i++) { currentPosVal = map[i, Width - 1]; if (currentPosVal == 1) { endstoredXPos = Width - 1; endstoredYPos = i; } } //If end not set look in bottom row for end if (endstoredXPos == 99 && endstoredYPos == 99) { for (int i = 0; i < Width; i++) { currentPosVal = map[7, i]; if (currentPosVal == 1) { endstoredXPos = i; endstoredYPos = Height - 1; } } if (endstoredXPos == 99 && endstoredYPos == 99) { } } // start midlle loop while (true) { lPos = 0; rPos = 0; uPos = 0; dPos = 0; //If current pos is not down the left hand edge if (storedXPos > 0) { lPos = map[storedYPos, storedXPos - 1]; } //If current pos square is not down the right hand edge if (storedXPos < Width - 1) { rPos = map[storedYPos, storedXPos + 1]; } //If current pos square is not in the top row if (storedYPos > 0) { uPos = map[storedYPos - 1, storedXPos]; } //If current pos square is not in the bottom row if (storedYPos < Height - 1) { dPos = map[storedYPos + 1, storedXPos]; } if (lPos == 1 && (lastX != storedXPos - 1 || lastY != storedYPos)) { lastX = storedXPos; lastY = storedYPos; storedXPos--; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); } else if (rPos == 1 && (lastX != storedXPos + 1 || lastY != storedYPos)) { lastX = storedXPos; lastY = storedYPos; storedXPos++; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); } else if (dPos == 1 && (lastX != storedXPos || lastY != storedYPos + 1)) { lastX = storedXPos; lastY = storedYPos; storedYPos++; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); } else if (uPos == 1 && (lastX != storedXPos || lastY != storedYPos - 1)) { lastX = storedXPos; lastY = storedYPos; storedYPos--; waypoints.Enqueue(new Vector2(storedXPos, storedYPos) * 32); } if (storedXPos == endstoredXPos && storedYPos == endstoredYPos) { break; } } } public void AddTexture(Texture2D texture) // method adds a texture to our texture list. { tileTextures.Add(texture); } //Reads number from array, store its value in textureIndex, Use textureIndex to get the texture from tileTextures, public void Draw(SpriteBatch batch) //Draw appropiate texture, Repeat through all elements of the array { int textureIndex; Texture2D texture; for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (levelNo == 0) { textureIndex = map[y, x]; if (textureIndex == -1) continue; texture = tileTextures[textureIndex]; batch.Draw(texture, new Rectangle(x * 32, y * 32, 32, 32), Color.White); } if (levelNo > 0) { textureIndex = map[y, x]; textureIndex += (levelNo * 2); if (textureIndex == -1) continue; texture = tileTextures[textureIndex]; batch.Draw(texture, new Rectangle(x * 32, y * 32, 32, 32), Color.White); } } } } } }
Since C# is compiled and can't do evals like scripted languages can (not that you should be doing that anyway) you should probably use streamreader to read the data from file (formatted perhaps as delimited text: csv or tsv) Assuming you're loading something similar to the map you have up there then a map file could look something like 0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0 0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0 0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0 0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0 0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0 0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0 0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0 0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0 0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0 0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0 0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0 0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0 0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1 where you would then loop through the file and read each line As each line is read in, you can then split the line by "," to create a 1d array which can then be assigned to an index in the 2d array. Loop for each line to create the entire 2d map array Take a look at this if you need help splitting strings in C#; note that the sample code splits at spaces " " and that you should use s.Split(','); for csv
With a file that small i would use: File.ReadAllLines , and after readling it loop over the lines with a foreach loop.