Skip to content

This lightweight library provides the core logic and functionality you need to build engaging match-3 games. Focus on game design and mechanics while leaving the complex logic to this library

License

Notifications You must be signed in to change notification settings

ninetailsrabbit/match3-board

Repository files navigation

Logo

Match3 Board

The core logic and functionality you need to build engaging match-3 games
· Report Bug · Request Features



📦 Installation

  1. Download Latest Release
  2. Unpack the ninetailsrabbit.match3_board folder into your /addons folder within the Godot project
  3. Enable this addon within the Godot settings: Project > Project Settings > Plugins

To better understand what branch to choose from for which Godot version, please refer to this table:

Godot Version match3-board Branch match3-board Version
GodotEngine main 1.x

Getting started 🚀

⚠️ DOCUMENTATION IS A WORK IN PROGRESS ⚠️

To start creating your Match3 game you have available 5 pillars provided from this plugin to build it:

  • 🔳 The Match3Board node handles the core game mechanics, including grid size, piece setup, and swap movement mode.
  • 💎 The PieceUI node provides the visual representation and interactive behavior of game pieces. You can customize it or create your own variations.
  • 📝 The PieceConfiguration defines the properties and behaviors of each piece type, such as its match logic and special abilities.
  • 🎲 The PieceWeight defines a weight value and a piece scene to be used for weight selection when drawing new pieces on the board. You can link any scene where the root node is PieceUI.
  • ⛓ The LineConnector which allows parts to be connected on the basis of a Line2D when LineConnected swap mode is selected on the board configuration.

Editor preview 🪲

This feature provides a preview of your game board before it's fully initialized. This allows you to:

  • Assess Layout: Visualize the size and layout of your board.
  • Add Empty Spaces: Easily adjust the spacing between game pieces.
  • Experiment with Textures: Test different textures for cells and pieces without affecting the final game.

You have available default textures on this plugin to visualize a preview in the editor, feel free to use your own ones. The nodes that are drawn are not the scenes that the board uses in the game, they are just sprites.

⚠️ This preview is temporary and will be removed when the game starts ⚠️


editor_preview_match_3


Parameters

  • Preview grid in editor: Enable or disable the preview
  • Clean current preview: Removes the current preview from the editor
  • Use placeholder textures: Use PlaceholderTexture2D as default texture to draw grids on the preview editor
  • Placeholder textures colors: Define colors for the placeholder textures to have a better visualization.
  • Preview pieces: The textures to preview in the grid randomly placed on each generation
  • Odd cell texture: The texture to place in odd cell positions in the board
  • Even cell texture: The texture to place in even cell positions in the board
  • Empty cells: Set empty cells where a piece shall not be drawn in the shape of Vector2i(row, column)

Board Parameters


editor_preview_match_3


Size

  • Grid width: The row width of the grid, a width of 7 means that 7 pieces will be drawed by row
  • Grid height: The column height of the grid, a height o 8 means that 8 pieces will be drawed by column
  • Cell size: The size of the cell in the world in the shape of Vector2(x, y). It's recommended to keep this values equals for better display
  • Cell offset: The offset from the corner if you want to create more space.

ℹ️ With the preview enabled, any changes you make to the board's parameters _(like grid size or piece definitions)_ will be instantly reflected in the preview window. This allows you to quickly iterate and experiment with different configurations ℹ️

Match configuration


board_match_parameters


Auto start

When enabled, the board prepare itself automatically when it's ready on the scene tree. If you disable it, you need to manually call the function prepare_board() on your script.

Pieces collision layer

The collision layer where the pieces are set. Its values are from 1 to 32 and this allows you to not override existing layers in your Godot project

Swap mode

This is the swap_mode to find matches on the pieces. They can be changed at runtime and the board emit the signal changed_swap_mode(previous, new) when this value it's changed

You have the next ones availables:

Adjacent

An individual piece can swap with adjacent pieces but diagonal neighbours are not included.

swap_adjacent

Adjacent with diagonals

Same as adjacent mode but this time diagonal neighbours are included

swap_adjacent

Adjacent only diagonals

Same as adjacent mode but this time only diagonal neighbours are included

swap_adjacent

Free

The piece can be swapped with any other

swap_free

Row

The piece can be swapped in the entire row it belongs

swap_adjacent

Column

The piece can be swapped in the entire column it belongs

swap_adjacent

Cross

The piece can be swapped on a cross that is a mix of Row & Column

swap_adjacent

Cross Diagonals

The piece can be swapped on cross but using diagonals instead

swap_adjacent

Connect Line

Connect the adjacent pieces from a line that originates from the selected cell until the maximum match of pieces or triggered manually.

swap_adjacent

Click mode

This is the click_mode to manipulate pieces in the board with the current swap mode. They can be changed at runtime and the board emit the signal changed_click_mode(previous, new) when this value it's changed

You have available the following ones:

  • Selection: You click on the piece to select and another click in the target piece to swap.
  • Drag: You hold the mouse and drag the piece into the target piece to swap. When the swap_mode is ConnectLine the piece is not dragged but instead you need to hold the mouse to keep connecting lines.

Customizable Input actions

When you're using the click_mode Selection and the swap_mode ConnectLine, there is two input actions you can define to consume or cancel the line connector matches.

