Description of the environment:
- I am implementing a (hobbyist) modern engine for (an old) PlayStation 1 video game
- Graphical data is represented as packets where it can represent either a polygon or a sprite,
(and they are transformed differently to end up as pixels on screen) - All those differents type of packets (18 in total) can in fact be reduced to 2 or 3 types at most (what I've done to reduce code surface), with some flags indicating what's present in them
For information purposes,
This format is more or less a variant of the HMD format by Sony, an efficient low-level format that gets consumed directly by the PlayStation 1 GPU, at the expense of being unfriendly to read/parse, etc ... (actually on the real PlayStation 1, one would emit few system library calls to load it and that was it)
Description of the problem:
- I need to find a (simple yet effective) way of realizing their content
- accounting that they can either be a polygon or a sprite
Long story short,
The following code snippets below probably explains better what's the content and the preliminary approach,
Interfaces that we'll work against:
/// <summary>
/// a graphics primitive.
/// </summary>
public interface IPrimitive
{
bool IsPolygon { get; }
bool IsSprite { get; }
}
/// <summary>
/// a polygon, i.e. triangle, quad.
/// </summary>
public interface IPolygon : IPrimitive
{
void GetMesh();
}
/// <summary>
/// a sprite, (internal representation has different meaning than a polygon).
/// </summary>
public interface ISprite : IPrimitive
{
void GetMesh();
}
Type present in game data:
/// <summary>
/// a packet representing graphical data : a polygon or a sprite.
/// </summary>
public class GraphicsPacket : IPolygon, ISprite
{
public GraphicsPacket(Stream stream)
{
// read packet ...
// there will be a flag indicating if it's a sprite
// and therefore should be treated differently
}
public bool IsSprite { get; }
public bool IsPolygon => !IsSprite;
void IPolygon.GetMesh()
{
if (IsSprite)
throw new InvalidOperationException("Instance is not a polygon");
}
void ISprite.GetMesh()
{
if (IsPolygon)
throw new InvalidOperationException("Instance is not a sprite");
}
}
Test of that whole logic:
public class Test
{
public void BuildPrimitive([NotNull] IPrimitive primitive)
{
if (primitive == null)
throw new ArgumentNullException(nameof(primitive));
// obviously here, 'as' cast would always be true for all cases
var polygon = primitive.IsPolygon;
if (polygon)
{
// do something with it
((IPolygon)polygon).GetMesh();
return;
}
var sprite = primitive.IsSprite;
if (sprite)
{
// do something with it
((ISprite)sprite).GetMesh();
return;
}
throw new NotSupportedException(nameof(primitive));
}
}
Question:
Is my approach for treating a graphics packet depending its content a good one ?
i.e.
- explicit interface implementation
- naive
bool
check and throw on invalid state
Strong arguments about considering splitting the concerns in such case,
- game data is just like that, why change the logic ?
- (my) modern, object-oriented approach, summarized this as few types (i.e. DRY concept)
- problem won't really vanish, as those graphics packet will always be either a polygon or a sprite (i.e. why fight against that logic after all ?)
Hope that makes sense to you, otherwise let me know how I can improve the question.