Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Another type of match-3 controls
#1
I like match-3 games (most common type of mobile game genre, I think). I've posted a couple of these before, but here's a control method that I don't think I've implemented before. Requires a bit more skill than just clicking.



Code:
' match3drag.n7
' -------------

visible vTileSize = 40
visible vMapRows = 12, vMapCols = 16
visible vMap = fill([type: 0, offs: 0, pop: 0], vMapCols, vMapRows)
visible vMapOffsX, vMapOffsY
visible vPieceColors = [[255, 32, 64], [64, 255, 32], [64, 32, 255], [192, 32, 255]]
visible vPath = [], vPathType

set window "match3drag", 800, 600
set redraw off

' Map draw offset.
vMapOffsX = (width(primary) - vMapCols*vTileSize)/2
vMapOffsY = (height(primary) - vMapRows*vTileSize)/2

' Set random types for map.
randomize time()
for y = 0 to vMapRows - 1  for x = 0 to vMapCols - 1  vMap[x][y].type = rnd(4)

' Game loop.
while not keydown(KEY_ESCAPE, true)
    ' Convert mouse to map coordinates.
    tileX = floor((mousex() - vMapOffsX)/vTileSize)
    tileY = floor((mousey() - vMapOffsY)/vTileSize)
    ' Valid position?
    if tileX >= 0 and tileX < vMapCols and tileY >= 0 and tileY < vMapRows
        if mousebutton(0)
            pos = Pos(tileX, tileY)
            type = vMap[tileX][tileY].type
            ' Start new path?
            if sizeof(vPath) = 0
                vPath[0] = pos
                vPathType = type
            ' Correct type?
            elseif type = vPathType
                ' Back to old position?
                if val(vPath, pos)
                    for i = sizeof(vPath) - 1 to 0
                        if vPath[i] = pos  break
                        else  free key vPath, i
                    next
                ' Add new position?
                else
                    lastPos = vPath[sizeof(vPath) - 1]
                    lastX = PosX(lastPos)
                    lastY = PosY(lastPos)
                    if tileY = lastY and |tileX - lastX| = 1 or
                            tileX = lastX and |tileY - lastY| = 1
                        vPath[sizeof(vPath)] = pos
                    endif
                endif
            endif
        else
            ' Pop?
            if sizeof(vPath) >= 3
                for i = 0 to sizeof(vPath) - 1
                    pos = vPath[i]
                    vMap[PosX(pos)][PosY(pos)].pop = (i + 1)*4
                next
            endif
            clear vPath
        endif
    ' Clear path if mouse button is released outside game area.
    elseif sizeof(vPath) > 0 and not mousebutton(0)
        clear vPath
    endif
   
    ' Update grid.
    for y = 0 to vMapRows - 1  for x = 0 to vMapCols - 1
        ' About to pop?
        if vMap[x][y].pop > 0
            vMap[x][y].pop = vMap[x][y].pop - 1
            ' Pop?
            if vMap[x][y].pop <= 0
                ' Copy above pieces and add draw offsets to make them fall.
                yy = y
                while yy > 0
                    vMap[x][yy].type = vMap[x][yy - 1].type
                    vMap[x][yy].offs = vMap[x][yy - 1].offs + vTileSize
                    vMap[x][yy].pop = vMap[x][yy - 1].pop
                    yy = yy - 1
                wend
                ' Add new piece at top.
                vMap[x][yy].type = rnd(4)
                vMap[x][yy].offs = vMap[x][yy + 1].offs + vTileSize
                vMap[x][yy].pop = 0
            endif
        endif
        ' Move down.
        vMap[x][y].offs = max(vMap[x][y].offs - 6, 0)
    next

    ' Draw.
    set color 0, 0, 0
    cls
   
    set clip rect vMapOffsX, vMapOffsY, vMapCols*vTileSize, vMapRows*vTileSize
    for y = 0 to vMapRows - 1  for x = 0 to vMapCols - 1
        set color vPieceColors[vMap[x][y].type]
        draw rect vMapOffsX + x*vTileSize + 2, vMapOffsY + y*vTileSize + 2 - vMap[x][y].offs,
                vTileSize - 4, vTileSize - 4, true
    next
    clear clip rect
   
    if sizeof(vPath) > 0
        for i = 0 to sizeof(vPath) - 1
            x = vMapOffsX + PosX(vPath[i])*vTileSize
            y = vMapOffsY + PosY(vPath[i])*vTileSize
            set color 255, 255, 255, 128
            draw rect x, y, vTileSize, vTileSize, true
            set color 255, 255, 255
            draw rect x, y, vTileSize, vTileSize 
        next
    endif
   
    set color 255, 255, 255
    set caret width(primary)/2, 4
    center "Mark three or more adjacent blocks of the same color, by drawing"
    center "a path with your left mouse button, to make them pop!"
   
    redraw
    fwait 60
wend

' Return map coordinates as single integer.
function Pos(x, y);  return y*vMapCols + x;  endfunc
' Return x part of single integer coordinates.
function PosX(pos);  return pos%vMapCols;  endfunc
' Return y part of single integer coordinates.
function PosY(pos);  return int(pos/vMapCols);  endfunc
Reply
#2
Excellent example, it has been great for me to find bugs I was making.
Reply
#3
I love this control system, and have not seen it before. It really adds a new dimension to this type of game, and makes it far more challenging. Thanks for sharing.
Reply
#4
Brilliant! Finally a game in which I do not die within the first few minutes! Absolute bliss! Very cool indeed...

Apart from not dying... how do I win? ... or is this where you tell me that this is actually conceptual? That would explain why I did not die... lol

I found a flaw in your game... no aliens!
Logic is the beginning of wisdom.
Reply
#5
This 3-tile matching game is really worth studying. The way it's coded is impressive. There are quite a few commands in there that I don't use very often like fill(), floor(), sizeof(), free key, set clip rect, clear clip rect...So, they're definitely worth digging into further. I really love this game. Thank you so much, Marcus Big Grin
Reply
#6
I did not invent these controls, used to be quite popular 20 years ago or so on the pc casual games market Big Grin

I used the bing ai image generator thing to generate a background image and some sprites, icecream related.

[Image: match3drag.jpg]

Now it looks a bit more like a game Smile But some of those "trees" in the background look a bit like ... brains.

Reply
#7
May I suggest a method of scoring? The player is timed. Each level has a limited time to reach a preset number of points. If successful, the next level, has a reduced time to acquire the same number of points. This continues until the player eventually fails. The player is then added to a hiscore table. Just a thought...

J
Logic is the beginning of wisdom.
Reply
#8
(02-14-2026, 07:09 PM)johnno56 Wrote: May I suggest a method of scoring? The player is timed. Each level has a limited time to reach a preset number of points. If successful, the next level, has a reduced time to acquire the same number of points. This continues until the player eventually fails. The player is then added to a hiscore table.  Just a thought...

J

Good idea, I'll see what I can put together.

I once posted a similar game here: https://www.naalaa.com/forum/thread-40.html (see the last attachment at the bottom) That one too uses AI generated art. No, I'm not an AI fan, but I think it's good for example games, tutorials and experiments.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)