So, no linked lists in AGK. How do i?

Started by Amon, February 28, 2018, 21:11:29

Previous topic - Next topic

Amon

manage my entities without using lists? A simple example from someone would be appreciated. ta.


:)

therevills

I'm not sure... but maybe Arrays... urrggg. I'm sure an AGK expert will be along soon :)

Amon


Naughty Alien

..Arrays in AGK are really handy and nicely done..Insert, Remove, etc..all is already there so it saves you from endless iterations..very handy..

https://www.appgamekit.com/documentation/guides/12_array_changes.htm

Qube

#4
Here's a quick working example :


Type tPerson
number As Integer
xPos As Float
yPos As Float
EndType

Global person As tPerson
Global people As tPerson[]

For count = 1 To 10
   person.number = count
   person.xPos = Random2( 0, 100 )
   person.yPos = Random2( 0, 100 )
   people.insert( person )
Next

For thisPerson = people.length To 0 Step -1
   Print people[ thisPerson ].number
   Print people[ thisPerson ].xPos
   Print people[ thisPerson ].yPos
Next

For thisPerson = people.length To 0 Step -1
   If people[ thisPerson ].xPos > 50
      people.remove( thisPerson )
   EndIf
Next
Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.

Amon

That's exactly what I was looking for Qube. Thanks m8.

:)

Derron

@ qube
So arrays are 1-based in AGK? And for loops stop before reaching the to-value?

I think you should start at arr.length-1 ... Or stop at 1 but subtract 1 when accessing the index ;-)

Bye
Ron

Qube

The example I gave always returns the right results so I've just assumed that's the right method. If it was wrong then I would of thought it would of thrown an out of bounds error. I do find that iterating backwards works best if your loop contains removal of elements.
Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.

Derron

If that works that I think this is a flaw in the language...


For count = 1 To 10
  'you create 1,2,3,4,5,6,7,8,9,10 -- 10 entries
  'agk does not fill arrays "index based" but similar to maps so "insert(15)"
  'does not increase array size to be of length 15
  '-> array has a length of 10 now
Next

For thisPerson = people.length To 0 Step -1
  'you go from 10 to 9, 8, 7, 6, 5, 4, 3, 2, 1 - and maybe also "0" (in BlitzMax you would at least)
  'you then access the array - people[10 to 0]
  '-> you access 10 - or 11 array entries if "to" means "inclusive to"
Next


Hope my comments explain what is wrong with your code - at least in my opinion. The first loop should be OK, the second for loop is accessing one entry too much. Imho it should segfault when trying to access the "0" person's property (as the person does not exist).

bye
Ron

MikeHart

#9
Arrays in AGK are ZERO based.

But...

when you define an array with a given size like myArray[10]

The 10 is the highest index, so you get 11 entries.

But #2...

array.Length() reports back the highest index, so your actual size of an array is length + 1

Many AGK developers people ignore index 0 and start with 1 so that .Length then makes more sense to them.

Derron

#10
> array.Length() reports back the highest index, so your actual size of an array is length + 1

Then this is literally wrong. "length" is commonly used to return the amount of entries (if like a linked list) or the size of an array (if used as a "pure array").


Qube did:
- insert 10 elements to the array. The arrays highest key (not index...imho) is "10" then. right?
- I could access them via people[1] to people[10]. right?
- starts another loop, iterating from key "10" down to key "0" (so 10,9,8...2,1,0(!)). right?
- - accesses people[10]. right?
- - accesses people[0]. right?

but people[0] was never defined.

It does not depend on whether the arrays are "zero/one"-based or if you have a linked list. Qube adds 10 items, but iterates over 11 - at least I understand it that way.
If "to" was inclusive (1 to 5 = 1,2,3,4,5) and not exclusive (1 to 5 = 1,2,3,4) then already the insert of the persons would only insert 9 persons (1,2,3,...8,9) and the iteration would try to access 10 persons (10,9...3,2,1).


bye
Ron

TomToad

Qube's code inserts 10 elements.  The highest element is index 9.  people.length returns 9.  Index goes from 0 to 9.  An empty array has a length of -1. Don't know why he iterates backwards, doing for thisPerson = 0 to people.length works just as well (but in opposite order).

Array indexing in AGK is one of the few things that don't make sense to me.  Maybe it is to remain consistent with DBPro so people coming from there can adapt easier?
------------------------------------------------
8 rabbits equals 1 rabbyte.

Derron

#12
Just to get that right:

Code (AppGameKit) Select

