How can I print somethying that isn't there? - c#

I'm doing a text based game for a school project and I see myself stuck with a quite stupid problem.
The concept is simple, there's a map, a player, some monsters and some items.
For the map data structure I decided to use a 2d array of char's that have a unicode for content.
On top of this, I have a camera, which has a radius. The player never moves on screen, it has a x and y, but what has motion on screen is the camera itself. This works quite fine except when I get to the corners or any outside wall.
I get my camera doing this
int size = cameraSize/2;
int top = player.GetY() - size, bottom = player.GetY() + size;
char[,] camera = new char[cameraSize, cameraSize];
Console.SetCursorPosition(0,0);
for (int i = top; i < bottom; i++)
{
for (int j = top; j < bottom; j++)
{
camera[i, j] = map.ReMapPosition(i, j);
Console.Write(camera[i,j]);
}
Console.Write("\n");
}
Console.SetCursorPosition(cameraSize,cameraSize);
Console.Write(player.GetPlayerChar());
My 'cameraSize' is declared on the beginning of the class and is filled when the constructor is called
private int cameraSize;
cameraSize = difficulty.GetCameraSize();
The class 'difficulty' is irrelevant for my problem.
My problem itself is that I can't make the player positioned on the center when I get to the border walls as there is nothing to get from the array, since these are negative positions.

There are two approaches to this sort of problem.
1) In your loop, check if a value if out of range and output the value by hand.
2) Wrap your array in a custom class which ignores out of range values.
Something like this:
class MyWrapper
{
private readonly char[,] data;
public MyWrapper(char[,] data)
{
this.data=data;
}
private bool InRange(int x, int y)
{
return x >= 0 && y >= 0 && x < data.GetLength(0) && y < data.GetLength(1);
}
public char this[int x, int y]
{
get
{
return InRange(x,y) ? data[x,y] : ' ';
}
set
{
if(InRange(x,y)) data[x,y] = value;
}
}
}
My recommendation is for set to throw an exception when called on out of range values, but my example swallows the failure instead.

C# can't "retrieve values that aren't there", but you do have a couple options
Check to see if you are trying to get a negative position, or a position that's too big, and return a space
Or
Increase the size of the array by cameraSize/2 on all sides, which would effectively increase both the width and the height by cameraSize, and then make it to where your player can only move around in the coordinates (cameraSize/2,cameraSize/2) and (mapWidth-cameraSize/2,mapHeight-cameraSize/2). (<-- The coordinates might by (y,x) because of how 2d arrays work and depending on how your code is written). That way, the camera always has a padding around it, so there shouldn't ever be negative indicies

Related

Minecraft like terrain in unity3d

I'm a fan of Minecraft's old terrain generation with amazing overhangs, mountains and generally interesting worlds. My problem is that right now I'm using perlin noise, which while good for smooth terrain doesn't really give sporadic jumps that would allow mountains in a mostly flat area.
On top of that with the method I'm using gets 2d perlin noise, puts it in an array and then gets every Y value under it and sets it to a block; This stops generation of overhangs like this: Old Minecraft Terrain Image
Right now I have this:
public class GenerateIdMap : MonoBehaviour {
[Serializable] public class IBSerDict : SerializableDictionaryBase<int, byte> {};
public int size = 60;
public int worldHeight = 3;
public float perlinScale = 15f;
public int seed;
public int heightScale = 10;
public int maxHeight = 256;
public IBSerDict defaultBlocks = new IBSerDict();
void Start()
{
if (seed != 0) seed = (int)Network.time * 10;
CreateMap();
}
byte[,,] CreateMap()
{
byte[,,] map = new byte[size, maxHeight, size];
for (int x = 0; x < size; x++)
{
for (int z = 0; z < size; z++)
{
int y = (int)(Mathf.PerlinNoise((x + seed) / perlinScale, (z + seed) / perlinScale) * heightScale) + worldHeight;
y = Mathf.Clamp(y, 0, maxHeight-1);
while (y > 0)
{
map[x, y, z] = GetBlockType(y);
y--;
}
}
}
return map;
}
byte GetBlockType(int y)
{
SortedDictionary<int, byte> s_defaultBlocks = new SortedDictionary<int, byte>(defaultBlocks);
foreach (var item in s_defaultBlocks.OrderBy(key => key.Key))
{
if (y <= item.Key)
{
print(item.Value);
return item.Value;
}
}
return 0;
} }
The GetBlockType function is new and for getting the default block at that height, I'll fix it up later but it works for now. If you instantiate a prefab at that vector3 you would see terrain. Can someone help me figure out how to make better terrain? Thanks in advance!
Both of your problems should be tackled individually.
The first issue regarding the lack of variation in the generated values can usually be fixed in one of two ways, the first way is to modify the input into the perlin noise, i.e. the octaves and persistance and the second is to mix the output of multiple functions and even use the output of one function as the input to another. By functions, I mean Perlin/Simplex/Voronoi etc.
With the former method, as you mentioned, it can be pretty difficult to get terrain with interesting features over a large area (the generated values are homogeneous), but by playing with the coordinate range and octaves/persistance, it can be possible. The second approach is probably recommended however, because by mixing the inputs and outputs of different functions you can get some really interesting shapes (Voronoi produces circular crator-like shapes).
In order to fix the problem you are having with the overhangs, you would need to change your approach to generating the world slightly. Currently, you are just generating the height values of the terrain and assigning each of those values to give you the terrain surface only. What you ideally would want to do is, generate a pseudo-random value to use as a pass flag for each of the blocks in the 3d space (also those underground). The flag would indicate whether a block should be placed or not in the 3d world.
This is slower, but would generate caves and overhangs as you need.

