Codesnippets > Code Snippets

Z Project - universal screen size scaling system

(1/12) > >>

ampos:
Yes, it is (again) a UNIVERSAL SCREEN SIZE SCALING SYSTEM   :S

I had the idea to port ALL gfx commands to use polyvectors and be resolution independents, so we can code to just 1 resolution and will work at all platforms, using the (almost) fastest polyvector system, targetting any target resolution with/without aspect ratio.

To start, I have made the initialization function and ported the very first function, DRAWSPRITE. If one of each us made 1 function, it could be done real soon. I will copy your functions to this first post to keep it updated. Please, post the function you are going to do before so no one else does the same.

HOW-TO USE

In your proyect, you only need to change the CONSTANTS x_orig and y_orig with the values of the screen size you are coding for (the size that will draw at size 1:1).

Call the "z_init" function at the start of your program. If you dont want it to keep the aspect ratio of your graphics, call it with value=0

That's all, just call the functions as if they were original GLBasic commands, same syntax. (Note that I added the "color" param to the function as optional; as it is going to be used by polyvector anyway, just put it!)

You call the functions with "absolute" values, as if they were for a fixed screen size. The commands themself will scale your graphics to the device resolution, leaving black borders for unused screen.

In many console games (I recall some Wii examples) they draw a background that fills the entire screen and the game is drawn really in a center 4:3 "window" in the center of the screen. An iPAD (1024x768) resolution game will look similar in a 800x480 android device. If you do not want the screen to be filled with black borders, just do this:


--- Code: GLBasic ---CLEARSCREEN -1 //if the entire screen is going to be redrawn, do not clear it before!
...your game here
SC()   //use this instead of showscreen

function SC:  //this routine will fill your entire screen with a nice background
   showscreen
   stretchsprite background,0,0,x_res,y_res
endfunction
 
Example:
   x_orig=1024;z_drawsprite id,512,0 will be always drawn at the center of the screen, even at a 320x240 screen resolution.


--- Code: GLBasic ---// --------------------------------- //
// Project: ProjectoZ
// Start: Tuesday, October 25, 2011
// IDE Version: 10.118

GLOBAL x_offset,y_offset                //offset to add to X&Y to display correctly
GLOBAL x_res,y_res                              //X&Y real screen size
GLOBAL x_zoom,y_zoom                    //zoom to scale sprites and so
GLOBAL x_orig=768,y_orig=1024   //the screen size our app is designed for
GLOBAL single_sheet=0                   //1 IF all sprites in a single sheet

FUNCTION initZ: keep_ratio=0
        LOCAL z

        GETSCREENSIZE x_res,y_res

        x_zoom=x_res/x_orig
        y_zoom=y_res/y_orig

        IF keep_ratio<>0
                z=MIN(x_zoom,y_zoom)
                x_zoom=z
                y_zoom=z
                x_offset=(x_res-(x_orig*x_zoom))/2
                y_offset=(y_res-(y_orig*y_zoom))/2
                IF x_offset<1 THEN x_offset=0
                IF y_offset<1 THEN y_offset=0

        ENDIF

        init_SC()

ENDFUNCTION

FUNCTION z_drawsprite: num%,x%,y%,color=0xFFFFFF
        LOCAL sx,sy,x1,y1,x2,y2

        GETSPRITESIZE num,sx,sy

        x1=x_offset+(x*x_zoom)
        x2=sx*x_zoom
        y1=y_offset+(y*y_zoom)
        y2=sy*y_zoom

//      STRETCHSPRITE num,x1,y1,x2,y2

        STARTPOLY num
        POLYVECTOR x1,y1,0,0,color
        POLYVECTOR x1,y1+y2,0,sy,color
        POLYVECTOR x1+x2,y1+y2,sx,sy,color
        POLYVECTOR x1+x2,y1,sx,0,color
        ENDPOLY

ENDFUNCTION

FUNCTION z_drawanim: num%,frame%,x%,y%,w%,h%,color=0xFFFFFF
        LOCAL sx,sy,x1,y1,x2,y2,ancho,alto,xa,ya

        GETSPRITESIZE num,sx,sy

        x1=x_offset+(x*x_zoom)
        x2=w*x_zoom
        y1=y_offset+(y*y_zoom)
        y2=h*y_zoom

        ancho=sx/w;alto=sy/h
        ya=INTEGER(frame/ancho)*h
        xa=MOD(frame,ancho)*w