⚠️ If this action does not exists, by default the consume is triggered with MOUSE_BUTTON_LEFT and the cancel with MOUSE_BUTTON_RIGHT ⚠️


Fill modes

This option defines the behaviour when the board is filling the empty gaps after consuming previous sequences of pieces.

You have available the following ones:

  • Fall down: The pieces fall down into the deepest empty column cell as they are drawn into the board
  • Side: Same behaviour as Fall down but if there is no empty space in the column and there is an empty space in the adjacent diagonal, the piece will move there.
  • In place: The pieces spawn in the same cell without gravity effects

Available pieces

This is an array of PieceWeight that will use the board to draw new pieces. A weight-based decision algorithm is used, i.e. the higher the value of the weight, the more likely it is to come out.

There is more extensive documentation in section How to create new pieces that explains in detail how to create the pieces scenes and add them to the board.

Note that the pieces you add here will be drawn on the board, i.e. the ones that can spawn when the board is in fill mode, this can be done as long as the is_disabled property is set to false

Drawing special pieces is the responsibility of the SequenceConsumer but nothing prevents you from placing them here and being part of the normal flow of the board.

class_name PieceWeight extends Resource

@export var weight: float = 1.0
@export var piece_scene: PackedScene


var is_disabled: bool =  false

var current_weight: float = weight
var total_accum_weight: float = 0.0


func reset_accum_weight() -> void:
	total_accum_weight = 0.0


func change_weight(new_value: float) -> void:
	current_weight = new_value


func change_to_original_weight() -> void:
	current_weight = weight


func enable() -> void:
	is_disabled = false


func disable() -> void:
	is_disabled = true

Available moves on start

This parameter acts as information that can be accessed on the variable current_available_moves about the moves this board can make. Each time the board returns to the initial state after consuming sequences, current_available_moves -= 1 it's triggered.

  • When a move it's consumed the board emits the signal movement_consumed
  • When no remaining moves are available the board emits the signal finished_available_movements

Add spawn pieces to the board

GridCellUI

Each square in the preview represents a GridCellUI node. This node serves as a visual representation of a cell within the game grid and is not designed for customization (although nothing prevents you from doing so)

The Swaps between pieces are done via this GridCellUI node so the pieces are never directly interacted with, it is the cells that contain the checks and commands to see if the swap is possible or not.

Position

To obtain the position of a cell you have access to variables row, column and method board_position(). This method returns a Vector2i(row, column).

In addition, there are methods to check for more advanced cases with other cells to know the relative position in the board

func in_same_row_as(other_cell: GridCellUI) -> bool

func in_same_column_as(other_cell: GridCellUI) -> bool

func in_same_position_as(other_cell: GridCellUI) -> bool

func in_same_grid_position_as(grid_position: Vector2) -> bool

func is_row_neighbour_of(other_cell: GridCellUI) -> bool

func is_column_neighbour_of(other_cell: GridCellUI) -> bool

func is_adjacent_to(other_cell: GridCellUI) -> bool

func in_diagonal_with(other_cell: GridCellUI) -> bool:

There are more methods available to determine if it is a corner or a border

func is_top_left_corner() -> bool:

func is_top_right_corner() -> bool

func is_bottom_left_corner() -> bool

func is_bottom_right_corner() -> bool

func is_top_border() -> bool

func is_bottom_border() -> bool

func is_right_border() -> bool

func is_left_border() -> bool:

Empty cell

If the position of this cell match with any of the empty_cells vectors from the Match3Board, this cell will change the variable can_contain_piece to false and you can choose if draw the background texture or not with the variable draw_background_texture.

Get neighbour cells

When the board is drawed and cells initialized, each one has access to the adjacent neighbours, you can access them with the variables:

neighbour_up,
neighbour_bottom,
neighbour_right,
neighbour_left,
diagonal_neighbour_top_right,
diagonal_neighbour_top_left,
diagonal_neighbour_bottom_right,
diagonal_neighbour_bottom_left

In addition you can access the neighbour cells that are available through the methods:

func available_neighbours(include_diagonals: bool = false) -> Array[GridCellUI]

func diagonal_neighbours() -> Array[GridCellUI]:

Piece

The cell has direct access to the related piece on variable current_piece, this GridCellUI class provides useful methods to manipulate them:

Information

Available methods to know if the cell has a piece or not

func is_empty() -> bool

func has_piece() -> bool

Add or remove

Methods to assign or remove a piece. This methods does not remove the piece from the board UI, only from the cell.

// Assign a piece only if the cell is empty unless "overwrite" is true
func assign_piece(new_piece: PieceUI, overwrite: bool = false) -> void

// Replace the current piece to the new one even if the cell is empty
func replace_piece(new_piece: PieceUI) -> PieceUI

// Remove the current piece and return it if the cell was not empty.
func remove_piece() -> PieceUI?

Swap (internal use, not recommended for manual use )

All the swap are dones through the cells, although it is not recommended to use these methods directly. Rather, set up the pieces and their rules individually and consume them with a SequenceConsumer.

func swap_piece_with(other_cell: GridCellUI) -> bool

func can_swap_piece_with(other_cell: GridCellUI) -> bool

About

This lightweight library provides the core logic and functionality you need to build engaging match-3 games. Focus on game design and mechanics while leaving the complex logic to this library

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published