Emthree - Functionality?

I’ve been playing around with emthree by @britzl

Is it possible with this API to create more complex boards than squares/rectangles like the gif below? What’s the best way to do so?

And also to have the bricks move down to fill all the empty slots even if that means they move left or right to do so?

Or to achieve those features do I need to build upon the API?

em3 demo runs very slow on my chrome and has some bugs.


What bugs have you found?

Blocks are misplaced as the screen shots show above.

You can use emthree.create_blocker() to create a blocker (these will not move and match). Use these to change the shape of the level.

This is not yet implemented. Added an issue for this. Not sure when I have the time to implement it though.

1 Like
function init(self)
	self.board = emthree.create_board(boardwidth, boardheight, blocksize)
	emthree.on_create_block(self.board, create_block)
	emthree.on_match(self.board, on_match)
	emthree.on_block_removed(self.board, on_block_removed)
	emthree.on_swap(self.board, on_swap)

	-- start the board
	for x=0,boardwidth-1 do
		emthree.create_spawner(self.board, x, boardheight - 1, "SPAWNER")
	end

        emthree.create_blocker(self.board, 2, 4, "BLOCKER")
	emthree.create_blocker(self.board, 1, 2, "BLOCKER")
	emthree.create_blocker(self.board, 0, 0, "BLOCKER")
	emthree.create_blocker(self.board, 0, 6, "BLOCKER")

	emthree.fill_board(self.board)
	emthree.stabilize(self.board, function()
		msg.post(".", "acquire_input_focus")
	end)

	self.on_touch = emthree.on_input
end

This is your INIT for the board on Ocean Commotion. Where would be best to create the blockers? Like so? But obviously in a cleaner fashion.

Yes, that looks good.

It’s probably a debug build?
We use glGetError() to verify our OpenGL calls, and that function is notoriously slow in Chrome.

1 Like


slow & bugs I can’t believe It’s Defold.

As @Mathias_Westerdahl pointed out the slowness is probably due to the combination of Chrome and Defold verifying each WebGL call. This can be avoided by adding --verify-graphics-calls=false to engine_arguments in the HTML template.

2 Likes

Build that you are testing was built with 1.2.127

INFO:ENGINE: Defold Engine 1.2.127 (c129eaf)

I’m sure that it will be much better if you build it yourself using 1.2.149 (and in release mode)

1 Like

I’ll try it later.

1 Like

I tried the latest version of the game and the result was much much better.
Please update the demo on github, the performance scared me.:worried:

2 Likes

New demo being uploaded here: https://britzl.github.io/Emthree/index.html

3 Likes

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.

  1. Loop all the blocks starting at bottom left block going bottom to top left to right.
  2. 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.
  3. 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.
  4. 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.

Could you please create a ticket for this in the Emthree GitHub repository? I’ll take a look as soon as I can.

1 Like

You created this ticket already further up in the thread. Did you want me to create a separate one?

1 Like

Ah, no. I have to many projects and sometimes lose track. I’ll take a look as soon as possible.

1 Like

First version of slide logic implemented on this branch: https://github.com/britzl/emthree/tree/slide

Please give it a try and let me know what you think!

1 Like

First version of slide logic implemented on this branch: https://github.com/britzl/emthree/tree/slide

Please give it a try and let me know what you think!

Thank you very much! I’ll go over it today and test it against my blocker setup.