Stepping

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
715
Am very happy with learning the Cerberus language now but what am I doing wrong here?
I'm using floats here everywhere but still there is some kind of stepping effect where you can see when you go into the scene using left and right keys.

First x changes, then y changes, again x.., instead of gradually both scale at the same time?

Code:
Strict

Import mojo2

#GLFW_WINDOW_WIDTH = 0
#GLFW_WINDOW_HEIGHT = 0
#HTML5_CANVAS_WIDTH = 1440
#HTML5_CANVAS_HEIGHT = 900

Function Main:Int()
    New Game
    Return 0
End

Class Game Extends App
   
    Field canvas:Canvas
    Field scaling:Float=10
    Field screen2:Image
    Field screen2canvas:Canvas
    Field nwidth:Float, nheight:Float
    Field startx:float, starty:float
    Field vwidth:Float = 640
    Field vheight:Float = 400
    Field awidth:Float
    Field aheight:Float
    Field enemeies:Int = 120
   
    Method OnCreate:Int()
   
        awidth=DesktopMode().Width
        aheight=DesktopMode().Height          
        SetDeviceWindow awidth,aheight,1
        awidth=DeviceWidth()
        aheight=DeviceHeight()
       
        canvas=New Canvas
        screen2=New Image(vwidth,vheight,0,0,0)
        screen2.SetFlagsMask(screen2.Managed)
        screen2canvas=New Canvas(screen2)
        screen2canvas.Clear 0,0.4,0
       
        screen2canvas.DrawRect 0,0,16,16
        screen2canvas.Flush  
        SetSwapInterval 1
        SetUpdateRate 0      
        Return 0
    End
   
     Method OnUpdate:Int()

        If KeyDown(KEY_LEFT) Then scaling = scaling - 0.02
        If KeyDown(KEY_RIGHT)Then scaling = scaling + 0.02
        If scaling < 0.0001 Then scaling = 0.0001 ' Avoid zero
        If scaling > 16 Then scaling = 16

        If KeyHit(KEY_ESCAPE) Then EndApp
        If JoyHit(JOY_BACK) Error ""
        Return 0      
    End
   
    Method OnRender:Int()

        canvas.Clear 0,0,0
        nwidth = Float(Float(awidth)/Float(vwidth))
        nheight = Float(Float(aheight)/Float(vheight))
        If nwidth > nheight Then nwidth = nheight
        If nheight > nwidth Then nheight = nwidth
        startx = (awidth-(vwidth*nwidth)) / 2
        starty = (aheight-(vheight*nheight)) / 2
       
        screen2canvas.SetColor 1,1,1
        screen2canvas.SetColor 0,0,0
        screen2canvas.Flush

        canvas.SetColor 1,1,1
        canvas.DrawRect startx,starty,nwidth*640,nheight*400,screen2,0,0,320/(scaling/2),200/(scaling/2)
        canvas.Flush
        Return 0
    End

End
 
Last edited:

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,035
Its a problem with the rounding to an integer value:

320/(scaling/2)
200/(scaling/2)

Width and Height of the source image don't change at the same time when the scaling changes.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
715
Thanks. Okay this is what I came up as a solution, it loops small changes until both x and y has changed before it exits the loop.
It still has a weird motion that I cannot understand.
Code:
Strict

Import mojo2

#GLFW_WINDOW_WIDTH = 0
#GLFW_WINDOW_HEIGHT = 0
#HTML5_CANVAS_WIDTH = 1440
#HTML5_CANVAS_HEIGHT = 900

Function Main:Int()
    New Game
    Return 0
End

