Log In  

LAST VERSION as USED in R-type 1.4 after optimizing it a bit further:

--97 tokens with Scaling and arbitrary size
function pd_rotate(x,y,rot,mx,my,w,flip,scale)
  scale=scale or 1
  w*=scale*4

  local cs, ss = cos(rot)*.125/scale,sin(rot)*.125/scale
  local sx, sy = mx+cs*-w, my+ss*-w
  local hx = flip and -w or w

  local halfw = -w
  for py=y-w, y+w do
    tline(x-hx, py, x+hx, py, sx-ss*halfw, sy+cs*halfw, cs, ss)
    halfw+=1
  end
end

This is a general-purpose sprite rotation function using tline with support for scaling and flipping

Cart #tline_sprite_rotation-5 | 2022-04-30 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
29

It always draw a screen-oriented rectangular area, (centered at x,y) large enough (w) to contain the rotated tiles (centered at mx,my), and calculates the rotated (rot 0 to 1) tline coordinates and deltas.

The catch is that you need to have the sprite in the map and must leave "clearance-space" around the map part to be rotated (matching the largest side of the sprite or you get some additional map tiles drawn as well, visible in pink in the example). But you can just prepare one rotating area and just swap tiles with mset().

LAST EDITED for a mistake that was messing up mx and my

P#78451 2020-06-24 05:59 ( Edited 2022-04-30 06:52)

1

see https://www.lexaloffle.com/bbs/?tid=37561 for a generic purpose tlne rotation without any constraints

P#78458 2020-06-24 08:21

Thanks again @TheRoboZ for posting this.
I've just started playing with it as a successor to Fred72's legendary RSPR() routine I'd been using for ages.

Early days, but looks like it might do the trick
(although, due to the way I render shadows, etc. I might end up using more tokens - might be worth it, depends on the perf improvement!)

Thanks again! 🤓👍

UPDATE: Woah, looks like mine + Fred's comments overlapped!
Thx @freds72, I'll give that another look, but I thought the token count was higher and/or inc. features I do not require (as all my current needs are for single, 8x8 sprites) 🤔

P#78459 2020-06-24 08:35 ( Edited 2020-06-24 10:14)
1

ok ok I see where I can have a much leaner version. Stay tuned!

P#78461 2020-06-24 10:37
2

I noticed a small optimization after posting:

--150 tokens

function draw_rotated_rect(x,y,sw_rot,mx,my,w,h)
    local dx, dy, r, cs, ss = 0, 0, max(w,h)/2, cos(sw_rot), -sin(sw_rot)
    if w>h then dy = (w-h)/2 else dx = (h-w)/2 end
    local ssx, ssy, cx, cy = mx - 0.3 -dx, my - 0.3 -dy, mx+r-dx, my+r-dy

    ssy -=cy
    ssx -=cx

    local delta_px = max(-ssx,-ssy)*8

    --this just draw a bounding box to show the exact draw area
    rect(x-delta_px,y-delta_px,x+delta_px,y+delta_px,5)

    local sx, sy =  cs * ssx + cx, -ss * ssx + cy

    for py = y-delta_px, y+delta_px do
        tline(x-delta_px, py, x+delta_px, py, sx + ss * ssy, sy + cs * ssy, cs/8, -ss/8)
        ssy+=1/8
    end
end

--108 tokens

function draw_rotated_square(x,y,sw_rot,mx,my,r)    
    local cs, ss = cos(sw_rot), -sin(sw_rot)    
    local ssx, ssy, cx, cy = mx - 0.3, my - 0.3, mx+r/2, my+r/2

    ssy -=cy
    ssx -=cx

    local delta_px = -ssx*8

    --this just draw a bounding box to show the exact draw area
    rect(x-delta_px,y-delta_px,x+delta_px,y+delta_px,5)

    local sx, sy =  cs * ssx + cx, -ss * ssx + cy

    for py = y-delta_px, y+delta_px do
        tline(x-delta_px, py, x+delta_px, py, sx + ss * ssy, sy + cs * ssy, cs/8, -ss/8)
        ssy+=1/8
    end
end

and for fixed 8x8 size you can optimize it even more.

P#78463 2020-06-24 11:05 ( Edited 2020-06-24 11:23)
3

Hey @Liquidream I added a more general purpose one with support for flip and scaling after using it in my game

