Bonjour,
Je développe une bibliothèque pour gérer et afficher des tilemaps (isométriques ou à base d'hexagones) pour mes différents projets de jeux.
Je voudrais votre avis et conseils sur la manière d'organiser mon code.
Ma question ne concerne pas l'implémentation. J'ai déjà écrit le code et je n'ai pas de problème particulier. C'est pourquoi je ne poste que les interfaces. Ce qui m'intéresse ici, c'est l'architecture des classes.
Le code est en Free Pascal mais il me semble facilement lisible et compréhensible par tout le monde.
Quelques remarques :
- Word est un entier non signé.
- La classe générique TGTilemap s'inspire des idées proposées ici.
- Les méthodes abstraites de conversion des coordonnées MapToScreen et ToScreenToMap sont implémentées dans les classes filles.
- J'utilise SDL pour l'affichage.
- La structure de donnée TTile et le mécanisme de gestion des animations se basent sur cet article.
Est-ce selon vous une bonne approche ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 { TGTilemap } generic TGTilemap<T> = class protected FHeight : Integer; FWidth : Integer; FTiles : array of array of T; public constructor Create(const AHeight : Integer; const AWidth : Integer); function GetTileAt(const AX : Integer; const AY : Integer) : T; procedure SetTileAt(const AX : Integer; const AY : Integer; AValue : T); property At[const AX : Integer; const AY : Integer] : T read GetTileAt write SetTileAt; default; end; PTile = ^TTile; TTile = record FImage : PSDL_Surface; //< Image FLocation : TSDL_Rect; //< position sur la surface SDL FBitflags : Byte; { Gestion des animations } FAnimspeed : ShortInt; //< vitesse des animations FNext : PTile; end; { TTilemap } TTilemap = class(specialize TGTilemap<Word>) private FImageManager : TImageManager; FTileData : array of TTile; FPTiles : array of PTile; public constructor Create(const AHeight : Integer; const AWidth : Integer; AImageManager : TImageManager); { Sérialisation binaire } procedure Save(AArchive : IArchive); procedure Load(AArchive : IArchive); { Sérialisation JSON } procedure Write(AJSON : TJSONObject); procedure Read(AJSON : TJSONObject); { Chargement des données de tuiles } procedure LoadTileset(AJSON : TJSONArray); { Calcul de coordonnées } function MapToScreen(const AX : Word; const AY : Word) : TPoint; virtual; abstract; function ScreenToMap(const AX : Word; const AY : Word) : TPoint; virtual; abstract; { Affichage } procedure Render(AScreen : PSDL_Surface; const ACameraX : Word; const ACameraY : Word); { Gestion des animations } procedure Update(const ADeltaTime : Integer); end; { TOrthogonalMap } TOrthogonalMap = class(TTilemap) const TILE_SIZE = 64; public { Calcul de coordonnées } function MapToScreen(const AX : Word; const AY : Word) : TPoint; override; function ScreenToMap(const AX : Word; const AY : Word) : TPoint; override; end; { TIsometricMap } TIsometricMap = class(TTilemap) const TILE_WIDTH = 126; TILE_HEIGHT = 64; ISO_EAST = 0; ISO_SOUTH_EAST = 1; ISO_SOUTH = 2; ISO_SOUTH_WEST = 3; ISO_WEST = 4; ISO_NORTH_WEST = 5; ISO_NORTH = 6; ISO_NORTH_EAST = 7; public { Calcul de coordonnées } function MapToScreen(const AX : Word; const AY : Word) : TPoint; override; function ScreenToMap(const AX : Word; const AY : Word) : TPoint; override; function IsoDeltaX(ADirection : Byte; AOddRow : Boolean) : Byte; function IsoDeltaY(ADirection : Byte; AOddRow : Boolean) : Byte; end; { THexagonalMap } THexagonalMap = class(TTilemap) const TILE_HEIGHT = 77; TILE_WIDTH = 76; HEX_EAST = 0; HEX_SOUTH_EAST = 1; HEX_SOUTH_WEST = 2; HEX_WEST = 3; HEX_NORTH_WEST = 4; HEX_NORTH_EAST = 5; public function MapToScreen(const AX : Word; const AY : Word) : TPoint; override; function ScreenToMap(const AX : Word; const AY : Word) : TPoint; override; function HexDeltaX(ADirection : Byte; AOddRow : Boolean) : ShortInt; function HexDeltaY(ADirection : Byte) : ShortInt; end;
J'ai l'impression que ma classe TTilemap a trop de responsabilités : gestion des données de tuiles, gestion des animations, affichage de la carte, sérialisation (binaire et JSON).
Partager