QB64 Phoenix Edition
Image falls to pieces, revealing another one. - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Programs (https://qb64phoenix.com/forum/forumdisplay.php?fid=7)
+---- Thread: Image falls to pieces, revealing another one. (/showthread.php?tid=426)



Image falls to pieces, revealing another one. - Dav - 05-17-2022

I've been trying to come up with some interesting transitions for an image slideshow (family album thing).  I have the regular fades and slides and swaps worked out, trying to get something fancier.  Here's something I thought of using rotozoom - break image up to pieces and drop them off the screen, revealing the other one. 

It's a mess.  Seems to work but thought I'd share it now to get some feedback/help with making it better.  Perhaps there's a better way to do this?   (There's 2 rotozoom subs in the code to compare them)

- Dav

Code: (Select All)
'===============
'IMAGEPIECES.BAS
'===============
'Coded by Dav, MAY/2022

RANDOMIZE TIMER

'=== make 1st image to use (background one)
image1& = _NEWIMAGE(1000, 650, 32)
_DEST image1&
FOR y = 0 TO _HEIGHT
    LINE (0, y)-(_WIDTH, y), _RGB(RND * 255, RND * 255, RND * 255), B
NEXT

'=== make 2nd image to use (will fall to pieces)
image2& = _NEWIMAGE(1000, 650, 32)
_DEST image2&
FOR y = 0 TO _HEIGHT
    LINE (0, y)-(_WIDTH, y), _RGB(0, 0, RND * 196), B
NEXT


row = 15: col = 10 '15x10 grid of pieces
xsize = _WIDTH / row: ysize = _HEIGHT / col
DIM SHARED piece&(row * col), piecex(row * col), piecey(row * col)
DIM dropspeed(row * col), rotatespeed(row * col)
DIM xwobble(row * col), xwobblespeed(row * col)

'====
main:
'====

bc = 1
FOR c = 1 TO col
    FOR r = 1 TO row

        'int x/y values for each piece
        x1 = (r * xsize) - xsize: x2 = x1 + xsize
        y1 = (c * ysize) - ysize: y2 = y1 + ysize
        piecex(bc) = x1: piecey(bc) = y1

        'make pieces images from image2& screen
        piece&(bc) = _NEWIMAGE(ABS(x2 - x1) + 1, ABS(y2 - y1) + 1, 32)
        _PUTIMAGE (0, 0), image2&, piece&(bc), (x1, y1)-(x2, y2)

        'int random values for each piece
        dropspeed(bc) = RND * 2 + 1
        rotatespeed(bc) = RND * 2 + 1

        xwobble(bc) = INT(RND * 3) + 1 'x move piece (1=none,2=left,3=right)
        xwobblespeed(bc) = INT(RND * 2) + .5 'how fast to wobble it

        bc = bc + 1

    NEXT
NEXT


'make main screen
_DEST 0
SCREEN _NEWIMAGE(1000, 650, 32)
CLS

'=== show 1st image on screen that will fall to pieces
FOR t = 1 TO row * col
    RotoZoom piecex(t) + (xsize / 2), piecey(t) + (ysize / 2), piece&(t), 1, 0
NEXT

PRINT "Press enter to break up screen and reveal image behind...";

_DISPLAY

SLEEP

drop = 0: wob = 0

