Functions and multiple outputs

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
What's the preferable way to multiple outputs in Cerberus functions?

A simple example would be if you have a pair of x and y coordinates that a function changes and now you want to output the new pair.

PSEUDOCODE
Code:
Function TransformXandY(float wX,float wY,int &SX,int &SY)
    SX = (wX - 10)
    SY = (wY - 10) 
End
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
The answer given there is just a relative change that it encodes and gives back, what if you really want two or more absolute variables back?
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
I know that I could simply use OO and have a refined chunk of information thrown back and forth that way, but is there any other way that is more direct in Cerberus?
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
I made an absolute encoding last week, which allows me to put x & y coordinates in the range of 0-65535 together into one INT, but this is a nasty as it cannot do anything else. I use it only for extreme speed and memory conservation.

I'm looking for something more flexible, something that would fit in-between this idea and OO. Not sure it exist.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
896
The answer given there is just a relative change that it encodes and gives back, what if you really want two or more absolute variables back?
Guess you didn't see the bit in the middle that tells you why you can not pass the SX and SY, and expect that it will change.
The parameter direction will be treated as a local variable and have absolutely no affect out side the AI_left method. This is down to only a copy being made of the value passed as the parameter and not the memory location of the variable, so it will not affect the original variable. With class objects, only the reference (aka it's address in memory) is being copied, so any change to that object affects that object directly.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
But arrays will right? Except arrays, in a way arrays is in the middle but it's still limited.

This is the OO solution I use now to test

Code:
Import mojo2

Class xy
    Global x:Int ' Field x:Int
    Global y:Int ' Field y:Int
End

Function Main()
    New Game
    Return 0
End

Class Game Extends App

    Field a:xy

    Method OnCreate()
    
        ' Create
        a = New xy()
        
        ' Set
        a.x = 10
        a.y = 10
        
        ' Change
        a = changexy(a)
        
        ' Print
        Print a.x
        Print a.y
        
        Return 0
    End
End

Function changexy:xy(parameter:xy)
    parameter.x = parameter.x + 1
    parameter.y = parameter.y + 10
    Return parameter
End
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
A bit more cleaned up, I'm not sure about the speed yet but it looks okay. It does not create anything new all the time.

Code:
Import mojo2

Function Main()
    New Game
    Return 0
End

Class Game Extends App
   
    Field a:xy = New xy() ' Create variable a of class xy
   
    Method OnCreate()
   
        ' Set
        a.x = 10
        a.y = 10
       
        ' Change
        a = changexy(a)
       
        ' Print
        Print a.x
        Print a.y
       
        Return 0
    End
End

Class xy
    Global x:Int ' Field x:Int
    Global y:Int ' Field y.Int
End

Function changexy:xy(parameter:xy)
    parameter.x = parameter.x + 1
    parameter.y = parameter.y + 10
    Return parameter
End
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
Good to know. That is true with most languages.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
I can't get the array of xy's to work correctly sadly. Not sure I use the correct syntax.

Code:
Strict
Import mojo2

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Field a:xy = New xy ' Create variable of type xy
    Field indices:xy[100] ' Create array of type xy
    
    Method OnCreate:Int()
    
        ' Set
        a.x = 10
        a.y = 10
        
        ' Change
        a = changexy(a)
        
        ' Print
        Print a.x
        Print a.y
        
        ' Test array
        ' indices[0].x = 10
        ' Print indices[0].x
        
        Return 0
    End
End

Class xy
    Field x:Int
    Field y:Int
End

Function changexy:xy(parameter:xy)
    parameter.x = parameter.x + 1
    parameter.y = parameter.y + 10
    Return parameter
End
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,307
Cerberus:
Class Game Extends App

    Field a:xy = New xy ' Create variable of type xy
    Field indices:xy[100] ' Create array of type xy
    
    Method OnCreate:Int()
        ' You forgot to initialize the array'
        For Local i:= 0 To 99
            indices[i] = New xy
        Next
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
Thanks! Got it working and it looks good too!
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
Put alien logic into it to try everything
Code:
Strict
Import mojo2

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Field canvas:Canvas
   
'    Field a:xy = New xy    ' Create simple variable of type xy
    Field indices:xy[100]    ' Create array of type xy
   
    Method OnCreate:Int()
       
        ' Inits
        For Local i := 0 To 99 ; indices[i] = New xy ; Next    ' Init Array
        canvas = New Canvas()                        ' Init canvas
        SetSwapInterval 1
        SetUpdateRate 0
       
        ' Continue init array
        For Local i := 0 To 99
            indices[i] = initxy(indices[i])
        Next  
           
        Return 0
    End
   
    Method Update:Int()  
        Return 0
    End
   
    Method OnRender:Int()
        canvas.Clear

        ' Loop all objects
        For Local i := Eachin indices
            canvas.DrawRect i.x,i.y,16,16                    ' Draw
            i = movexy(i)                                ' Update
        Next

        ' For Local i := 0 To 99
        '     canvas.DrawRect indices[i].x,indices[i].y,16,16    ' Draw
        '     indices[i] = movexy(indices[i])                ' Update
        ' Next

        canvas.Flush
        Return 0      
    End

End

Class xy
    Field x:Int
    Field y:Int
    Field vx:Int
    Field vy:Int
End

Function initxy:xy(p:xy)
    p.x = Rnd(640)
    p.y = Rnd(480)
    p.vx = Rnd(1,2)
    If Rnd(1) >= 0.5 Then p.vx = -p.vx
    p.vy = Rnd(1,2)
    Return p
End

Function movexy:xy(p:xy)
    p.x = p.x + p.vx
    If p.x < 0 Or p.x >= 640 Then p.vx = -p.vx
    p.y = p.y + p.vy
    If p.y < 0 Or p.y >= 480 Then p.vy = -p.vy
    Return p
End
 

Gerry Quinn

Active member
Tutorial Author
Joined
Jun 24, 2017
Messages
165
Standard: create a class e.g. a Point class with fields x and y.

Quick and dirty: use an array. You can pass an array or just create one in your function and return it. (Or another collection type such as a stack.)
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
Here I use the standard way and I enjoy having data and code separate.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
The only thing I miss is to be able to express one as a constant like you can in JavaScript and JSON.

For example Return an xy that you create witthout object. It's an object of course. But you create it on the spot. Just one of those small things. There's workarounds of course.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
When I want to output a value on the fly and create a test variable of xy, it does not work.


Code:
Strict
Import mojo2

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Const n:Int = 100

    Field canvas:Canvas
'    Field a:xy = New xy    ' Create simple variable of type xy
    Field indices:xy[n]        ' Create array of type xy
    
    Method OnCreate:Int()
        
        ' Inits
        canvas = New Canvas()                        ' Init canvas
        SetSwapInterval 1
        SetUpdateRate 0
        For Local i := 0 Until n ; indices[i] = New xy ; Next    ' Init Array
        For Local i := Eachin indices ; i = initxy(i) ; Next
        
        Return 0
    End
    
    Method OnRender:Int()
        canvas.Clear

        ' Loop all objects
        For Local i := Eachin indices
            canvas.DrawRect i.x,i.y,16,16                    ' Draw
            i = movexy(i)                                ' Update
        Next

        ' For Local i := 0 Until n
        '     canvas.DrawRect indices[i].x,indices[i].y,16,16    ' Draw
        '     indices[i] = movexy(indices[i])                ' Update
        ' Next
        
        canvas.Flush
        Return 0       
    End

End

Class xy
    Field x:Int
    Field y:Int
    Field vx:Int
    Field vy:Int
End

Function initxy:xy(p:xy)
    p.x = Rnd(640)
    p.y = Rnd(480)
    p.vx = Rnd(1,2)
    If Rnd(1) >= 0.5 Then p.vx = -p.vx
    p.vy = Rnd(1,2)
    Return p
End

Function movexy:xy(p:xy)
    p.x = p.x + p.vx
    If p.x < 0 Or p.x >= 640 Then p.vx = -p.vx
    p.y = p.y + p.vy
    If p.y < 0 Or p.y >= 480 Then p.vy = -p.vy

    ' Create output of only zeros (does not work)
    Local test:xy = New xy
    test.x = 0
    test.y = 0
    test.vx = 0
    test.vy = 0   
    Return test

    ' Return p
End
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
It does work if you exclude the Each loop and index manually.

Code:
Strict
Import mojo2

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Const n:Int = 100

    Field canvas:Canvas
'    Field a:xy = New xy    ' Create simple variable of type xy
    Field indices:xy[n]        ' Create array of type xy
   
    Method OnCreate:Int()

        ' Inits
        canvas = New Canvas()                        ' Init canvas
        SetSwapInterval 1
        SetUpdateRate 0
        For Local i := 0 Until n ; indices[i] = New xy ; Next    ' Init Array
        For Local i := Eachin indices ; i = initxy(i) ; Next
       
        Return 0
    End
   
    Method OnRender:Int()
        canvas.Clear

        ' Loop all objects
        'For Local i := Eachin indices
        '    canvas.DrawRect i.x,i.y,16,16                    ' Draw
        '    i = movexy(i)                                ' Update
        'Next

         For Local i := 0 Until n
             canvas.DrawRect indices[i].x,indices[i].y,16,16    ' Draw
             indices[i] = movexy(indices[i])                ' Update
         Next
       
        canvas.Flush
        Return 0      
    End

End

Class xy
    Field x:Int
    Field y:Int
    Field vx:Int
    Field vy:Int
End

Function initxy:xy(p:xy)
    p.x = Rnd(640)
    p.y = Rnd(480)
    p.vx = Rnd(1,2)
    If Rnd(1) >= 0.5 Then p.vx = -p.vx
    p.vy = Rnd(1,2)
    Return p
End

Function movexy:xy(p:xy)
    p.x = p.x + p.vx
    If p.x < 0 Or p.x >= 640 Then p.vx = -p.vx
    p.y = p.y + p.vy
    If p.y < 0 Or p.y >= 480 Then p.vy = -p.vy

    ' Create output of only zeros (does not work)
    Local test:xy = New xy
    test.x = 0
    test.y = 0
    test.vx = 0
    test.vy = 0
    Return test

    Return p
End
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,134
Though am a bit worried about this part, wondering if it's creating objects, there gonna be millions of calls.

Code:
Local test:xy = New xy

EDIT which brought me here:

It's a bit silver tape to use a global as a forever constant. But for now it's okay. I might actually keep this solution.

Code:
Strict
Import mojo2

Global test:xy = New xy ' To be re-used as constant forever

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Const n:Int = 100

    Field canvas:Canvas
'    Field a:xy = New xy    ' Create simple variable of type xy
    Field indices:xy[n]        ' Create array of type xy
    
    Method OnCreate:Int()

        ' Inits
        canvas = New Canvas()
        SetSwapInterval 1
        SetUpdateRate 0
        For Local i := 0 Until n ; indices[i] = New xy ; Next
        For Local i := 0 Until n ; indices[i] = initxy( indices[i]) ; Next
        Return 0
    End
    
    Method OnRender:Int()
        canvas.Clear

         For Local i := 0 Until n
             canvas.DrawRect indices[i].x,indices[i].y,16,16    ' Draw
             indices[i] = movexy(indices[i])                ' Update
         Next
        
        canvas.Flush
        Return 0       
    End

End

Class xy
    Field x:Int
    Field y:Int
    Field vx:Int
    Field vy:Int
End

Function initxy:xy(p:xy)
    p.x = Rnd(640)
    p.y = Rnd(480)
    p.vx = Rnd(1,2)
    If Rnd(1) >= 0.5 Then p.vx = -p.vx
    p.vy = Rnd(1,2)
    Return p
End

Function movexy:xy(p:xy)
    p.x = p.x + p.vx
    If p.x < 0 Or p.x >= 640 Then p.vx = -p.vx
    p.y = p.y + p.vy
    If p.y < 0 Or p.y >= 480 Then p.vy = -p.vy

    ' Create a xy constant and output
    ' Local test:xy = New xy ; test.x = 0 ; test.y = 0 ; test.vx = 0 ; test.vy = 0
    ' Return test
    
    ' TEST OF OUTPUTTING A CONSTANT XY (should put everything in the corner still)
     test.x = 0
    test.y = 0
    test.vx = 0
    test.vy = 0
     Return test ' Comment this line to get back to normal
 
    Return p
End
 
Last edited:
Top Bottom