Posted: 25th Aug 2021 20:19
Most irritating thing about AppGameKit for me is the fact I can't seem to have gobal dynamic variables/constants.

Given the following example, the constants are inaccessible from within a function. Using MAP_WIDTH inside a function will throw an error stating that "h" is not defined. Solution would be to make "h" global so it can reach function scope but of course you can't do that because a global must be a literal.

+ Code Snippet
w = getVirtualWidth() / 64
h = getVirtualHeight() / 64

#CONSTANT MAP_WIDTH = w
#CONSTANT MAP_HEIGHT = h



If I make h and w constants themselves, well then I can't use them to dimension an array because the constant will point to a function (getVirtualWidth) and you can't have that in an array definition. This is a very annoying limitation.
Posted: 25th Aug 2021 21:48
With the example you posted I would expect the behaviour you describe, typically a constant should be a static value but AppGameKit has this weird implementation where we can define an expression call it a constant, but when used this way it is not a constant, its is a macro.

The language is flexible enough to enable this duality which can come in very handy but the limitation is the duality itself, most languages demand a static value for array definitions as its a memory allocation problem, I understand your frustration but I also understand the dual purpose of the #Constant keyword will/does cause confusion and you also have to take scope into account, MAP_WIDTH gets replaced with w and if w is local or out of scope of the macro usage then I would expect it to throw an error

#CONSTANT MAP_WIDTH getVirtualWidth() / 64 << for example works fine as all values are inscope but it still can not be used to define an array because its morphed from a constant to a macro

Again I get it can be confusing but if you apply separation to the usage then it makes perfect sense.
Posted: 26th Aug 2021 4:00
You don't need the = for constants. Constants perform a simple substitution. In your case

w = getVirtualWidth() / 64
h = getVirtualHeight() / 64

#CONSTANT MAP_WIDTH w
#CONSTANT MAP_HEIGHT h

Referencing MAP_WIDTH like this;

abc = MAP_WIDTH

will substitute MAP_WIDTH for w and result in;

abc = w
Posted: 26th Aug 2021 4:12
I'm well aware of that, doesn't change the fact there's no simple way to define a calculated value for use within a function.
Posted: 26th Aug 2021 4:18
i've just resorted to DIMing the array at what i'd consider max possible (that i'd want to support) then only using, say, w and h values.
for the most part i dont expect its wasting too much memory.
Posted: 26th Aug 2021 12:42
there's no simple way to define a calculated value for use within a function.


Sorry if I misunderstand, but, isn't that what global variables are for?

i've just resorted to DIMing the array at what i'd consider max possible


I usually just define an empty array and use .insert and for a grid array I use a single dimension and use (y*width+x) to get the array index from the grid x,y .. I find this is slightly faster
Posted: 27th Aug 2021 17:37
You can use a constant in the function, but wouldn't be able to use it to define an array:
+ Code Snippet
#CONSTANT MAP_WIDTH = GetVirtualWidth() / 64

dim map[MAP_WIDTH, MAP_HEIGHT] as MapObj  // error


So you're thinking, just make a global instead, right? Wrong. Global must be an integer literal or constant
+ Code Snippet
global thing = getVirtualWidth() / 64


And by constant, it really means literal because you can't assign a constant to a global, you'll get the same error still.

This is the only way I was able to get my constant value to work in both array allocation and for use in a function. But this also means I had to explicitly define the resolution. It's just an extra step I don't feel should be necessary.
+ Code Snippet
global _screenWidth = 1024
global _screenHeight = 768

SetVirtualResolution( _screenWidth, _screenHeight )

#CONSTANT MAP_WIDTH = _screenWidth / 64
#CONSTANT MAP_HEIGHT = _screenHeight / 64

dim map[MAP_WIDTH, MAP_HEIGHT] as MapObj



The way AppGameKit treats constants is misleading, because it's not a constant at all.

For example, everytime you use MY_INT you'll get a different value. Maybe I needed the next integer for a specific object id and that'll never change for the remainder of the program, but can't do it this way since the constant maps to the function call rather than assigning the returned value.

+ Code Snippet
global myInt = 0
#CONSTANT MY_INT = getInt()

function getInt()
	inc myInt
endfunction myInt
	
Posted: 27th Aug 2021 18:12
Asking for a dynamic constant is a bit of an oxymoron, it can not be both a constant and dynamic, I agree that the AppGameKit implementation is misleading but you seem to be adding unnecessary confusion

You can use a constant in the function, but wouldn't be able to use it to define an array:


Yes, because when defined like that is is not a constant, its a macro, again misleading I agree, arrays must be defined with a static value so AppGameKit can allocate enough memory, if you want a dynamic array define it empty [-1] use .insert

So you're thinking, just make a global instead, right? Wrong. Global must be an integer literal or constant

And by constant, it really means literal because you can't assign a constant to a global, you'll get the same error still.


a global can be anything if you define it right, static values can be assigned off the bat but dynamic values must be defined after the declaration, maybe this is causing your unexpected behaviour?

+ Code Snippet
global _screenWidth = 1024
global thing  :  thing  = getVirtualWidth() / 64


^^ both are valid, but each use case differs

To assign a dynamic constant (which is not a constant, its a macro) to a global
+ Code Snippet
#Constant MYConst  GetDeviceWidth()

Global myGlobal : myGlobal = MYConst


to assign a static constant (which is indeed a constant) to a global
+ Code Snippet
#Constant MYConst 1024
 
Global myGlobal = MYConst
Posted: 28th Aug 2021 14:49
Since what you want is a global variable and not a constant, isn't the solution here to not try to make it a constant?
Posted: 28th Aug 2021 20:36
@Phaelax ... OK, I stand corrected, you are right!

This should work, I see no reason why it does not as there are no scope issues

+ Code Snippet
#Constant SCREEN_WIDTH 1024
#Constant SCREEN_HEIGHT 768

#Constant RES_WIDTH SCREEN_WIDTH*1.5
#Constant RES_HEIGHT SCREEN_HEIGHT*1.5

SetWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT, 0 )
SetVirtualResolution( RES_WIDTH, RES_HEIGHT) &lt;&lt; error on this line


