BASIC

Author Topic: Little autoscaling system with a virtual Image (suitable for Android).  (Read 6817 times)

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3482
    • View Profile
    • Space Fractal
Rater to write a story about this one, you can instead read about it in this thread, who started it (there is a project in that link, so im did not add this here again):
http://www.glbasic.com/forum/index.php?topic=9834.msg85756#msg85756

Here is code which would do scaling a virtual image to any resolution and uses either side letterbox or top/bottom. If the scaling is close to a perfect scaling, its would been pefectly that and might crop few pixels.

This code using a 428x240 virtual image, but could been use any virtual resolution. Also when you have scaling value, you could eventuelly expand this code to could uses the whole image, if you game supports that (examping a scrolling game). Im have not do that, but its give you a idea.

The main idea here is using PaintImage() which perfecm all scaling calcuations for you, before checking mousestate and for drawing the virtual screen. Hence its a function.

Code: GLBasic [Select]
// ----------------------------------------------------------------------------- CONFIG VARIABLES
GLOBAL VW = 428                                 // The virtual Width screen
GLOBAL VH = 240                                 // The virtual Height screen

// ----------------------------------------------------------------------------- DECLARE VARIABLES
GLOBAL FramesPerSecond                          // Helmos fps Routine
GLOBAL sx,sy                                    // Android Get Screen Size (pixels)
GLOBAL PX#, PY#, PW#, PH#                       // The calculate rectangle
GLOBAL sx, sy                                   // The screen resolution
GLOBAL scaling                                  // perform scaling value

// ----------------------------------------------------------------------------- SETUP SCREEN
SETSCREEN 960, 640, 0                           // a test resolution (this skips on Android, but nice for testing on Windows
SYSTEMPOINTER TRUE                              // Show mouse
LIMITFPS 60                                     // Vertical sync limit fps
AUTOPAUSE TRUE                                  // Set pause when lost focus

// ----------------------------------------------------------------------------- LOAD VISUAL ASSETS
LOADSPRITE "Media/TEST.bmp",1                   // Background image test

// ----------------------------------------------------------------------------- SET OUTPUT SCREEN / TOUCH
//      --- ANDROID SETS
CREATESCREEN 1,200,VW,VH                       // Create virtual screen
GETSCREENSIZE sx,sy                            // Get Screen Size of the current window
scaling=sx/VW                                  // set scaling for any resolution, letter boxed top/bottom
IF scaling*VH>sy THEN scaling=sy/VH            // set scaling for any resolution, letter boxed side

// round up to a perfect scaling, if its very close
LOCAL sc=INTEGER(FMOD(scaling, 1)*10)          // a integer reminder of a float.
IF sc<>0 THEN scaling=scaling+0.025            // make sure the image is used the whole screen and not lost one px.
IF sc=9 THEN scaling=INTEGER(scaling+0.1)      // if very close to a perfect scaling (like 1.9, 2.9 etc), perfect scaling it.
IF sc=4 THEN scaling=INTEGER(scaling)+0.5      // if very close to a half pixel perfect scaling (like 1.4, 2.4 etc).


// ----------------------------------------------------------------------------- MAIN GAME LOOP
WHILE TRUE
// ----------------------------------------------------------------------------- DISPLAY
        // --- SET VIRTUAL SCREEN
        ALPHATESTING 0.0                           // GLBv12 alpha on
        SMOOTHSHADING FALSE                        // Hard pixels
        USESCREEN 1                                // Set Virtual screen buffer

//  --- DRAW TEST IMAGE
        CLEARSCREEN RGB(0, 0, 0)
        DRAWSPRITE 1,0,0

//  --- CHECK MOUSESTATE BASED ON THE VIRTUAL SCREEN ---
        PaintImage(200, 0, 0, 0, 0, scaling, 0, 0)  // calculate retangle of the virtual image placement (but its dont draw it)
       
        LOCAL xpos#, ypos#, button1, button2        // Declare some local variables
        MOUSESTATE xpos, ypos, button1, button2     // check mousestate
        xpos#=(xpos-PX)/scaling                     // calculate mousestate based on virtual image instead of surface
        ypos#=(ypos-PY)/scaling                     // calculate mousestate based on virtual image instead of surface

        IF xpos<0 THEN xpos=0                       // check edges of the virtual image
        IF ypos<0 THEN ypos=0
        IF xpos>VW THEN xpos=VW
        IF ypos>VH THEN ypos=VH

        xpos=INTEGER(xpos)                          // final xpos mouse position
        ypos=INTEGER(ypos)                          // final ypos mouse position


