00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023
00024
00025
00026
00027 #include "SpriteEngine.h"
00028 #include "SoundEngine.h"
00029
00030
00031 AnimFrames::AnimFrames(UInt16 numFrames, DmResID bitmapID, DmResID maskID, Coord hotSpotX, Coord hotSpotY, OptimizationMode optimizationMode)
00032 {
00033 this->numFrames = numFrames;
00034 this->bitmapID = bitmapID;
00035 this->maskID = maskID;
00036 this->hotSpotX = hotSpotX;
00037 this->hotSpotY = hotSpotY;
00038 this->optimizationMode = optimizationMode;
00039
00040
00041 MemHandle resH = DmGetResource( bitmapRsc, bitmapID );
00042 ErrNonFatalDisplayIf( !resH, "Missing bitmap" );
00043 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00044
00045 this->width = resP->width;
00046 this->height = resP->height;
00047
00048 MemPtrUnlock(resP);
00049 DmReleaseResource( resH );
00050
00051 00052 00053 00054 00055 frameDescriptors = new FrameDescriptor[numFrames];
00056
00057
00058 switch(optimizationMode)
00059 {
00060 case AnimFrames::optBUFFER:
00061 {
00062 WinHandle oldDrawH = WinGetDrawWindow();
00063 UInt16 error = errNone;
00064
00065 for (int frameIdx = 0; frameIdx < numFrames; frameIdx++)
00066 {
00067 {
00068
00069 MemHandle resH = DmGetResource( bitmapRsc, bitmapID + frameIdx);
00070 ErrNonFatalDisplayIf( !resH, "Missing bitmap" );
00071 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00072
00073 frameDescriptors[frameIdx].offScreenBitmap = WinCreateOffscreenWindow(resP->width, resP->height, screenFormat, &error);
00074 WinSetDrawWindow(frameDescriptors[frameIdx].offScreenBitmap);
00075 WinDrawBitmap (resP, 0,0);
00076
00077 MemPtrUnlock(resP);
00078 DmReleaseResource( resH );
00079 }
00080
00081 {
00082
00083 MemHandle resH = DmGetResource( bitmapRsc, maskID + frameIdx);
00084 ErrNonFatalDisplayIf( !resH, "Missing mask" );
00085 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00086
00087 frameDescriptors[frameIdx].offScreenMask = WinCreateOffscreenWindow(resP->width, resP->height, screenFormat, &error);
00088 WinSetDrawWindow(frameDescriptors[frameIdx].offScreenMask);
00089 WinDrawBitmap (resP, 0,0);
00090 MemPtrUnlock(resP);
00091 DmReleaseResource( resH );
00092 }
00093 }
00094
00095 WinSetDrawWindow(oldDrawH);
00096 }
00097 break;
00098
00099 case AnimFrames::optNONE:
00100 case AnimFrames::optNO_MASK:
00101 for (int frameIdx = 0; frameIdx < numFrames; frameIdx++)
00102 {
00103 frameDescriptors[frameIdx].offScreenBitmap = NULL;
00104 frameDescriptors[frameIdx].offScreenMask = NULL;
00105 }
00106 break;
00107 }
00108 }
00109
00110
00111 AnimFrames::~AnimFrames()
00112 {
00113 for (int frameIdx = 0; frameIdx < numFrames; frameIdx++)
00114 {
00115 if (frameDescriptors[frameIdx].offScreenBitmap != NULL)
00116 {
00117 WinDeleteWindow(frameDescriptors[frameIdx].offScreenBitmap, false);
00118 }
00119
00120 if (frameDescriptors[frameIdx].offScreenMask != NULL)
00121 {
00122 WinDeleteWindow(frameDescriptors[frameIdx].offScreenMask, false);
00123 }
00124 }
00125
00126 delete[] frameDescriptors;
00127 }
00128
00129
00130 void AnimFrames::getBounds(Coord x, Coord y, RectangleType *bounds) const
00131 {
00132 ErrNonFatalDisplayIf(bounds == NULL, "getBounds: bounds == NULL");
00133
00134 bounds->topLeft.x = x - hotSpotX;
00135 bounds->topLeft.y = y - hotSpotY;
00136 bounds->extent.x = width;
00137 bounds->extent.y = height;
00138 }
00139
00140
00141 void AnimFrames::draw(UInt16 index, Coord x, Coord y, RectangleType *bounds) const
00142 {
00143 UInt16 error;
00144
00145 WinHandle drawWindow = WinGetDrawWindow();
00146
00147 switch(optimizationMode)
00148 {
00149 case AnimFrames::optBUFFER:
00150 case AnimFrames::optNO_MASK:
00151 quickDraw(index, x, y, drawWindow, NULL, bounds);
00152
00153 break;
00154
00155 case AnimFrames::optNONE:
00156 WinHandle offScreenH = WinCreateOffscreenWindow(width, height, screenFormat, &error);
00157 WinSetDrawWindow(offScreenH);
00158 quickDraw(index, x, y, drawWindow, offScreenH, bounds);
00159 WinSetDrawWindow(drawWindow);
00160 WinDeleteWindow(offScreenH, false);
00161
00162 break;
00163 }
00164 }
00165
00166
00167 void AnimFrames::quickDraw(UInt16 index, Coord x, Coord y, WinHandle drawWindow, WinHandle offScreenH, RectangleType *bounds) const
00168 {
00169 if (bounds != NULL)
00170 getBounds(x, y, bounds);
00171
00172 RectangleType size;
00173 size.topLeft.x = 0;
00174 size.topLeft.y = 0;
00175 size.extent.x = width;
00176 size.extent.y = height;
00177
00178
00179 switch(optimizationMode)
00180 {
00181 case AnimFrames::optBUFFER:
00182
00183
00184 WinCopyRectangle(frameDescriptors[index].offScreenMask, drawWindow, &size, x - hotSpotX, y - hotSpotY, winMask);
00185 SoundEngine::timeTick();
00186 WinCopyRectangle(frameDescriptors[index].offScreenBitmap, drawWindow, &size, x - hotSpotX, y - hotSpotY, winOverlay);
00187 SoundEngine::timeTick();
00188
00189 break;
00190
00191 case AnimFrames::optNONE:
00192
00193 {
00194
00195 MemHandle resH = DmGetResource( bitmapRsc, maskID + index);
00196 ErrNonFatalDisplayIf( !resH, "Missing mask" );
00197 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00198
00199 WinDrawBitmap (resP, 0,0);
00200
00201 MemPtrUnlock(resP);
00202 DmReleaseResource( resH );
00203
00204 WinCopyRectangle(offScreenH, drawWindow, &size, x - hotSpotX, y - hotSpotY, winMask);
00205
00206 SoundEngine::timeTick();
00207 }
00208
00209 {
00210
00211 MemHandle resH = DmGetResource( bitmapRsc, bitmapID + index);
00212 ErrNonFatalDisplayIf( !resH, "Missing bitmap" );
00213 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00214
00215 WinDrawBitmap (resP, 0,0);
00216
00217 MemPtrUnlock(resP);
00218 DmReleaseResource( resH );
00219
00220 WinCopyRectangle(offScreenH, drawWindow, &size, x - hotSpotX, y - hotSpotY, winOverlay);
00221
00222 SoundEngine::timeTick();
00223 }
00224
00225 break;
00226
00227
00228 case AnimFrames::optNO_MASK:
00229 {
00230 MemHandle resH = DmGetResource( bitmapRsc, bitmapID + index);
00231 ErrNonFatalDisplayIf( !resH, "Missing bitmap" );
00232 BitmapType* resP = (BitmapPtr)MemHandleLock(resH);
00233
00234 WinDrawBitmap (resP, x - hotSpotX, y - hotSpotY);
00235
00236 MemPtrUnlock(resP);
00237 DmReleaseResource( resH );
00238
00239 SoundEngine::timeTick();
00240 }
00241 }
00242 }
00243
00244
00245 AnimFrames::OptimizationMode AnimFrames::getOptimizationMode() const
00246 {
00247 return optimizationMode;
00248 }
00249
00250
00251
00252
00253 Sprite::Sprite(DmResID bitmapID, DmResID maskID, Coord hotSpotX, Coord hotSpotY, Boolean visible, AnimFrames::OptimizationMode optimizationMode)
00254 {
00255 animFrames = new AnimFrames(1, bitmapID, maskID, hotSpotX, hotSpotY, optimizationMode);
00256 ownsAnimFrames = true;
00257
00258 this->visible = visible;
00259 move(0,0);
00260 setFrame(0);
00261 }
00262
00263
00264 Sprite::Sprite(AnimFrames& animFrames, Boolean visible)
00265 {
00266 this->animFrames = &animFrames;
00267 ownsAnimFrames = false;
00268
00269 this->visible = visible;
00270 move(0,0);
00271 setFrame(0);
00272 }
00273
00274
00275 Sprite::~Sprite()
00276 {
00277 if (ownsAnimFrames)
00278 delete animFrames;
00279 }
00280
00281
00282 void Sprite::show()
00283 {
00284 visible = true;
00285 }
00286
00287
00288 void Sprite::hide()
00289 {
00290 visible = false;
00291 }
00292
00293
00294 Boolean Sprite::setVisibility(Boolean visible)
00295 {
00296 Boolean oldVisible = visible;
00297 this->visible = visible;
00298
00299 return oldVisible;
00300 }
00301
00302
00303 Boolean Sprite::isVisible() const
00304 {
00305 return visible;
00306 }
00307
00308
00309 void Sprite::setFrame(UInt16 frameIndex)
00310 {
00311 this->frameIndex = frameIndex;
00312 }
00313
00314
00315 void Sprite::move(Coord x, Coord y)
00316 {
00317 this->x = x;
00318 this->y = y;
00319 }
00320
00321
00322 void Sprite::draw(RectangleType *bounds) const
00323 {
00324 if (!visible)
00325 {
00326 if (bounds != NULL)
00327 {
00328 bounds->topLeft.x = 0;
00329 bounds->topLeft.y = 0;
00330 bounds->extent.x = 0;
00331 bounds->extent.y = 0;
00332 }
00333
00334 return;
00335 }
00336
00337 animFrames->draw(frameIndex, x, y, bounds);
00338 }
00339
00340
00341 void Sprite::getBounds(RectangleType *bounds) const
00342 {
00343 animFrames->getBounds(x, y, bounds);
00344 }
00345
00346
00347 void Sprite::quickDraw(WinHandle drawWindow, WinHandle offScreenH, RectangleType *bounds) const
00348 {
00349 if (!visible)
00350 {
00351 if (bounds != NULL)
00352 {
00353 bounds->topLeft.x = 0;
00354 bounds->topLeft.y = 0;
00355 bounds->extent.x = 0;
00356 bounds->extent.y = 0;
00357 }
00358
00359 return;
00360 }
00361
00362
00363 animFrames->quickDraw(frameIndex, x, y, drawWindow, offScreenH, bounds);
00364 }
00365
00366
00367 AnimFrames::OptimizationMode Sprite::getOptimizationMode() const
00368 {
00369 return animFrames->getOptimizationMode();
00370 }
00371
00372
00373
00374 SpriteGroup::SpriteGroup(int maxSprites)
00375 {
00376 ErrNonFatalDisplayIf(maxSprites == 0, "maxSprites == 0");
00377 this->maxSprites = maxSprites;
00378 this->currSprites = 0;
00379
00380 this->theSprites = new Sprite*[maxSprites];
00381
00382 this->offscreenH = NULL;
00383 this->maxWidth = 0;
00384 this->maxHeight = 0;
00385 this->oldMaxWidth = -1;
00386 this->oldMaxHeight = -1;
00387 this->needBuffer = false;
00388 }
00389
00390
00391 SpriteGroup::~SpriteGroup()
00392 {
00393 delete [] theSprites;
00394
00395 if (offscreenH != NULL)
00396 WinDeleteWindow(offscreenH, false);
00397 }
00398
00399
00400 void SpriteGroup::addSprite(Sprite& sprite)
00401 {
00402 ErrNonFatalDisplayIf(currSprites == maxSprites, "SpriteGroup size exhausted");
00403
00404 this->theSprites[currSprites] = &sprite;
00405
00406
00407 if (sprite.getOptimizationMode() == AnimFrames::optNONE)
00408 {
00409 RectangleType bounds;
00410 sprite.getBounds(&bounds);
00411
00412 maxWidth = max(bounds.extent.x, maxWidth);
00413 maxHeight = max(bounds.extent.y, maxHeight);
00414
00415 needBuffer = true;
00416 }
00417
00418 currSprites++;
00419 }
00420
00421
00422 void SpriteGroup::draw(RectangleType *bounds)
00423 {
00424 if (currSprites == 0)
00425 return;
00426
00427 WinHandle drawWindow = WinGetDrawWindow();
00428 if (needBuffer)
00429 {
00430 if ((maxWidth != oldMaxWidth) || (maxHeight != oldMaxHeight))
00431 {
00432 if (offscreenH != NULL)
00433 {
00434 WinDeleteWindow(offscreenH, false);
00435 offscreenH = NULL;
00436 }
00437
00438 oldMaxWidth = maxWidth;
00439 oldMaxHeight = maxHeight;
00440
00441 UInt16 error;
00442 offscreenH = WinCreateOffscreenWindow(maxWidth, maxHeight, screenFormat, &error);
00443 }
00444
00445 WinSetDrawWindow(offscreenH);
00446 }
00447
00448
00449 RectangleType spriteBounds;
00450 for(int i = 0; i < currSprites; i++)
00451 {
00452 this->theSprites[i]->quickDraw(drawWindow, offscreenH, &spriteBounds);
00453 Canvas::uniteBounds(&spriteBounds, bounds, bounds);
00454 }
00455
00456 if (needBuffer)
00457 WinSetDrawWindow(drawWindow);
00458 }