I’ve been working on finishing a match 3 game for the last 6 weeks. All going well should release in the next 2-3 weeks.
I’ve used @britzl emthree as the base https://github.com/britzl/emthree
I can’t get diagonal drops to work at all. I’ve attempted a few different implementations and I always end up with two outcomes.
A) A working version that is boringly slow and feels stiff and rigid that is inefficient making it unusable
B) A fast version that is a buggy mess and unusable
The base function that deals with it is (only for vertical drops);
local function collapse(board, callback)
assert(board, "You must provide a board")
assert(callback, "You must provide a callback")
local duration = board.config.collapse_duration
local direction = DIRECTIONS[board.config.slide_direction]
local collapsed = false
local blocks = board.slots
local empty_x = nil
local empty_y = nil
local block_size = board.block_size
local function check_collapse(x, y)
local block = blocks[x][y]
if block and block.blocker then
empty_x = nil
empty_y = nil
elseif block and block.spawner then
-- do nothing
elseif block then
if empty_x and empty_y then
--
-- Move to empty slot
--
blocks[empty_x][empty_y] = block
blocks[x][y] = nil
block.x = empty_x
block.y = empty_y
--
-- Calc new position and animate
---
local to = vmath.vector3((block_size / 2) + (block_size * empty_x), (block_size / 2) + (block_size * empty_y), 0)
go.animate(block.id, "position", go.PLAYBACK_ONCE_FORWARD, to, board.config.slide_easing, duration)
collapsed = true
empty_x = empty_x - direction.x
empty_y = empty_y - direction.y
end
-- first empty slot
elseif not empty_x then
empty_x = x
empty_y = y
end
end
if board.config.slide_direction == M.SLIDE_DOWN then
for x = 0,board.width - 1 do
empty_x = nil
empty_y = nil
for y = 0,board.height - 1 do
check_collapse(x, y)
end
end
elseif board.config.slide_direction == M.SLIDE_UP then
for x = 0,board.width - 1 do
empty_x = nil
empty_y = nil
for y = board.height-1,0,-1 do
check_collapse(x, y)
end
end
elseif board.config.slide_direction == M.SLIDE_LEFT then
for y = 0,board.height - 1 do
empty_x = nil
empty_y = nil
for x = 0, board.width-1 do
check_collapse(x, y)
end
end
elseif board.config.slide_direction == M.SLIDE_RIGHT then
for y = 0,board.height - 1 do
empty_x = nil
empty_y = nil
for x = board.width-1,0,-1 do
check_collapse(x, y)
end
end
end
if collapsed then
delay(duration, callback)
else
callback()
end
end
The above function from my understanding works like this.
- Loop all the blocks starting at bottom left block going bottom to top left to right.
- Loop calls check_collapse to see if the current block is empty, if it is assign its x, y to empty_x and empty_y then move onto the next block.
- If the last block in the column was empty then empty_x and empty_y will have the values of the last block and the current block will move down to fill the empty block.
- If a block was moved empty_x and empty_y are set to the old position of the block that was moved to then fill that gap that was just created.
Anyone smarter than me able to help provide some tips/insight into what modifications would be needed to the existing code to get diagonal drops working?
I found this reddit post on one approach https://www.reddit.com/r/gamedev/comments/5pge5y/how_i_implemented_diagonal_falling_in_a_match3/
I haven’t been able to find any other information. All the resources I can find do not handle diagonal falling.