function draw_rotated_tile(x,y,rot,mx,my,w,flip,scale)
  scale = scale or 1
  w+=.8
  local halfw, cx  = scale*-w/2, mx + w/2 -.4
  local cs, ss, cy = cos(rot)/scale, -sin(rot)/scale, my-halfw/scale-.4
  local sx, sy, hx, hy = cx + cs*halfw, cy - ss*halfw, w*(flip and -4 or 4)*scale, w*4*scale

  --this just draw a bounding box to show the exact draw area
  rect(x-hx,y-hy,x+hx,y+hy,5)

  for py = y-hy, y+hy do
    tline(x-hx, py, x+hx, py, sx + ss*halfw, sy + cs*halfw, cs/8, -ss/8)
    halfw+=1/8
  end
end
P#80283 2020-08-03 00:23

Thanks a lot @TheRoboZ 🤓👍

P#80293 2020-08-03 04:57

Since this has been used in a couple carts, here is the last updated version as used in R-type:

--123 tokens with scaling and arbitrary size
function pd_rotate(x,y,rot,mx,my,w,flip,scale)
scale=scale or 1
local halfw, cx=scale-w/2, mx + .5
local cy,cs,ss=my-halfw/scale,cos(rot)/scale,sin(rot)/scale
local sx, sy, hx, hy=cx+cs
halfw, cy+sshalfw, w(flip and -4 or 4)scale, w4scale
for py=y-hy, y+hy do
tline(x-hx, py, x+hx, py, sx -ss
halfw, sy + cs*halfw, cs/8, ss/8)
halfw+=.125
end
end

P#105732 2022-01-27 07:25
1

Since this has been used in a couple carts, here is the last updated version as used in R-type:

--123 tokens with scaling and arbitrary size
function pd_rotate(x,y,rot,mx,my,w,flip,scale)
  scale=scale or 1
  local halfw, cx=scale*-w/2, mx + .5
  local cy,cs,ss=my-halfw/scale,cos(rot)/scale,sin(rot)/scale
  local sx, sy, hx, hy=cx+cs*halfw, cy+ss*halfw, w*(flip and -4 or 4)*scale, w*4*scale
  for py=y-hy, y+hy do
  tline(x-hx, py, x+hx, py, sx -ss*halfw, sy + cs*halfw, cs/8, ss/8)
  halfw+=.125
  end
end
P#105733 2022-01-27 07:25 ( Edited 2022-01-27 07:26)
:: dw817
1

Cart #tline_sprite_rotation_mod-0 | 2022-01-31 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

Here is @simonwilson's rocket. I wanted to see if this rotation was any better with less jaggies than the one he wrote. I'm not seeing a difference.

P#106060 2022-01-31 18:47
1

@dw817 For R-type I was constraining rotation angles to fixed step (when drawn, calculation uses continuous rotation)

function pd_rotate(x,y,rot,mx,my,w,flip,scale)
  local step = 1/16
  scale=scale or 1
  rot=rot\step * step
  local halfw, cx=scale*-w/2, mx + .5
  local cy,cs,ss=my-halfw/scale,cos(rot)/scale,sin(rot)/scale
  local sx, sy, hx, hy=cx+cs*halfw, cy+ss*halfw, w*(flip and -4 or 4)*scale, w*4*scale
  for py=y-hy, y+hy do
  tline(x-hx, py, x+hx, py, sx -ss*halfw, sy + cs*halfw, cs/8, ss/8)
  halfw+=.125
  end
end

Liek this you get 22.5, 45, etc...
still there is some intrinsic jagginess that sometimes depends on the sprite (I got the rocket from the cart and it was not symmetrical, so I fixed it here). For r-type homing missiles I had a problem when at some angles they looked weird when horizontal, so I drew them with an equal but opposite offset and they appear straight when rotated

You can also add a bit of manual anti-aliasing when drawing the sprite to hide it a bit (bottom rocket), but for real-time smoothing or dithering I have no idea.

P#106112 2022-02-01 11:38
:: dw817

That =IS= better, @TheRoboZ. I figured intelligent dithering would fix a lot of the jagginess. Well done.

P#106130 2022-02-01 17:19
:: Xeonic

@TheRoboZ very cool
mind explaining how this fetches textures i am having a difficult time understanding how it gets any texture coordinates.

P#111009 2022-04-28 16:48
1

@Xeonic it uses tline so it is reading from the map area. You need to put your sprite to be rotated in an area of the map editor. Check the updated cart and description above.

P#111024 2022-04-29 04:15
1

Sorry, there was a typo in this line:

local sx, sy = mx+cs-w, my+ss-w

you need to add half w to the starting my coordinate when calling the function and not inside the rotation code. Anyway see the updated cart

P#111093 2022-04-30 06:36 ( Edited 2022-04-30 06:53)
:: Xeonic

ohh nice way cleaner
10/10

P#111233 2022-05-03 08:24

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2022-08-18 01:11:20 | 0.079s | Q:39