C# - Per Pixel Collision Detection

Here's my situation I'm making a 2D maze game(XNA 4.0). I have figured out that the best way to do collision detection is by using per-pixel detection. While searching it up on the internet I have found people explaining or showing code for two things colliding(i.e. mouse & player, player & player, two shapes). What I would like to do is have this collision detect whether the player collides with a wall or not(the background is black but the maze walls are white). Could someone explain how to do this or to give some sort of starting point with the code. Much Appreciated.
P.S. A link to a website or anything relating to my question would also be helpful
The best way to go about this CPU-intensive operation is checking for hitbox collision first, then the per-pixel collision.
Most of this code can be found in this helpful video.
static bool IntersectsPixel(Rectangle hitbox1, Texture2D texture1, Rectangle hitbox2, Texture2D texture2)
{
Color[] colorData1 = new Color[texture1.Width * texture1.Height];
texture1.GetData(colorData1);
Color[] colorData2 = new Color[texture2.Width * texture2.Height];
texture2.GetData(colorData2);
int top = Math.Max(hitbox1.Top, hitbox2.Top);
int bottom = Math.Min(hitbox1.Bottom, hitbox2.Bottom);
int right = Math.Max(hitbox1.Right, hitbox2.Right);
int left = Math.Min(hitbox1.Left, hitbox2.Left);
for(y = top; y< bottom; y++)
{
for(x = left; x < right; x++)
{
Color color1 = colorData1[(x - hitbox1.Left) + (y - hitbox1.Top) * hitbox1.Width]
Color color2 = colorData2[(x - hitbox2.Left) + (y - hitbox2.Top) * hitbox2.Width]
if (color1.A != 0 && color2.A != 0)
return true;
}
}
return false;
}
You can call this method like so:
if (IntersectsPixel(player.hitbox, player.texture, obstacle.hitbox, obstacle.texture))
{
// Action that happens upon collision goes here
}
Hope I could help you out,
- GHC
Create a matrix of bools representing your sprite and a matrix of bools representing your maze (the matrix representing your sprite needs to have the same dimensions as your maze).
then you can do something simple like iterate over all x-y coordinates and check whether or not they're both true
// as an optimization, store a bounding box to minimize the
// coordinates of what you need to check
for(int i = 0; i < width, i++) {
for(int j = 0; j < height, j++) {
if(sprite[i][j] && maze[i][j]) {
collision = true
//you might want to store the coordinates
}
}
}
If you want to be very fancy you can flatten your maze matrix and use bit operations

Having some issues with procedurally generating a map