Class Game Extends App
 
    Field canvas:Canvas
    Field scaling:Float=10
    Field screen2:Image
    Field screen2canvas:Canvas
    Field nwidth:Float, nheight:Float
    Field startx:float, starty:float
    Field vwidth:Float = 640
    Field vheight:Float = 400
    Field awidth:Float
    Field aheight:Float
    Field enemeies:Int = 120
    Field scalex:Int = 0
    Field scaley:Int = 0
 
    Method OnCreate:Int()
 
        awidth=DesktopMode().Width
        aheight=DesktopMode().Height        
        SetDeviceWindow awidth,aheight,1
        awidth=DeviceWidth()
        aheight=DeviceHeight()
     
        canvas=New Canvas
        screen2=New Image(vwidth,vheight,0,0,0)
        screen2.SetFlagsMask(screen2.Managed)
        screen2canvas=New Canvas(screen2)
        screen2canvas.Clear 0,0.4,0
     
        screen2canvas.DrawRect 0,0,16,16
        screen2canvas.Flush
        SetSwapInterval 1
        SetUpdateRate 0    
                scalex =  320/(scaling/2)
        scaley =  200/(scaling/2)
        Return 0
    End
 
     Method OnUpdate:Int()
       
        If KeyDown(KEY_LEFT)
          Local oldx:Int = scalex
          Local oldy:Int = scaley
          Repeat  
               scaling = scaling - 0.001
                  scalex =  320/(scaling/2)
               scaley =  200/(scaling/2)
             Until (oldx<>scalex) And (oldy <> scaley)
         Endif

        If KeyDown(KEY_RIGHT)
           Local oldx:Int = scalex
          Local oldy:Int = scaley
          Repeat  
              scaling = scaling + 0.001
                  scalex =  320/(scaling/2)
                  scaley =  200/(scaling/2)
          Until (oldx<>scalex) And (oldy <> scaley)
        Endif
       
        If scaling < 0.0001 Then scaling = 0.0001 ' Avoid zero
        If scaling > 16 Then scaling = 16

        If KeyHit(KEY_ESCAPE) Then EndApp
        If JoyHit(JOY_BACK) Error ""
        Return 0    
    End
 
    Method OnRender:Int()

        canvas.Clear 0,0,0
        nwidth = Float(Float(awidth)/Float(vwidth))
        nheight = Float(Float(aheight)/Float(vheight))
        If nwidth > nheight Then nwidth = nheight
        If nheight > nwidth Then nheight = nwidth
        startx = (awidth-(vwidth*nwidth)) / 2
        starty = (aheight-(vheight*nheight)) / 2
     
        screen2canvas.SetColor 1,1,1
        screen2canvas.SetColor 0,0,0
        screen2canvas.Flush
             
        canvas.SetColor 1,1,1
        canvas.DrawRect startx,starty,nwidth*640,nheight*400,screen2,0,0, scalex,scaley
        canvas.Flush
        Return 0
    End

End
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,035
I would use 1 scalefactor for both X and Y, not separate ones that are calculated from different values.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
715
What do you mean? I use one scalefactor, those other two named x & y are just variables
to check that they are not allowed to be update until both have changed.

I'm not sure if this is a good way dealing with it I feel its a problem that's worth spending more time think about.
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,035
I mean you have a different scale factor/value/variable for x and y. Just use the same for both.
 

Phil7

Administrator
CX Code Contributor
3rd Party Tool Dev
Joined
Jun 26, 2017
Messages
602
I looked at your first code again and I am not quite sure what exactly you are after. The main issue I see is that you are zooming in by changing the width and height of the subrectangle of your image. This means you can only zoom in steps of whole pixels.
If you change the line to this, you get a much smoother experience.
Code:
canvas.DrawRect startx,starty,nwidth*640.0*scaling,nheight*400.0*scaling,screen2
Still @MikeHart s comment is true and be aware that you can also get some "graininess" with floats if you do lots of calculations with them. They are only pretty accurate from 0.0 to 1.0.
 

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
715
I was also thinking about the fact that I've missed to adjust coordinates with +0.5. But yes you're right.


EDIT Actually it is the beginning of an extreme version of trying to do this.

I know the above uses AA but that's only half the story there's something more deep going on here.
 
Last edited:

Jimmy

Active member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
715
No not Cerberus, I meant graphics-wise in general. Cerberus is a great learning tool to try these kind of experiments.
 
Top Bottom