Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / Returning a Type in a function

Author
Message
Richard_6
7
Years of Service
User Offline
Joined: 3rd Feb 2017
Location:
Posted: 29th Sep 2017 04:18 Edited at: 29th Sep 2017 04:23
I would like to learn more about how to return a type from a function.

Example:


I thought this was not possible until I saw a recent example code written by Markus in this thread.

I'm now wondering if its possible to receive arguments too and how to structure this.
tmu
7
Years of Service
User Offline
Joined: 2nd Feb 2017
Location:
Posted: 29th Sep 2017 05:33
arguments:



Did not try to compile and run this but the general concept should be fine. Please do correct it everyone..
Richard_6
7
Years of Service
User Offline
Joined: 3rd Feb 2017
Location:
Posted: 29th Sep 2017 13:19
Hi tmu. Thanks for your response. I'm actually looking for a way to RETURN a Type from a function. This is specially useful when we want to return more than one variable from the functions.

Something like this:


Scraggle
Moderator
20
Years of Service
User Offline
Joined: 10th Jul 2003
Location: Yorkshire
Posted: 29th Sep 2017 14:07
That's what happens in TMU's argsRefDemo() function.
You pass a type into the function is a reference (the REF keyword) and any changes you make to it in the function also happen outside the function.

That's the closest you are going to get to what you are asking for. The only alternative is to use global variables and change those in the function but that's not a good alternative.
ShaunRW
DBPro Developer
16
Years of Service
User Offline
Joined: 7th Jan 2008
Location: Brisbane, Australia
Posted: 30th Sep 2017 03:00 Edited at: 30th Sep 2017 03:00
It looks like you're trying to access the type properties straight from the function call, like this -> Demo().A. You need to assign it to a variable of the returned type, then access the properties through that variable. See the code below:
=PRoF=
21
Years of Service
User Offline
Joined: 17th Mar 2003
Location: Milton Keynes, UK
Posted: 30th Sep 2017 12:40
This definitely falls into the "You learn something new every day" category

Thanks for the great example tmu, I was not aware of the ref command.
Richard_6
7
Years of Service
User Offline
Joined: 3rd Feb 2017
Location:
Posted: 30th Sep 2017 16:10
ShaunRW, this is exactly what I was referring to. I'm wondering if would be possible to pass arguments using your example.
ShaunRW
DBPro Developer
16
Years of Service
User Offline
Joined: 7th Jan 2008
Location: Brisbane, Australia
Posted: 1st Oct 2017 06:32
I'm not 100% sure what you mean by passing arguments using my example. But if you mean using functions to pass their return value straight to other functions, you can do this:

PartTimeCoder
AGK Tool Maker
9
Years of Service
User Offline
Joined: 9th Mar 2015
Location: London UK
Posted: 1st Oct 2017 16:19
^^, you can, but not sure why you would want to, I'm sure there is some logical application to using this approach but I would not adopt it as a coding standard, it looks suspiciously like spaghetti code to me! lol

also bear in mind AppGameKit is a interpreted language so you should avoid adding unnecessary overhead, in the below example....



MyType is being declared twice, both as local variables, this is adding overhead, sure in a 10 line example it don't matter but do this over and over in a full game and your FPS will suffer, if the type is being used in the main scope then it should be global, pass it by ref and access its members directly, this is a much faster approach when you have 10k lines of code all fighting for limited resources



or array of types


array of types, method 2
ShaunRW
DBPro Developer
16
Years of Service
User Offline
Joined: 7th Jan 2008
Location: Brisbane, Australia
Posted: 2nd Oct 2017 02:37
@PartTimeCoder I do agree with you. I was trying to make sense of richard_6s' question about passing arguments from functions.

OT:
Also, in your last 3 examples you declared Var as global, is there a reason to declare variables as global even though they are always passed into functions? I was always told to avoid globals as much as I can. This lead to me to creating function that take data by ref, only to call other functions inside that also take the same data by ref, and so on . Is this also considered a bad coding style?

Example:
PartTimeCoder
AGK Tool Maker
9
Years of Service
User Offline
Joined: 9th Mar 2015
Location: London UK
Posted: 2nd Oct 2017 18:28
my first few examples do beg the question "why not use the global directly" but expand the concept over an entire game code base and you see the logic behind my thinking, I hope lol

I'll try and explain

