Match 3 as in bejeweled, candy crush, etc... (cause a week ago I didn't know they were called match3)
I wrote a version of a workable example of this style of game in DBP years ago and now I'm making one for AGK. My current method requires looping through all gems 3 times per cycle, which I feel could be improved. Not that running through an 8x8 nest loop 3 times would really affect performance, but I feel it's inefficient.
Initially, I had a 1D array containing gems. To find a gem at a particular grid location, I had to loop through all the gems to find the one at that location. Terrible! But AppGameKit doesn't let you use a UDT in a multi-dimensional array. So, second idea, store gems in an array as before, then build a 2D array for the map which references an index in the gem array. It's not my preferred method but it's manageable.
Here's what I mean:
Type Gem
sprite as integer
status as integer
acc as float
EndType
gems as Gem[64]
map as integer[8,8]
// Build initial map
for x = 0 to 7
for y = 0 to 7
// make random gem
g as Gem
g.sprite = cloneSprite(gembase[random(0,6)])
g.status = 0
// insert at end of array
gems.insert(g)
// store the gem at this location in the map
map[x,y] = gems.length
next y
next x
The tricky part comes from the fact that gems can move into different map locations, so the data in the map array must be constantly juggled around. That's fine, I can do that. Now here's why everything takes 3 separate loops.
First, apply gravity to the gems so they drop. A gem cannot drop beyond the one below it. Therefore, if a gem hits another one below it, it loses all acceleration. I also start at the top row and work my way down. The reason for this to create a cascade effect in that column when a gem is removed. If I started at the bottom and worked my way up, the entire column would shift down together, never spacing apart. If I start at the top, each gem in that column will drop in the next cycle following the last one, creating the cascading effect rather than dropping like they're stuck together. This is merely personal preference.
Once the gems have settled (stopped moving/updating), I need to update their positions in the map array. I can't do it in the first loop I just described because I need to loop through the gems starting at the bottom row and working my way up, otherwise I'd overwrite a gem. Because the gems drop down, I know the bottom most spot is where a gem was deleted, thus that spot is free. So if a gem was previously at (3,4) and I deleted (3,5) then (3,5) is free to overwrite first. Once (3,4) is copied, that space then becomes free to overwrite and so on.
So because my gravity needs to work from reading top to bototm but updating gem positions needs to work from bottom to top, that's 2 separate loops there that I can't integrate. The 3rd loop comes from when I begin to check for gem matches. I can't check matches unless everything (gravity and positions) have finalized updating.
It's clear in my head, hopefully my explanation was clear too. So my actual question is, does anyone see a way to integrate this all together to reduce the number of iterations over the map data? Or perhaps a better way to go about it altogether? Like I said, my method works, it just seems tedious and a bit unnecessary I think.