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.

Newcomers AppGameKit Corner / I'm having problems with array collisions.....need some help please

Author
Message
countryside
11
Years of Service
User Offline
Joined: 15th Mar 2013
Location:
Posted: 30th Dec 2017 17:30
I'm experimenting with arrays and array collisions
what is happening is I will get a error at line 125
stating :"array index out of bounds , index:6, array length:5 in main.agc line 125
sometime I will run it again and everything works fine
then the next time it will throw up a error but not always the same index# or array length#
I'm at my wits end....any help would be greatly appreciated.
line 125 is in the function collisions()


// Project: me_clowns_arrays
// Created: 2017-12-29

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "me_clowns_arrays" )
SetWindowSize( 1024, 768, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // 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


type clownType
sprite as integer
speed as integer
x as integer
y as integer
direction as integer
endtype

type scarytype
sprite as integer
speed as integer
x as integer
y as integer
state as integer
endtype

image = LoadImage ( "clown.png" )

// create sprites for each clown face
for i = 1 to clown.length
clown[i].x=random(1,500)
clown[i].y=random(25,700)
clown[i].speed=random(1,5)
clown [ i ].sprite = CreateSprite ( image )
SetSpriteScale(clown[i].sprite, .2,.2)
SetSpriteVisible (clown[i].sprite,1)
SetSpritePosition(clown[i].sprite,clown[i].x,clown[i].y)

next i



image = LoadImage ( "scary.png" )

// create scary faces
for i = 1 to scary.length
scary[i].x= random(550,1020)
scary[i].y= random(25,700)
scary[i].speed=random(1,5)
scary [ i ].sprite = CreateSprite ( image )
SetSpriteScale(scary[i].sprite,.2,.2)
SetSpriteVisible (scary[i].sprite,1)
SetSpritePosition(scary[i].sprite,scary[i].x,scary[i].y)

next i

global clown as clownType[10]
global scary as scarytype[10]

do
moveclown()
movescary()
collisions()
Print( ScreenFPS() )
print("Clowns:")
print(clown.length)
print("")
print("scary faces:")
print(scary.length)
Sync()
loop


function moveclown()

for i = 1 to clown.length

x = GetSpriteX ( clown [ i ].sprite )
y = GetSpriteY ( clown [ i ].sprite )

y = y + clown[i].speed

SetSpritePosition ( clown [ i ].sprite, x, y )
if getspritey(clown[i].sprite)>700
SetSpritePosition(clown[i].sprite,random(1,500),0)
endif
next i

endfunction


function movescary()

for z = 1 to scary.length

x = GetSpriteX ( scary [ z ].sprite )
y = GetSpriteY ( scary [ z ].sprite )

x = x - scary[z].speed

SetSpritePosition ( scary [ z ].sprite, x, y )
if getspritex(scary[z].sprite)<2
SetSpritePosition(scary[z].sprite,1020,random(1,700))
endif
next z

endfunction


function collisions()

for c = 1 to clown.length
for cc=1 to scary.length

if GetSpriteCollision(clown[c].sprite,scary[cc].sprite)=1////// This is line 125 ////

SetSpriteVisible(scary[cc].sprite,0)
setspritevisible(clown[c].sprite,0)
clown.remove(c)
scary.remove(cc)

//deletesprite(scary[cc].sprite)
//deletesprite(clown[c].sprite)

endif

next cc
next c
endfunction
Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 30th Dec 2017 18:09
The problem is your collisions() function.
You are resizing the arrays using the remove() command while iterating through the number of items in the array so you end up trying to access an index that you deleted in the previous loop! This will only happen when two scarys collide with the same clown and so the bug will appear random but it is there all the time

In other words ...you remove the same clown more than once causing you to try accessing an array index that doesn't exist.
countryside
11
Years of Service
User Offline
Joined: 15th Mar 2013
Location:
Posted: 30th Dec 2017 18:47
Thanks Bengismo that does make sense and did cross my mind.....I tried to delete the sprites that collide but that throws a error telling me sprite 10000? does not exist ....not really sure what else to try
countryside
11
Years of Service
User Offline
Joined: 15th Mar 2013
Location:
Posted: 30th Dec 2017 21:26
well I managed to get it to work....not really the way I wanted too, but it works :->
just moved the sprites off screen when hit then had to to set the sprites that hit to a( state=1)
and since they move right to left and top to bottom I just had to check and see if the
sprites state=1 and just kept it off the screen while the others were able to keep moving
if they didn't collide.....anyway it was a good day to dig deep into this, since the tempurature
outside here in Wisconsin is at -30 degrees windchill.
Supertino
6
Years of Service
User Offline
Joined: 22nd Jun 2017
Location: Behind you!
Posted: 3rd Jan 2018 14:49 Edited at: 3rd Jan 2018 14:50
late to the party I know could you not ExitFunction once the collision happens to avoid having to continue the iterations ?

Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 3rd Jan 2018 15:20 Edited at: 3rd Jan 2018 15:22
Good point, but he wanted to find all the collisions that have occurred though, so needs the loop to continue to find the others.

On finding a collision he could just add the "next c" code inside the if statement so that a clown isn't deleted twice which would work ok. It looks like he has already changed his code away from the function above though.
IronManhood
9
Years of Service
User Offline
Joined: 6th Feb 2015
Location: US
Posted: 4th Jan 2018 13:13
I think this is working.

Conjured Entertainment
AGK Developer
18
Years of Service
User Offline
Joined: 12th Sep 2005
Location: Nirvana
Posted: 4th Jan 2018 16:09 Edited at: 4th Jan 2018 16:15
If arrays start at 0, and the length count starts at 1, then wouldn't you need to limit the length to length-1 to avoid going out of bounds with the array

So, change your for loops...

from ...

for c = 1 to clown.length
for cc=1 to scary.length

to...

for c = 0 to clown.length -1
for cc=0 to scary.length -1

or...

for c = 1 to clown.length -1
for cc=1 to scary.length -1

...depending on whether you want to use slot zero or not.

Coding things my way since 1981 -- Currently using AppGameKit V2 Tier 1
Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 4th Jan 2018 17:17
^^^ That doesnt help and wasnt the problem. It would actually still have the same bug.

Accessing Variable[Variable.length] doesnt cause an out of bounds anyway.
https://www.appgamekit.com/documentation/guides/12_array_changes.htm
Quote: "Note that because arrays start at index 0 and allow the size parameter as a valid index,"


The problem was with removing an array member then trying to access the same one again on the next iteration of the loop
IronManhood
9
Years of Service
User Offline
Joined: 6th Feb 2015
Location: US
Posted: 4th Jan 2018 18:18 Edited at: 4th Jan 2018 18:25
I think the issue here is that for loops don't update the end parameter after they have begun. So removing an array index in the for loop won't update the end parameter, allowing the loop to continue past the length of the newly resized array causing an error. I think while and repeat loops update their parameters so you could use them to avoid this issue. I could be wrong.
Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 4th Jan 2018 18:58 Edited at: 4th Jan 2018 19:17
Quote: "I think the issue here is that for loops don't update the end parameter after they have begun. So removing an array index in the for loop won't update the end parameter, allowing the loop to continue past the length of the newly resized array causing an error. "

This is not quite correct ...the end parameter (array.length) is updated and checked on every loop itteration.

The problem was that the original code had two loops (inner and outer). The inner loop deleted (removed) an array member that was being addressed in the OUTER loop. So on the next run through of the inner loop it then checked against a collision with outer loop index which no longer exists. Both the outer and inner loop indexes needed to be updated on the removal of an array member. In the original code this means both c and cc needed to be updated but ONLY the inner loop was updated.
puzzler2018
User Banned
Posted: 4th Jan 2018 19:38 Edited at: 4th Jan 2018 19:41
Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 4th Jan 2018 19:53 Edited at: 4th Jan 2018 19:54
lol....that code STILL has the same bug and would still fail for the same reason.

You can delete the last of the clowns and continue to still try to check for a collision of it with other scarys after you have removed them all...!!!

Cant believe people are struggling with this.

Theres no need to repeat the Array.length value it is updated with every remove.
puzzler2018
User Banned
Posted: 4th Jan 2018 19:54
Give me 10 mins
puzzler2018
User Banned
Posted: 4th Jan 2018 20:07
Yep this went all way to ground 0



I added temporary

x=getpointerx()
y=getpointery()

to Moveclown function cause it was taking ages for clown to meet up with scary on the last couple and took ages
Bengismo
6
Years of Service
User Offline
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 4th Jan 2018 20:17 Edited at: 4th Jan 2018 22:22
But your code still has the bug...you were just lucky that it didnt happen to occur!! lol

Consider what happens if the last clown is removed.... Your code continues on to check if it (a removed clown) collides with other scarys even AFTER you removed it!! BANG ERROR

You can use the Array.length variables to check against...no need to duplicate and decrmeent those values either....AGK does it for you.

I believe the solution involves adding a "next c" inside the if collision check....
puzzler2018
User Banned
Posted: 4th Jan 2018 20:19
Good one...lol -) cheered me up something magical lol
IronManhood
9
Years of Service
User Offline
Joined: 6th Feb 2015
Location: US
Posted: 5th Jan 2018 00:04
Quote: "This is not quite correct ...the end parameter (array.length) is updated and checked on every loop itteration."


Just confirmed this. I'm not quite sure why I thought the other way. I guess I had never really tested that before. Learned something new
Golelorn
7
Years of Service
User Offline
Joined: 20th Nov 2016
Location:
Posted: 21st Jan 2018 00:10 Edited at: 21st Jan 2018 00:52
The problem is you don't have a check to exit your for loop(or not stop it) when the array is out of bounds. You'll need to add that.

Your code is removing your outermost array index while the for loop is still in progress. So in the error provided it was running clown[6] scary[cc] your if statement fired off removing the 6th element in your clown array. So the next iteration runs clown[6] scary[cc+1] Uh oh!! It can't run that if statement, because clown[6] no longer exist! Resulting in your error message. Which, is exactly what Bengismo said in the second comment lol

Add this before your the line that is failing(line 125):

if cc>scary.length or c>clown.length then continue // You may want to say NEXT C here instead of continue - I believe that may be more efficient and again that is what Bengismo suggested

per help: continue allows you to skip the current iteration of a loop and proceed immediately to the next iteration. So your if statement is ignored in this case.



* an empty array comes back as -1 not 0
** arrays work from innermost to outer

Login to post a reply

Server time is: 2024-04-20 07:36:03
Your offset time is: 2024-04-20 07:36:03