I'm building a very simple 2d tile map. It just spawns a few different grass tiles in random locations here's what it looks like:
public int tileHeight; //y
public int tileWidth; //x
int tileHeightCounter;
int tileWidthCounter;
public GameObject[] floorTiles;
void Start(){
tileHeightCounter = 0;
tileWidthCounter = 0;
while(tileHeightCounter < tileHeight){
Vector3 tileSpawnPoint = new Vector3 (tileWidthCounter, tileHeightCounter, 0);
GameObject groundTiles = (GameObject)Instantiate (floorTiles[Random.Range(0, floorTiles.Length)], tileSpawnPoint, Quaternion.identity);
groundTiles.transform.parent = transform;
if (tileWidthCounter == tileWidth) {
tileWidthCounter = 0;
tileHeightCounter++;
}
tileWidthCounter++;
}
}
I've run into two problems- say your tileHeight is 10 and your tileWidth is also 10 then the map it generates should be a 10x10 with 100 total tiles randomly distributed.
Instead two weird things are occurring the first is that if your map is 10x10 it actually generates a 10x9 meaning it stops one layer short on the y axis. The second is a grid(grass tile) is being created at 0,0 but the rest of the map is being created with at least x being 1 meaning that the map has a single tile attached to the bottom left sticking out.
I'm a bit confused as to whats going on here or how to fix it. Any help is much appreciated.
The issue is that you're using a < less than, so once it actually hits the tileHeight it exits the loop one iteration too early. Make it <=.

Topological Sorting, finding dependencies faster