//      --- PRINT DEBUG INFO
        FramesPerSecond=FPS()
        PRINT "SCALING     : "+scaling,117,24
        PRINT "GETSCREEN X : "+sx,117,34
        PRINT "GETSCREEN Y : "+sy,117,44
        PRINT "MOUSE X     : "+xpos,117,56
        PRINT "MOUSE Y     : "+ypos,117,66
        PRINT "FPS         : "+FramesPerSecond,117,78


// ----------------------------------------------------------------------------- DISPLAY [END]

// ----------------------------------------------------------------------------- OUTPUT AND SCALE
        USESCREEN -1         // Set Backbuffer
        SMOOTHSHADING FALSE  // Hard pixels

        // Paint the image
        PaintImage(200, 0, 0, 0, 0, scaling, 0, 1)  

    // this is a example how to check, if its have been a letter boxed viw.
        // draw a line to the border, if its a side letter box
        IF PX>0
                DRAWRECT PX-scaling, 0, scaling+0.5, PH, RGB(255, 255, 255)
                DRAWRECT PX+PW, 0, scaling+0.5, PH, RGB(255, 255, 255)
        ENDIF

        IF PY>0
        // draw a line to the border, if its a top/bottom letter box
                DRAWRECT 0, PY-scaling, PW, scaling+0.5, RGB(255, 255, 255)
                DRAWRECT 0, PY+PH, PW, scaling+0.5, RGB(255, 255, 255)
        ENDIF

// ----------------------------------------------------------------------------- OUTPUT AND SCALE [END]
SHOWSCREEN
WEND
// ----------------------------------------------------------------------------- MAIN GAME LOOP [END]

FUNCTION FPS:
        // Created by Hemlos (a long time ago), updated Aug.7,2014
        STATIC OSTimeCurrent$, OSTimePrevious$, FPSBuffer
        LOCAL FramesPerSecond
        OSTimePrevious$ = OSTimeCurrent$
        INC FPSBuffer, 1
        OSTimeCurrent$ = PLATFORMINFO$("TIME")
        IF OSTimePrevious$ <> OSTimeCurrent$
                FramesPerSecond = FPSBuffer
                FPSBuffer = 0
        ENDIF
        RETURN FramesPerSecond
ENDFUNCTION

