Codesnippets > Code Snippets
BMax-like wrapper to GLB commands
(1/1)
AndyH:
Hi all - bit of a delay in posting this (away at family party) and I haven't finished the bits I wanted to yet (collisions and text print still to do) but here's the BMax-like wrapper I was talking about.
It contains a combination of code I've written, with code found on the forums integrated or modified to fit in.
You have to call oInitialiseSprites() at the start of your program to set up some values. In BMax I would just write code 'outside' of a function in the sprites include file and it would be run but I don't think GLB supports that (include files must only contain functions, types and global declarations from what I can tell).
Once you've called the initialise function, you are free to start using the functions within. Note that you must use the functions to load sprites or animations, otherwise you'll get conflicts.
Here's a brief summary of what the functions allow you to do:
= oLoadSprite( "filename" ) // load a single sprite, returns an ovine sprite Id (not a GLB sprite id) for you to reference your sprite
= oReserveSprite() // just returns and ovine sprite Id - useful if you want to manipulate sprites yourself such as with GRABSPRITE but don't want to load a sprite in - just creates the place holder for it
= oLoadTiles( "filename", width, height ) // load a tilestrip in, returns the ovine sprite Id - uses LOADANIM and keeps the tiles/frames in one sprite. Tilestrips can not (currently) be rotated, scaled or have colour applied to it. It is intended for drawing game levels from tilemaps or simple animation. Gernot has added a function to allow ANIM's to be rotated and scaled so I'll update this to allow that. If Gernot can also give us the colour parameter for ROTOZOOMANIM (as I believe it uses POLYVECTOR) then this could support the colour modifier too.
= oLoadAnim( "filename", width, height ) // load an animation strip in, returns the ovine sprite Id. Internally, each animation frame is GRABSPRITE'd into it's own sprite. This allows the use of rotate, zoom and colour modification commands. There appears to be a bug with GRABSPRITE where coloured pixels bordering with transparent pixels are altered in the GRABSPRITE version of the sprite which only appears with ZOOM or ROTATION is used. I'm hoping Gernot will fix this.
oAutoMidHandle( TRUE or FALSE ) // set whether auto mid-handle (the pivot point) is on or off - automatically sets the handle to the middle of the sprite if TRUE when oLoad.... functions are used.
oSetHandle( ovineSpriteId, hx, hy ) // allow you to set the handle (pivot point) to a specific X and Y position of a sprite / tilemap already loaded in with one of the oLoad... functions
oMidHandle( ovineSpriteId ) // set the handle to the mid-point of the supplied ovine sprite Id
oSetScale( scale ) // set the scale for all sprite drawing from this point on (excludes tilemaps currently). 1=normal, 0.5 = half size, 2.0 = double size
oSetRotation( angle ) // set the rotation for all sprite drawing from this point on
oSetColor( rgbValue ) // sets the colour modifier for all sprite drawing from this point on ( RGB(255,255,255) will draw the sprite normally, RGB(255,0,0) will make the sprite Red etc)
oSetPrecision( TRUE or FALSE ) // if TRUE - your game will use the real SIN / COS functions supplied by GLB. If FALSE, will use the QSIN and QCOS variants which may be faster on some platforms (eg: GP2X) but with less accuracy. I've not noticed a problem with these.
oDrawSprite( ovineSpriteId, xPos, yPos, Frame ) // draws the sprite at the X and Y position, with the handle, colour, rotation and scale as set previously. Note that on platforms that have hardware accelerated support (Windows, Mac, Linux) the rotation, scale and colour modifiers will be pretty quick. On GP2X, PocketPC and Smart Phones you are advised to use these sparingly as it will all be done in software.
Example
If you have used BMax then the above may not need much explanation. Here's a brief example of the commands:
--- Code: (glbasic) ---oInitialiseSprites()
oAutoMidHandle(TRUE) // from this point on, all oLoad... commands will set the handle to the centre of the sprite
spr1 = oLoadSprite("sprite1.png") // load a single frame sprite in, variable spr1 contains the Id of that ovineSpriteId
spr2 = oLoadSprite("sprite2.png") // load a second single frame sprite in
oSetHandle( spr2, 16,0 ) // change the handle (pivot point) of sprite 2 to be 16 across, 0 down
oAutoMidHandle(FALSE) // from this point on, all oLoad/// commands will leave the handle at top/left (0,0)
spr3 = oLoadAnim("player.png", 32,32, 10) // load an animation for the player in this example, where each frame is 32x32 in size and there are 10 frames to load in.
oSetHandle (spr3, 16,32 ) // set the handle for all frames in this animation to the bottom centre (where his feet are)
oSetPrecision( FALSE ) // use the quick QCOS/QSIN functions for rotations and scale
oDrawSprite( spr1, 320, 240, 1 ) // draw the sprite at the centre of the screen (assuming 640x480 game window) but it's handle will mean it will be centred too. It only has one frame cause we used oLoadSprite
oSetScale( 2 ) // set scale to 2
oSetRotation( 45 ) // set angle
oSetColor( RGB(0,255,128) ) // lets tint the colour value
oDrawSprite( spr2, 320, 240, 1 ) // draws this sprite at a scale of 2, 45 degree angle with a greeny-blue tint
// more sprite drawing from this point on would use same scale, rotation and color values until you set them to a different value
// now a for loop
oSetColor( RGB(255,255,255) )
FOR t = 1 TO 20
oSetScale (t / 10) // set the scale
oSetRotation( t * 18 ) // set the scale
oDrawSprite( spr3, t*40, 100, MOD(t, 10) ) // draw frames from the animation going across the screen using current scale+rotation
NEXT t
// put everything back
oSetScale(1)
oSetRotation(0)
SHOWSCREEN
MOUSEWAIT
--- End code ---
Note that I have used variables spr1, spr2 and spr3 in the example above although these variables could be called anything, or in most cases you'd store them in your own types for access later. These just store the special ovine sprite Id's returned by function and refers to an array index in oSprites[]. You can write more functions to allow access to this, or access the type'd properties directly if you wish. Confession: I've not actually tried to run the code above as I've just typed in directly into the forum, but should all work, if not probably just a silly typo on my part
The code:
Well here it is, I've got this in an include file in my project. Will add more to this, fix bugs, make changes etc as my game develops. Feel free to use this in your own games if you want, but would appreciate if you'd share your ideas or improvements with the whole GLB community as the idea of all this is to help make things easier to do :D As per the usual disclaimers - it's work in progress, will probably get optimised as time goes on, and use at your own risk.
Note: new version(s) can be found in later posts in this thread. Scroll down to see them.
--- Code: (glbasic) ---// --------------------------------- //
// Project: A wrapper around SPRITES
// so never need to manage Id's directly
// --------------------------------- //
// Version: 1.000
// --------------------------------- //
// --------------------------------- //
// Please retain comments-free to use
// these functions in any freeware or
// commercial programs. Given to the
// community without any warranties
// of any kind. Please send updates
// or improvements to andyh@ovine.net
// --------------------------------- //
// TODO:
// - PRINT TEXT command (with color and rotation/scaling options)
// - Collision functions - decide to use anim or sprite collide, box collision, point collision with box, point collision with sprite or anim
// (note collisions only work with unscales/rotated sprites/anims)
// note also collisions must take into account the handle!
TYPE OSprType
id // Sprite Id
w;h // width and height
hx;hy // handle X and Y
maxframes // total num of frames,
// 0 = Tilemap (use DRAWANIM) - no scale, rotate or color support - but can be used to draw tilemaps quickly
// 1 = Single Sprite
// >1 = the count of sprite Id's used, ie: id+(maxFrames-1) == last sprite Id FOR this animation
ENDTYPE
GLOBAL oSprites[] AS OSprType
// this global type is used to store settings that modify the way sprites are drawn
TYPE OSpriteSettings
scale // scale for sprite
rotation // current rotation settings for sprite
color // RGB colour to apply (POLYVECTOR)
midHandle // auto-mid handle mode (T/F)
mathPre // maths precision (TRUE = use real COS/SIN, FALSE = use false SIN/COS)
ENDTYPE
GLOBAL OSprSettings AS OSpriteSettings
FUNCTION oInitialiseSprites:
OSprSettings.color = RGB(255,255,255)
OSprSettings.scale = 1.0
OSprSettings.rotation = 0
OSprSettings.midHandle = TRUE
OSprSettings.mathPre = TRUE
ENDFUNCTION
// starts at SPRITE ID = 1, Sprite Id = 0 is reserved for loading
@FUNCTION _GetNextSpriteID:
STATIC _oSprNextId
INC _oSprNextId, 1
RETURN _oSprNextId
ENDFUNCTION
// Get next oSprites, starts at 0
@FUNCTION _GetNextOSprID:
STATIC _oSprNextArrayId
INC _oSprNextArrayId, 1
RETURN (_oSprNextArrayId - 1)
ENDFUNCTION
// --------------------------------- //
// Project: Loading routines - only load
// sprites at start or when not in middle
// of a gameloop where you are updating the
// screen - do not load sprites directly
// with the GLB LOADSPRITE command
// --------------------------------- //
FUNCTION oLoadSprite: _file$
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
LOADSPRITE _file$, t.id
t.maxframes = 1 // defines a single sprite
GETSPRITESIZE t.id,t.w,t.h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
// used to reserve a sprite Id and slot for own use (eg: if you want to GRABSPRITE)
FUNCTION oReserveSprite:
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
t.maxframes = 1 // defines a single sprite
t.w = 0
t.h = 0
t.hx = 0
t.hy = 0
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
FUNCTION oLoadTiles: _file$, _w, _h
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
LOADANIM _file$, t.id, _w, _h
t.maxframes = 0 // defines a tilemap of frames in a sprite
GETSPRITESIZE t.id,t.w,t.h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
FUNCTION oLoadAnim: _file$, _w, _h, _maxframes
LOCAL t AS OSprType
LOCAL num
LOADANIM _file$, 0, _w, _h
LOCAL i
SETTRANSPARENCY RGB(0,0,0)
FOR i=0 TO _maxframes-1
DRAWRECT 0,0, _w,_h, RGB(0,0,0) // transparent colour
DRAWANIM 0, i, 0,0
LOCAL nextSprite
nextSprite = _GetNextSpriteID()
IF t.id = 0 THEN t.id = nextSprite
GRABSPRITE nextSprite, 0,0, _w,_h
NEXT
t.maxframes = _maxframes // defines a sequence of grabbed sprites
t.w = _w
t.h = _h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
LOADSPRITE "", 0 // clear out temporary sprite from memory
BLACKSCREEN
SETTRANSPARENCY RGB(255,0,128)
RETURN _GetNextOSprID()
ENDFUNCTION
// - Modifiers
FUNCTION oAutoMidHandle: x
OSprSettings.midHandle = x
ENDFUNCTION
FUNCTION oSetHandle: _sprId, _hx, _hy
oSprites[_sprId].hx = _hx
oSprites[_sprId].hy = _hy
ENDFUNCTION
FUNCTION oMidHandle: _sprId
oSprites[_sprId].hx = oSprites[_sprId].w/2
oSprites[_sprId].hy = oSprites[_sprId].h/2
ENDFUNCTION
FUNCTION oSetScale: _scale
OSprSettings.scale = _scale
ENDFUNCTION
FUNCTION oSetRotation: _rotation
OSprSettings.rotation = _rotation
ENDFUNCTION
FUNCTION oSetColor: _color
OSprSettings.color = _color
ENDFUNCTION
FUNCTION oSetPrecision: x
OSprSettings.mathPre = x
ENDFUNCTION
FUNCTION oDrawSprite: _spr, _x, _y, _frame
SELECT oSprites[_spr].maxframes
CASE 0 // -------- A tilemap --------
DRAWANIM oSprites[_spr].id, _frame, _x - oSprites[_spr].hx, _y - oSprites[_spr].hy
DEFAULT // -------- A Sprite --------
LOCAL sprId
LOCAL dframe
IF _frame > oSprites[_spr].maxframes - 1
dframe = oSprites[_spr].maxframes - 1
ELSE
dframe = _frame
ENDIF
sprId = oSprites[_spr].id + dframe
IF OSprSettings.color RGB(255,255,255)
// must use polyvector to draw the sprite
_oRotoZoomPoly( _spr, sprId, _x, _y, OSprSettings.rotation, OSprSettings.scale, OSprSettings.color)
ELSEIF OSprSettings.scale = 1 AND OSprSettings.rotation 0
// must use ROTOSPRITE
_oRotoPivot( _spr, sprId, _x, _y, OSprSettings.rotation)
ELSEIF OSprSettings.scale 1 AND OSprSettings.rotation = 0
// must use ZOOMSPRITE
_oZoomSprite( _spr, sprId, _x, _y, OSprSettings.scale)
ELSEIF OSprSettings.scale 1 AND OSprSettings.rotation 0
// must use ROTOZOOMSPRITE
_oRotoZoomPivot( _spr, sprId, _x, _y, OSprSettings.rotation, OSprSettings.scale)
ELSE
// use DRAWSPRITE
DRAWSPRITE sprId, _x - oSprites[_spr].hx, _y - oSprites[_spr].hy
ENDIF
ENDSELECT
ENDFUNCTION
// TODO : Optimise this
@FUNCTION _oZoomSprite: _spr, _id, _x, _y, _scale
LOCAL sx, sy, hx,hy
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
hx = oSprites[_spr].hx
hy = oSprites[_spr].hy
DEC hx, sx
DEC hy, sy
hx = hx * _scale
hy = hy * _scale
ZOOMSPRITE _id, _x-hx-sx, _y-hy-sx, _scale, _scale
ENDFUNCTION
@FUNCTION _oRotoZoomPivot: _spr, _id, _x,_y, _angle, _scale
LOCAL sx, sy, rx,ry, px,py
LOCAL cosp, sinp
cosp=QCOS(_angle)
sinp=QSIN(_angle)
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
px = oSprites[_spr].hx
py = oSprites[_spr].hy
// reverse rotate pivot point arount center
// of sprite
DEC px, sx
DEC py, sy
rx = (px*cosp + py*sinp) * _scale
ry = (py*cosp - px*sinp) * _scale
// adjust center
INC rx,sx
INC ry,sy
// perform drawing
ROTOZOOMSPRITE _id, _x-rx, _y-ry, _angle, _scale
ENDFUNCTION
FUNCTION _oRotoZoomPoly: _spr, _id, _x,_y, _angle, _scale, _col
LOCAL sinp, cosp, spw, sph, dx, dy
LOCAL hx, hy, dxp, dxm, dyp, dym
sinp = QSIN(_angle)
cosp = QCOS(_angle)
spw = oSprites[_spr].w
sph = oSprites[_spr].h
dx=spw/2
dy=sph/2
hx = (dx - oSprites[_spr].hx)
hy = (dy - oSprites[_spr].hy)
dxp = (dx+hx) * _scale
dxm = (dx-hx) * _scale
dyp = (dy+hy) * _scale
dym = (dy-hy) * _scale
STARTPOLY _id
POLYVECTOR _x - cosp * dxm - sinp * dym, _y - cosp * dym + sinp * dxm, 0, 0, _col
POLYVECTOR _x - cosp * dxm + sinp * dyp, _y + cosp * dyp + sinp * dxm, 0, sph, _col
POLYVECTOR _x + cosp * dxp + sinp * dyp, _y + cosp * dyp - sinp * dxp, spw, sph, _col
POLYVECTOR _x + cosp * dxp - sinp * dym, _y - cosp * dym - sinp * dxp, spw, 0, _col
ENDPOLY
ENDFUNCTION
FUNCTION _oRotoZoomPolyBAK: _spr, _id, _x,_y, _angle, _scale, _col
LOCAL sphi, cphi, spx, spy, dx, dy
sphi=QSIN(_angle)
cphi=QCOS(_angle)
spx = oSprites[_spr].w
spy = oSprites[_spr].h
dx=spx/2*_scale
dy=spy/2*_scale
LOCAL hx, hy
hx = (spx/2-oSprites[_spr].hx)*_scale
hy= (spy/2-oSprites[_spr].hy)*_scale
// hx = ((spx/2)*_scale)-(oSprites[_spr].hx*_scale)
// hy= ((spy/2)*_scale)-(oSprites[_spr].hy*_scale)
STARTPOLY _id
POLYVECTOR _x - cphi* (dx-hx) - sphi* (dy-hy), _y - cphi*(dy-hy) + sphi*(dx-hx), 0, 0, _col
POLYVECTOR _x - cphi* (dx-hx) + sphi* (dy+hy), _y + cphi*(dy+hy) + sphi*(dx-hx), 0, spy, _col
POLYVECTOR _x + cphi* (dx+hx) + sphi*(dy+hy), _y + cphi*(dy+hy) - sphi*(dx+hx), spx, spy, _col
POLYVECTOR _x + cphi* (dx+hx) - sphi*(dy-hy), _y - cphi*(dy-hy) - sphi*(dx+hx), spx, 0, _col
ENDPOLY
ENDFUNCTION
@FUNCTION _oRotoPivot: _spr, _id, _x, _y, _angle
LOCAL sx, sy, rx,ry, px,py
LOCAL cosp, sinp
cosp=QCOS(_angle)
sinp=QSIN(_angle)
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
px = oSprites[_spr].hx
py = oSprites[_spr].hy
DEC px, sx
DEC py, sy
rx = px*cosp + py*sinp
ry = py*cosp - px*sinp
INC rx,sx
INC ry,sy
ROTOSPRITE _id, _x-rx, _y-ry, _angle
ENDFUNCTION
FUNCTION QSIN: x
IF OSprSettings.mathPre THEN RETURN SIN(x)
WHILE x>360.0; DEC x, 360.0; WEND
WHILE x180.0 THEN x = 180.0-x
x = x/57.296
x = 1.2732 * x -0.4053 * x * ABS(x)
x = 0.225*(x*ABS(x)-x)+x
RETURN x
ENDFUNCTION
FUNCTION QCOS: x
IF OSprSettings.mathPre THEN RETURN COS(x)
RETURN QSIN(x+90)
ENDFUNCTION
INLINE
float qInvSqrt(float x){
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
ENDINLINE
FUNCTION QSQR: y
INLINE
return 1.0f / qInvSqrt(y);
ENDINLINE
ENDFUNCTION
--- End code ---
bigsofty:
Very nice work indeed Andy! :)
AndyH:
New version, some improvements and bug fixes.
New oSprColl and oAnimColl commands which take into account the handles of a sprite during the collision but currently not the scale and rotation (will see about a solution to that at a later date) and not for Tilemaps yet. They take the ovine sprite Id as the parameters.
Tilemaps (anim frames) now can rotate and scale. If GLBasic supports the colour parameter for the ROTOZOOMANIM command (or similar) then will be able to add colour support too)
--- Code: (glbasic) ---// --------------------------------- //
// Project: A wrapper around SPRITES
// so never need to manage Id's directly
// --------------------------------- //
// Version: 1.001
// --------------------------------- //
// --------------------------------- //
// Please retain comments-free to use
// these functions in any freeware or
// commercial programs. Given to the
// community without any warranties
// of any kind. Please send updates
// or improvements to andyh@ovine.net
// --------------------------------- //
// TODO:
// - PRINT TEXT command (with color and rotation/scaling options)
// - Collision functions - decide to use anim or sprite collide, box collision, point collision with box, point collision with sprite or anim
// (note collisions only work with unscales/rotated sprites/anims)
// note also collisions must take into account the handle!
TYPE OSprType
id // Sprite Id
w;h // width and height
hx;hy // handle X and Y
maxframes // total num of frames,
// 0 = Tilemap (use DRAWANIM) - no scale, rotate or color support - but can be used to draw tilemaps quickly
// 1 = Single Sprite
// >1 = the count of sprite Id's used, ie: id+(maxFrames-1) == last sprite Id FOR this animation
ENDTYPE
GLOBAL oSprites[] AS OSprType
// this global type is used to store settings that modify the way sprites are drawn
TYPE OSpriteSettings
scale // scale for sprite
rotation // current rotation settings for sprite
color // RGB colour to apply (POLYVECTOR)
midHandle // auto-mid handle mode (T/F)
mathPre // maths precision (TRUE = use real COS/SIN, FALSE = use false SIN/COS)
ENDTYPE
GLOBAL OSprSettings AS OSpriteSettings
FUNCTION oInitialiseSprites:
OSprSettings.color = RGB(255,255,255)
OSprSettings.scale = 1.0
OSprSettings.rotation = 0
OSprSettings.midHandle = TRUE
OSprSettings.mathPre = TRUE
// TODO: to support point collision with Sprite/anim must create a sprite (id = 1) that is just 1 pixel
ENDFUNCTION
// starts at SPRITE ID = 1, Sprite Id = 0 is reserved for loading
@FUNCTION _GetNextSpriteID:
STATIC _oSprNextId
INC _oSprNextId, 1
RETURN _oSprNextId
ENDFUNCTION
// Get next oSprites, starts at 0
@FUNCTION _GetNextOSprID:
STATIC _oSprNextArrayId
INC _oSprNextArrayId, 1
RETURN (_oSprNextArrayId - 1)
ENDFUNCTION
// --------------------------------- //
// Project: Loading routines - only load
// sprites at start or when not in middle
// of a gameloop where you are updating the
// screen - do not load sprites directly
// with the GLB LOADSPRITE command
// --------------------------------- //
FUNCTION oLoadSprite: _file$
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
LOADSPRITE _file$, t.id
t.maxframes = 1 // defines a single sprite
GETSPRITESIZE t.id,t.w,t.h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
// used to reserve a sprite Id and slot for own use (eg: if you want to GRABSPRITE)
FUNCTION oReserveSprite:
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
t.maxframes = 1 // defines a single sprite
t.w = 0
t.h = 0
t.hx = 0
t.hy = 0
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
FUNCTION oLoadTiles: _file$, _w, _h
LOCAL t AS OSprType
LOCAL num
t.id = _GetNextSpriteID()
LOADANIM _file$, t.id, _w, _h
t.maxframes = 0 // defines a tilemap of frames in a sprite
t.w = _w
t.h = _h
//GETSPRITESIZE t.id,t.w,t.h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
RETURN _GetNextOSprID()
ENDFUNCTION
FUNCTION oLoadAnim: _file$, _w, _h, _maxframes
LOCAL t AS OSprType
LOCAL num
LOADANIM _file$, 0, _w, _h
LOCAL i
SETTRANSPARENCY RGB(255,0,128)
BLACKSCREEN
FOR i=0 TO _maxframes-1
DRAWRECT 0,0, _w+6,_h+6, RGB(255,0,128) // transparent colour
DRAWANIM 0, i, 3,3
LOCAL nextSprite
nextSprite = _GetNextSpriteID()
IF t.id = 0 THEN t.id = nextSprite
GRABSPRITE nextSprite, 3,3, _w,_h
NEXT
t.maxframes = _maxframes // defines a sequence of grabbed sprites
t.w = _w
t.h = _h
IF OSprSettings.midHandle
t.hx = t.w/2
t.hy = t.h/2
ELSE
t.hx = 0
t.hy = 0
ENDIF
DIMPUSH oSprites[], t
LOADSPRITE "", 0 // clear out temporary sprite from memory
BLACKSCREEN
//SETTRANSPARENCY RGB(255,0,128)
RETURN _GetNextOSprID()
ENDFUNCTION
// - Modifiers
FUNCTION oAutoMidHandle: x
OSprSettings.midHandle = x
ENDFUNCTION
FUNCTION oSetHandle: _sprId, _hx, _hy
oSprites[_sprId].hx = _hx
oSprites[_sprId].hy = _hy
ENDFUNCTION
FUNCTION oMidHandle: _sprId
oSprites[_sprId].hx = oSprites[_sprId].w/2
oSprites[_sprId].hy = oSprites[_sprId].h/2
ENDFUNCTION
FUNCTION oSetScale: _scale
OSprSettings.scale = _scale
ENDFUNCTION
FUNCTION oSetRotation: _rotation
OSprSettings.rotation = _rotation
ENDFUNCTION
FUNCTION oSetColor: _color
OSprSettings.color = _color
ENDFUNCTION
FUNCTION oSetPrecision: x
OSprSettings.mathPre = x
ENDFUNCTION
// do not use with TILEMAPS yet!
FUNCTION oAnimColl: _spr1, _f1, _x1, _y1, _spr2, _f2, _x2, _y2
LOCAL sprId1, sprId2
LOCAL dframe
IF _f1 > oSprites[_spr1].maxframes - 1
dframe = oSprites[_spr1].maxframes - 1
ELSE
dframe = _f1
ENDIF
sprId1 = oSprites[_spr1].id + dframe
IF _f2 > oSprites[_spr2].maxframes - 1
dframe = oSprites[_spr2].maxframes - 1
ELSE
dframe = _f2
ENDIF
sprId2 = oSprites[_spr2].id + dframe
LOCAL tmp
RETURN ANIMCOLL( sprId1, 0, _x1 - oSprites[_spr1].hx, _y1 - oSprites[_spr1].hy, sprId2, 0, _x2 - oSprites[_spr2].hx, _y2 - oSprites[_spr2].hy)
ENDFUNCTION
FUNCTION oSprColl: _spr1, _x1, _y1, _spr2, _x2, _y2
RETURN SPRCOLL( oSprites[_spr1].id, _x1 - oSprites[_spr1].hx, _y1 - oSprites[_spr1].hy, oSprites[_spr2].id, _x2 - oSprites[_spr1].hx, _y2 - oSprites[_spr1].hy)
ENDFUNCTION
FUNCTION oDrawSprite: _spr, _x, _y, _frame
SMOOTHSHADING FALSE
SELECT oSprites[_spr].maxframes
CASE 0 // -------- A tilemap --------
IF OSprSettings.scale = 1 AND OSprSettings.rotation = 0
DRAWANIM oSprites[_spr].id, _frame, _x - oSprites[_spr].hx, _y - oSprites[_spr].hy
ELSE
_oRotoZoomAnimPivot( _spr, _frame, _x, _y, OSprSettings.rotation, OSprSettings.scale)
ENDIF
DEFAULT // -------- A Sprite --------
LOCAL sprId
LOCAL dframe
IF _frame > oSprites[_spr].maxframes - 1
dframe = oSprites[_spr].maxframes - 1
ELSE
dframe = _frame
ENDIF
sprId = oSprites[_spr].id + dframe
IF OSprSettings.color RGB(255,255,255)
// must use polyvector to draw the sprite
_oRotoZoomPoly( _spr, sprId, _x, _y, OSprSettings.rotation, OSprSettings.scale, OSprSettings.color)
ELSEIF OSprSettings.scale = 1 AND OSprSettings.rotation 0
// must use ROTOSPRITE
_oRotoPivot( _spr, sprId, _x, _y, OSprSettings.rotation)
ELSEIF OSprSettings.scale 1 AND OSprSettings.rotation = 0
// must use ZOOMSPRITE
_oZoomSprite( _spr, sprId, _x, _y, OSprSettings.scale)
ELSEIF OSprSettings.scale 1 AND OSprSettings.rotation 0
// must use ROTOZOOMSPRITE
_oRotoZoomPivot( _spr, sprId, _x, _y, OSprSettings.rotation, OSprSettings.scale)
ELSE
// use DRAWSPRITE
DRAWSPRITE sprId, _x - oSprites[_spr].hx, _y - oSprites[_spr].hy
ENDIF
ENDSELECT
ENDFUNCTION
// TODO : Optimise this
@FUNCTION _oZoomSprite: _spr, _id, _x, _y, _scale
LOCAL sx, sy, hx,hy
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
hx = oSprites[_spr].hx
hy = oSprites[_spr].hy
DEC hx, sx
DEC hy, sy
hx = hx * _scale
hy = hy * _scale
ZOOMSPRITE _id, _x-hx-sx, _y-hy-sx, _scale, _scale
ENDFUNCTION
@FUNCTION _oRotoZoomPivot: _spr, _id, _x,_y, _angle, _scale
LOCAL sx, sy, rx,ry, px,py
LOCAL cosp, sinp
cosp=QCOS(_angle)
sinp=QSIN(_angle)
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
px = oSprites[_spr].hx
py = oSprites[_spr].hy
// reverse rotate pivot point arount center
// of sprite
DEC px, sx
DEC py, sy
rx = (px*cosp + py*sinp) * _scale
ry = (py*cosp - px*sinp) * _scale
// adjust center
INC rx,sx
INC ry,sy
// perform drawing
ROTOZOOMSPRITE _id, _x-rx, _y-ry, _angle, _scale
ENDFUNCTION
@FUNCTION _oRotoZoomAnimPivot: _spr, _frame, _x,_y, _angle, _scale
LOCAL sx, sy, rx,ry, px,py
LOCAL cosp, sinp
cosp=QCOS(_angle)
sinp=QSIN(_angle)
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
px = oSprites[_spr].hx
py = oSprites[_spr].hy
// reverse rotate pivot point arount center
// of sprite
DEC px, sx
DEC py, sy
rx = (px*cosp + py*sinp) * _scale
ry = (py*cosp - px*sinp) * _scale
// adjust center
INC rx,sx
INC ry,sy
// perform drawing
ROTOZOOMANIM oSprites[_spr].id, _frame, _x-rx, _y-ry, _angle, _scale
ENDFUNCTION
@FUNCTION _oRotoZoomPoly: _spr, _id, _x,_y, _angle, _scale, _col
LOCAL sinp, cosp, spw, sph, dx, dy
LOCAL hx, hy, dxp, dxm, dyp, dym
sinp = QSIN(_angle)
cosp = QCOS(_angle)
spw = oSprites[_spr].w-0.5
sph = oSprites[_spr].h-0.5
dx=spw/2
dy=sph/2
hx = (dx - oSprites[_spr].hx)
hy = (dy - oSprites[_spr].hy)
dxp = (dx+hx) * _scale
dxm = (dx-hx) * _scale
dyp = (dy+hy) * _scale
dym = (dy-hy) * _scale
STARTPOLY _id
POLYVECTOR _x - cosp * dxm - sinp * dym, _y - cosp * dym + sinp * dxm, 0.5, 0.5, _col
POLYVECTOR _x - cosp * dxm + sinp * dyp, _y + cosp * dyp + sinp * dxm, 0.5, sph, _col
POLYVECTOR _x + cosp * dxp + sinp * dyp, _y + cosp * dyp - sinp * dxp, spw, sph, _col
POLYVECTOR _x + cosp * dxp - sinp * dym, _y - cosp * dym - sinp * dxp, spw, 0.5, _col
ENDPOLY
ENDFUNCTION
@FUNCTION _oRotoPivot: _spr, _id, _x, _y, _angle
LOCAL sx, sy, rx,ry, px,py
LOCAL cosp, sinp
cosp=QCOS(_angle)
sinp=QSIN(_angle)
sx = oSprites[_spr].w / 2
sy = oSprites[_spr].h / 2
px = oSprites[_spr].hx
py = oSprites[_spr].hy
DEC px, sx
DEC py, sy
rx = px*cosp + py*sinp
ry = py*cosp - px*sinp
INC rx,sx
INC ry,sy
ROTOSPRITE _id, _x-rx, _y-ry, _angle
ENDFUNCTION
FUNCTION QSIN: x
IF OSprSettings.mathPre THEN RETURN SIN(x)
WHILE x>360.0; DEC x, 360.0; WEND
WHILE x180.0 THEN x = 180.0-x
x = x/57.296
x = 1.2732 * x -0.4053 * x * ABS(x)
x = 0.225*(x*ABS(x)-x)+x
RETURN x
ENDFUNCTION
FUNCTION QCOS: x
IF OSprSettings.mathPre THEN RETURN COS(x)
RETURN QSIN(x+90)
ENDFUNCTION
INLINE
float qInvSqrt(float x){
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
ENDINLINE
FUNCTION QSQR: y
INLINE
return 1.0f / qInvSqrt(y);
ENDINLINE
ENDFUNCTION
--- End code ---
D2O:
:)
Navigation
[0] Message Index
Go to full version