Since I needed it, I made a rotatable polyvector function
CREATESCREEN 1, 1,32,32
USESCREEN 1
DRAWRECT 0,0,16,16,RGB(255,0,0)
DRAWRECT 16,0,16,16,RGB(0,255,0)
DRAWRECT 0,16,16,16,RGB(0,0,255)
DRAWRECT 16,16,16,16,RGB(255,255,0)
USESCREEN -1
GLOBAL imh, imw
GETSPRITESIZE 1,imw,imh
LOCAL dir
WHILE KEY(1) = FALSE
CLEARSCREEN RGB(0,0,0)
rotopoly(dir,dir,dir)
PRINT dir,0,0
SHOWSCREEN
IF dir < 360
INC dir, 1
ELSE
dir = 0
ENDIF
WEND
END
FUNCTION rotopoly: x, y, dir
LOCAL w = imw/2, h = imh/2
STARTPOLY 1, 2
POLYVECTOR cast_x(x,w,dir+90), cast_y(y,h,dir+90), 0, 0, RGB(255,255,255)
POLYVECTOR cast_x(x,-w,-dir+180), cast_y(y,h,-dir+180), 0, h*2, RGB(255,255,255)
POLYVECTOR cast_x(x,w,-dir+180), cast_y(y,-h,-dir+180), w*2, 0, RGB(255,255,255)
POLYVECTOR cast_x(x,w,dir-90), cast_y(y,h,dir-90), w*2, h*2, RGB(255,255,255)
ENDPOLY
ENDFUNCTION
FUNCTION cast_x: x, dist, dir
RETURN x+(COS(dir)*dist)
ENDFUNCTION
FUNCTION cast_y: y, dist, dir
RETURN y+(SIN(dir)*dist)
ENDFUNCTION
I did something similar with my Guru Logic Champs game for Wiz. Came in very handy as one of the ROTO commands didn't work on the Wiz (can't remember exactly what now though).
Scott, tried your piece of code, and while it is ok for square shapes, rectangles are not catered for ;(
Heres my code that I use for similar situations (Its a bit of a hack around of Gernots "Glowy Line" function) ....
FUNCTION PolRot: x, y, w, h, rot, im, sx, sy, sw, sh
LOCAL tint1=RGB(255,255,255)
LOCAL tint2=RGB(255,255,255)
LOCAL scx=1,scy=1
LOCAL w,ddx,ddy,lg,dx,dy,ux,uy
LOCAL width=w
LOCAL width2=w/2
LOCAL height=h
LOCAL height2=h/2
LOCAL ly=(SIN(rot)*-(width2*scy))+y
LOCAL lx=(COS(rot)*-(width2*scx))+x
LOCAL ry=(SIN(rot)*(width2*scy))+y
LOCAL rx=(COS(rot)*(width2*scx))+x
LOCAL sz=height*scy
//line width
LOCAL w = sz
// direction of line
ddx = rx-lx
ddy = ry-ly
lg = SQR(ddx*ddx+ddy*ddy)
// IF lg>=0.5
//
// short caps
lg=lg*2
// dir vector
dx=ddx*w/lg
dy=ddy*w/lg
// up vector
ux=dy
uy=-dx
STARTPOLY im
POLYVECTOR lx+ux, ly+uy, sx, sy, tint1
POLYVECTOR lx-ux, ly-uy, sx, sy+sh, tint1
POLYVECTOR rx-ux, ry-uy, sx+sw, sy+sh, tint2
POLYVECTOR rx+ux, ry+uy, sx+sw, sy, tint2
ENDPOLY
ENDFUNCTION
I used this for my text routines so I could have a gradient look on my fonts. It also caters for scaling of the shape to (with the scx, scy vars)
Hope this is of hekp to somebody
Thanks, I'll have to try that out.
Well guys I couldn't get your code examples to work when I first tried (likely error on my part) so I re-invented the wheel.
I decided I wanted to replace all the Drawsprite style commands in my almost-ready iPhone game PowFish with polygons instead to get a bit of a performance boost. Problem is to get that performance boost all the sprites have to be on one single Texture Atlas. So, I wrote a small test routine to ape DRAWSPRITE, DRAWANIM and ROTOZOOMANIM - except using Polyvectors. The routine requires that the sprite co-ords and sizes are stored in an array but it otherwise works much the same as DRAWSPRITE, etc. The functions I defined were PolySprite, PolyAnim, PolyZoomAnim and PolyRotoZoomAnim.
As far as I know it works for any x,y sized sprite. The code for my PolyRotoZoomAnim looks hopelessly unoptimised in comparison to whatever it is that you guys are doing. I wouldn't know how to optimise it though. Luckily rotating sprites aren't often used in PowFish. Full source & sprites are included in a zip file.
LOADSPRITE "playerstanding.png", 1 // Just one sprite
LOADANIM "playerwalking.png", 2, 32, 64 // Animation frames are 32 by 64
LOADSPRITE "textureatlas.png", 20 // The texture atlas for use with Polyvector
GLOBAL sprites[] // Array to hold sprite details in
DIM sprites[3][12][4] // sprite [sprite number] [animation frame] [x co-ords, y co-ords, x width, y height]
GLOBAL drawmethod = 0 // 0 = drawsprite mode, 1 = Polyvector mode
GLOBAL an = 0 // anim character walking from 0 to 11
GLOBAL animdelay = 0 // delay in animation frames
GLOBAL ang = 0 // Angle to draw sprite at
GLOBAL sca = 1 // scale of sprite
GLOBAL scadelay = 0
GLOBAL drawdelay = 0 // used to flip between Drawsprite and Polyvector
GLOBAL sine[] // precalculate sine and cosine
GLOBAL cosine[]
DIM sine[360]
DIM cosine[360]
// variables for use with the PolySprite functions
GLOBAL patx, paty, patxx, patyy, porwidth, porheight, porcentx, porcenty, pwidth, pheight, pcentx, pcenty
GLOBAL pltx, plty, plbx, plby, prtx, prty, prbx, prby, pcolour, pminx, pminy, pmaxx, pmaxy
// Initialise this example
SetupSpriteData()
PrecalculateAngles()
// Main Loop
WHILE KEY(01) = FALSE
IF drawmethod = 0
ALPHAMODE -1.0
DRAWSPRITE 1, 96, 128
DRAWANIM 2, an, 224, 128
ROTOZOOMANIM 2, an, 352, 128, 0, sca
ROTOZOOMANIM 2, an, 480, 128, ang, sca
PRINT "DRAWSPRITE style", 235, 40
ELSEIF drawmethod = 1
ALPHAMODE -1.0
STARTPOLY 20, 1
PolySprite(1, 96, 128)
PolyAnim(2, an, 224, 128)
PolyZoomAnim(2, an, 352, 128, sca)
PolyRotoZoomAnim(2, an, 480, 128, ang, sca)
ENDPOLY
PRINT "Polysprite function calls", 205, 40
ENDIF
INC animdelay
IF animdelay = 4
animdelay = 0
INC an
IF an = 12 THEN an = 0
ENDIF
INC ang
IF ang = 360 THEN ang = 0
INC drawdelay
IF drawdelay = 120 THEN drawmethod = 1
IF drawdelay = 240
drawmethod = 0
drawdelay = 0
ENDIF
INC scadelay
IF scadelay >= 360 THEN scadelay = 0
sca = 2-sine[scadelay]
SHOWSCREEN
WEND
// End the program
END
// End the program
FUNCTION PolySprite: sprite, minx, miny
patx = sprites[sprite][0][0]
paty = sprites[sprite][0][1]
patxx = sprites[sprite][0][0]+sprites[sprite][0][2]
patyy = sprites[sprite][0][1]+sprites[sprite][0][3]
pminx = minx
pminy = miny
pmaxx = pminx+sprites[sprite][0][2]
pmaxy = pminy+sprites[sprite][0][3]
pcolour = RGB(255, 255, 255)
POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour
ENDFUNCTION
FUNCTION PolyAnim: sprite, frame, minx, miny
patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]
pminx = minx
pminy = miny
pmaxx = pminx+sprites[sprite][frame][2]
pmaxy = pminy+sprites[sprite][frame][3]
pcolour = RGB(255, 255, 255)
POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour
ENDFUNCTION
FUNCTION PolyZoomAnim: sprite, frame, xpos, ypos, scale
patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]
porwidth = sprites[sprite][frame][2]
porheight = sprites[sprite][frame][3]
pwidth = sprites[sprite][frame][2] * scale
pheight = sprites[sprite][frame][3] * scale
porcentx = porwidth / 2
porcenty = porheight / 2
pcentx = pwidth / 2
pcenty = pheight / 2
pminx = xpos + (porcentx - pcentx)
pminy = ypos + (porcenty - pcenty)
pmaxx = xpos + (porcentx + pcentx)
pmaxy = ypos + (porcenty + pcenty)
pcolour = RGB(255, 255, 255)
POLYVECTOR pminx, pminy, patx, paty, pcolour
POLYVECTOR pminx, pmaxy, patx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pmaxy, patxx, patyy, pcolour
POLYVECTOR pmaxx, pminy, patxx, paty, pcolour
POLYVECTOR pminx, pminy, patx, paty, pcolour
ENDFUNCTION
FUNCTION PolyRotoZoomAnim: sprite, frame, xpos, ypos, angle, scale
angle = 359 - angle
patx = sprites[sprite][frame][0]
paty = sprites[sprite][frame][1]
patxx = sprites[sprite][frame][0]+sprites[sprite][frame][2]
patyy = sprites[sprite][frame][1]+sprites[sprite][frame][3]
porwidth = sprites[sprite][frame][2]
porheight = sprites[sprite][frame][3]
pwidth = sprites[sprite][frame][2] * scale
pheight = sprites[sprite][frame][3] * scale
porcentx = porwidth / 2
porcenty = porheight / 2
pcentx = pwidth / 2
pcenty = pheight / 2
pminx = -porcentx
pminy = -porcenty
pmaxx = porcentx
pmaxy = porcenty
pltx = ((cosine[angle]*pminx) - (sine[angle]*pminy)) * scale
plty = ((sine[angle]*pminx) + (cosine[angle]*pminy)) * scale
plbx = ((cosine[angle]*pminx) - (sine[angle]*pmaxy)) * scale
plby = ((sine[angle]*pminx) + (cosine[angle]*pmaxy)) * scale
prtx = ((cosine[angle]*pmaxx) - (sine[angle]*pminy)) * scale
prty = ((sine[angle]*pmaxx) + (cosine[angle]*pminy)) * scale
prbx = ((cosine[angle]*pmaxx) - (sine[angle]*pmaxy)) * scale
prby = ((sine[angle]*pmaxx) + (cosine[angle]*pmaxy)) * scale
xpos = xpos + porcentx
ypos = ypos + porcenty
pltx = xpos + pltx
plty = ypos + plty
plbx = xpos + plbx
plby = ypos + plby
prtx = xpos + prtx
prty = ypos + prty
prbx = xpos + prbx
prby = ypos + prby
pcolour = RGB(255, 255, 255)
POLYVECTOR pltx, plty, patx, paty, pcolour
POLYVECTOR plbx, plby, patx, patyy, pcolour
POLYVECTOR prbx, prby, patxx, patyy, pcolour
POLYVECTOR prbx, prby, patxx, patyy, pcolour
POLYVECTOR prtx, prty, patxx, paty, pcolour
POLYVECTOR pltx, plty, patx, paty, pcolour
ENDFUNCTION
FUNCTION PrecalculateAngles:
FOR i = 0 TO 359
sine[i] = SIN(i)
cosine[i] = COS(i)
NEXT
ENDFUNCTION
FUNCTION SetupSpriteData:
// Set up sprite data for use to simulate Drawsprite-like function calls //
RESTORE spritestuff
READ sprites[1][0][0]
READ sprites[1][0][1]
READ sprites[1][0][2]
READ sprites[1][0][3]
FOR i = 0 TO 11
READ sprites[2][i][0]
READ sprites[2][i][1]
READ sprites[2][i][2]
READ sprites[2][i][3]
NEXT
ENDFUNCTION
// Start of sprite data. Clumsy but I couldn't be bothered to store this information in a file just for this test routine
STARTDATA spritestuff:
DATA 128, 64, 32, 64 // sprite 1: start x co-ord, start y co-ord, x width, y height
DATA 0, 0, 32, 64 // sprite 2, anim-number 0: start x co-ord, start y co-ord, x width, y height
DATA 32, 0, 32, 64 // sprite 2, anim-number 1: start x co-ord, start y co-ord, x width, y height
DATA 64, 0, 32, 64 // sprite 2, anim-number 2: start x co-ord, start y co-ord, x width, y height
DATA 96, 0, 32, 64 // sprite 2, anim-number 3: start x co-ord, start y co-ord, x width, y height
DATA 128, 0, 32, 64 // sprite 2, anim-number 4: start x co-ord, start y co-ord, x width, y height
DATA 160, 0, 32, 64 // sprite 2, anim-number 5: start x co-ord, start y co-ord, x width, y height
DATA 192, 0, 32, 64 // sprite 2, anim-number 6: start x co-ord, start y co-ord, x width, y height
DATA 224, 0, 32, 64 // sprite 2, anim-number 7: start x co-ord, start y co-ord, x width, y height
DATA 256, 0, 32, 64 // sprite 2, anim-number 8: start x co-ord, start y co-ord, x width, y height
DATA 288, 0, 32, 64 // sprite 2, anim-number 9: start x co-ord, start y co-ord, x width, y height
DATA 0, 64, 32, 64 // sprite 2, anim-number 10: start x co-ord, start y co-ord, x width, y height
DATA 32, 64, 32, 64 // sprite 2, anim-number 11: start x co-ord, start y co-ord, x width, y height
ENDDATA
[attachment deleted by admin]
Had a quick look and it does exactly what it says on the tin :)
Have you compared the drawspeed when you've got hundreds of these polyvectors vs sprites? Is there a substantial difference? I'll have a play later.
I did something similar for my Blitz iPod game and got a massive increase in speed, so I'm expecting likewise.
Nicely done, putting the sin and cos in arrays should cut down on processing a little.
As far as I've experienced, if you use polyvector correctly you can put a bunch of stuff on the screen where the sprite commands may lag.
Ian, I have a benchmarking app I wrote specifically for testing the difference between drawsprite and the different polyvector modes (and variables). My experiments with that led me to conclude Polyvector is always faster and that once you're into drawing hundreds of sprites the Polyvector Triangle or Strip method is practically essential.
I could upload the benchmarking app if people would like it. It might be interesting to see what kind of performance differences people get on different devices. At the moment I just have an iPod Touch (3GS equivalent) to test it with.
(edit: I have yet to test the PolySprite functions I wrote to see how much faster they might be on the iPhone. However, I don't think I'm going to do that. I'm going to be dangerous and just assume they'll be faster. I'll know once I've had the time to update PowFish with them.)
Quoteconclude Polyvector is always faster and that once you're into drawing hundreds of sprites the Polyvector Triangle or Strip method is practically essential.
My tests confirm this too; as I stated -
QuoteI did something similar for my Blitz iPod game and got a massive increase in speed, so I'm expecting likewise.
I'm using POLYVECTOR in pretty much everything now.
:)
The only issues I've experienced is when systems have old drivers or don't support OpenGL, then things crawl or are horribly distorted.
I've also had trouble with creating trapezoids, either my vector order is off or something, but the textures don't bend correctly.