For count = 1 To 10
   person.number = count
   person.xPos = Random2( 0, 100 )
   person.yPos = Random2( 0, 100 )
   people.insert( person )
Next


contains then:
people[0].number = 1
people[1].number = 2
...
people[9].number =10

people.length is "9" as "9" was the highest element used during insert. If one did people.Insert(person, count+5) it would have been "14" - while there would have still been 10 entries in it?


Code (AppGameKit) Select

For thisPerson = people.length To 0 Step -1
   Print people[ thisPerson ].number
   Print people[ thisPerson ].xPos
   Print people[ thisPerson ].yPos
Next


So that does:
print people[9].number
print people[8].number
...
print people[0].number


In that case this will work. But it will fail once you use an offset in the insert() command. Seems you need to use "people.find(thisPerson)" **1 in that case. Seems to differ a bit from what I am used to. Surely something error prone :-)


**1
Code (AGK) Select

myArray as integer[5] = [3,4,1,5,2,6]
myArray.sort() // array is now [1,2,3,4,5,6]
index = myArray.find(4) // will return "3" as array indexes start at 0

Source: https://www.appgamekit.com/documentation/guides/12_array_changes.htm


@ TomToad
Thanks. Think that explains what happened.

bye
Ron

Amon


Global DeviceWidth as integer
Global DeviceHeight as integer



SetWindowSize( GetDeviceWidth(), GetDeviceHeight(), 0 )
SetWindowAllowResize( 0 ) // allow the user to resize the window


// set display properties
SetVirtualResolution( 540, 960 ) // doesn't have to match the window
SetOrientationAllowed( 1, 0, 0, 0 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

Global GreyCube
Global RedCube
Global OrangeCube
Global YellowCube
Global GreenCube
Global BlueCube
Global PurpleCube
Global PinkCube


RedCube = LoadImage("Red.png")
OrangeCube = LoadImage("Orange.png")
YellowCube = LoadImage("Yellow.png")
GreenCube = LoadImage("Green.png")
BlueCube = LoadImage("Blue.png")
PurpleCube = LoadImage("Purple.png")
PinkCube = LoadImage("Pink.png")
GreyCube = LoadImage("Grey.png")

Global GameArray as integer [8,12]

file = OpenToRead("level1.txt")
level$ =  ReadLine(file)
CloseFile(file)

local X = 0
local y = 0

For iter=1 to Len(level$)
if x = 8
x = 0
y = y + 1
endif
GameArray[x,y] = val((Mid(level$, iter, 1)))
x = x + 1
next

for x = 1 to 8
for y = 1 to 12
if GameArray[x,y] = 1
gCube as TGreyCube
CreateSprite(GreyCube)
gCube.x = x * 64
gCube.y = y * 64
GCubeStore.insert(gCube)
endif
next
next

for tgc = 0 to GCubeStore.length-1
SetSpritePosition(GreyCube, gCube.x, gCube.y)
next

do


    Print( ScreenFPS() )


    Sync()
loop

Type TGreyCube
x as float
y as float
EndType
Global GCubeStore as TGreyCube[]


I'm trying to read numbers from a level file and place the cubes in the array. Then display them in their positions. It only shows 2 cubes though.

Qube

#14
Quote from: TomToad on March 01, 2018, 09:14:45Don't know why he iterates backwards, doing for thisPerson = 0 to people.length works just as well (but in opposite order).
Because if you are iterating forward and remove an element then it's crash out with an out of bounds error. That's why I iterate backwards when removing :)

Quote from: DerronIn that case this will work. But it will fail once you use an offset in the insert() command. Seems you need to use "people.find(thisPerson)" **1 in that case. Seems to differ a bit from what I am used to. Surely something error prone :-)
iterate backwards if you plan on removing element and iterate forward if you are planning on inserting elements.

*EDIT* Just to clarify that I would only do that if I needed to go through all the elements and take action.

Quote from: MikeHartMany AGK developers people ignore index 0 and start with 1 so that .Length then makes more sense to them.
I don't :P - In my example it assigns 10 people and person 1 is array element 0. I can understand why they would start from element 1 but I always prefer to start at 0 with arrays.
Mac Studio M1 Max ( 10 core CPU - 24 core GPU ), 32GB LPDDR5, 512GB SSD,
Beelink SER7 Mini Gaming PC, Ryzen 7 7840HS 8-Core 16-Thread 5.1GHz Processor, 32G DDR5 RAM 1T PCIe 4.0 SSD
MSI MEG 342C 34" QD-OLED Monitor

Until the next time.