AGS Plugin API ::GetVirtualScreen()

Started by Scorpiorus, Mon 03/05/2004 22:31:03

Previous topic - Next topic

Scorpiorus

I'm fiddling with Allegro and AGS trying to draw (working at 16bit color) a translucient image directly onto the virtual screen by means of Allegro functions, so I have:

...
if (event == AGSE_POSTSCREENDRAW) {

   //getting virtual screen:
   BITMAP* virt = engine->GetVirtualScreen();

   //set blender functions for (16bit)
   set_blender_mode(0,0,0, 100); //a = 100

   //setting drawing mode to use the blender functions
   drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);

   //draw a rectangle (with a=100)
   rectfill(virt, x1,y1,x2,y2, color);
}

...but filled rectangle turns out solid like it would ignore DRAW_MODE_TRANS but uses DRAW_MODE_SOLID instead. No other modes like DRAW_MODE_XOR orÃ,  DRAW_MODE_xxx_PATTERN work as well.

So, I create a temporary memory bitmap (exactly the same as the virtual screen), fill it with the virtual screen content, draw the rectangleÃ,  onto it and then blit it back to the virtual screen:

...
if (event == AGSE_POSTSCREENDRAW) {

   //getting virtual screen:
   BITMAP* virt = engine->GetVirtualScreen();

   //creating a temporary canvas to draw onto:
   BITMAP* temp = create_bitmap_ex(16, 640, 480);

   //fill it with what on the virtual screen:
   blit(virt, temp, 0,0,0,0,640,480);

   //set blender functions for (16bit)
   set_blender_mode(0,0,0, 100); //alpha = 100

   //setting drawing mode to use the blender functions:
   drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);

   //draw a rectangle onto temp:
   rectfill(temp, x1,y1,x2,y2, color);

   //blit back to the virtual screen:
   blit(temp, vert, 0,0,0,0,640,480);

   //destroy temp as we finished with it:
   destroy_bitmap(temp);
}

And that works just fine but affects the perfomance. Although Allegro initialized with SYSTEM_NONE all the drawing routines work well (I just need to specify some things like color depth here and there).


AGS plugin API states that IAGSEngine::GetVirtualScreen() function returns a pointer to the Allegro memory bitmap (checking its with Allegro says the same: linear/memory/640x480x16bit).

So, is virtual screen a true Allegro bitmap?
If so, how does plugin api BlitSpriteTranslucent() function work?
I'd use it, btw, but I'm actually trying to render polygons. Allegro manual states that in FLAT rendering mode they are drawn using the same mode from drawing_mode() - i.e. DRAW_MODE_TRANS in that case. And drawing into a temporary bitmap, then blitting to virtual screen works with them as well.

~Cheers

Pumaman

The BITMAP struct includes a vtable with function pointers for all drawing operations on that bitmap. So if you call rectfill on the virtual screen, it's effectively calling:
virt.rectfill(...);

thus it's calling into AGS's copy of allegro, where the drawing mode is solid. When you call drawing_mode, it will only affect drawing onto bitmaps created by your copy of allegro.

This is the sort of reason why I'd prefer to have as many drawing operations as possible supported via the plugin API, so you don't have to use your own copy of allegro.

Scorpiorus

Code: ags
AL_INLINE(void, rectfill, (BITMAP *bmp, int x1, int y1, int x2, int y2, int color),
{
Ã,  Ã, ASSERT(bmp);

Ã,  Ã, bmp->vtable->rectfill(bmp, x1, y1, x2, y2, color);
})
oops... I see.

As a quick workaround I just change the drawing function pointer to one I need, perform operation and restore it back to the original value.

But you are certainly right about having interface through the plugin api. Heh, it's rather silly to attach a 200-400kBytes of code if it's already there in the AGS engine.

Thanks for helping me out :)

~Cheers

Kweepa

I've got a similar question...
I'm trying to draw into a sprite slot, like this:
Code: ags

void
EffectsUpdate()
{
Ã,  Ã,  Ã,  BITMAP *bmp = engine->GetSpriteGraphic(gSpriteToBurn);
Ã,  Ã,  Ã,  if (bmp)
Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã, long w, h, d;
Ã,  Ã,  Ã,  Ã,  Ã, engine->GetBitmapDimensions(bmp, &w, &h, &d);
Ã,  Ã,  Ã,  Ã,  Ã, int p = w*h*gFireSide;
Ã,  Ã,  Ã,  Ã,  Ã, int q = w*h*(1-gFireSide);

Ã,  Ã,  Ã,  Ã,  Ã, // now write to the sprite
Ã,  Ã,  Ã,  Ã,  Ã, switch (d)
Ã,  Ã,  Ã,  Ã,  Ã, {
Ã,  Ã,  Ã,  Ã,  Ã, case 16:
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, unsigned short **a = (unsigned short **) engine->GetRawBitmapSurface(bmp);

Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, for (int y = 0; y < h; ++y)
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  int yy = q + w*y;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  for (int x = 0; x < w; ++x)
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, // should use a lookup table
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, int t = gFireArray[yy + x];
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, if (t < 64)
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  // purple - transparent
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  a[y][x] = 0xF81F;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, else if (t < 64+128)
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  // red - yellow
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  a[y][x] = 0xF800 + 16*(t-64);
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, else
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, {
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  // yellow - white
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  a[y][x] = 0xFFE0 + (t-192)/2;
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, engine->ReleaseBitmapSurface(bmp);
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  break;
Ã,  Ã,  Ã,  Ã,  Ã, }
Ã,  Ã,  Ã,  }
}

Is this all I need to do?
It doesn't seem to change the sprite (it's assigned to an object).
The code is definitely being run (I set a breakpoint).
Is there some way to tell the sprite or sprite cache to update?

Thanks,
Steve
Still waiting for Purity of the Surf II

Pumaman

Looks ok. I take it you checked that the code is actually stepping inside the "case 16:" clause? The other possibility is that the sprite cache is discarding the image before it's actually displayed, though this is unlikely.

A couple of other silly things to check, like is gSpriteToBurn the one you expect it to be?

Kweepa

#5
Yup, I stepped in there.
Kind of hard to check it's the right one, but if you say it looks right I'll keep checking here - I guess I'll check the top left pixel, etc.
Thanks CJ.

EDIT: I need to do this in a repeatedly_execute to see the modified sprite (#200):

Code: ags

Ã,  if (GetObjectGraphic(OBJECT_TORCH2) == 200)
Ã,  {
Ã,  Ã,  SetObjectGraphic(OBJECT_TORCH2, 201);
Ã,  }
Ã,  else
Ã,  {
Ã,  Ã,  SetObjectGraphic(OBJECT_TORCH2, 200);
Ã,  }


So it needs to change, render, change, render to keep updating. I can fake it by having two objects sharing the sprite that I toggle, or two sprites sequentially applied to the object, but it would be nice (and clean) to have some way of telling the engine that the sprite has changed.

EDIT2: Two sprites works. The two object idea failed.
Still waiting for Purity of the Surf II

Pumaman

Ah, I didn't realise you were changing it after it was already visible on an object. Object and character graphics are cached for performance reasons, so yeah you'll have to do something like that to get it to update. I'll see about a cleaner way to do it.

Kweepa

I put the messy code in a plugin, so the only problem is it allocates memory for two sprites instead of one. That's not too bad I think.
Still waiting for Purity of the Surf II

SMF spam blocked by CleanTalk