1 /******************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011 OmegaSDG **
5 ******************************/
7 #include <Gosu/Image.hpp>
8 #include <libxml/parser.h>
9 #include <libxml/tree.h>
12 #include "resourcer.h"
15 Sprite::Sprite(Resourcer
* rc
)
23 boost::unordered_map
<std::string
, Gosu::Image
*>::iterator it
;
24 for (it
= imgs
.begin(); it
!= imgs
.end(); it
++) {
25 Gosu::Image
* img
= (*it
).second
;
30 bool Sprite::init(const std::string
& descriptor
)
32 this->descriptor
= descriptor
;
33 return processDescriptor() && loadPhases();
36 void Sprite::draw() const
38 img
->draw((double)c
.x
, (double)c
.y
, (double)0);
41 bool Sprite::setPhase(const std::string
& name
)
44 boost::unordered_map
<std::string
, Gosu::Image
*>::iterator phase
;
45 phase
= imgs
.find(name
);
46 if (phase
!= imgs
.end()) {
47 Gosu::Image
* newImg
= (*phase
).second
;
48 changed
= img
!= newImg
;
54 coord_t
Sprite::getCoordsByPixel()
59 coord_t
Sprite::getCoordsByTile()
62 coords
.x
= c
.x
/ img
->width();
63 coords
.y
= c
.y
/ img
->height();
64 coords
.z
= c
.z
; // XXX: revisit when we have Z-buffers
68 void Sprite::setCoordsByPixel(coord_t coords
)
73 void Sprite::setCoordsByTile(coord_t coords
)
75 // FIXME: use Area's tile width
79 // XXX: set c.z when we have Z-buffers
82 void Sprite::moveByPixel(coord_t dc
)
89 void Sprite::moveByTile(coord_t dc
)
91 // FIXME: use Area's tile width
92 c
.x
+= dc
.x
* img
->width();
93 c
.y
+= dc
.y
* img
->height();
94 // XXX: set c.z when we have Z-buffers
98 * Try to load in descriptor.
100 bool Sprite::processDescriptor()
102 XMLDocRef doc
= rc
->getXMLDoc(descriptor
, "dtd/sprite.dtd");
105 const xmlNode
* root
= xmlDocGetRootElement(doc
.get()); // <sprite>
108 xmlNode
* node
= root
->xmlChildrenNode
; // children of <sprite>
111 for (; node
!= NULL
; node
= node
->next
) {
112 if (!xmlStrncmp(node
->name
, BAD_CAST("sheet"), 6)) {
113 str
= xmlNodeGetContent(node
);
114 xml
.sheet
= (char*)str
;
116 str
= xmlGetProp(node
, BAD_CAST("tilesizex"));
117 xml
.tilesize
.x
= atol((char*)str
); // atol
119 str
= xmlGetProp(node
, BAD_CAST("tilesizey"));
120 xml
.tilesize
.y
= atol((char*)str
); // atol
122 else if (!xmlStrncmp(node
->name
, BAD_CAST("phases"), 7) &&
123 !processPhases(node
))
129 bool Sprite::processPhases(xmlNode
* phases
)
131 for (xmlNode
* phase
= phases
->xmlChildrenNode
; phase
!= NULL
;
133 if (!xmlStrncmp(phase
->name
, BAD_CAST("phase"), 6))
134 if (!processPhase(phase
))
139 bool Sprite::processPhase(xmlNode
* phase
)
141 /* Each phase requires a 'name'. Additionally,
142 * one of either 'pos' or 'speed' is needed.
143 * If speed is used, we have sub-elements. We
144 * can't have both pos and speed.
146 const std::string key
= (char*)xmlGetProp(phase
, BAD_CAST("name"));
148 const xmlChar
* pos
= xmlGetProp(phase
, BAD_CAST("pos"));
149 const xmlChar
* speed
= xmlGetProp(phase
, BAD_CAST("speed"));
152 Log::err(descriptor
, "pos and speed attributes in "
153 "element phase are mutually exclusive");
156 if (!pos
&& !speed
) {
157 Log::err(descriptor
, "must have pos or speed attribute "
163 const unsigned value
= (unsigned)atoi((const char*)pos
); // atol
164 xml
.phases
[key
] = value
;
167 // TODO: Load animated sprites
168 // Load <member> subelements
174 bool Sprite::loadPhases()
177 if (!rc
->getBitmap(src
, xml
.sheet
))
180 boost::unordered_map
<std::string
, unsigned>::iterator it
;
181 for (it
= xml
.phases
.begin(); it
!= xml
.phases
.end(); it
++) {
182 const std::string
& name
= (*it
).first
;
183 unsigned idx
= (*it
).second
;
184 Gosu::Image
* image
= loadImage(src
, idx
);
185 imgs
[name
] = img
= image
;
190 Gosu::Image
* Sprite::loadImage(const Gosu::Bitmap
& src
, unsigned pos
)
192 unsigned x
= (unsigned)((xml
.tilesize
.x
* pos
) %
194 unsigned y
= (unsigned)((xml
.tilesize
.y
* pos
) /
195 src
.width() * xml
.tilesize
.y
); // ???
197 // FIXME: check for index out of bounds
199 return rc
->bitmapSection(src
, x
, y
, (unsigned)xml
.tilesize
.x
,
200 (unsigned)xml
.tilesize
.y
, true);