void update_walk_behind_images() { int ee, rr; int bpp = (thisroom.ebscene[play.bg_frame]->GetColorDepth() + 7) / 8; Bitmap *wbbmp; for (ee = 1; ee < MAX_OBJ; ee++) { update_polled_stuff_if_runtime(); if (walkBehindRight[ee] > 0) { wbbmp = BitmapHelper::CreateBitmap( (walkBehindRight[ee] - walkBehindLeft[ee]) + 1, (walkBehindBottom[ee] - walkBehindTop[ee]) + 1, thisroom.ebscene[play.bg_frame]->GetColorDepth()); wbbmp->Clear(wbbmp->GetMaskColor()); int yy, startX = walkBehindLeft[ee], startY = walkBehindTop[ee]; for (rr = startX; rr <= walkBehindRight[ee]; rr++) { for (yy = startY; yy <= walkBehindBottom[ee]; yy++) { if (thisroom.object->GetScanLine(yy)[rr] == ee) { for (int ii = 0; ii < bpp; ii++) wbbmp->GetScanLineForWriting(yy - startY)[(rr - startX) * bpp + ii] = thisroom.ebscene[play.bg_frame]->GetScanLine(yy)[rr * bpp + ii]; } } } update_polled_stuff_if_runtime(); if (walkBehindBitmap[ee] != NULL) { gfxDriver->DestroyDDB(walkBehindBitmap[ee]); } walkBehindBitmap[ee] = gfxDriver->CreateDDBFromBitmap(wbbmp, false); delete wbbmp; } } walkBehindsCachedForBgNum = play.bg_frame; }
long loadcompressed_allegro(Stream *in, Common::Bitmap **bimpp, color *pall, long read_at) { short widd,hitt; int ii; Bitmap *bim = *bimpp; delete bim; widd = in->ReadInt16(); hitt = in->ReadInt16(); bim = BitmapHelper::CreateBitmap(widd, hitt, 8); if (bim == NULL) quit("!load_room: not enough memory to decompress masks"); *bimpp = bim; for (ii = 0; ii < hitt; ii++) { cunpackbitl(&bim->GetScanLineForWriting(ii)[0], widd, in); if (ii % 20 == 0) update_polled_stuff_if_runtime(); } in->Seek(Common::kSeekCurrent, 768); // skip palette return in->GetPosition(); }
void DrawSpriteWithTransparency(Bitmap *ds, Bitmap *sprite, int x, int y, int alpha) { if (alpha <= 0) { // fully transparent, don't draw it at all return; } int surface_depth = ds->GetColorDepth(); int sprite_depth = sprite->GetColorDepth(); if (sprite_depth < surface_depth // CHECKME: what is the purpose of this hack and is this still relevant? #if defined(IOS_VERSION) || defined(ANDROID_VERSION) || (ds->GetBPP() < surface_depth && psp_gfx_renderer > 0) // Fix for corrupted speechbox outlines with the OGL driver #endif ) { // If sprite is lower color depth than destination surface, e.g. // 8-bit sprites drawn on 16/32-bit surfaces. if (sprite_depth == 8 && surface_depth >= 24) { // 256-col sprite -> truecolor background // this is automatically supported by allegro, no twiddling needed ds->Blit(sprite, x, y, kBitmap_Transparency); return; } // 256-col sprite -> hi-color background, or // 16-bit sprite -> 32-bit background Bitmap hctemp; hctemp.CreateCopy(sprite, surface_depth); if (sprite_depth == 8) { // only do this for 256-col -> hi-color, cos the Blit call converts // transparency for 16->32 bit color_t mask_color = hctemp.GetMaskColor(); for (int scan_y = 0; scan_y < hctemp.GetHeight(); ++scan_y) { // we know this must be 1 bpp source and 2 bpp pixel destination const uint8_t *src_scanline = sprite->GetScanLine(scan_y); uint16_t *dst_scanline = (uint16_t*)hctemp.GetScanLineForWriting(scan_y); for (int scan_x = 0; scan_x < hctemp.GetWidth(); ++scan_x) { if (src_scanline[scan_x] == 0) { dst_scanline[scan_x] = mask_color; } } } } if (alpha < 0xFF) { set_trans_blender(0, 0, 0, alpha); ds->TransBlendBlt(&hctemp, x, y); } else { ds->Blit(&hctemp, x, y, kBitmap_Transparency); } } else { if (alpha < 0xFF && surface_depth > 8 && sprite_depth > 8) { set_trans_blender(0, 0, 0, alpha); ds->TransBlendBlt(sprite, x, y); } else { ds->Blit(sprite, x, y, kBitmap_Transparency); } } }
void DynamicSprite_CopyTransparencyMask(ScriptDynamicSprite *sds, int sourceSprite) { if (sds->slot == 0) quit("!DynamicSprite.CopyTransparencyMask: sprite has been deleted"); if ((spritewidth[sds->slot] != spritewidth[sourceSprite]) || (spriteheight[sds->slot] != spriteheight[sourceSprite])) { quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same size"); } Bitmap *target = spriteset[sds->slot]; Bitmap *source = spriteset[sourceSprite]; if (target->GetColorDepth() != source->GetColorDepth()) { quit("!DynamicSprite.CopyTransparencyMask: sprites are not the same colour depth"); } // set the target's alpha channel depending on the source bool sourceHasAlpha = (game.spriteflags[sourceSprite] & SPF_ALPHACHANNEL) != 0; game.spriteflags[sds->slot] &= ~SPF_ALPHACHANNEL; if (sourceHasAlpha) { game.spriteflags[sds->slot] |= SPF_ALPHACHANNEL; } unsigned int maskColor = source->GetMaskColor(); int colDep = source->GetColorDepth(); int bytesPerPixel = (colDep + 1) / 8; unsigned short *shortPtr; unsigned int *longPtr; for (int y = 0; y < target->GetHeight(); y++) { unsigned char * sourcePixel = source->GetScanLineForWriting(y); unsigned char * targetPixel = target->GetScanLineForWriting(y); for (int x = 0; x < target->GetWidth(); x++) { shortPtr = (unsigned short*)sourcePixel; longPtr = (unsigned int*)sourcePixel; if ((colDep == 8) && (sourcePixel[0] == maskColor)) { targetPixel[0] = maskColor; } else if ((bytesPerPixel == 2) && (shortPtr[0] == maskColor)) { ((unsigned short*)targetPixel)[0] = maskColor; } else if ((bytesPerPixel == 3) && (memcmp(sourcePixel, &maskColor, 3) == 0)) { memcpy(targetPixel, sourcePixel, 3); } else if ((bytesPerPixel == 4) && (longPtr[0] == maskColor)) { ((unsigned int*)targetPixel)[0] = maskColor; } else if ((bytesPerPixel == 4) && (sourceHasAlpha)) { // the fourth byte is the alpha channel, copy it targetPixel[3] = sourcePixel[3]; } else if (bytesPerPixel == 4) { // set the alpha channel byte to opaque targetPixel[3] = 0xff; } sourcePixel += bytesPerPixel; targetPixel += bytesPerPixel; } } }
int is_route_possible(int fromx, int fromy, int tox, int toy, Bitmap *wss) { wallscreen = wss; suggestx = -1; // ensure it's a memory bitmap, so we can use direct access to line[] array if ((wss == NULL) || (!wss->IsMemoryBitmap()) || (wss->GetColorDepth() != 8)) quit("is_route_possible: invalid walkable areas bitmap supplied"); if (wallscreen->GetPixel(fromx, fromy) < 1) return 0; Bitmap *tempw = BitmapHelper::CreateBitmapCopy(wallscreen, 8); if (tempw == NULL) quit("no memory for route calculation"); if (!tempw->IsMemoryBitmap()) quit("tempw is not memory bitmap"); int dd, ff; // initialize array for finding widths of walkable areas int thisar, inarow = 0, lastarea = 0; int walk_area_times[MAX_WALK_AREAS + 1]; for (dd = 0; dd <= MAX_WALK_AREAS; dd++) { walk_area_times[dd] = 0; walk_area_granularity[dd] = 0; } for (ff = 0; ff < tempw->GetHeight(); ff++) { const uint8_t *tempw_scanline = tempw->GetScanLine(ff); for (dd = 0; dd < tempw->GetWidth(); dd++) { thisar = tempw_scanline[dd]; // count how high the area is at this point if ((thisar == lastarea) && (thisar > 0)) inarow++; else if (lastarea > MAX_WALK_AREAS) quit("!Calculate_Route: invalid colours in walkable area mask"); else if (lastarea != 0) { walk_area_granularity[lastarea] += inarow; walk_area_times[lastarea]++; inarow = 0; } lastarea = thisar; } } for (dd = 0; dd < tempw->GetWidth(); dd++) { for (ff = 0; ff < tempw->GetHeight(); ff++) { uint8_t *tempw_scanline = tempw->GetScanLineForWriting(ff); thisar = tempw_scanline[dd]; if (thisar > 0) tempw_scanline[dd] = 1; // count how high the area is at this point if ((thisar == lastarea) && (thisar > 0)) inarow++; else if (lastarea != 0) { walk_area_granularity[lastarea] += inarow; walk_area_times[lastarea]++; inarow = 0; } lastarea = thisar; } } // find the average "width" of a path in this walkable area for (dd = 1; dd <= MAX_WALK_AREAS; dd++) { if (walk_area_times[dd] == 0) { walk_area_granularity[dd] = MAX_GRANULARITY; continue; } walk_area_granularity[dd] /= walk_area_times[dd]; if (walk_area_granularity[dd] <= 4) walk_area_granularity[dd] = 2; else if (walk_area_granularity[dd] <= 15) walk_area_granularity[dd] = 3; else walk_area_granularity[dd] = MAX_GRANULARITY; /*char toprnt[200]; sprintf(toprnt,"area %d: Gran %d", dd, walk_area_granularity[dd]); winalert(toprnt); */ } walk_area_granularity[0] = MAX_GRANULARITY; tempw->FloodFill(fromx, fromy, 232); if (tempw->GetPixel(tox, toy) != 232) { // Destination pixel is not walkable // Try the 100x100 square around the target first at 3-pixel granularity int tryFirstX = tox - 50, tryToX = tox + 50; int tryFirstY = toy - 50, tryToY = toy + 50; if (!find_nearest_walkable_area(tempw, tryFirstX, tryFirstY, tryToX, tryToY, tox, toy, 3)) { // Nothing found, sweep the whole room at 5 pixel granularity find_nearest_walkable_area(tempw, 0, 0, tempw->GetWidth(), tempw->GetHeight(), tox, toy, 5); } delete tempw; return 0; } delete tempw; return 1; }