Quote: "Also, in your last 3 examples you declared Var as global, is there a reason to declare variables as global even though they are always passed into functions?"


I declared Var as global because its being used in the main scope (prior to and within the main game loop), and (according to my own coding preference) this is the only place the global should be used, you can access the global directly in the function yes, but it can simplify array depth by passing a type as ref and access a single element or type of the array, it also helps separate logic from functionality, without a full example its hard to explain but see below and you will get my drift.

Quote: "I was always told to avoid globals as much as I can. This lead to me to creating function that take data by ref, only to call other functions inside that also take the same data by ref, and so on . Is this also considered a bad coding style?"


I think you would be hard pushed to write any program without using at least one global, game states, scores, and a abundance of other information needs to be stored somewhere, right?

so that being said with a well thought out data structure you can minimize global use, or have a whole game running from a single global var.....


so back to passing by ref using the above as an example, to access an enemy bullet in a function to make the enemy fire you would use "gGame.enemy[x].bullet[y].sprite_id" in the function as the global, but IMO its easier to pass the enemy array as ref from the logic part of your code, it ends up a lot more readable and allows you to access specific parts of your main global without having to retype the gGame.bla every time you access the array, you do not need access to every game variable inside every function so some segregation can really help the logic flow, readability and structure of your code

simple example:


as you can see I only access the actual global from the logic, send the enemy type to the main fire function and the bullet type to the bullet fire function, obviously this is a quick air code example and it would need elaborating to make it work but it should highlight my reasoning for preferring to use ref rather than the global directly, and you only need to use ref when you want to change a value of the array or type, if your function only reads values you can pass them normally but if calling a second function that will change the value (as per the above example) then the root function needs the ref keyword.

Hope that makes some sense.

janbo
15
Years of Service
User Offline
Joined: 10th Nov 2008
Location: Germany
Posted: 3rd Oct 2017 03:10 Edited at: 3rd Oct 2017 03:17
Nice thread
Just in case someone tries to use PartTimeCoder's code...
Maybe a bit picky but please only use one bullet type

and

is redundant
Do this:


Besides that I like this method it's a good balance between ref's and globals
Sometimes you cut the global earlier because you are including other files and don't want to add everything to the gGame global.
Althrough you should make setter and getter for every attribute if you made a good include file/library so you don't need to access any globals from other include files, not ?
Hope that makes sense to you guys
MikeHart
AGK Bronze Backer
20
Years of Service
User Offline
Joined: 9th Jun 2003
Location:
Posted: 3rd Oct 2017 09:21
What I have done in my game is that I have an array that stores precreated types of my entities. Then another array which tells me which array indices are unused.

When I create a new entity, I simply lookup an index in the unused aray and change the values of that type in the entities array. Remove the index for the unused array. Whenever I remove an entity,
I put its index back into the unused array list. No need to reference. Works like a charm.
Running Windows 7 Home, 64 bit, 8 GB ram, Athlon II X2 255, ATI Radeon HD 4200. Using AGK2 Tier 1.
ShaunRW
DBPro Developer
16
Years of Service
User Offline
Joined: 7th Jan 2008
Location: Brisbane, Australia
Posted: 4th Oct 2017 06:17 Edited at: 4th Oct 2017 06:19
@PartTimeCoder, Thanks for the info . That is how I used globals, I just wanted to make sure i'm doing the right thing.

Another thing I do when I create sub systems, I use a global that is never accessed outside the sub systems source file.
subSystem:

Then main might look like this:

Would keeping this array under that single global game manager type, and passing it by ref to the sub system be a better solution?


Also if declaring local variable adds overhead, would nesting the declaration in a conditional have any effect on perfomance?



@Richard_6, Sorry for taking over your thread . Did you get the answer you were after?
PartTimeCoder
AGK Tool Maker
9
Years of Service
User Offline
Joined: 9th Mar 2015
Location: London UK
Posted: 4th Oct 2017 17:56 Edited at: 4th Oct 2017 17:57
Quote: "Another thing I do when I create sub systems, I use a global that is never accessed outside the sub systems source file."


Yes, I am building a GUI lib, the globals for each ui object are never accessed outside the objects source file, with the exception of the main event function, only that function uses the globals, if 1 lib needs to get or set info in another lib then like janbo says use getter/setter functions, this does not affect performance in any way but I find it a logical coding style, its readable, easily managed and easier to bug track, I neglected my own advice when I started this a while back and used separate globals, it would benefit from a single GUI global to tidy things up