DO

    _PUTIMAGE (0, 0), image1& 'background image

    'show 1st image breaking up
    FOR t = 1 TO row * col
        tx = piecex(t): tx2 = piecex(t) + xsize
        ty = piecey(t): ty2 = piecey(t) + ysize
        SELECT CASE xwobble(t)
            CASE 1
                'RotoZoom piecex(t) + (xsize / 2), piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, (ang * rotatespeed(t))
                RotoZoom3 piecex(t) + (xsize / 2), piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, 1, (ang * rotatespeed(t))
            CASE 2
                'RotoZoom piecex(t) + (xsize / 2) - wob, piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, (ang * rotatespeed(t))
                RotoZoom3 piecex(t) + (xsize / 2) - wob, piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, 1, (ang * rotatespeed(t))
                wob = wob - xwobblespeed(t)
            CASE 3
                'RotoZoom piecex(t) + (xsize / 2) + wob, piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, (ang * rotatespeed(t))
                RotoZoom3 piecex(t) + (xsize / 2) + wob, piecey(t) + (ysize / 2) + (drop * dropspeed(t)), piece&(t), 1, 1, (ang * rotatespeed(t))
                wob = wob + xwobblespeed(t)
        END SELECT

        drop = drop + .1: ang = ang + .1

        _LIMIT 3500
    NEXT

    _DISPLAY

    'see if all pieces off screen
    done = 1
    FOR d = 1 TO row * col
        IF piecey(d) + drop < _HEIGHT THEN done = 0
    NEXT
    IF done = 1 THEN EXIT DO

LOOP

'release pieces from memory
FOR p = 1 TO row * col
    _FREEIMAGE piece&(p)
NEXT

GOTO main



SUB RotoZoom (X AS LONG, Y AS LONG, Image AS LONG, Scale AS SINGLE, Rotation AS SINGLE)
    DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
    W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
    px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
    px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
    sinr! = SIN(-Rotation / 57.2957795131): cosr! = COS(-Rotation / 57.2957795131)
    FOR i& = 0 TO 3
        x2& = (px(i&) * cosr! + sinr! * py(i&)) * Scale + X: y2& = (py(i&) * cosr! - px(i&) * sinr!) * Scale + Y
        px(i&) = x2&: py(i&) = y2&
    NEXT
    _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
    _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
END SUB

SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE)
    ' This assumes you have set your drawing location with _DEST or default to screen.
    ' X, Y - is where you want to put the middle of the image
    ' Image - is the handle assigned with _LOADIMAGE
    ' xScale, yScale - are shrinkage < 1 or magnification > 1 on the given axis, 1 just uses image size.
    ' These are multipliers so .5 will create image .5 size on given axis and 2 for twice image size.
    ' radianRotation is the Angle in Radian units to rotate the image
    ' note: Radian units for rotation because it matches angle units of other Basic Trig functions
    '       and saves a little time converting from degree.
    '       Use the _D2R() function if you prefer to work in degree units for angles.

    DIM px(3) AS SINGLE: DIM py(3) AS SINGLE ' simple arrays for x, y to hold the 4 corners of image
    DIM W&, H&, sinr!, cosr!, i&, x2&, y2& '   variables for image manipulation
    W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
    px(0) = -W& / 2: py(0) = -H& / 2 'left top corner
    px(1) = -W& / 2: py(1) = H& / 2 ' left bottom corner
    px(2) = W& / 2: py(2) = H& / 2 '  right bottom
    px(3) = W& / 2: py(3) = -H& / 2 ' right top
    sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation) ' rotation helpers
    FOR i& = 0 TO 3 ' calc new point locations with rotation and zoom
        x2& = xScale * (px(i&) * cosr! + sinr! * py(i&)) + X: y2& = yScale * (py(i&) * cosr! - px(i&) * sinr!) + Y
        px(i&) = x2&: py(i&) = y2&
    NEXT
    _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
    _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
END SUB



RE: Image falls to pieces, revealing another one. - James D Jarvis - 05-17-2022

I don't think you'd have to do much more than just break it into sperate triangles (as opposed to keeping the pieces as rectangles) and it would look better.


RE: Image falls to pieces, revealing another one. - bplus - 05-17-2022

Looks good to me @Dav. When I first read the title, I just imaged all the pixels dropping, maybe accelerating with gravity...

but yours works, there are plenty of ways this could be done. Did you need both RotoZoom subs?

With RotoZoom3 you could spin the images on all 3 axis, scale x and y from -1 to 1, different stages for each piece in the falling loop.

You could make it slower and have individual pieces start the fall-out.


RE: Image falls to pieces, revealing another one. - Coolman - 05-17-2022

excellent. i may do a speed test on this code if i have time.