Goal:
I’m currently working on an addition to an already existing library (a maze generator). What I’m trying to do is define a new way of storing the maze (partially in memory and partially on the hard disk).
-Skip to the Problem paragraph if you just want to see the question. I added some extra information since you might suggest a completely other approach.
Current situation:
The current way the maze generator stores mazes (in memory) is with a Map. The Map contains a bunch of InnerMapArrays which each contain a line of pixels in the maze. Points can be read/written in the maze like this:
… //Code that creates maze map
map[x][y] = true;
In the Map class there’s a method to return the correct array (x)
public override InnerMapArray this[int x]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return innerData[x];
}
}
Then it will call [y] on the innerData which also contains a similar method to ultimately return the right pixel.
Problem:
Going back to what I want to do is create a new Map type that saves parts of the maze in memory and parts of the maze on the disk. I want to load areas of the maze in sets of 100x100 pixels for example, not by line. (In the image below the red part should be loaded when pixel x=50,y=50 is changed for example)
The current implementation of the Map/InnerMapArray structure does not allow for this. What I want is a way to actually get the X and Y that are passed in one method.
What I thought that could possibly work is the following (not working code):
public override InnerMapArray this[int x][int y]
{
get
{
//load a certain 100x100 part of the maze in memory and set it as current
//so while generating the maze pixels near the currently generated/read pixel
//can be read really fast while others far away won't use any memory
}
}
Sadly the C# compiler doesn’t allow this. Does anyone have a clue that could help me solve this issue in a ‘nice’ way.
The way to achieve what you want is:
public overrride InnerMapArray this[int x, int y] { ... }
This code works only if you have a "double" indexer like this to be overriden in de base class of course. Hope this helps :)
Related
I'm currently working on a OO representation of a simplified chess game. Most of it is straightforward enough but one design decision I'm a little unsure about is the relationship between the chessBoard and pieces. The bottom line is I'm trying to figure out the best way to represent the chessboard / piece relationship so that I can easily and efficiently query "given a spot, is there a piece here" and "given a piece, what spot is it on"?
Currently, the Piece class stores both their own location (using a Spot class) and a reference to the Board class. The board class represents the board as a Dictionary<Spot, Piece> (the simplified game only has a few pieces so it felt unnecessary to store a mostly empty array of N by M spots like other examples I've seen) to track what spots on the board have what pieces on them. This is useful and seems intuitive to me since the piece can use the reference to the board when trying to move and ask "is there anyone at this spot?" and it can return the piece if any that is on a given spot. Similarly, in order to move the piece I need to know where it currently is and storing the location on the piece itself seems like a good OO approach.
The part where I'm running into some questions / trouble is how to keep those values in sync such that if I call (public method) Board.MovePiece() or (private setter) Piece.CurrentPosition = new spot() both Piece.CurrentPosition and the Board's Dictionary<Spot, Piece> are updated properly. Keeping everything as private as possible while making sure that calling a method on either the board or the piece while keeping the other class in sync is very tricky if not impossible. If C# had friend classes like C++ I could just make the Board a friend of the Piece then they could set each other's private vars no problem (I'm aware of internal which improves things but I don't think it prevents other code in the project from theoretically calling stuff it shouldn't). Right now my solution to this is a custom setter on the piece.CurrentPosition property so that every call to change it results in the correct call to public board members (which absolutely works) but I feel like I could do better. The biggest risk is the board methods are public and could be called outside the piece class and thus not update the piece location but I'm not a huge fan of the redundancy / slight complexity smell the code has currently.
Here's a simplified look at my code:
public class Board : IBoard
{
private uint _width;
private uint _height;
private Dictionary<Spot, Piece> _pieceLocations;
public Board(uint width, uint height)
{
_width = width;
_height = height;
_pieceLocations = new Dictionary<Spot, Piece>();
}
// heavily used by piece when determining legal moves, what pieces and free spaces are in range etc.
public Piece CheckSpot(Spot spot)
{
Piece piece;
if (_pieceLocations.TryGetValue(transformSpot(spot), out piece))
{
return piece;
}
return null;
}
/// remove instead of null to potentially optimize space a bit
public bool RemovePiece(Spot spot)
{
if (spot != null)
{
return _pieceLocations.Remove(transformSpot(spot));
}
return false;
}
/// This function will simply attempt to just move the piece to the specified destination.
/// It's up to the caller to make sure the move is a valid chess move, etc
public Spot MovePiece(Spot destination, Piece pieceToBeMoved)
{
// remove piece from current position
// note the need to have current position here
RemovePiece(pieceToBeMoved.CurrentPosition);
// attempt to place at and return new position
return PlacePiece(destination, pieceToBeMoved);
}
/// Simply places piece at specified destination if not occupied by another piece
private Spot PlacePiece(Spot destination, Piece pieceToPlace)
{
var transformedDestination = transformSpot(destination);
//business logic to check for stuff like a piece already at destination
_pieceLocations.Add(transformedDestination, pieceToPlace);
return transformedDestination;
}
Note transformSpot just makes sure coordinates are not out of bounds and "wraps them around" to be within board dimensions if need be.
public abstract class Piece : IPiece
{
protected IBoard _board;
public ColorType Color { get; protected set; }
private Spot _currentPosition;
public Piece(ColorType color, Spot currentPosition, IBoard board)
{
_board = board;
Color = color;
CurrentPosition = currentPosition ?? throw new ArgumentNullException(nameof(currentPosition), "When creating a piece you must specify a location");
}
public Spot CurrentPosition {
get { return _currentPosition; }
// I wanted to make sure that the piece's current position was always in sync with the board.
// Calling <Board> functinos here seemed like a reasonable approach.
protected set {
// if position is being set to null remove from board
if (value == null)
{
_board.RemovePiece(_currentPosition);
_currentPosition = null;
}
else
{
_currentPosition = _board.MovePiece(value, this);
}
}
}
public void Move()
{
// note that I now need the current position to figure out where I can go etc.
// insert logic to determine where we can move using chess rules etc.
var destination = new Spot(x,y);
// if spot is occupied remove piece
var occupyingPiece = _board.CheckSpot(destination);
if (occupyingPiece != null)
{
occupyingPiece.RemovePiece();
}
// call custom setter which in turn updates board to move piece from current spot to destination
CurrentPosition = destination;
}
public void RemovePiece()
{
// call custom setter which in turn updates board to remove piece
CurrentPosition = null;
}
And some super rough pseudo code for the main driver
List<Piece> whitePieces = generateWhitePieces();
List<Piece> blackPieces = generateBlackPieces();
while (gameActive)
{
//somehow determine which piece to move
var pieceToMove = whitePieces.PickPiece();
// could pass and store CurrentPosition at this level but if it's not stored on the piece or easily
// accessible from the board but feels slightly icky
pieceToMove.Move();
pieceToMove = blackPieces.PickPiece();
pieceToMove.Move();
// etc.
}
Again, main flaw on top of some possibly unneeded complexity seems to be that Board.MovePiece() needs to be public for Piece to call it but that means anyone can also call MovePiece() and move something on the board without updating the piece.
Possible solutions I have considered:
I'm totally overthinking this and this is a fairly reasonable approach.
having the piece own its own location feels right, just wish I had better access modifiers to protect sensitive values but allow friends to change them (I'm aware of internal but doesn't seem to solve my issues fully)
I could just remove currentPos and:
have the board class maintain a Dictionary<Piece, Spot>
This feels like simply shifting the issue and having board maintain two dictionaries of essentially the same info in different orders feels silly, but at least it tightly couples the data together and allows the board to be the "authority" on where everything is. Leaning towards this but have a feeling this could be optimized somehow with the right data structure
have the main driver / game class maintain a dictionary / tuple list of pieces and their current position and have the Piece.Move() pass back info on where the board tells them they are now.
Again this just feels like we're shifting the issue but even more so. On the other hand I can kinda see the rationale for the game to want to keep track of pieces but that still feels pretty anti OO and I'd probably prefer keeping this to the Board as described above.
In theory could also
Just make current position setter public so Board could change it directly and add some complex checks in both the Board functions and the Piece.CurrentPosition setter to make sure if one is changed so is the other.
Feels much worse and adds more complexities / risks than it solves in my opinion. If it weren't for this issue CurrentPosition should have a private setter.
Anyway would very much appreciate any feedback / insight!
EDIT: to be clear I'm assuming that the piece class owns its logic when it comes to how it can move, and uses the state of the board to determine what spaces it can move to. Something like Piece.DetermineMove(). Specifically the piece needs to know where it is and what pieces if any are on the spaces it can move to, pieces that threaten it, etc.
If that's a poor design I'm all ears but I have a hard time believing that a Piece class shouldn't own its own movement logic in an OOP design.
Opinions are going to be thick on this one, and there's really no absolutely correct answer. Each will have pros and cons, some of which you might not find out until much later on in development. That being said, here's mine. :)
What you really want to do is ensure that there is only one method to do any operation in your application, and only one place that biblical data is stored in the application (religious connotations aside, biblical meaning "true").
You can start with logical objects (in your domain) and attempt to place this one method into the object that it makes sense for. If it doesn't make sense, then you might need a different [mental] model.
You've started with Board, Piece and Spot and I like this so far. Since we want to keep the data for a location of a piece in one place, I think we want to do that at the board level, because it will make movement easier (a piece won't have to go "up" to the board and back "down" to another piece).
This means a Piece won't have a Spot property, only a type (knight, bishop, etc) and ColorType (white/black). The board will have the dictionary for the pieces with the Spot as the key (it's a good key - there can only be one piece on a square). This makes a lot of the logic easier. Moving a piece means taking it out of the dict and putting it back in at the destination:
// Move attempt method might look like this:
Piece thisPiece = ... ;
Spot old = (1, 1); // origin ..
Spot new = (2, 2); // .. destination
// do some validation
if (pieces.Contains(new) && pieces[new].color == thisPiece.color)
throw new SpotOccupiedByFriendlyPieceAndThisIsntACastleException();
// capture a piece
if (pieces.Contains(new) && pieces[new].color != thisPiece.color)
{
pieces.Remove(new);
}
pieces.Remove(old); // move the old piece from "old"...
pieces.Add(new, thisPiece); //... to "new"
By putting all the pieces in a Dictionary<Spot, Piece> at the board level, there's only one collection that holds the pieces-to-spots relationship (the board owns it), and the board can perform all the logic it needs to.
I'm using Unity2D and coding in C#. I have a class 'TileInfoArray' which holds an array of 'TileInfo' classes. 'TileInfo' contains a bunch of data for the game's tilemap including what sprite should be shown, the movement cost, etc.
Sample of 'TileInfoArray':
public class TileInfoArray {
private TileInfo[] arr;
. . .
public void SetSprite(int index, Sprite sprite) {
arr[index].sprite = sprite;
}
}
This code is called with a simple
'world.tileInfoArray.SetSprite(index, sprite_Cobblestone);', yet later when I call 'world.tileInfoArray[index].sprite' for that same index, I get the default sprite I used when I created the array.
tileInfoArray = new TileInfoArray(WorldSizeTiles);
tileInfoArray.Populate(new TileInfo());
If anyone was interested. 'Populate' just calls a for loop that adds starting data.
I'm confused as to why this is. I have verified that the indexes are always within range and mapped correctly, and the array starts with assigned default data. I'm aware that something like 'TileInfoArray array = world.tileInfoArray' would just copy the data, and trying 'array[index].sprite = newSprite' wouldn't affect the original 'world.tileInfoArray', but since I'm calling a method from the class that holds the array, shouldn't that then change its data?
Any help would be much appreciated. I will be out of town for the weekend, but I'll be back first thing Monday to answer any questions and hopefully just look like a big dummy for missing an obvious mistake.
I'm working on a personal project that, like many XNA projects, started with a terrain displacement map which is used to generate a collection of vertices which are rendered in a Device.DrawIndexedPrimitives() call.
I've updated to a custom VertexDeclaration, but I don't have access to that code right now, so I will post the slightly older, but paradigmatically identical (?) code.
I'm defining a VertexBuffer as:
VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
where 'vertices' is defined as:
VertexPositionNormalTexture[] vertices
I've also got two index buffers that are swapped on each Update() iteration. In the Draw() call, I set the GraphicsDevice buffers:
Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;
Ignoring what I hope are irrelevant lines of code, I've got a method that checks within a bounding shape to determine whether a vertex is within a certain radius of the mouse cursor and raises or lowers those vertex positions depending upon which key is pressed. My problem is that the VertexBuffer.SetData() is only called once at initialization of the container class.
Modifying the VertexPositionNormalTexture[] array's vertex positions doesn't get reflected to the screen, though the values of the vertex positions are changed. I believe this to be tied to the VertexBuffer.SetData() call, but you can't simply call SetData() with the vertex array after modifying it.
After re-examining how the IndexBuffer is handled (2 buffers, swapped and passed into SetData() at Update() time), I'm thinking this should be the way to handle VertexBuffer manipulations, but does this work? Is there a more appropriate way? I saw another reference to a similar question on here, but the link to source was on MegaUpload, so...
I'll try my VertexBuffer.Swap() idea out, but I have also seen references to DynamicVertexBuffer and wonder what the gain there is? Performance supposedly suffers, but for a terrain editor, I don't see that as being too huge a trade-off if I can manipulate the vertex data dynamically.
I can post more code, but I think this is probably a lack of understanding of how the device buffers are set or data is streamed to them.
EDIT: The solution proposed below is correct. I will post my code shortly.
First: I am assuming you are not adding or subtracting vertices from the terrain. If you aren't, you won't need to alter the indexbuffer at all.
Second: you are correct in recognizing that simply editing your array of vertices will not change what is displayed on screen. A VertexBuffer is entirely separate from the vertices it is created from and does not keep a reference to the original array of them. It is a 'snapshot' of your vertices when you set the data.
I'm not sure about some of what seem to be assumptions you have made. You can, as far as I am aware, call VertexBuffer.SetData() at any time. If you are not changing the number of vertices in your terrain, only their positions, this is good. Simply re-set the data in the buffer every time you change the position of a vertex. [Note: if I am wrong and you can only set the data on a buffer once, then just replace the old instance of the buffer with a new one and set the data on that. I don't think you need to, though, unless you've changed the number of vertices]
Calling SetData is fairly expensive for a large buffer, though. You may consider 'chunking' your terrain into many smaller buffers to avoid the overhead required to set the data upon changing the terrain.
I do not know much about the DynamicVertexBuffer class, but I don't think it's optimal for this situation (even if it sounds like it is). I think it's more used for particle vertices. I could be wrong, though. Definitely research it.
Out of curiosity, why do you need two index buffers? If your vertices are the same, why would you use different indices per frame?
Edit: Your code for creating the VertexBuffer uses BufferUsage.WriteOnly. Good practice is to make the BufferUsage match that of the GraphicsDevice. If you haven't set the BufferUsage of the device, you probably just want to use BufferUsage.None. Try both and check performance differences if you like.
In my program the source rectangle for drawing can either be a regular rectangle, an empty rectangle, or a rectangle with an X or Y of -1. If the rectangle is normal (example being (0, 0, 64, 64)) then it just draws that from the texture. If it is Rectangle.Empty it draws nothing and just continues with the loop. If the source rectangle has an X or Y of -1 then it is determined to be a collision tile.
The problem with this is that it -1 is not intuitive. It is confusing and a bad solution. Also if there come to be more tile types it will start getting ridiculous like -2 meaning a slow tile or -3 meaning a water tile.
Another problem is that since I did not know there were going to be collision tiles early on and regular XNA rectangles were fine, the entire system (thankfully only around 1,000 of lines of code at the moment) uses XNA rectangles. I figure I'm going to have to make a separate class at this point and update everything but I'm not sure.
What would be a good solution to this? I have not really dabbled in extension methods at all. Could they be applied to the Rectangle class and be given methods like IsCollisionTile() or IsBlankTile()? Initially I was hoping I could derive from the Rectangle class to make a Tile class but unfortunately the class is sealed. I suppose another simple solution could be just making a global constants class with -1 being CollisionTile, 0 being BlankTile, et cetera. This would at least make it slightly more understandable but this still looks ugly to me:
if (tiles[y, x].X == Constants.BlankTile)
continue;
if (tiles[y, x].X == Constants.CollisionTile)
{
Utility.DrawRectangle(spriteBatch, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), collisionTileColor);
continue;
}
spriteBatch.Draw(tileset, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), tiles[y, x], Color.White);
If only there was a property I could use like Tag with controls. I'd really like to not abandon using the Rectangle class because it is so embedded in to the system and the program is purely functional, just not aesthetic in this regard. Ideally, I'd prefer a solution that just allows the Rectangle class to be extended to somehow be able to communicate with its clients what kind of tile it is supposed to be.
Well then, that took a lot more typing than I had originally hoped for. Sorry for the long read x_x
I would recommend setting global constants. The problem with extension methods in this case arises because Rectangle is a struct, a value type. That means that your extension method is working with a copy of the rectangle, not the original.
If the class can't be inherited from (which would usually be the appropriate solution here. Shame on you Microsoft!) then extension methods could defiantly work as you described.
Problem is - IMO it's less in style with C# and OOP in general to use methods that function like getters. That's what getters are for.
Because of that, I think the global constants option is more in line with the general style, but that's just my opinion.
From a totally programmatic POV - both methods are valid where the global constant class might be slightly faster (though I'm not sure of this)
At the beginning, you should consider, when do you use your Methods
IsCollisionTile() and IsBlankTile()
You have two choices:
*) You wanna use it globally, then you should better write a Utility-Class to have your Methods right there where you need them:
public static class CollisionHelper
{
public static Boolean IsCollisionTile(ITile tileToCheck)
{
...
}
}
*) Second, if you wanna use it only in connection with your tiles, you should definitly write an extension method, e.g. to accept every ITile-Object. Extensions methods are a great way to widely EXTEND the capabilities of classes. A sample could be:
public class RectangleTile : ITile
{
public static Boolean IsCollisionTile(this ITile tileToCheck)
{
...
}
}
I hope you have now an idea about Extension-Methods and how you could use them to solve your problem very easily ;)
So, I currently have a Board class that is composed of Pieces. Each Piece has a color and a string that describes the kind of piece. It also has a 2d matrix with bits either set on or off, that allows me to know which pixels to paint with the desired color or not.
My question is, which class should have the responsability to draw the pieces on the board? On one hand, I'd say the Piece class should do it. But to do it, I'd have to pass a Board as reference to Piece's Draw() method and although it's not terrible I find it kinda awkward. This raises the problem that Piece would have "to know" the Board class.
On the other hand, I could just have the Piece have a
Boolean[,] IsPixelSet(int x, int y)
and Board would then have a method of the form:
void DrawPieceOnBoard() {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (piece.IsPixelSet(x, y) {
board.DrawPixelAt(x, y, piece.GetColor());
}
}
}
}
How would you do it? And why? I can't see a clear winner in any of these approaches.
Thanks
edit
I'm not talking about actually drawing things on screen. What happens is that I'm implementing a Tetris game (currently, no GUI) and I need at every moment to set the Pixels of a Square on different positions on the board as it falls to the ground. The board basically only has an accessor and a mutator for each one of the (x, y) points. Let's now say I want to draw a Square(a type of Piece) on the Board. Should the Piece know of the board and its Draw() method make the changes to the Board, or should the Board access Piece's getter method and do it itself?
FWIW, in general MVC theory, neither class should draw itself.
Presentation would be a concern of a separate view.
I'd say the Piece draws. For example, your function does not allow to enhance the Piece to allow them to have several colors.
The Piece does not have to know all the Board, just some method (maybe part of an interface) Draw(x,y,color).
In my opinion the Piece should draw the piece and the Board should draw the board.
I would have something like this:
class Piece
{
Image Render(Rectangle bounds) { /* */ }
}
class Board
{
void Render(Graphics g)
{
//Draw the base
foreach (piece in Pieces)
{
var rect = figureOutPosition(); //Positioning logic to
g.DrawImage(location, rect, piece.Render(rect));
}
//Draw any overlays
}
}
I agree with nonnb, there's no logical concept of "drawing" for a chess piece or a board, it could be argued that the board has references to all the pieces, so it should draw itself. But that argument equally says that it could be a helper object, or the environment that does the drawing.
I'd personally opt for a rendering class (for example, maybe you want to be able to print the board in ASCII for a record of all the moves), or maybe in the future upgrade to a 3d rendering engine or something... that's just my 0.2¢
It does not matter. What you may want to do is to make it so that either board depends on piece or piece on board for everything you do.
I'd go for the Composite Design Pattern - mostly the same solution as #Pondidum.
Drawable has the method draw()
Board isA Drawable
Piece isA Drawable
Board hasA array of Drawable.