Are extension methods the solution to this problem?
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 a开发者_开发技巧t 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 ;)
精彩评论