|
|
| Templated inheritance vs normal inheritance |
|
J-Gamer
Member #12,491
January 2011
|
In my game, I have a class Drawable, which is just an interface class with a few pure virtual functions. Derived from that I have an SfmlDrawable, which is never directly used, but the classes derived from SfmlDrawable are. To save myself the hassle of defining a new class for each drawable I wanted to have, I opted to do it this way: 1template<class Follow, class Data>
2class SfmlDrawable : public Drawable {
3public:
4 SfmlDrawable(Follow* e, std::shared_ptr<SfData> env) : entity(e), graphics_env(env) {init();};
5 void draw() {}; //Do nothing since we don't know what to draw.
6 ... //Other functions
7private:
8 void init() {}; //Initialize extra.
9 std::shared_ptr<SfData> graphics_env; //The graphical environment
10 Data extra; //The extra data needed to be able to draw.
11 Follow* entity; //The entity this class represents.
12}
13
14typedef SfmlDrawable<Player, sf::CircleShape> SfmlPlayer;
15template<> void SfmlPlayer::draw(); //override the draw method
16template<> void SfmlPlayer::init(); //override init to set the player color.
17... //Override every function that needs overriding.
18
19... //Do so for every drawable.
And have the implementation of the overridden functions in a .cpp file. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
I don't know why you're doing it like this with templates. I read this earlier but I was a little stupified. It's not at all like what I have : 1
2
3/*
4 *
5 * _______ ___ ____ __ _______ _______
6 * /\ ____\ /| \ / __\ /\ \ /\ ____\ /\ ____\
7 * \ \ ___/_ || _ \ | /__/____\ \ \ \ \ ___/_ \ \ _____
8 * \ \ ____\ || |_\ \ |\ \ /_ _\\ \ \ \ \ ____\ \ _____ \
9 * \ \ ___/_ || ___ \ \ \ \//\ / \ \ ____\ \ ___/_ / ____\ \
10 * \ ______\||_|__/_\ \ \ _/ | \ _____\\ ______\ /______\
11 * /______/|/_/ /_/ ______/ /_____/ /______/ /______/
12 *
13 *
14 * EAGLE 5
15 * Edgar's Agile Gui Library and Extensions
16 *
17 * Copyright 2009-2013+ by Edgar Reynaldo
18 *
19 * See EagleLicense.txt for allowed uses of this library.
20 *
21 */
22
23
24
25#ifndef EagleGraphics_HPP
26#define EagleGraphics_HPP
27
28#include "Eagle5/EagleColor.hpp"
29#include "Eagle5/EagleEvents.hpp"
30#include "Eagle5/EagleImage.hpp"
31#include "Eagle5/EagleFont.hpp"
32#include "Eagle5/EagleContainer.hpp"
33
34
35
36
37enum EAGLE_DISPLAY_FLAGS {
38 EAGLE_WINDOWED = 1 << 0,
39 EAGLE_FULLSCREEN = 1 << 1,
40 EAGLE_OPENGL = 1 << 2,
41 EAGLE_DIRECT3D_INTERNAL = 1 << 3,
42 EAGLE_RESIZABLE = 1 << 4,
43 EAGLE_NOFRAME = 1 << 5,
44 EAGLE_GENERATE_EXPOSE_EVENTS = 1 << 6,
45 EAGLE_OPENGL_3_0 = 1 << 7,
46 EAGLE_OPENGL_FORWARD_COMPATIBLE = 1 << 8,
47 EAGLE_FULLSCREEN_WINDOW = 1 << 9,
48 EAGLE_MINIMIZED = 1 << 10,
49 EAGLE_USE_PROGRAMMABLE_PIPELINE = 1 << 11
50};
51
52
53enum IMAGE_DRAWING_FLAGS {
54 DRAW_NORMAL = 0,
55 DRAW_HFLIP = 1,
56 DRAW_VFLIP = 2,
57 DRAW_HVFLIP = 3
58};
59
60
61
62
63
64class REGION_INFO {
65
66public :
67 REGION_INFO();
68 REGION_INFO(float srcx , float srcy , float srcw , float srch);
69
70 float sx;
71 float sy;
72 float sw;
73 float sh;
74};
75
76
77
78class SCALE_INFO {
79
80public :
81 SCALE_INFO();
82 SCALE_INFO(float xscale , float yscale);
83
84 float x;
85 float y;
86};
87
88
89
90class RESIZE_INFO {
91
92public :
93 RESIZE_INFO();
94 RESIZE_INFO(float destx , float desty , float destw , float desth);
95
96 float dx;
97 float dy;
98 float dw;
99 float dh;
100
101};// destination rectangle
102
103
104
105class ROTATE_INFO {
106
107public :
108 ROTATE_INFO();
109 ROTATE_INFO(float pivotx , float pivoty , float destx , float desty , float theta);
110
111 float cx;
112 float cy;
113 float dx;
114 float dy;
115 float angle;
116};
117
118
119
120class EagleDrawingInfo {
121
122private :
123 void CheckUse();
124
125public :
126
127 EagleDrawingInfo();
128 EagleDrawingInfo(float destx , float desty);
129
130 bool use_any;
131 bool use_region;
132 bool use_scale;
133 bool use_resize;// if false, destination point will be used, which is default
134 bool use_rotate;
135 bool use_tint;
136
137 float dx;
138 float dy;
139
140 REGION_INFO region;// sx sy sw sh
141 SCALE_INFO scale;// x y
142 RESIZE_INFO resize;// dx dy dw dh
143 ROTATE_INFO rotate;// cx cy dx dy angle
144 EagleColor tint;// r g b a
145 int flags;// DRAW_HFLIP DRAW_VFLIP DRAW_HVFLIP
146
147 void SetDest(float x , float y);// overrides resize, scale, and rotate
148 void SetRegion(REGION_INFO r);
149 void SetScale(SCALE_INFO s);// only used with rotate
150 void SetResize(RESIZE_INFO r);// overrides scale and rotate, latest setting wins
151 void SetRotate(ROTATE_INFO r);// overrides resize
152 void SetTintColor(EagleColor c);
153 void SetFlags(int f);
154
155
156 void ClearSettings();
157};
158
159
160
161
162class EagleGraphicsContext {
163
164protected :
165 int scrw;
166 int scrh;
167
168 EagleImage* backbuffer;
169 EagleImage* drawing_target;
170
171 PointerManager<EagleImage> images;
172 PointerManager<EagleFont> fonts;
173
174
175
176
177public :
178 EagleGraphicsContext();
179
180 virtual ~EagleGraphicsContext() {}
181
182 // creation/destruction
183 virtual bool Create(int width , int height , int flags)=0;
184 virtual bool Valid()=0;
185 virtual void Destroy()=0;
186
187 // clears target bitmap
188 virtual void Clear(EagleColor c)=0;
189
190 // basic drawing operations
191 virtual void PutPixel(int x , int y , EagleColor c)=0;
192 virtual void DrawRectangle(int x , int y , int w , int h , int thickness , EagleColor c)=0;
193 virtual void DrawFilledRectangle(int x , int y , int w , int h , EagleColor c)=0;
194 virtual void DrawCircle(int cx , int cy , int radius , int thickness , EagleColor c)=0;
195 virtual void DrawFilledCircle(int cx , int cy , int radius , EagleColor c)=0;
196 virtual void DrawTriangle(int x1 , int y1 , int x2 , int y2 , int x3 , int y3 , int thickness , EagleColor c)=0;
197 virtual void DrawFilledTriangle(int x1 , int y1 , int x2 , int y2 , int x3 , int y3 , EagleColor c)=0;
198
199 // precise drawing operations
200 virtual void PutPixel(float x , float y , EagleColor c)=0;
201 virtual void DrawRectangle(float x , float y , float w , float h , float thickness , EagleColor c)=0;
202 virtual void DrawFilledRectangle(float x , float y , float w , float h , EagleColor c)=0;
203 virtual void DrawCircle(float cx , float cy , float radius , float thickness , EagleColor c)=0;
204 virtual void DrawFilledCircle(float cx , float cy , float radius , EagleColor c)=0;
205 virtual void DrawTriangle(float x1 , float y1 , float x2 , float y2 , float x3 , float y3 , float thickness , EagleColor c)=0;
206 virtual void DrawFilledTriangle(float x1 , float y1 , float x2 , float y2 , float x3 , float y3 , EagleColor c)=0;
207
208 // image drawing operations
209 virtual void Draw(EagleImage* src , float x , float y , int flags = DRAW_NORMAL)=0;
210// virtual void Draw(EagleImage* src , EagleDrawingInfo info = EagleDrawingInfo())=0;
211
212 // getters
213 virtual EagleImage* GetBackBuffer()=0;
214 virtual EagleImage* GetScreen()=0;
215 virtual EagleImage* GetDrawingTarget()=0;
216
217 // utilities
218 virtual void FlipDisplay()=0;
219 virtual void HoldDrawing()=0;
220 virtual void ReleaseDrawing()=0;
221 virtual void SetDrawingTarget(EagleImage* dest)=0;
222 void DrawToBackBuffer();
223
224 // image creation / loading / sub division
225 virtual EagleImage* CreateImage(int width , int height , IMAGE_TYPE type)=0;
226 virtual EagleImage* LoadImage(std::string file , IMAGE_TYPE type)=0;
227 virtual EagleImage* CreateSubImage(EagleImage* parent , int x , int y , int width , int height)=0;
228
229 // font loading
230 virtual EagleFont* LoadFont(std::string file , int height , int flags , IMAGE_TYPE type)=0;
231
232 // event handler registration
233 virtual void RegisterDisplayInput(EagleEventHandler* queue)=0;
234
235};
236
237
238#endif // EagleGraphics_HPP
Can you explain why you need the template, and can't simply derive new classes with out it? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
l j
Member #10,584
January 2009
|
I've seen people use templates as a way to get 'compile time polymorphism'.
|
|
J-Gamer
Member #12,491
January 2011
|
I chose for a template implementation for two reasons:
" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
gnolam
Member #2,030
March 2002
|
OT: Quote: /* * _______ ___ ____ __ _______ _______ * /\ ____\ /| \ / __\ /\ \ /\ ____\ /\ ____\ * \ \ ___/_ || _ \ | /__/____\ \ \ \ \ ___/_ \ \ _____ * \ \ ____\ || |_\ \ |\ \ /_ _\\ \ \ \ \ ____\ \ _____ \ * \ \ ___/_ || ___ \ \ \ //\ / \ \ ____\ \ ___/_ / ____\ \ * \ ______\||_|__/_\ \ \ _/ | \ _____\\ ______\ /______\ * /______/|/_/ /_/ ______/ /_____/ /______/ /______/ */
That is some seriously mangled ASCII art... -- |
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
It's Matthew's code parser, cuz it looks fine here in my editor. As for OT, I still don't get it. What classes will derive from SFML drawable? Why? Just to inherit a draw and init method? That seems kinda silly. Are these gonna be full objects or what? What are these things that you're making a class for? My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|
J-Gamer
Member #12,491
January 2011
|
Edgar Reynaldo said: As for OT, I still don't get it. What classes will derive from SFML drawable? Why? Just to inherit a draw and init method? That seems kinda silly. Are these gonna be full objects or what? What are these things that you're making a class for?
Quote: typedef SfmlDrawable<Player, sf::CircleShape> SfmlPlayer;
This is how I make a new class. Player is a class from my game, and is an entity that runs around on the game world. All SfmlPlayer needs to be able to draw itself is a circle, which is initialized in the overridden init method. That is as far as "inheritance" goes here. SfmlPlayer, SfmlZombie, SfmlBullet,... actually are SfmlDrawable specializations. 1class SfmlDrawable : public Drawable {
2public:
3 SfmlDrawable(std::shared_ptr<SfData> env) : graphics_env(env) {};
4 virtual void draw() {};
5 ... //Other functions, all virtual
6protected:
7 std::shared_ptr<SfData> graphics_env;
8}
9
10class SfmlPlayer : public SfmlDrawable {
11public:
12 SfmlPlayer(std::shared_ptr<SfData> env, Player* p) : SfmlDrawable(env), p(p) {
13 //Contents of init-method to initialize our shape.
14 }
15 void draw();
16 //Name other functions that need to be overridden
17private:
18 sf::CircleShape shape;
19 Player* p;
20}
And write those last 10+ lines of code for SfmlZombie, SfmlBullet,... Templates are code generators, and since all SfmlDrawable classes have the same class layout, it's easier to automate the code generation. " There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo |
|
|