Aller au contenu

Building a drag-to-merge tile game in Scratch

Ce contenu n’est pas encore disponible dans votre langue.

💡 Need help with complex game mechanics? Struggling with drag-and-drop systems? 🚀 Get Expert Help

GS

GameMech_Sarah

Posted on January 23, 2024 • Intermediate

🧩 Help with creating a merge puzzle game

Hi everyone! I’m working on a merge-style puzzle game similar to 2048 or Threes, but with a twist - players can drag to create lines and merge all tiles in that line at once.

The core mechanics I want to implement:

  • Drag from one tile to create a selection line
  • Merge all matching tiles along the drawn line
  • Apply gravity so tiles fall down after merging
  • Chain reactions when new matches are created
  • Score system based on merge combinations

I’m particularly struggling with the line detection and tile merging logic. Any guidance on how to approach this complex system would be amazing! 🙏

PD

PuzzleDev_Expert

Replied 4 hours later • ⭐ Best Answer

Excellent project idea @GameMech_Sarah! Merge games with line mechanics are really engaging. Here’s a comprehensive system that will give you professional-quality merge gameplay:

🎯 Merge Game System Architecture

Here’s how the complete merge system works:

flowchart TD A[🚀 Game Start] --> B[Initialize Grid] B --> C[Spawn Initial Tiles] C --> D[🎮 Player Input Loop] D --> E{Input Type?} E -->|Mouse Down| F[Start Line Drawing] E -->|Mouse Drag| G[Update Line Path] E -->|Mouse Up| H[Process Line Selection] F --> I[Record Start Position] G --> J[Track Mouse Path] H --> K[Find Tiles in Line] K --> L{Valid Merge?} L -->|Yes| M[Merge Tiles] L -->|No| N[Clear Selection] M --> O[Apply Gravity] O --> P[Check for Chains] P --> Q{New Matches?} Q -->|Yes| M Q -->|No| R[Update Score] R --> S[Spawn New Tiles] S --> T{Game Over?} T -->|No| D T -->|Yes| U[🏆 End Game] N --> D style A fill:#e1f5fe style B fill:#f3e5f5 style M fill:#e8f5e8 style O fill:#fff3e0 style U fill:#fce4ec

🏗️ Step 1: Grid System Setup

First, create the foundation with a grid-based tile system:

    when flag clicked
// Initialize game variables
set [GridWidth v] to [6]
set [GridHeight v] to [8]
set [TileSize v] to [60]
set [Score v] to [0]
delete all of [Grid v]
delete all of [SelectedTiles v]

// Create empty grid
repeat ((GridWidth) * (GridHeight))
add [0] to [Grid v]
end

// Spawn initial tiles
repeat [15]
set [RandomPos v] to (pick random [1] to (length of [Grid v]))
if <(item (RandomPos) of [Grid v]) = [0]> then
replace item (RandomPos) of [Grid v] with (pick random [1] to [3])
end
end
  

🎨 Step 2: Visual Grid Display

Create a tile sprite that handles the visual representation:

    // Tile sprite code
when flag clicked
hide
set [TileID v] to [0]

when I receive [update display v]
if <(TileID) ≤ (length of [Grid v])> then
set [TileValue v] to (item (TileID) of [Grid v])
if <(TileValue) > [0]> then
show
switch costume to (TileValue)
// Calculate position from grid index
set [GridX v] to (((TileID) - [1]) mod (GridWidth))
set [GridY v] to (round (((TileID) - [1]) / (GridWidth)))
go to x: (([GridX] * [TileSize]) - [150]) y: (([GridY] * [TileSize]) - [100])
else
hide
end
end
  

🖱️ Step 3: Line Drawing System

Implement the drag-to-select line mechanism:

    // Main game controller
when flag clicked
set [Drawing v] to [0]
set [LineStartX v] to [0]
set [LineStartY v] to [0]

forever
if <mouse down?> then
if <(Drawing) = [0]> then
// Start drawing line
set [Drawing v] to [1]
set [LineStartX v] to (mouse x)
set [LineStartY v] to (mouse y)
delete all of [SelectedTiles v]
broadcast [line start v]
else
// Continue drawing line
broadcast [line update v]
end
else
if <(Drawing) = [1]> then
// Finish line and process merge
set [Drawing v] to [0]
broadcast [line end v]
end
end
end
  

🔍 Step 4: Tile Selection Logic

Detect which tiles are along the drawn line:

    // Custom block: find tiles in line
define find tiles in line (startX) (startY) (endX) (endY)
delete all of [SelectedTiles v]
set [LineLength v] to (sqrt (((endX) - (startX)) * ((endX) - (startX)) + ((endY) - (startY)) * ((endY) - (startY))))
set [Steps v] to (round ((LineLength) / [10]))

repeat (Steps)
set [Progress v] to ((counter) / (Steps))
set [CheckX v] to ((startX) + ((Progress) * ((endX) - (startX))))
set [CheckY v] to ((startY) + ((Progress) * ((endY) - (startY))))

// Convert screen position to grid position
set [GridX v] to (round (((CheckX) + [150]) / (TileSize)))
set [GridY v] to (round (((CheckY) + [100]) / (TileSize)))

if <<(GridX) ≥ [0]> and <(GridX) < (GridWidth)>> then
if <<(GridY) ≥ [0]> and <(GridY) < (GridHeight)>> then
set [GridIndex v] to (((GridY) * (GridWidth)) + (GridX) + [1])
if <not <[SelectedTiles v] contains (GridIndex)?>> then
add (GridIndex) to [SelectedTiles v]
end
end
end
end
  

🔄 Step 5: Merge Processing

Handle the actual tile merging logic:

    // Custom block: process merge
define process merge
if <(length of [SelectedTiles v]) < [2]> then
stop [this script v]
end