I am working on a graph problem for months now and I am at a point where I am looking for new input from others.
I spend hours in the library and hit the books. I am pretty confident that I found a solution but maybe someone here can give me a new perspective.
Problem:
I have a 2d plane and rectangles on it. Rectangles can overlap each other and I have to find an order of these rectangles. To visualize imagine windows on your screen and you have to find an order so that it looks right.
To give you a picture of it this may be one output:
Given:
A function that decides whether two rectangles overlap each other
public bool overlap(Rect a, Rect b) {...}
A function that given 2 rectangles overlap, decides which is has to be drawn first
//returns [1 => a before b, -1 => b before a, 0 => a & b have no "before (<)" relation]
public int compare(Rect a, Rect b) {...}
Rectangle entities with
int x,y,width,height
Screen width and height
int screen.width, int screen.height
runtime complexity of these two functions can be neglected for the solution of this problem.
The problem can be abstracted to a dependency graph in which I want to find a correct evaluation order. The rectangles are nodes and the isBefore relation specifies arcs between the nodes. The graph can have multiple connected components as shown in the pictures. So just throwing Sort over all nodes will not do. Note: compare avoids circular dependencies, so the graph will remain acyclic. So the good news is : and order actually exists, yayy!
Now here comes the hard part:
How do I find the dependencies as fast as possible in order to build the graph and run a topological sorting algorithm on it.
The most naive and worst way to do it is to just execute compare for each object on each object thus ending up with O(n²) complexity. But this is just not acceptable here since I may have thousands of these rectangles on the screen.
So how do I minimize the number of nodes I have to compare a node with in oder to find all dependencies?
Now here is my solution. Maybe you should read this after finding something yourself in oder to avoid to be biased.
First of all the problem can be simplified by taking away 1 dimension. The problems will still be isomorphic but much easier to understand, at least for me.
So let's just take lines(rectangles) on a big line(screen). A line has a position and a length. Lines that overlap build a connected component.
Since we have a finite amount of lines we can find the smallest line
of our set of lines in O(n).
In order for 2 lines to overlap their maximum distance is just the length of our smallest line. Anything above can't overlap with us.
We divide the screen by the size of the smallest line and end up with discrete chunks. We create a HashMap and a bucket for each chunk. We can now sort a line into these buckets.
we run over the set again O(n) and can decide very easy in which buckets we have to put our line. position % smallest.length = i and (position + length) % smallest.length = j will give the indicies of our HashMap. We sort the line into our HashMap from bucket[i] to bucket[j].
We have now minimized the set of lines we have to compare a line with in order to find all its dependencies. After doing this for all lines we only have to compare a line with all other lines in bucket[i-1] to bucket[j+1]. Any other line would be fo far away from us to overlap anyways. The modulo operation is efficent. The additional memory for the buckets shouldn't be very much.
This is the best I came up with. Maybe someone here has a better solution.
Some observations:
dividing screen by size of smallest line would make the algorithm very unpredictable and is not even necessary. You can use any size of bucket and the algorithm would work.
inspecting bucket[i-1] to bucket[j+1] is not necessary, bucket[i] to bucket[j] is enough
Let A and B be rectangles, B is not wider than A. Then part of left or right edge of B lies on A or those rectangles do not overlap (will be used later).
So the algorithm I made:
For every rectangle calculate ranges of buckets it belongs to
(bucketXFrom, bucketXTo, bucketYFrom, bucketYTo). This is class
RectangleInBucket.
Sort them by (bucketXTo - bucketXFrom). As there are not so many buckets, it is basically one step radix sort.
For every rectangle, starting from those with smallest width, scan all buckets it belongs to. If there are rectangles, compare to them and save relations where exist. Save rectagle into buckets under left and right edge.
I made total number of buckets equal to number of rectangles, it seems to work best.
It is usually faster than naive algorithm, but not as much as one could expect. As rectagles can (and do) belong to many buckets, one relation is reexamined many times. This increases number of steps. Moreover it uses not so cheap structures for this deduplication. But number of compare calls is reduced easily by several folds. It pays off even when this call is dirt cheap and the difference increases when the compare fuction is not trivial. And finally the code:
public class Rectangle
{
public int x;
public int y;
public int width;
public int height;
}
/// <summary>
/// Creates array of objects
/// </summary>
protected T[] InitializeArray<T>(int length) where T : new()
{
T[] array = new T[length];
for (int i = 0; i < length; ++i)
{
array[i] = new T();
}
return array;
}
/// <summary>
/// Creates array of objects
/// </summary>
protected T[,] InitializeArray<T>(int length, int width) where T : new()
{
T[,] array = new T[length, width];
for (int i = 0; i < length; ++i)
{
for (int j = 0; j < width; ++j)
{
array[i, j] = new T();
}
}
return array;
}
protected class RectangleInBucket
{
public readonly Rectangle Rect;
public readonly int RecNo;
public readonly int bucketXFrom;
public readonly int bucketXTo;
public readonly int bucketYFrom;
public readonly int bucketYTo;
public RectangleInBucket(Rectangle rectangle, int recNo, int bucketSizeX, int bucketSizeY)
{
Rect = rectangle;
RecNo = recNo;// arbitrary number unique for this rectangle
bucketXFrom = Rect.x / bucketSizeX;
bucketXTo = (Rect.x + Rect.width) / bucketSizeX;
bucketYFrom = Rect.y / bucketSizeY;
bucketYTo = (Rect.y + Rect.height) / bucketSizeY;
}
}
/// <summary>
/// Evaluates rectagle wrapped in RectangleInBucket object against all rectangles in bucket.
/// Saves result into tmpResult.
/// </summary>
protected void processBucket(Dictionary<long, int> tmpResult, List<RectangleInBucket> bucket, RectangleInBucket rib)
{
foreach (RectangleInBucket bucketRect in bucket)
{
if (bucketRect.RecNo < rib.RecNo)
{
long actualCouple = bucketRect.RecNo + (((long)rib.RecNo) << 32);
if (tmpResult.ContainsKey(actualCouple)) { continue; }
tmpResult[actualCouple] = overlap(bucketRect.Rect, rib.Rect) ? compare(bucketRect.Rect, rib.Rect) : 0;
}
else
{
long actualCouple = rib.RecNo + (((long)bucketRect.RecNo) << 32);
if (tmpResult.ContainsKey(actualCouple)) { continue; }
tmpResult[actualCouple] = overlap(rib.Rect, bucketRect.Rect) ? compare(rib.Rect, bucketRect.Rect) : 0;
}
}
}
/// <summary>
/// Calculates all couples of rectangles where result of "compare" function is not zero
/// </summary>
/// <param name="ra">Array of all rectangles</param>
/// <param name="screenWidth"></param>
/// <param name="screenHeight"></param>
/// <returns>Couple of rectangles and value of "compare" function</returns>
public List<Tuple<Rectangle, Rectangle, int>> GetRelations(Rectangle[] ra, int screenWidth, int screenHeight)
{
Dictionary<long, int> tmpResult = new Dictionary<long, int>();
// the key represents couple of rectangles. As index of one rectangle is int,
// two indexes can be stored in long. First index must be smaller than second,
// this ensures couple can be inserted only once. Value of dictionary is result
// of "compare" function for this couple.
int bucketSizeX = Math.Max(1, (int)Math.Sqrt(screenWidth * screenHeight / ra.Length));
int bucketSizeY = bucketSizeX;
int bucketsNoX = (screenWidth + bucketSizeX - 1) / bucketSizeX;
int bucketsNoY = (screenHeight + bucketSizeY - 1) / bucketSizeY;
List<RectangleInBucket>[,] buckets = InitializeArray<List<RectangleInBucket>>(bucketsNoX, bucketsNoY);
List<RectangleInBucket>[] sortedRects = InitializeArray<List<RectangleInBucket>>(bucketsNoX);
for (int i = 0; i < ra.Length; ++i)
{
RectangleInBucket rib = new RectangleInBucket(ra[i], i, bucketSizeX, bucketSizeY);
sortedRects[rib.bucketXTo - rib.bucketXFrom].Add(rib);// basically radix sort
}
foreach (List<RectangleInBucket> sorted in sortedRects) // start with most narrow rectangles
{
foreach (RectangleInBucket rib in sorted) // all of one width (measured in buckets)
{
for (int x = rib.bucketXFrom; x <= rib.bucketXTo; ++x)
{
for (int y = rib.bucketYFrom; y <= rib.bucketYTo; ++y)
{
processBucket(tmpResult, buckets[x, y], rib);
}
}
for (int y = rib.bucketYFrom; y <= rib.bucketYTo; ++y)
{
buckets[rib.bucketXFrom, y].Add(rib); // left edge of rectangle
if (rib.bucketXFrom != rib.bucketXTo)
{
buckets[rib.bucketXTo, y].Add(rib); // right edge of rectangle
}
}
}
}
List<Tuple<Rectangle, Rectangle, int>> result = new List<Tuple<Rectangle, Rectangle, int>>(tmpResult.Count);
foreach (var t in tmpResult) // transform dictionary into final list
{
if (t.Value != 0)
{
result.Add(Tuple.Create(ra[(int)t.Key], ra[(int)(t.Key >> 32)], t.Value));
}
}
return result;
}