main.agc:23: error: Variable "screen_height" is used without being defined or initialised


It seems you can not define a macro-constant with another constant

this
+ Code Snippet
Global SCREEN_WIDTH = 1024
Global SCREEN_HEIGHT = 768

#Constant RES_WIDTH SCREEN_WIDTH*1.5
#Constant RES_HEIGHT SCREEN_HEIGHT*1.5

SetWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT, 0 )
SetVirtualResolution( RES_WIDTH, RES_HEIGHT)


and this
+ Code Snippet
#Constant  SCREEN_WIDTH 1024
#Constant  SCREEN_HEIGHT 768

Global RES_WIDTH : RES_WIDTH = SCREEN_WIDTH*1.5
Global RES_HEIGHT : RES_HEIGHT = SCREEN_HEIGHT*1.5

SetWindowSize( SCREEN_WIDTH, SCREEN_HEIGHT, 0 )
SetVirtualResolution( RES_WIDTH, RES_HEIGHT)


both work

Now I see what you are saying, I think for the future I will use constants for static values only and sack this macro-like behaviour because it does seem a bit hit and miss.
Posted: 30th Aug 2021 16:40
Since what you want is a global variable and not a constant, isn't the solution here to not try to make it a constant?


The resolution won't change once the game starts, therefore the map dimensions I calculate will never change once defined. To me, that is a constant. I guess it's more a semantic thing at this point. Perhaps "#constant" should be renamed "#macro" or something.
Posted: 30th Aug 2021 17:56
Perhaps "#constant" should be renamed "#macro" or something.


I agree, the #Constant keyword should be treated with the same definition restrictions as Global, and dynamic #Constants should be allowed only with the #Macro keyword.

Personally speaking, I would back a Kickstarter for AGK3 that dumps the custom scripting engine and opt for Lua, no other changes, no functions updates, just replace the language with something more stable and far more powerful.

AGK is a fantastic tool and the C++ side is faultless IMO, the best and easiest C++ game lib I have stumbled across but I use Basic for the 1 click compile for web, mobile etc so its very handy but the quirks can sometimes be very annoying.