//      STRETCHANIM num,frame,x1,y1,x2,y2

        IF single_sheet=0 THEN STARTPOLY num
        POLYVECTOR x1,y1,xa,ya,color                    //TL
        POLYVECTOR x1,y1+y2,xa,ya+h,color               //BL
        POLYVECTOR x1+x2,y1+y2,xa+w,ya+h,color  //
        POLYVECTOR x1+x2,y1,xa+w,ya,color
        IF single_sheet=0
                ENDPOLY
        ELSE
                POLYNEWSTRIP
        ENDIF
ENDFUNCTION

FUNCTION z_rotozoomanim: num%,frame%,x%,y%,w%,h%,ang,size,color=0xFFFFFF
        LOCAL sx,sy,x1,y1,x2,y2,ancho,alto,xa,ya,x3,x4,y3,y4,xcos,ysin,xs,ys,sw,sh

        GETSPRITESIZE num,sx,sy
        sw=w;sh=h

        x=x_offset+(x*x_zoom)-(((w*size)-w)/2)
        w=w*x_zoom*size
        y=y_offset+(y*y_zoom)-(((h*size)-h)/2)
        h=h*y_zoom*size
        INC x2,x1;INC y2,y1

        ancho=sx/sw;alto=sy/sh
        ya=INTEGER(frame/ancho)*sh
        xa=MOD(frame,ancho)*sw

                h=h/2
                w=w/2
                INC x,w
                INC y,h

                x1 = x
                y1 = y
                x2 = x
                y2 = (y + h)
                x3 = (x + w)
                y3 = y
                x4 = (x + w)
                y4 = (y + h)

                xcos = tCOS(ang)
                ysin = tSIN(ang)

                x1 = x - (xcos * w) - (ysin * h)
                y1 = y - (xcos * h) + (ysin * w)

                x2 = x - (xcos * w) + (ysin * h)
                y2 = y + (xcos * h) + (ysin * w)

                x3 = x + (xcos * w) - (ysin * h)
                y3 = y - (xcos * h) - (ysin * w)

                x4 = x + (xcos * w) + (ysin * h)
                y4 = y + (xcos * h) - (ysin * w)

                SELECT single_sheet
                        CASE 0
                                STARTPOLY num
                                        POLYVECTOR x1, y1, xa, ya,color                         //TL
                                        POLYVECTOR x2, y2, xa, ya + sh,color            //BL
                                        POLYVECTOR x4, y4, xa + sw, ya + sh,color       //BR
                                        POLYVECTOR x3, y3, xa + sw, ya,color            //TR
                                ENDPOLY
                        CASE 1
                                POLYVECTOR x2, y2, xa, ya + sh,color            //BL
                                POLYVECTOR x1, y1, xa, ya,color                         //TL
                                POLYVECTOR x4, y4, xa + sw, ya + sh,color       //BR
                                POLYVECTOR x3, y3, xa + sw, ya,color            //TR
                                POLYNEWSTRIP
                ENDSELECT

ENDFUNCTION

