Tilengine - The 2D retro graphics engine forum
Sprite warping (or wraping?) - Printable Version

+- Tilengine - The 2D retro graphics engine forum (http://tilengine.org/forum)
+-- Forum: English forums (http://tilengine.org/forum/forumdisplay.php?fid=3)
+--- Forum: Support (http://tilengine.org/forum/forumdisplay.php?fid=7)
+--- Thread: Sprite warping (or wraping?) (/showthread.php?tid=2281)

Pages: 1 2


Sprite warping (or wraping?) - System64 - 11-15-2022

Hi! (again!)
I'm trying to implement sprite warping, so if a part of the sprite goes out of screen, it is warped to the opposite side of the screen (see the picture).
[Image: image.png]

Do you have an idea how I can achieve this please? The booleans fields for X and Y warping in the Sprite struct are ready.


RE: Sprite warping (or wraping?) - megamarc - 11-16-2022

Hi!

Tilengine clips all sprites so they don't get draw outside of the viewport. Yo can simulate sprite warping from the application level by using two sprites, one on each side of the screen where they get clipped.

What is the use case of sprite warping by the way?


RE: Sprite warping (or wraping?) - System64 - 11-16-2022

(11-16-2022, 12:36 AM)megamarc Wrote: Hi!

Tilengine clips all sprites so they don't get draw outside of the viewport. Yo can simulate sprite warping from the application level by using two sprites, one on each side of the screen where they get clipped.

What is the use case of sprite warping by the way?

There are some levels in Mario games or VVVVVV where the right is linked to the left, let me show you some exemples.

https://www.youtube.com/watch?v=7_E8NcFk_ps
https://www.youtube.com/watch?v=jUBJ_fj6kPk


RE: Sprite warping (or wraping?) - megamarc - 11-16-2022

I see, good examples. For warping effect I'd use two sprites, one on each side of the viewport, each one being clipped on its own side. I guess that's what original SMB3 did. I'd keep both sprites synchronised all the time with the same animation frame, but put one inside the viewport and the other completely outside. Only when the character gets warped at the edges, I'd relocate the "hidden" sprite to be on the opposite side. Do you get the idea?


RE: Sprite warping (or wraping?) - System64 - 11-16-2022

(11-16-2022, 07:14 AM)megamarc Wrote: I see, good examples. For warping effect I'd use two sprites, one on each side of the viewport, each one being clipped on its own side. I guess that's what original SMB3 did. I'd keep both sprites synchronised all the time with the same animation frame, but put one inside the viewport and the other completely outside. Only when the character gets warped at the edges, I'd relocate the "hidden" sprite to be on the opposite side. Do you get the idea?

Yeah, I think it's quite simple to do that, thanks for your suggestion!
I'll try this, I'm messing up with the Bitmap mode now, and you can do really funny things!, I made functions for drawing rectangles and lines, trying to figure out how to draw a circle.

Code:
proc drawRectWH(bitmap: TLN_Bitmap, x: int, y: int, w: int, h: int, stroke: uint = 0, strokeColor: uint8 = 1, color: uint8 = 1): void =
    # Drawing stroke
    if stroke > 0:
        # Top and bottom
        for i in x-(stroke.int div 2)..x+w+(stroke.int div 2)-1:
            for j in y-(stroke.int div 2)..(y+(stroke.int div 2)-1):
                if (i >= 0 and i < bitmap.getBitmapWidth()-1) and (j >= 0 and j < bitmap.getBitmapHeight()-1):
                    bitmap.getBitmapPtr(i, j)[] = strokeColor
        for i in x-(stroke.int div 2)..x+w+(stroke.int div 2)-1:
            for j in y-(stroke.int div 2)+h..(h+y+(stroke.int div 2)-1):
                if (i >= 0 and i < bitmap.getBitmapWidth()-1) and (j >= 0 and j < bitmap.getBitmapHeight()-1):
                    bitmap.getBitmapPtr(i, j)[] = strokeColor

        # Sides
        for i in x-(stroke.int div 2)..x-(stroke.int div 2)+stroke.int-1:
            for j in y+(stroke.int div 2)..y+h-(stroke.int div 2):
                if (i >= 0 and i < bitmap.getBitmapWidth()-1) and (j >= 0 and j < bitmap.getBitmapHeight()-1):
                    bitmap.getBitmapPtr(i, j)[] = strokeColor
        for i in x-(stroke.int div 2)+w..x+w+(stroke.int div 2)-1:
            for j in y+(stroke.int div 2)..y+h-(stroke.int div 2):
                if (i >= 0 and i < bitmap.getBitmapWidth()-1) and (j >= 0 and j < bitmap.getBitmapHeight()-1):
                    bitmap.getBitmapPtr(i, j)[] = strokeColor

    # Drawing Inside
    for i in x+(stroke.int div 2)..x+w.int-(stroke.int div 2)-1:
        for j in y+(stroke.int div 2)..y+(h.int-stroke.int div 2)-1:
            if (i >= 0 and i < bitmap.getBitmapWidth()-1) and (j >= 0 and j < bitmap.getBitmapHeight()-1):
                bitmap.getBitmapPtr(i, j)[] = color
   
    return

proc drawLine(bitmap: TLN_Bitmap, x: int, y: int, x2: int, y2: int): void =
    let lineLength = sqrt(pow(x2.float - x.float, 2) + pow(y2.float - y.float, 2))
    for i in 0..round(lineLength * sqrt(2.float64)).int:
        var myX = round(x.float + (i.float / lineLength) * (x2.float - x.float))
        var myY = round(y.float + (i.float / lineLength) * (y2.float - y.float))
        bitmap.getBitmapPtr(myX.int, myY.int)[] = 1
    return

Here is some of my works!
[Image: image.png]


RE: Sprite warping (or wraping?) - megamarc - 11-16-2022

Hi,
I've done a quick warping mockup, here's the source code, just place in "samples" directoy and treat it as a regular sample
   


RE: Sprite warping (or wraping?) - megamarc - 11-16-2022

Good work with drawing primitives :-)

For drawing filled circles, I once implemented it on a gfx library. I used bresenham's circle algorithm, but instead of directly plotting the edge pixels, I used them to fill an array of pairs of left/right edge values for each affected scanline. Then filled each scanline with solid color between its left and right edges and voila, filled circle.

This is very old MS-DOS Borland C source with the base algorithm, but you got the idea.
http://csourcecodes.blogspot.com/2016/06/bresenhams-circle-drawing-algorithm-c-program-implementation.html


RE: Sprite warping (or wraping?) - System64 - 11-16-2022

(11-16-2022, 08:34 AM)megamarc Wrote: Good work with drawing primitives :-)

For drawing filled circles, I once implemented it on a gfx library. I used bresenham's circle algorithm, but instead of directly plotting the edge pixels, I used them to fill an array of pairs of left/right edge values for each affected scanline. Then filled each scanline with solid color between its left and right edges and voila, filled circle.

This is very old MS-DOS Borland C source with the base algorithm, but you got the idea.
http://csourcecodes.blogspot.com/2016/06/bresenhams-circle-drawing-algorithm-c-program-implementation.html

Thanks a lot for the sample and the algorithm! Both are pretty simple! I'll try to implement that.
This is the same principle for vertical warping and warping on both directions (but you need 4 sprites in this case).


RE: Sprite warping (or wraping?) - megamarc - 11-17-2022

Hi,

You don't need 4 sprites to warp in both directions, just 2 sprites. Here is the simplified source.

Beware that you cannot warp in both axis at the same time, that is, trying to warp in a corner breaks the logic rules. You should restrict your gameplay to avoid reaching a corner!


RE: Sprite warping (or wraping?) - System64 - 11-21-2022

(11-17-2022, 03:00 AM)megamarc Wrote: Hi,

You don't need 4 sprites to warp in both directions, just 2 sprites. Here is the simplified source.

Beware that you cannot warp in both axis at the same time, that is, trying to warp in a corner breaks the logic rules. You should restrict your gameplay to avoid reaching a corner!

Hi
Effectively, you only need 2 sprites if you are not taking corners in consideration. I considered the case with the corners but I didn't precised about that, I am sorry. For this specific case, you need 4 sprites.

About the circle algorithm, I made a varient that let you make a filled circle, it works very well.
Code:
proc drawCircleFill(bitmap: TLN_Bitmap, centerX: int, centerY: int, radius: int): void =
    var
        x = 0
        y = radius
        m = 5 - 4 * radius

    while (x <= y):
        bitmap.drawLine(centerX - x, centerY - y, centerX + x, centerY - y)
        bitmap.drawLine(centerX - y, centerY - x, centerX + y, centerY - x)
        bitmap.drawLine(centerX - y, centerY + x, centerX + y, centerY + x)
        bitmap.drawLine(centerX - x, centerY + y, centerX + x, centerY + y)

        if (m > 0):
           
            dec y
            m -= 8 * y;
        inc x
        m += 8 * x + 4

proc drawLine(bitmap: TLN_Bitmap, x: int, y: int, x2: int, y2: int): void =
    var
        dy = y2 - y
        dx = x2 - x
        err = 2 * dy - dx
        myY = y

    for myX in x..x2:
        bitmap.getBitmapPtr(myX, myY)[] = 1

        if err >= 0:
            myY += 1
            err -= 2 * dx
       
        err += 2 * dy
[Image: image.png]

I also have a suggestion for tiles. I noticed there is still 5 unused bits in the tile struct, so you maybe can add a blending flag for individual tiles, so you can enable or disable transparency for individual tiles, unless you planned something else with thoses bits? What do you think about this idea?