Form and movement representation of a hexagonal plane

The most basic way of representing a quadrile plane (a bunch of squares) is to use a two-dimensional array.
In C# we declare this as int[,] and can make our plane as big as we want:
string[3,3] => tic-tac-toe board (or similar)
string[8,8] => chess or checkers board
To "move" an item on the plane, we would just asign it toa new "position"
//using our tic-tac-toe board:
string[0,0] = "x"; //top-left
string[1,1] = "o"; //middle-middle
//to move
string[0,1] = bN; //Black Knight's starting positon
string[2,2] = bN; //Black Knight moves
string[0,1] = String.Empty;
So, how would you represent a hexagonal plane (a bunch of hexagons) and how would movement from one position to the next be handled?
Note: This is not purely theoretical, as I have an idea for a little game in my head which would require this kind of movement, but I can't wrap my head around how it would be done. I've looked through some of the other questions here, but can't really find a good match...
I do not know if this is the optimal solution but what I would do is create a new class of board the board would be a collection of "cells" each cell would contain a pointer to each of it's neighboring cell (or null if the cell is on a edge). You could implement some iterators on the board class that would walk the cells.
You would have to treat it more like a List instead of a vector. But it is at least a start.
Another solution is set you board up like this
and still just use the [,] to access each cell but it will take a little more math to figure out if you are traversing cells (Up Right is [+1,-1], Right is [+1,0], Down Right is [0,+1], Down Left is [-1,+1], Left is [-1,0], Up Left is [0,-1])
EDIT
If you want vertical walls instead of a slant just take make your width(X) equal X + Y*2 then on each row make the current row number (y) and make the cells 0 to Y-y and X-y to X off limits.
Example:
const int X = 10;
const int Y = 10;
int grid[,] = new int[X+(2*Y), Y];
bool IsCellOffLimits(int x, int y)
{
return (x < Y-y || x > X-y || y < 0 || y > Y);
}
you waste a little memory space but it gives you a board like this
If you are Very Clever© you can just use the normal space but just have your code have anything in that Y-y or X-y range be on the opposite side of the board. But ill leave that code up to the reader.
Three directions, left/right, up/down, funny angle one way/other way.
public class Player
{
public int X { get; set; }
public int Y { get; set; }
public void MoveLeft() { X++; }
public void MoveRight() { X--; }
public void MoveUp() { Y++; }
public void MoveDown() { Y--; }
public void MoveFunny() { Y++; X++; }
public void MoveOtherFunny() { Y--; X--; }
}

Categories