Functions and multiple outputs

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,126
I wonder why Eachin did that though. Maybe there's internal optimization and it assumes what the target is.
Be careful with Eachin, I'm not fond of it so I might have missed some detail about it but I've looked through the code this evening and can't find what could possibly be doing that.

I just do a normal FOR NEXT loop and the problem is gone.
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,126
Seems to work :)

It might seem unusual to have data and code separate instead of methods but it will be helpful
when things grow.

screen.png


Screenshot.png


Code:
Strict
Import mojo2
Const n:Int = 100
Global test:xy = New xy

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

Class Game Extends App
   
    Field canvas:Canvas
    Field Obj:xy[n]

    Method OnCreate:Int()
        canvas = New Canvas() ; SetSwapInterval 1 ; SetUpdateRate 0
        For Local i := 0 Until n ; Obj[i] = New xy ; initxy(Obj[i]) ; Next
        Return 0
    End
   
    Method OnRender:Int()   
        canvas.Clear
        For Local i := 0 Until n
            canvas.DrawRect Obj[i].x,Obj[i].y,Obj[i].size,Obj[i].size    ' Draw

            Obj[i] = movexy(Obj[i])                                ' Update

        Next       
        canvas.Flush
        Return 0   
    End
   
End

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

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

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

SLotman

Active member
3rd Party Module Dev
Joined
Jul 3, 2017
Messages
192
My first reaction was to do it in the WORST way possible! 😁

Code:
Function TransformXandY:float[](wX:float, wY:float)
    local s:float[2]
    s[0] = (wX - 10)
    s[1] = (wY - 10) 
    return s
End
 

Gerry Quinn

Active member
Tutorial Author
Joined
Jun 24, 2017
Messages
163
That's not a particularly bad way of doing it, IMO. You have a const method that returns a tuple and you avoid polluting your namespace with a return POD class. It's a useful tool to have in your repertoire anytime you are doing something like this that's not going to be all over your code. Even when it's something that may well end up refactored away.

Then again I've been know to return arrays of arrays, stacks of stacks, or a combination...
 

Podge

Member
Joined
Nov 10, 2019
Messages
61
Hey Jimmy,

I don't understand this:

Global test:xy = New xy

What does this do and why? What is xy? Howcome it is not declared as say an Int or a Float? What does "New xy" do?

I'd really appreciate if you could just give me an idiots explanation. I really don't get this type of programming. What the hell is xy? How does the compiler know what it is?

Global a:Int = 0 , that I get. What is xy and a New xy. And y :)

Cheers,
Podge.

PS: I am a qualified blacksmith and welder. If you have any stupid questions about those topics I would be happy to try and answer them :)
 

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,126
No worries I'll try my best to explain!

Cerberus has a few handy types inbuilt such as Int, Float, String, and Bool. You know those already and each allows you to do what they do best.

But you can also grow your own type and that's what I do here:

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


To make one for youself you use types that already exist, in this case it's just a bunch of ints.
xy is just a name that I picked, much like int or string or pacman, and it could be anything. I picked xy because I first used it only to represent a 2d coordinate and to me it sounded good. A better name for this would have been "point" perhaps. As you see I added more stuff with time.

The reason that I defined a type named xy was becuase this allows me to talk about about these variables as a group and make the code simpler and more clear. You need to be a bit more wordy though when you use your own defined types, compared to the inbuilt ones. This is what makes it hard to grasp, becuase it looks so different even though it is not.

An int or string could be created simply like this:
Local a:Int
Global a:String


Global or local here tells where you can access the variables, it's the "scope" of the variables.

A customized type though needs a longer definition:
Global test:xy = New xy

Notice that the only additional word compared to primitive ones is "New xy" and that this might strike you as redudant as you already told the computer that you are creating a variable using Local or Global, and you've already told the type to use the type :xy. But this is how it is with non-primitives.

Look in the class and you see x y etc. That means that any variable that we assign this type now actually has all these things in it!
That means that we can access a part of it only if we want, using dot syntax like so:
test.x = 10
test.vy = 199


or we could treat it as a whole if we have same type:
test2 = test

I hope this clears things up, just ask if something is still muddy!
 
Last edited:

Podge

Member
Joined
Nov 10, 2019
Messages
61
No worries I'll try my best to explain!

Cerberus has a few handy types inbuilt such as Int, Float, String, and Bool. You know those already and each allows you to do what they do best.

But you can also grow your own type and that's what I do here:

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


To make one for youself you use types that already exist, in this case it's just a bunch of ints.
xy is just a name that I picked, much like int or string or pacman, and it could be anything. I picked xy because I first used it only to represent a 2d coordinate and to me it sounded good. A better name for this would have been "point" perhaps. As you see I added more stuff with time.

The reason that I defined a type named xy was becuase this allows me to talk about about these variables as a group and make the code simpler and more clear. You need to be a bit more wordy though when you use your own defined types, compared to the inbuilt ones. This is what makes it hard to grasp, becuase it looks so different even though it is not.

An int or string could be created simply like this:
Local a:Int
Global a:String


Global or local here tells where you can access the variables, it's the "scope" of the variables.

A customized type though needs a longer definition:
Global test:xy = New xy

Notice that the only additional word compared to primitive ones is "New xy" and that this might strike you as redudant as you already told the computer that you are creating a variable using Local or Global, and you've already told the type to use the type :xy. But this is how it is with non-primitives.

Look in the class and you see x y etc. That means that any variable that we assign this type now actually has all these things in it!
That means that we can access a part of it only if we want, using dot syntax like so:
test.x = 10
test.vy = 199


or we could treat it as a whole if we have same type:
test2 = test

I hope this clears things up, just ask if something is still muddy!
This is brilliant. Thank you for taking the time to explain this. It's a technique that I will be using. Very much appreciated!
 
Top Bottom