// id     = id of the image
// x#     = x pos of the image
// y#     = y pos of the image
// xspot  = 0 = center, -1 = left, 1 = right hotspot
// yspot  = 0 = center, -1 = top, 1 = bottom hotspot
// zoom   = scaling
// mirror = should the image been mirrored?
// draw   = 1 draw the image after calculate the retangle
//          0 do NOT draw the image, but just calculate the retangle)
FUNCTION PaintImage: id, x#, y#, xspot, yspot, zoom#, mirror=0, draw=1
        // get size of the incoming sprite
        LOCAL h#, w#
        GETSPRITESIZE id, w, h
        IF w<1 OR h<1
                RETURN 0
        ENDIF

        // calculate rectangle of the sprite positions
        IF xspot=-1 THEN PX=x#+0.5
        IF xspot=0 THEN PX=sx/2.0-(w#*zoom#/2.0)+x#+0.5
        IF xspot=1 THEN PX=sx-w#*zoom#-x#+0.5
        IF yspot=-1 THEN PY=y#
        IF yspot=0 THEN PY=sy/2.0-(h*zoom#/2.0)+y#
        IF yspot=1 THEN PY=sy-h#*zoom#-y#

        // checks if the rectangle is on the screen
        IF PY-PH>sy OR PX-PW>sx OR PY<-h*zoom*1.2 OR PX<-w*zoom*1.2 THEN RETURN 0

        // perform scaling to the image.
        PW=INTEGER(w*zoom#)
        PH=INTEGER(h*zoom#)

        // should the image draw or not? usable for rectangle calculate for ingame controls.
        IF draw=0 THEN RETURN 0


        // draw the image (using STRETCHSPRITE)
        IF zoom<1 THEN SMOOTHSHADING TRUE
        IF mirror=1
                STRETCHSPRITE id, PX, PY, -ABS(PW), ABS(PH)
        ELSE
                STRETCHSPRITE id, PX, PY, ABS(PW), ABS(PH)
        ENDIF
                IF zoom<1 THEN SMOOTHSHADING FALSE
        RETURN 1
ENDFUNCTION
 
« Last Edit: 2014-Aug-08 by spacefractal »
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
Good going!

Just a bump here so people keep this in mind. ;)

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3482
    • View Profile
    • Space Fractal
im have just update the code, so the virtual resolution can been set in a variable, start in the code (here of course testing with 428x240).

Mousepos will still correspons to the virtual image retangle, not the full screen. That why im used PaintImage() for calculate the mouse position. Its was to calculate the retangle, where the game would paint the virtual image on the screen.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
Great, this is much smaller, smarter and cleaner code then what I had before. :good:

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1579
  • Particle Hawk
    • View Profile
heh i forgot about that FPS() function, i made several styles. Glad to see it does the trick on android.
IMO its a cheap trick, as it doesnt actually track time, but rather waits for the time on the OS to tick a second.
I like it though for several reasons;
For one thing, it uses the OS to keep track of time as opposed to the program doing it.
The math load on the cpu is minimal as opposed to tracking milliseconds, as its just an incrementing integer here.
And the update happens once per second.

I cleaned it up, optimized it for you..
I made the updater LOCAL, this is an optimization.
A compliation optimization too, got rid of the semicolons.


Code: GLBasic [Select]
FUNCTION FPS:
        // Created by Hemlos (a long time ago), updated Aug.7,2014
        STATIC OSTimeCurrent$, OSTimePrevious$, FPSBuffer
        LOCAL FramesPerSecond
        OSTimePrevious$ = OSTimeCurrent$
        INC FPSBuffer, 1
        OSTimeCurrent$ = PLATFORMINFO$("TIME")
        IF OSTimePrevious$ <> OSTimeCurrent$
                FramesPerSecond = FPSBuffer
                FPSBuffer = 0
        ENDIF
        RETURN FramesPerSecond
ENDFUNCTION
 
« Last Edit: 2014-Aug-08 by Hemlos »
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
Yep, I borrowed it from you from some older thread. ;/ ;)

I find it usefull while I understand nothing that goes on, but it works fine on all OSes.
I use it often on my snippets down the snippet section and the game I´m doing while in development.
I hope you don´t mind, it is really nice!

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1579
  • Particle Hawk
    • View Profile
If you use it, use the one i updated above.
I dont mind at all, i am a firm believer in sharing code for especially for learning purposes.

There are other ways of doing it too...if your program  needs to syncronize across different libs per say, you should use one that tracks the milliseconds.

edit: For instance, my 3d particle engine requires a very precise tracker reporting from the end of the main loop before the showscreen.
« Last Edit: 2014-Aug-08 by Hemlos »
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
Thanks a lot for sharing Hemlos, I really like it and even better now optimized by its own owner! :good: :booze:
Super thanks!

Hey, why don´t you put it on its own thread? I´m sure this deserves it. ;)

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1579
  • Particle Hawk
    • View Profile
im sure there are some threads with it...id have to dig around first before doing that.

aboout linux mint 17 test....itll run a terminal program, but not an opengl window.....bug?
In GLbasic, i did set the options and multiplatform to be linux...i attached it here
and here is a screenshot of it running in windows attached as well
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
oh my...that is a lot different from what I had on osx...I´d need sometime to think...heck maybe I can get an old hd or linux-on-pendrive to help this front.
Can we take this discussion to a more specific thread? We could use your latest thread on linux or open a newer one, your call.

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3482
    • View Profile
    • Space Fractal
im have updatedd the post with the update to the fps function. im diddent touch this one really and was not a part of this snippet.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1579
  • Particle Hawk
    • View Profile
I dont know...let me know..It seems to be based on your other thread Erico
Merge?

what do you think SF?
« Last Edit: 2014-Aug-08 by Hemlos »
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
Oh no, I mean your lib is perfect.

What I take as bad, is the image you uploaded from the virtual screen apk test on another thread, that one is not using this code spacefractal upgraded here.
But is should work if you did the changes I mentioned a couple posts before and I´m pretty sure there should not be any red parts into it.

So I wonder now if virtual screens are working on linux. I have to figure this out myself.
I will create a post about it or invade your linux post ;/

Thanks for testing! And super thanks for the FPS lib!

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3482
    • View Profile
    • Space Fractal
im seperated my version of the virtual screen, so other easier could search and find it, which was based on the code Erico did for the Android Resolution test, but cleaned it up, so its can been used in any resolution rather than doing hardcoded one, used with his style in code.

So for Android, you should newer hardcode resolutions, which can go wrong. Its even better if its used with Android Extras (its not that hard to uses the basic features and the bug fixes im fixed).

The FPS code was really not a part of this code, but im just added it anyway for some reason, and updated my post to reflect that.

For the Resolution test code and pictures, Erico gave and asked us to test, should been posted in his thread, not mine. Its uses two differents of code.....
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4116
    • View Profile
    • Portfolio
It is fine Space!

It even got Hemlos to update his lib! :) :good:  :P

My concern is actually on the virtual screen on Linux here and how a GLB game goes on Linux.
Give me a while to set up a linux distro to try figure this out.

Mac/Linux/PC output of a tool or a game is really important imho. I gotta check what is going on