Hi all,
I was wondering if anyone might know how to make an alpha mask like you might do in After Effects. A good example that I've been trying to replicate with no success is the classic Star Wars transition where you have a circle that gradually gets smaller, until the screen is black.
I know that I can draw a black rectangle and a circle, then scale the circle down but I cant figure out how to cut the circle from the rectangle to create the mask.
I hope I'm making sense.. it would basically be a black rectangle with a scalable transparent circle in the middle that cuts through the black revealing whatever is drawn onto the screen below it.
Any help would be much appreciated. Thanks!!
[Edit: 2022, January 31st]
Anyone coming across this should take a look at Krystman's post on url Circular Clipping Masks. It looks in a thorough manner at different ways of achieving the effect described, and similar effects.
[Post pre-2022]
[Some of the original discussion of the original poster's idea hidden. Click 'show' for details]
Redefine the question
Let's re-examine the effect you're asking about.
What you're asking for is a screen sized area of black with a protected space in the middle. That space happens to be a circle. So what you want to do is draw black on the screen except for at the central circle.
Decreasing circles with a still image
This is reasonably easy to implement. It only needs 4 calls to circ per frame.
After drawing the image, we signal to _draw (via a variable called state) that we should now switch to a different function, one that doesn't use cls. That function, for the reducing circle effect, just decreases the radius of the 4 calls to circ (not circfill) by a little every frame.
I use 4 calls to cover a few gaps that otherwise would occur due to the exact positions of the pixels that get put on screen by circ, and to give it symmetry (so it's not a rectangle when it gets down to the last few pixels). This is done by having origins at {{63,63},{64,63},{63,64},{64,64}}.
The example I give here lets you experiment with different values for the reduction of the radius of the circle. Reducing 2 pixels a frame is reasonably fast and covers all the gaps; larger values will leave gaps, smaller values will be slower.
Decreasing circles with animation going on
While there is animation going on you need a slightly more complex algorithm, in that you need to put the background back on the screen every time, and overwrite it with whatever is outside your circle. You could just do this with circs again, drawing them all in from the outside of the screen to your inner circle every frame, or you could try blocking in the edge with rectfills - which will hopefully be more efficient - then the circs don't have to come in all the way from the edge of the screen.
I hope these comments give you the idea of what needs to be done. I encourage you to try it out. :-)
[Edited last couple of paragraphs to remove items - as better solutions have been posted by others below - while still keeping the fundamentals of the advice I gave. Additionally, the following:]
It's good to see that others have commented too - you seem to be getting plenty of help.
Also, inspired by your question I now have this as a work in progress:
I think what PLS wants is the reverse, guys.
Here is both. Watch as one scene vanishes from the shrinking iris circle and then is RECOVERED with an entirely different scene in a reverse-direction expanding iris circle.
Thank you both for the in-depth info and carts! I'm on lunch break at work right now so I'm hoping to be able to dive into the code a little more once I get home. Thank you both again for your time and answers!
DW I have a question about copying the screen to sprites using memcpy. Lets say I have every single cell in the sprite book filled up with game assets, will using memcpy overwrite those sprites?
Also this technique would not work with an active, animated background right?
I think you can, PLS. Understand the method I am using is only copying a screen that did not earlier record all the locations and elements of sprites and tiles.
In a complete program you would have those draw automatically and you would not need to use MEMCPY() or RELOAD() at all.
Let me see, try this ...
Here you've got some bobs traveling and bouncing from left to right.
Use the following keys to experiment:
LEFT and RIGHT to decrease and increase the iris view
the (O) key to swap between sprites viewed and their animation pattern.
So in your game you would show your sprites and animation, then for an upcoming next level close the iris on it. Then press (O) (z key) to change scenes and then expand again to show an entirely different animated view.
HOPE THIS HELPS !
Simpler version - without memcpy nor weird circle proportions!
Freds, I'm using CIRC(). I can't get any weirder than that. :) You can change the thickness to 1 instead of 2 for the white optional visual outline or leave it out completely ... if you think it's weird.
Also last version (above an hour ago) does not use MEMCPY() but does effect of iris expansion or compression for two animated scenes.
Yours is nifty at that with sqrt() to develop an inverted circle. That's pretty neat to see.
TIME() is flawed though. If you use it, press ESC and RESUME, the clock messes up the timing breaking all timed events.
function _draw() print(time()) end |
@freds72, thanks for the beautiful iris effect. Code very simple to use, too. Will be using it in an upcoming game.
[Please log in to post a comment]