// Check if all selected tiles have the same value
set [FirstTileValue v] to (item (item [1] of [SelectedTiles v]) of [Grid v])
set [CanMerge v] to [1]
set [MergeCount v] to [0]

repeat (length of [SelectedTiles v])
set [TileIndex v] to (item (counter) of [SelectedTiles v])
set [TileValue v] to (item (TileIndex) of [Grid v])

if <<(TileValue) = (FirstTileValue)> and <(TileValue) > [0]>> then
change [MergeCount v] by [1]
else
set [CanMerge v] to [0]
end
end

if <<(CanMerge) = [1]> and <(MergeCount) ≥ [3]>> then
// Perform merge
set [NewValue v] to ((FirstTileValue) + [1])
set [MergeScore v] to ((MergeCount) * (FirstTileValue) * [10])
change [Score v] by (MergeScore)

// Clear merged tiles
repeat (length of [SelectedTiles v])
set [TileIndex v] to (item (counter) of [SelectedTiles v])
replace item (TileIndex) of [Grid v] with [0]
end

// Place new merged tile at first position
set [FirstPos v] to (item [1] of [SelectedTiles v])
replace item (FirstPos) of [Grid v] with (NewValue)

play sound [merge success v]
broadcast [apply gravity v]
else
play sound [invalid merge v]
end
  

⬇️ Step 6: Gravity System

Make tiles fall down after merging:

    // Custom block: apply gravity
define apply gravity
set [ChangeMade v] to [1]

repeat until <(ChangeMade) = [0]>
set [ChangeMade v] to [0]

repeat (GridWidth)
set [Column v] to (counter)

// Process each column from bottom to top
repeat ((GridHeight) - [1])
set [Row v] to ((GridHeight) - (counter))
set [CurrentIndex v] to (((Row) * (GridWidth)) + (Column))
set [BelowIndex v] to ((CurrentIndex) + (GridWidth))

if <(item (CurrentIndex) of [Grid v]) > [0]> then
if <(item (BelowIndex) of [Grid v]) = [0]> then
// Move tile down
replace item (BelowIndex) of [Grid v] with (item (CurrentIndex) of [Grid v])
replace item (CurrentIndex) of [Grid v] with [0]
set [ChangeMade v] to [1]
end
end
end
end
end

broadcast [check for chains v]
  

⚡ Step 7: Chain Reaction System

Automatically detect and process new matches after gravity:

    // Custom block: check for automatic chains
define check for chains
set [ChainFound v] to [0]

// Check for horizontal matches
repeat (GridHeight)
set [Row v] to (counter)
set [MatchCount v] to [1]
set [LastValue v] to [0]

repeat (GridWidth)
set [Col v] to (counter)
set [Index v] to (((Row) - [1]) * (GridWidth) + (Col))
set [CurrentValue v] to (item (Index) of [Grid v])

if <<(CurrentValue) = (LastValue)> and <(CurrentValue) > [0]>> then
change [MatchCount v] by [1]
else
if <(MatchCount) ≥ [3]> then
// Found a chain - mark for merging
set [ChainFound v] to [1]
// Process this chain...
end
set [MatchCount v] to [1]
set [LastValue v] to (CurrentValue)
end
end
end

if <(ChainFound) = [1]> then
wait [0.5] seconds
broadcast [apply gravity v]
end
  

🎮 Pro Tips for Merge Games

  • Visual Feedback: Highlight selected tiles and show merge previews
  • Smooth Animations: Add falling animations for gravity effects
  • Progressive Difficulty: Introduce new tile types as score increases
  • Special Tiles: Add power-ups like bombs or wildcards
  • Combo System: Reward consecutive merges with score multipliers

This system creates a fully functional merge game with line-drawing mechanics! The key is breaking it down into manageable components and testing each part thoroughly. 🧩✨

GS

GameMech_Sarah

Replied 2 hours later

@PuzzleDev_Expert This is incredible! 🤩 The system works perfectly!

I’ve implemented the basic version and it’s so satisfying to play. Quick question - how would I add different tile types that have special merge rules?

ST

SpecialTiles_Dev

Replied 1 hour later

@GameMech_Sarah Great question! Here’s how to add special tile types:

    // Special tile merge rules
define check special merge (tileType)
if <(tileType) = [bomb]> then
// Bomb tiles clear surrounding area
repeat [9]
set [OffsetX v] to (((counter) - [1]) mod [3] - [1])
set [OffsetY v] to (round (((counter) - [1]) / [3]) - [1])
set [TargetX v] to ((GridX) + (OffsetX))
set [TargetY v] to ((GridY) + (OffsetY))

if <<(TargetX) ≥ [0]> and <(TargetX) < (GridWidth)>> then
if <<(TargetY) ≥ [0]> and <(TargetY) < (GridHeight)>> then
set [TargetIndex v] to (((TargetY) * (GridWidth)) + (TargetX) + [1])
replace item (TargetIndex) of [Grid v] with [0]
end
end
end
else
if <(tileType) = [wildcard]> then
// Wildcard can merge with any adjacent tile type
// Implementation here...
end
end
  

You can create bombs, wildcards, multipliers, and more! Each special tile just needs its own merge logic. 💥

VB

Vibelf_Community

Pinned Message • Moderator

🧩 Ready to Master Puzzle Game Development?

Fantastic discussion on merge game mechanics! For developers looking to create even more sophisticated puzzle games, our community can help you implement:

  • 🎯 Advanced matching algorithms
  • 🌟 Power-up and special tile systems
  • 📊 Dynamic difficulty adjustment
  • 🏆 Achievement and progression systems

📚 Related Puzzle Game Topics

Want to create addictive puzzle games? Get personalized guidance from our expert game development tutors!