Using rawdraw to display a portion of an image

Started by Dave Gilbert, Thu 28/02/2013 14:08:47

Previous topic - Next topic

Dave Gilbert

So my game takes place in the wintertime, and I have a snow animation the plays whenever the characters are outside:


(black layer added so you can see the thing!)

I also have interiors with windows:



What I would like to do is take a small piece of the snow...



and display it over the window and animate it:



I've looked in the manual, and while there seems to be a way to resize a whole image using rawdraw, there doesn't seem to be a way to just cut out a small piece. Is such a thing possible? Currently I've been importing the whole snow image as an animated object and using one huge walkbehind area, but I was wondering if there was a more elegant (not to mention memory efficient) way of doing it.

Thanks!

-Dave

Crimson Wizard

#1
I found you may actually pass negative coordinates to DrawImage.
This means, you may make an object of a smaller size (size of window), then create frames for its animations, using cityscape pic as a background and applying different snow frames on top, with negative offset. This will make a snow pic drawn starting from some other point of image, rather than 0,0, while the resulting image will be still of a size of a cityscape pic (because sprites you draw upon never resize).

Simple example, for clarification:
Code: ags

DynamicSprite *base_pic = DynamicSprite.CreateFromExistingSprite(CITYSCAPE_PIC_ID);
DrawingSurface *ds = base_pic.GetDrawingSurface();
ds.DrawImage(-83, -68, SNOW_FRAME_ID);
ds.Release();

Scavenger

#2
I'm pretty sure that, with judicious use of the ViewFrame functions, and the Crop dynamic sprite function, you can hijack an animation loop and make it show whatever you want. Just make a blank loop with however many frames you have in your animation, and crop down each sprite and apply it to the view. I'm pretty sure if you do it more than once and composite the result, you'll be able to have multiple windows.

For every frame (done on_room_enter_before_fadein):
1) Make a new dynamic sprite (sprsnow) out of the existing frame.
2) Crop it to the dimensions you want using dynamicsprite.crop
3) Make a new dynamic sprite (sprbgsnow), use a drawing surface to paste the resulting sprite (sprsnow) back at the dimensions you need (making the final sprite the size of the room/your screen with lots of transparent space).
4) If there is more than one window, repeat the crop and paste the result onto the drawingsurface again.
5) Save the resulting surface, use the dynamic sprite slot (sprbgsnow) to change the view's frame.
And then
6) Apply the resulting view to an object with a baseline of 0.

You'll only have to do this ONCE, on room enter, so it shouldn't be too memory inefficient.

Limitations: You can only have rectangular windows. I'm pretty sure using some coding majicks you MIGHT (and I stress, might) be able to create a custom mask using magic pink and an alpha channel for each room (making a sprite entirely made out of magic pink, and using the alpha channel to fade it out where the snow would be), making your windows whatever shape you want, but I'm not sure how to do that, or how magic pink and alpha channels interact in-engine.

Edit: I'm not sure if AGS supports alpha channels on drawing surfaces, you may have to use AGSBlend. Again, not sure.

Dave Gilbert

Got it to work! I did not know about the DynamicSprite.crop command. It solved everything.

Thanks. :)

SMF spam blocked by CleanTalk