Quote: "subSystem:"


I do exactly that in most cases, create a temp type fill the data then add it to the main type array with insert, I was playing with a pixel type room transition using sprites at 5x5 pixels per pixel and filled the screen, the creation of the 100's of sprites was very slow using the temp>>insert method and I saw a drastic speed increase using the global directly, so it is slower for sure, but if the speed does not impact the code then its my preferred method to use a temp type as its cleaner reading

Quote: "Would keeping this array under that single global game manager type, and passing it by ref to the sub system be a better solution?"


to be honest I don't know if there's a speed impact with either method but my preference would be to pass it as ref, it keeps the code in stacks, the main loop logic used the global, player lib uses the player array, enemy lib uses the enemy array and make get/setters for info that needs sharing.

Having been coding with PureBasic for nearly 2 decades I adopted this style of coding using structured linked lists (much like AGK's type arrays) to kind of map out the code structure, many many messy projects got scrapped because I ended up lost in a maze of code that had no structure, random function calls accessing a plethora of globals, bug tracking was a nightmare!, I self taught a system to manage it all and AppGameKit fits so very well into that coding style, so thats why I prefer to structure it, but I think each programmer has to find his own style taking what they learn from each project, example code, other peoples code and forum advice, after a while a natural style will set in.
tmu
7
Years of Service
User Offline
Joined: 2nd Feb 2017
Location:
Posted: 4th Oct 2017 19:10
My recent approach to using arrays for bullets and like has been to declare a type with an array of types and a count variable. To find an unused slot, just use the count as index. To delete an item, replace it with the last item in array (count gives the index) and reduce count by 1. Never need to loop anything and never need to resize array if you can live with some reasonable max size. Well OK, you need to loop all the time in AppGameKit, but in theory anyway. Some overhead of copy of course. Typically none of this matters of course.


Richard_6
7
Years of Service
User Offline
Joined: 3rd Feb 2017
Location:
Posted: 5th Oct 2017 14:13
There are great insights here and I’m learning a lot from you all!

I use as ref a lot and been trying to avoid global variables. However, in this case I just wanted to use a local variable to return an object which I think its not possible. No big deal, though.

My initial purpose was to try to make some of my functions a little more elegant

Right now I have something like this:


So if I'd need GridNum and InitGrid I would have to go through this function twice (and both are together because they share a lot of things in common).

It’s just a tiny improvement but could be used in other parts. I actually got intrigued the way Markus returned a type in a previous example (just like ShaunRW has shown here), so I started wondering those possibilities. Cheers!
PartTimeCoder
AGK Tool Maker
9
Years of Service
User Offline
Joined: 9th Mar 2015
Location: London UK
Posted: 5th Oct 2017 14:45
Quote: "So if I'd need GridNum and InitGrid I would have to go through this function twice (and both are together because they share a lot of things in common)."


Sure that makes sense I do that a lot also for common items, no point overloading with functions.

Quote: "I actually got intrigued the way Markus returned a type in a previous example"


but you must declare the type both inside and outside the function which makes no sense to me, sure it can be done like that I just don't see the advantage, as the type has to be defined before the function call it makes more scene to me to send the already declared type to the function rather that declaring and returning a new type to replace the type you already declared, if we could declare a var as a function return type "var as myType()" then it would be a logical way to go, but like I said above each to his own.

That's the thing I love about programming, so many different ways to solve the same puzzle lol
Markus
Valued Member
20
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 5th Oct 2017 19:18
Quote: "Right now I have something like this:"

i believe here you need also ref or you have a copy of array
LevelNow as LevelNow[]
this GridVar you return is also a copy but its maybe useful if you not need to edit the values and its much shorter than the writing style to access the array element.
generally its good to think about speed optimization, but the base, the agk interpreter core not considered this in his conception.
Quote: " so many different ways to solve the same puzzle lol"

agree


AGK (Steam) V2017.09.25 : Windows 10 Pro 64 Bit : AMD (17.9.3) Radeon R7 265 : Mac mini OS Sierra (10.12.2)

Login to post a reply

Server time is: 2024-04-20 09:15:23
Your offset time is: 2024-04-20 09:15:23