FUNCTION z_print: t$,x,y,font=100,centered=1,zoom=1,color=0xFFFFFF,underline=0,italic=0
        LOCAL fx,fy,l,c$,tx,ty,dx,dy,fxz,fyz,t1,t2,t3,t4,tl
        LOCAL line_width=2              //width of the underline line in pixels at zoom 1 (100%)
        LOCAL outline=2                 //width of the outline in underline in pixels at zoom 1 (100%)
        LOCAL und_pos=.9                //vertical position of underline (in % of Font Y size)
        LOCAL ital_ang=.5               //inclination of font (in % of font X size)

        GETSPRITESIZE font,fx,fy
        fx=fx/16;fy=fy/16                       //change to fy/8 if you dont use full charset fonts
        fxz=fx*zoom*x_zoom;fyz=fy*zoom*y_zoom
        tl=LEN(t$,1)*zoom*x_zoom

        x=x_offset+(x*x_zoom)
        y=y_offset+(y*y_zoom)

        DEC x,(LEN(t$,1)*zoom*centered*x_zoom)/2

        IF underline=1  
                t1=line_width*(zoom*y_zoom);IF t1<1 THEN t1=1
                t2=fxz/4
                t3=fyz*und_pos
                t4=outline*(zoom*x_zoom);IF t4<1 THEN t4=1

                STARTPOLY   //this can be changed with a call to z_drawline...
                POLYVECTOR x-t2-t4,y+t3-t4,0,0,0
                POLYVECTOR x-t2-t4,y+t3+t1+t4,0,0,0
                POLYVECTOR x+t2+tl+t4,y+t3+t1+t4,0,0,0
                POLYVECTOR x+t2+tl+t4,y+t3-t4,0,0,0
                ENDPOLY

                STARTPOLY
                POLYVECTOR x-t2,y+t3,0,0,color
                POLYVECTOR x-t2,y+t3+t1,0,0,color
                POLYVECTOR x+t2+tl,y+t3+t1,0,0,color
                POLYVECTOR x+t2+tl,y+t3,0,0,color
                ENDPOLY

        ENDIF

    italic=italic*zoom*fx*ital_ang*x_zoom
        STARTPOLY font,2
        FOR n=0 TO LEN(t$)-1
                c$=MID$(t$,n,1)
                l=ASC(c$)

                ty=ASR(l,4)
                tx=INTEGER(MOD(l,ty*16))
                dx=tx*fx
                dy=ty*fy

                POLYVECTOR x,y+fyz,dx,dy+fy,color                       //BL
                POLYVECTOR x+italic,y,dx,dy+1,color                     //TL
                POLYVECTOR x+fxz,y+fyz,dx+fx,dy+fy,color        //BR
                POLYVECTOR x+fxz+italic,y,dx+fx,dy+1,color      //TR
                POLYNEWSTRIP
                INC x,LEN(c$,1)*zoom*x_zoom
        NEXT
        ENDPOLY
ENDFUNCTION

FUNCTION z_drawline: x1,y1,x2,y2,color=0xFFFFFF,width=1
        LOCAL w=(x2-x1)*x_zoom
        LOCAL h=(y2-y1)*y_zoom

        x1=x_offset+(x1*x_zoom)
        y1=y_offset+(y1*y_zoom)
        x2=x_offset+(x2*x_zoom)
        y2=y_offset+(y2*y_zoom)

        width=width*x_zoom
        glLineWidth (width)
        DRAWLINE x1,y1,x2,y2,color
        glLineWidth(1)

//      STARTPOLY
//      POLYVECTOR x1,y1,0,0,color
//      POLYVECTOR x1+w,y1+h,0,0,color
//      POLYVECTOR x1+w+1,y1+1+h,0,0,color
//      POLYVECTOR x1+1,y1+1,0,0,color
//      ENDPOLY

ENDFUNCTION

FUNCTION z_drawrect: x,y,w,h,color=0xFFFFFF

        x=x_offset+(x*x_zoom)
        y=y_offset+(y*y_zoom)
        w=w*x_zoom
        h=h*y_zoom

        STARTPOLY
        POLYVECTOR x,y,0,0,color
        POLYVECTOR x,y+h,0,0,color
        POLYVECTOR x+w,y+h,0,0,color
        POLYVECTOR x+w,y,0,0,color
        ENDPOLY

ENDFUNCTION

INLINE
#define OGL                             ::
typedef float           GLfloat;
ENDINLINE

