I began setting up my system by taking the Grid system supplied by Pack publishing (). This is how it's initialized:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is Point)
{
Point p = obj as Point;
return this.X == p.X && this.Y == p.Y;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
int hash = 6949;
hash = hash * 7907 + X.GetHashCode();
hash = hash * 7907 + Y.GetHashCode();
return hash;
}
}
public override string ToString()
{
return "P(" + this.X + ", " + this.Y + ")";
}
}
public enum CellType
{
Empty,
Road,
Structure,
SpecialStructure,
None
}
public class Grid
{
private CellType[,] _grid;
private int _width;
public int Width { get { return _width; } }
private int _height;
public int Height { get { return _height; } }
private List<Point> _roadList = new List<Point>();
private List<Point> _specialStructure = new List<Point>();
private List<Point> _houseStructure = new List<Point>();
public Grid(int width, int height)
{
_width = width;
_height = height;
_grid = new CellType[width, height];
}
public enum CellType
{
Empty,
Road,
Structure,
SpecialStructure,
None
}
public class Grid
{
private CellType[,] _grid;
private int _width;
public int Width { get { return _width; } }
private int _height;
public int Height { get { return _height; } }
private List<Point> _roadList = new List<Point>();
private List<Point> _specialStructure = new List<Point>();
private List<Point> _houseStructure = new List<Point>();
public Grid(int width, int height)
{
_width = width;
_height = height;
_grid = new CellType[width, height];
}
public void Update()
{
Console.Write("GRID IS RUNNING");
}
// Adding index operator to our Grid class so that we can use grid[][] to access specific cell from our grid.
public CellType this[int i, int j]
{
get
{
return _grid[i, j];
}
set
{
if (value == CellType.Road)
{
_roadList.Add(new Point(i, j));
}
if (value == CellType.SpecialStructure)
{
_specialStructure.Add(new Point(i, j));
}
if (value == CellType.Structure)
{
_houseStructure.Add(new Point(i, j));
}
_grid[i, j] = value;
}
}
After I initialized it, I called it from another function like this.
public int width, height;
Grid placementGrid;
private void Start()
{
placementGrid = new Grid(width, height);
Debug.Log(placementGrid.GetRandomRoadPoint());
}
It seems to initialize perfectly. But when I call the functions inside it, I'm returned a null value. I tried calling this function for example:
public Point GetRandomRoadPoint()
{
if (_roadList.Count == 0)
{
return null;
}
return _roadList[UnityEngine.Random.Range(0, _roadList.Count)];
}
I have no idea what I'm doing wrong. I'm basically trying to create a pedestrian AI system for my procedurally generated town.
I tried debugging several times, but I can't seem to find my way around it.
Related
I have my unity project set up with a graph like this:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is Point)
{
Point p = obj as Point;
return this.X == p.X && this.Y == p.Y;
}
return false;
}
public override int GetHashCode()
{
unchecked
{
int hash = 6949;
hash = hash * 7907 + X.GetHashCode();
hash = hash * 7907 + Y.GetHashCode();
return hash;
}
}
public override string ToString()
{
return "P(" + this.X + ", " + this.Y + ")";
}
}
public enum CellType
{
Empty,
Road,
Structure,
SpecialStructure,
None
}
public class Grid
{
public CellType[,] _grid;
private int _width;
public int Width { get { return _width; } }
private int _height;
public int Height { get { return _height; } }
public List<Point> _roadList = new List<Point>();
public List<Point> _specialStructure = new List<Point>();
public List<Point> _houseStructure = new List<Point>();
public Grid(int width, int height)
{
_width = width;
_height = height;
_grid = new CellType[width, height];
}
// Adding index operator to our Grid class so that we can use grid[][] to access specific cell from our grid.
public CellType this[int i, int j]
{
get
{
return _grid[i, j];
}
set
{
if (value == CellType.Road)
{
_roadList.Add(new Point(i, j));
}
if (value == CellType.SpecialStructure)
{
_specialStructure.Add(new Point(i, j));
}
if (value == CellType.Structure)
{
_houseStructure.Add(new Point(i, j));
}
_grid[i, j] = value;
}
}
And I'm instantiating a series of gameobjects using an L-System algorithm and adding their X and Z positions to the graph like this:
public Grid AddToGrid(Vector3Int position, string type)
{
//CellType parsed_enum = (CellType)System.Enum.Parse(typeof(CellType), type);
switch (type)
{
case "Structure":
placementGrid._houseStructure.Add(new Point((int)position.x, (int)position.z));
break;
case "SpecialStructure":
placementGrid._specialStructure.Add(new Point((int)position.x, (int)position.z));
break;
case "Road":
placementGrid._roadList.Add(new Point((int)position.x, (int)position.z));
break;
}
return placementGrid;
}
And then in one of my scripts I'm calling another function:
public List<Point> GetWakableAdjacentCells(int x, int y, bool isAgent)
{
List<Point> adjacentCells = GetAllAdjacentCells(x, y);
Debug.Log("Adjacent Cells"+ adjacentCells.Count);//3
Debug.Log("X"+x); //-1
Debug.Log("Y"+y);//1
for (int i = adjacentCells.Count - 1; i >= 0; i--)
{
Debug.Log(adjacentCells[i].X); //-1
Debug.Log(adjacentCells[i].Y);//2
if (IsCellWakable(_grid[adjacentCells[i].X, adjacentCells[i].Y], isAgent) == false)
{
adjacentCells.RemoveAt(i);
}
}
return adjacentCells;
}
But this says "index was outside the bounds of the array" at if condition. I've commented each relevant value next to the variables for ease.
The function this condition is checking is this:
public static bool IsCellWakable(CellType cellType, bool aiAgent = false)
{
Debug.Log("boo");
if (aiAgent)
{
return cellType == CellType.Road;
}
return cellType == CellType.Empty || cellType == CellType.Road;
}
What am I doing wrong?
is there a way to implement a grid in such a way way that minus values can be accessed?
Well you commented yourself
// -1
-> -1 can not be a valid index in c#.
If you want to have a wrap around you could probably do e.g.
public CellType this[int i, int j]
{
get
{
i = (i % _width) + _width) % _width;
j = (j % _height) + _height) % _height;
return _grid[i, j];
}
set
{
i = (i % _width) + _width) % _width;
j = (j % _height) + _height) % _height;
switch(value)
{
case CellType.Road:
_roadList.Add(new Point(i, j));
break;
case CellType.SpecialStructure:
_specialStructure.Add(new Point(i, j));
break;
case CellType.Structure:
_houseStructure.Add(new Point(i, j));
break;
}
_grid[i, j] = value;
}
}
This means of course that your grid is basically "infinite" and crossing the top boarder you will be at the bottom again etc.
I have done a console game called "Labyrinth", now I want to bring it to Windows Forms, but I have some problems and exceptions and I can't understand how to make it work.
So, here is functional for printing field in console:
Base class Cell(it has children, like Wall, Door,Key,Empty, Player)
abstract class Cell
{
protected ConsoleColor foregroundColor;
protected ConsoleColor backgroundColor;
protected char symbol;
public Cell(ConsoleColor foregroundColor = ConsoleColor.White,
ConsoleColor backgroundColor = ConsoleColor.Black,
char symbol = ' ')
{
this.foregroundColor = foregroundColor;
this.backgroundColor = backgroundColor;
this.symbol = symbol;
}
public virtual void Draw()
{
Console.ForegroundColor = foregroundColor;
Console.BackgroundColor = backgroundColor;
Console.Write(symbol);
}
}
Here is class FileStorer that works with file(reads level from .txt file) and fills the array string[] field
class FileStorer
{
private string path;
public string[] Result;
public FileStorer(string path)
{
this.path = path;
Result = new string[0];
ReadFile();
}
private void Add(string item)
{
string[] newStr = new string[Result.Length + 1];
for (int i = 0; i < Result.Length; i++)
{
newStr[i] = Result[i];
}
newStr[Result.Length] = item;
Result = newStr;
}
public void ReadFile()
{
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Add(line);
}
}
}
}
Class Field
class Field
{
private bool toggle_key = false;
private Cell[,] field;
public int Width
{
get { return field.GetLength(1); }
}
public int Height
{
get { return field.GetLength(0); }
}
public Field(int width, int height)
{
field = new Cell[height, width];
}
public Cell this[int x, int y]
{
get { return field[y, x]; }
set { field[y, x] = value; }
}
public void Print()
{
Console.SetCursorPosition(0, 0);
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
this[x, y].Draw();
}
Console.WriteLine();
}
}
public bool NotOutOfField(int x, int y)
{
return x >= 0 && x < Width && y >= 0 && y < Height;
}
public void MakeEmpty(int x, int y)
{
this[x, y] = new Empty();
}
public bool CanMakeStep(int x, int y)
{
if (NotOutOfField(x, y) && this[x, y] is Empty)
return true;
if (NotOutOfField(x, y) && this[x, y] is Key && !toggle_key)
{
toggle_key = true;
Key.count--;
return true;
}
if (NotOutOfField(x, y) && this[x, y] is Door && toggle_key)
{
toggle_key = false;
Door.count--;
return true;
}
return false;
}
}
Here is class LevelLoader that fills array Cell[,] with proper classes (Door,Key etc.)
class LevelLoader
{
private string[] field;
public LevelLoader(int level)
{
field = new FileStorer($"../../Levels/{level}.txt").Result;
}
public void LoadField(out Field cellField, out Player player)
{
cellField = new Field(field[0].Length, field.Length);
player = new Player(0, 0);
for (int y = 0; y < field.Length; y++)
{
for (int x = 0; x < field[y].Length; x++)
{
switch (field[y][x])
{
case '#':
cellField[x, y] = new Wall();
break;
case ' ':
cellField[x, y] = new Empty();
break;
case 'K':
cellField[x, y] = new Key();
break;
case 'D':
cellField[x, y] = new Door();
break;
case 'P':
player = new Player(x, y);
goto case ' ';
default:
break;
}
}
}
}
}
And finally in class Level I have methods that puts characters on field and prints them
private void PutCharactersOnField()
{
for (int y = 0; y < gameField.Height; y++)
{
for (int x = 0; x < gameField.Width; x++)
{
if (!(gameField[x, y] is Wall) && !((gameField[x, y] is Key)) && !((gameField[x, y] is Door)))
{
gameField[x, y] = new Empty();
}
}
}
gameField[player.X, player.Y] = player;
}
public void PrintLevel()
{
gameField.Print();
player.Draw();
LivesMessage();
if (Door.count == 0)
{
Win();
};
}
I have done some changes for winforms, and I got IndexOutOfRanfeExceprion, I can't understand what went wrong, so here are the same classes and functions but changed for Winforms.
Class Cell
public abstract class Cell
{
public string Path;
public Image Image;
public Cell(string path)
{
Path = path;
if (!File.Exists(Path))
{
throw new Exception("File does not exist: " + Path);
}
Image = new Bitmap(Path);
}
public virtual void Draw(Graphics gr, int j, int i, int side, int x, int y)
{
gr.DrawImage(this.Image, j * side + x, i * side + y, new Rectangle(new Point(0, 0), new Size(side, side)), GraphicsUnit.Pixel);
}
}
FileStorer wasn't modified.
Class Player
public class Player:Cell
{
public string path;
protected Direction direction;
public Image SpriteAnimation;
public int X, Y;
public Size Scale;
public int CurrentFrame = 2;
public int CurrentAnimation = 5;
public Image Part;
public int speed;
public Direction CurrentDirection
{
get { return direction; }
}
public Player() : base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png") { }
public Player(Size scale, int x, int y, Image spriteAnimation):base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png")
{
SpriteAnimation = spriteAnimation;
Scale = scale;
X = x;
Y = y;
speed = 2;
if (!File.Exists(Path))
{
throw new Exception("File does not exist: " + Path);
}
base.Image = new Bitmap(Path);
}
public Player(int x, int y) : base("D:\\GIT\\maze-game\\MazeGame\\MazeGame\\Resources\\sprite.png")
{
X = x;
Y = y;
}
public void Action()
{
switch (direction)
{
case Direction.Left:
CurrentAnimation = 1;
break;
case Direction.Up:
CurrentAnimation = 3;
break;
case Direction.Right:
CurrentAnimation = 0;
break;
case Direction.Down:
CurrentAnimation = 2;
break;
}
}
public void Static()
{
switch (direction)
{
case Direction.Left:
CurrentAnimation = 6;
break;
case Direction.Up:
CurrentAnimation = 8;
break;
case Direction.Right:
CurrentAnimation = 5;
break;
case Direction.Down:
CurrentAnimation = 7;
break;
}
}
public void Rotate(int dx, int dy)
{
if (dx == -speed)
direction = Direction.Left;
else if (dx == speed)
direction = Direction.Right;
else if (dy == -speed)
direction = Direction.Up;
else if (dy == speed)
direction = Direction.Down;
}
public void MakeStep(int dx, int dy)
{
X += dx;
Y += dy;
}
public void DrawAction(Graphics gr, int x, int y)
{
gr.DrawImage(SpriteAnimation, X + x, Y + y, new Rectangle(new Point(75 * CurrentFrame, 170 * CurrentAnimation), new Size(75, 170)), GraphicsUnit.Pixel);
}
public void DrawStatic(Graphics gr, int x, int y)
{
gr.DrawImage(SpriteAnimation, X + x, Y + y, new Rectangle(new Point(75 * CurrentFrame, 170 * (CurrentAnimation - 5)), new Size(75, 170)), GraphicsUnit.Pixel);
}
}
Class LevelLoader was modified juct for player cell
case 'P':
player = new Player(new Size(35, 75), 100, 100,player.Image);
goto case ' ';
Class Field
class Field
{
private bool toggle_key = false;
private readonly Cell[,] field;
public int Width
{
get { return field.GetLength(1); }
}
public int Height
{
get { return field.GetLength(0); }
}
public Field(int width, int height)
{
field = new Cell[height, width];
}
public Cell this[int x, int y]
{
get { return field[y, x]; }
set { field[y, x] = value; }
}
public void Print(Graphics gr, int side, int j, int i)
{
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
this[x, y].Draw(gr, x, y,side, j, i);
}
}
}
public bool NotOutOfField(int x, int y)
{
return x >= 0 && x < Width && y >= 0 && y < Height;
}
public void MakeEmpty(int x, int y)
{
this[x, y] = new Empty();
}
public bool CanMakeStep(int x, int y)
{
if (NotOutOfField(x, y) && this[x, y] is Empty)
return true;
if (NotOutOfField(x, y) && this[x, y] is Key && !toggle_key)
{
toggle_key = true;
Key.count--;
return true;
}
if (NotOutOfField(x, y) && this[x, y] is Door && toggle_key)
{
toggle_key = false;
Door.count--;
return true;
}
return false;
}
}
Here are Level class method PrintLevel,(PutCharactersOnField wasn't modified)
public void PrintLevel(Graphics gr)
{
gameField.Print(gr, mapSide,point.X, point.Y);
player.DrawStatic(gr, point.X,point.Y);
if (Door.count == 0)
{
Win();
};
}
I'm very new in this topic, but I want to deal with this issue.So, I need help, what is wrong, where I made a mistake?
**Exception was called in the stack of calls
I am trying to create a custom texture class, and I want to be able to choose if I the texture is 8bit or float a.k.a I want to be able to set _buffer to be either RGBFloat[] or RGBByte[] but I cant figure out how to do it with out making the whole class generic but if I do it generic it will be possible to set other object types other then just the ones that I want to limit it to. Maybe its possible to use inheritance or interface in some way, I don't know.
Example C# Code: (the places with T are not correct, just placeholder)
public struct RGBFloat
{
public float R { get; }
public float G { get; }
public float B { get; }
public RGBFloat(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
}
public struct RGBByte
{
public byte R { get; }
public byte G { get; }
public byte B { get; }
public RGBByte(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
}
public enum TextureFormat
{
RGBFloat,
RGBByte
}
public class Texture2D
{
public int Width { get; }
public int Height { get; }
private T[] _buffer; // want it to be able to be either RGBFloat[] or RGBByte[] but nothing else.
public Texture2D(int width, int height, TextureFormat textureFormat)
{
Width = width;
Height = height;
switch (textureFormat)
{
case TextureFormat.RGBFloat:
_buffer = new RGBFloat[width * height];
break;
default:
_buffer = new RGBByte[width * height];
break;
}
}
public T this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public T this[int x, int y]
{
get { return (_buffer[Width * y + x]); }
set { _buffer[Width * y + x] = value; }
}
}
Example of a working generic class I have created that is similar to my TextureClass but this one is meant to be able to support any object type.
public class Computebuffer<T>
{
public int Count { get; }
private T[] _buffer;
public Computebuffer(int count)
{
Count = count;
_buffer = new T[count];
}
public T this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public void Initialize(T value)
{
for (int i = 0; i < Count; i++)
{
_buffer[i] = value;
}
}
public void SetData(T[] data)
{
for (int i = 0; i < data.Length; i++)
{
_buffer[i] = data[i];
}
}
public void GetData(T[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = _buffer[i];
}
}
public void Clear()
{
_buffer = new T[Count];
}
}
EDIT 1: (Updated version, almost working):
Issue: With this code I am able to add a RGBFloat to a Texture2D and that doesn't make sense. (see main program)
public interface IRGBType { }
public struct RGBFloat : IRGBType
{
public float R { get; }
public float G { get; }
public float B { get; }
public RGBFloat(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
}
public struct RGBByte : IRGBType
{
public byte R { get; }
public byte G { get; }
public byte B { get; }
public RGBByte(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
}
public class Texture2D<T> where T : struct, IRGBType
{
public int Width { get; }
public int Height { get; }
private IRGBType[] _buffer;
public Texture2D(int width, int height)
{
Width = width;
Height = height;
_buffer = new IRGBType[width * height];
Initialize();
}
private void Initialize()
{
Type type = this.GetType();
if (type == typeof(RGBByte))
{
for (int i = 0; i < Width * Height; i++)
{
_buffer[i] = new RGBByte(0, 0, 0);
}
}
else
{
for (int i = 0; i < Width * Height; i++)
{
_buffer[i] = new RGBFloat(0, 0, 0);
}
}
}
public IRGBType this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public IRGBType this[int x, int y]
{
get { return (_buffer[Width * y + x]); }
set { _buffer[Width * y + x] = value; }
}
}
MainProgram:
Texture2D<RGBFloat> texFloat = new Texture2D<RGBFloat>(64, 64);
Texture2D<RGBByte> texByte = new Texture2D<RGBByte>(64, 64);
texFloat[32, 32] = new RGBFloat(10, 50, 60);
texByte[32, 32] = new RGBFloat(0.9f, 0.24f, 0.5f); // this should not work I should not be able to add a RGBFloat to a RGBByte Texture2D
EDIT 2: (Updated version v3) still one issue, how would I Initialize _buffer array with an optional value, so new Texture2D<RGBFloat>(64, 64) should Initialize with new RGBFloat(0,0,0) and Texture2D<RGBFloat>(64, 64, new RGBFloat(0.5f,0.6f,0.7f)) should Initialize with value provided:
public class Texture2D<T> where T : struct, IRGBType
{
public int Width { get; }
public int Height { get; }
private T[] _buffer;
public Texture2D(int width, int height, T? initializeValue = null)
{
Width = width;
Height = height;
_buffer = new T[width * height];
Initialize(initializeValue);
}
private void Initialize(T? value)
{
Type type = this.GetType();
T rgb;
if (type == typeof(RGBFloat))
{
rgb = value ?? new RGBFloat(0, 0, 0); // Error: Operator '??' cannot be applied to operands of type 'T' and 'RGBFloat'
}
else
{
rgb = value ?? new RGBByte(0, 0, 0); // Error: Operator '??' cannot be applied to operands of type 'T' and 'RGBByte'
}
for(int i = 0; i < Width*Height; i++)
{
_buffer[i] = rgb;
}
}
public T this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public T this[int x, int y]
{
get { return (_buffer[Width * y + x]); }
set { _buffer[Width * y + x] = value; }
}
}
EDIT 3: The full final version that now works correctly:
public interface IRGBType { }
public struct RGBFloat : IRGBType
{
public float R { get; }
public float G { get; }
public float B { get; }
public RGBFloat(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
}
public struct RGBByte : IRGBType
{
public byte R { get; }
public byte G { get; }
public byte B { get; }
public RGBByte(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
}
public class Texture2D<T> where T : struct, IRGBType
{
public int Width { get; }
public int Height { get; }
private T[] _buffer;
public Texture2D(int width, int height, T? initializeValue = null)
{
Width = width;
Height = height;
_buffer = new T[width * height];
if (initializeValue.HasValue)
{
for (int i = 0; i < Width * Height; i++)
{
_buffer[i] = initializeValue.Value;
}
};
}
public T this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public T this[int x, int y]
{
get { return (_buffer[Width * y + x]); }
set { _buffer[Width * y + x] = value; }
}
}
}
You can create an interface that your RGBFloat and RGBByte structs implement, and limit the generic type to that interface. The interface can just be a "marker", with nothing in it:
public interface IRGBType { }
public struct RGBFloat : IRGBType
{
public float R { get; }
public float G { get; }
public float B { get; }
public RGBFloat(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
}
public struct RGBByte : IRGBType
{
public byte R { get; }
public byte G { get; }
public byte B { get; }
public RGBByte(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
}
You can then have your generic class only accept types that implement this interface:
public class Texture2D<T> where T: IRGBType
{
...
}
If you know that you'll always have this interface implemented by a struct, you can further restrict the generic:
public class Texture2D<T> where T: struct, IRGBType
{
...
}
EDIT: Make sure to use the generic T parameter everywhere in your class, not the interface. This is necessary to ensure type safety, otherwise your indexers can accept any IRGBType, which can be very problematic. Correct usage:
public class Texture2D<T> where T: struct, IRGBType
{
private T[] _buffer;
public Texture2D(int width, int height)
{
...
_buffer = new T[width * height];
...
}
public T this[int i]
{
get => _buffer[i];
set => _buffer[i] = value;
}
}
You can try using only one generic struct like this:
public struct RGB<T>
where T : struct,
IComparable, IFormattable, IConvertible,
IComparable<T>, IEquatable<T>
{
public T R { get; }
public T G { get; }
public T B { get; }
public RGB(T r, T g, T b)
{
R = r;
G = g;
B = b;
}
}
public class RGBComputeBuffer<T>
where T : struct,
IComparable, IFormattable, IConvertible,
IComparable<T>, IEquatable<T>
{
public int Count { get; private set; }
private RGB<T>[] _buffer;
public RGBComputeBuffer(int count)
{
_buffer = new RGB<T>[count];
Count = count;
}
public RGB<T> this[int i]
{
get { return _buffer[i]; }
set { if ( !_buffer[i].Equals(value) ) _buffer[i] = value; }
}
public void Initialize(RGB<T> value)
{
for ( int i = 0; i < Count; i++ )
_buffer[i] = value;
}
public void SetData(RGB<T>[] data)
{
Array.Resize(ref _buffer, data.Length);
Count = data.Length;
for ( int i = 0; i < data.Length; i++ )
_buffer[i] = data[i];
}
public void GetData(RGB<T>[] data)
{
Array.Resize(ref data, _buffer.Length);
for ( int i = 0; i < data.Length; i++ )
data[i] = _buffer[i];
}
public void Clear()
{
_buffer = new RGB<T>[Count];
}
}
Example of usage:
var bufferOfRGBByte = new RGBCompositeBuffer<byte>(100);
var bufferOfRGBFloat = new RGBCompositeBuffer<float>(100);
An interface would be your best bet. By having RGBFloat and RGBByte implement an interface then you can use that interface type in your array. It will also allow adding other RGB types later.
public interface IRGB
{
}
public struct RGBFloat : IRGB
{
public float R { get; }
public float G { get; }
public float B { get; }
public RGBFloat(float r, float g, float b)
{
R = r;
G = g;
B = b;
}
}
public struct RGBByte : IRGB
{
public byte R { get; }
public byte G { get; }
public byte B { get; }
public RGBByte(byte r, byte g, byte b)
{
R = r;
G = g;
B = b;
}
}
public enum TextureFormat
{
RGBFloat,
RGBByte
}
public class Texture2D
{
public int Width { get; }
public int Height { get; }
private IRGB[] _buffer; // want it to be able to be either RGBFloat[] or RGBByte[] but nothing else.
public Texture2D(int width, int height, TextureFormat textureFormat)
{
Width = width;
Height = height;
switch (textureFormat)
{
case TextureFormat.RGBFloat:
_buffer = new IRGB[width * height];
break;
default:
_buffer = new IRGB[width * height];
break;
}
}
public IRGB this[int i]
{
get { return (_buffer[i]); }
set { _buffer[i] = value; }
}
public IRGB this[int x, int y]
{
get { return (_buffer[Width * y + x]); }
set { _buffer[Width * y + x] = value; }
}
}
If you want to access the R,G,B variables however you may need to add some kind of accessor methods/properties to the interface.
How can I call the parameter which is inside the method instance in the other class, as I want to make a calculation with the method and display it.
class Box
{
int width = 10;
int height = 15;
public int Area(int Area)
{
Area = width * height;
return Area;
}
public int Perimeter(int Para)
{
Para = 2 * (height + width);
return Para;
}
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
static void Main(string[] args)
{
Box b = new Box();
b.Area(Area);
b.Perimeter(Para);
Console.ReadLine();
}
It is giving me en error on b.Area(Area); and b.Perimeter(Para);
Maybe you wanted to do this:
class Program
{
static void Main(string[] args)
{
Box box = new Box(10, 15);
Console.WriteLine("Area is: " + box.CalculateArea());
Console.WriteLine("Perimeter is: " + box.CalculatePerimeter());
Console.ReadLine();
}
}
public class Box
{
public int Width { get; set; }
public int Height { get; set; }
public Box(int width, int height)
{
Width = width;
Height = height;
}
public int CalculateArea()
{
return Width * Height;
}
public int CalculatePerimeter()
{
return 2 * (Width + Height);
}
}
why the result in the area of the rectangle and it's perimeter comes out by zero?
in using C#
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
rec r = new rec();
r.L = Convert.ToInt32(Console.ReadLine());
r.wi = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(r.area());
Console.WriteLine(r.per());
}
}
class rec
{
int l;
int w;
public int L
{
set
{
l = L;
}
get
{
return l;
}
}
public int wi
{
set
{
w = wi;
}
get
{
return w;
}
}
public rec()
{
}
public rec(int x, int y)
{
l = x;
w = y;
}
public double area()
{
return l * w;
}
public int per()
{
return 2 * l + 2 * w;
}
}
}
set should be using implicit value parameter. Your code sets properties to they current value instead:
private int width;
public int Width
{
get { return width; }
set { width = value; }
}
Note that since you don't use any logic in get/set you can use auto-implemented properties instead:
public int Width {get;set;} // no need to define private backing field.