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).
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.
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?
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.
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?
(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
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.
(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.
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).
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!
11-21-2022, 09:05 PM (This post was last modified: 11-21-2022, 09:15 PM by System64.)
(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
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?