INLINE
} extern "C" { void __stdcall glLineWidth( GLfloat width );; }; namespace __GLBASIC__ {
ENDINLINE
FUNCTION glLineWidth: width
        INLINE
                OGL glLineWidth(width);
        ENDINLINE
ENDFUNCTION


INLINE
        }       //  + + + A T T E N T I O N + + +
                // int __a__ needs to be a n^2 value.
                // Higher values give better precision
                // but larger lookup tables as well!

                const unsigned int __a__ = 131072 ;
                const DGInt __b__ = (360.0 / __a__) ;
                const unsigned int __c__ = (__a__ - 1) ;
                DGInt _sin_tbl_[__c__] ;
                DGInt _cos_tbl_[__c__] ;
                const DGInt __d__ = (1 / __b__);
        namespace __GLBASIC__ {
ENDINLINE

FUNCTION init_SC:
        INLINE
                for(int i=0; i < __c__; ++i)
                {
                        _sin_tbl_[i] = SIN( i * __b__ ) ;
                        _cos_tbl_[i] = COS( i * __b__ ) ;
                }
        ENDINLINE
ENDFUNCTION // INIT_SIN_COS_TABLES

// ------------------------------------------------------------- //
// ---  TCOS  ---
// ------------------------------------------------------------- //
FUNCTION tCOS: x        // in degrees
        INLINE
                return _cos_tbl_[ (int)(x * __d__) & __c__ ] ;
        ENDINLINE
ENDFUNCTION // TCOS



// ------------------------------------------------------------- //
// ---  TSIN  ---
// ------------------------------------------------------------- //
FUNCTION tSIN: x  // in degrees
        INLINE
                return _sin_tbl_[ (int)(x * __d__) & __c__ ] ;
        ENDINLINE
ENDFUNCTION // TSIN




 
HOW TO MAKE FUNCTIONS

I think that the z_drawsprite function is easy enough to understand, but to clarify how to calculate target resolutions

Initial X & Y coordinates are calculated with


--- Code: GLBasic ---        x1=x_offset+(x*x_zoom)
        y1=y_offset+(y*y_zoom)
You have to use, mandatory, x_offset & y_offset, as the init function will set this values correctly if the user wants or not "aspect ratio lock"

The target sprite sizes are easily calculated too with


--- Code: GLBasic ---        x2=sx*x_zoom
        y2=sy*y_zoom
 
being sx and sy, current sprite size.

0.01 - Initial release
        - DRAWSPRITE
0.02 - PRINT (with attributes)
0.03 - DRAWLINE
          DRAWRECT
          Added a "+1" on z_print text print part to fix gfx glitches
0.04 - DRAWANIM (it needs in the function the size of the anim frame)
          ROTOZOOMANIM (it needs in the function the size of the anim frame
          Uses tCOS and tSIN for faster SIN/COS
          Updated PRINT to use POLYNEWSTRIP
          The variable SINGLESHEET can be used to use POLYNEWSTRIP when drawing multiple sprites from a single sheet.
          The DRAWLINE command has the option WIDTH, through OpenGL itself.
0.05- Minor update. Removed some old lines. Add more explanations for use.
0.06- RotoZoomAnim had a bug

Wampus:
Good stuff. Can be used as a basis for scalable control schemes too.

ampos:
Added  Z_PRINT.

Nobody wants to contribute?

ampos:
I have added more things:

DRAWANIM, that needs also the size of the sprite animation frame.

ROTOZOOMANIM, also need the frame size. It uses also tCOS and tSIN functions for speed.

The DRAWLINE get a WIDTH option, that is set using OpenGL.

PRINT uses POLYNEWSTRIP, making it much more faster.

Some functions read the global variable SINGLESHEET. If =1, they will use POLYNEWSTRIP, making it MUCH faster if you are drawing multiple sprites from the same sprite sheet.

Example:

You have a sheet with multiple flowers pictrures. You normally will use this to draw:


--- Code: GLBasic ---FOREACH f IN flowers()
   Z_DRAWSPRITE f.id,f.x,f.y
NEXT
SHOWSCREEN
That will be


--- Code: GLBasic ---FOREACH f IN flowers()
   Z_DRAWANIM f.id,f.frame,f.x,f.y
       {STARTPOLY f.id
       ...blah...blah POLYVECTOR
       ENDPOLY}
NEXT
SHOWSCREEN
Ok, the SINGLESHEET has to be done this way:


--- Code: GLBasic ---SINGLESHEET=1
STARTPOLY id,2
FOREACH f IN flowers()
   Z_DRAWSPRITE f.id,f.x,f.y
NEXT
ENDPOLY
SHOWSCREEN
Will translate into:


--- Code: GLBasic ---SINGLESHEET=1
STARTPOLY id,2
FOREACH f IN flowers()
   Z_DRAWSPRITE f.id,f.x,f.y
      {blah, blah... POLYVECTOR
      NEWPOLYSTRIP}
NEXT
ENDPOLY
SHOWSCREEN
Probably I will not create DRAWANIM or ROTOSPRITE as it can be used easily in ROTOZOOMANIM with frame=0

bigsofty:
Congrats and thanks Ampos, great stuff!  :good:

Navigation

[0] Message Index

[#] Next page

Go to full version