Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Swapping tiles — Gideros Forum

Swapping tiles

sunnyguysunnyguy Member
edited June 2012 in General questions
Hello, everyone!
So here is my problem - I need a swapping tiles behavior for my game, like when you touch one tile then move your finger to nearest tile and release then they swap with each other, but without actually dragging the tile itself (I guess it's kinda confusing explanation :D ).
I accidentally stumbled upon an exact example of what I need (it's for NME framework). Here is the link - http://www.joshuagranick.com/blog/2012/02/22/nme-game-example-pirate-pig/. There is a source code as well but though it looks rather simple, I'm quite a newbie in programming, so it's not much use for me :| .

Comments

  • Ooookay - this might be a long post, so here goes.

    When you talked about swapping tiles my first thought was that you were talking about the native tilemap support and I thought ok, I've just worked this out time to post.

    However on closer reading (always a good idea, read twice - post once! :) ), basically what your looking to create is a basic "match3 engine" where by you have a collection of "tiles" (game objects, sprites, whatever) and you can swap their positions by touching and or dragging them around.

    First things first (if you haven't completed these steps yet - I suggest you do before progressing).

    1. Create your "tiles", you need a list of objects each with an x,y coordinate on the screen, a simple table can be used to hold all of the "tiles".

    2. Create a function that responds to a single touch and can then scan the list of "tiles" and based on their x,y positions (and tile width / height), return either the position or a reference to the sprite that was "touched", you can easily recognise this (and ensure you've got the right one) by setting it's alpha, colour modifier or scaling.

    Now it get's a little more complex! :)

    3. You need to use a "state machine" so that you know what "state" your game is in - basically this just means creating a simple variable that holds a number, where the number is used to represent the state, it's a way of remembering what your game is supposed to be doing at any given time.

    For a simple touch based match 3 you'll be going through (approximately) the following states.

    a - waiting for the first tile to be touched (selected)
    b - acknowledge the touch and then wait for the second tile - this can either be via a dragging movement or via another press
    c - acknowledge the second tile being pressed and then swap their positions - this can either be immediate or via some kind of animation
    d - check for matches (more on this later) and then destroy all the appropriate tiles, if no matches then go back to state a, other wise go to state e
    e - fill in the gaps, by sliding tiles from above down into position and filling in any gaps at the top - you'll stay in this state until the sliding anim is finished and then go back to state d (this will allow you to check for combo's where one match kicks off another one).

    Checking for matches can start to get a little complex, the way I usually do it is by creating a 2D array (ie a table of tables) where each element in the array is either nil or 0 (an empty space) or the index (or reference) to the sprite / tile at this location - note, although you'll have several "tiles" all with the same image, they'll actually have different indexes (or references) as they are actually separate objects - you'll need to store a property with each tile to say which "image" is being used so can see if two "tiles" should be considered the same...

    By using some simple logic you can (at stage d) walk through the array fairly easily and see if there are any blocks of three or more tiles that have the same "image" and then you'll be able to mark them as destroyed.

    I would suggest starting at step 1. and then posting your code, it might be good learning experience for others as well.

    I've deliberately avoided posting code as I think you (and others) would actually learn a LOT more from experimenting and trying to complete the steps yourself, however feel free to ask any more questions if needed.

    Jon...
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • sunnyguysunnyguy Member
    edited June 2012
    @techdojo, hey, thanks for taking your time to help me, I'm kinda busy right now, so I looked through your post very quickly, I'll read it better later. And it seems I have confused you a little, I don't need a match-three behavior, I need only the swapping one :-\"

    Edit: Well, maybe I'm not that busy :-) Now I'm confused myself :D I thought that it can be done with the native tilemap... To make things clear I'll try to explain one more time. I want to make a tile map with two layers - 1st one is a background one and the 2nd is objects layer, so you can swap only objects not the whole layers. What I want to know is how to make an object layer and how can I operate objects to make them swap with each other when you drag one object on another (as I said without actually dragging them, like in the Pirate Pig game example). That's pretty much everything I need to know. And forgive me for being confusing and confused :D
  • If all you want is the swapping functionality you will still want to follow the first 2 steps posted by techdojo.

    If I'm understanding what you want correctly, then you will need to do the following:

    3.) Add an event listener for MOUSE_DOWN, use your function created in techdojo's step 2 to take the x and y from the click and select your starting tile.

    4.) Add an event listener for MOUSE_UP, use your function created in techdojo's step 2 to take the x and y from the event and select your end tile. If the start and end tile are not the same, swap their locations.
  • I would strongly recommend NOT using native tilemap to support an objects layer because if you ever want to move or animate an object independently then it'll have to be a sprite, however...

    If you DO want to use tilemaps, then you need to create a basic tilemap (using Tiled is the easiest way) and then use the code example from here

    http://www.giderosmobile.com/forum/discussion/699#Item_15

    to create a basic map.

    When you build a map you call the setTile function to build up the tile indexes internally - this function is *really* confusing if you look at the documentation but if you think of the "tile sheet" as an 2D array of tiles then your actually specifying the COLUMN (tx) and ROW (ty) of the tile - so if your sheet is 16 tiles wide by 16 tiles high and you want tile 19 then it's on ROW 2, COLUMN 3.

    This is not made any easier by the fact if you call getTile then according to the doc's it would actually return the tile index.

    However the actual process of "swapping" tiles would involve getting the index of both the source and destination tiles, converting them into row and column values ie. integer divide the index by the number of tiles per row to get the row (not forgetting to +1 as indexes in Lua start at 1 not 0) and modulo the index by the number of tiles per row to get the column (again +1), once you have the two sets of row and column values you just make the appropriate calls to setTile
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • Would there be anything wrong with keeping a separate 2D array to keep track of objects? So long as you have tileHeight and tileWidth you could calculate where the objects should appear on the screen and just make sure the tilemap is added before the objects, so the objects would appear on top.
  • Would there be anything wrong with keeping a separate 2D array to keep track of objects? So long as you have tileHeight and tileWidth you could calculate where the objects should appear on the screen and just make sure the tilemap is added before the objects, so the objects would appear on top.
    But how exactly can I calculate this?
  • I'll try to write some rough code to give the idea, but since TileMap inherits from Sprite you should be able to make an objectlayer and add both your TileMap and your object layer to a parent sprite so in case you want anything else to move the map around you can move this parent Sprite around.
    local map = Sprite.new()
    local tilemap = TileMap.new() -- Setup your tilemap
    local objectLayer = Sprite.new()
    local objects = {}
     
    --whatever is added first should appear on the bottom
    map:addChild(tilemap)
    map:addChild(objectLayer)
    stage:addChild(map)
     
    local tileWidth = 30
    local tileHeight = 30
     
    --assuming obj is some type of sprite
    local function addObject(x,y,obj)
       if not objects[x] then objects[x] = {} end
       if not objects[x][y] then objects[x][y] = {} end
       objects[x][y] = obj -- put in 2D array to keep track of what tile the object is in
       obj:setPosition(getCoordsFromTilePos(x,y))
       objectLayer:addChild(obj)
    end
     
    --this assumes your arrays start with 1
    local function getCoordsFromTilePos(x,y)
       return tileWidth*(x-1),tileHeight*(y-1) 
    end
    I've just started using Gideros and am new to Lua, but I think this should be a decent way to go about this.
  • gorkemgorkem Maintainer
    I've just started using Gideros and am new to Lua, but I think this should be a decent way to go about this.
    Feel free to post your small code snippets of your own to relevant forum category if you feel it's beneficial to other community members :)
  • @zvardin
    Thank you very much, it's working :)>-
  • @sunnyguy Awesome! Glad to hear it!

    @gorkem When I have some that would be useful to most people definitely will! :) Really enjoying it so far!
Sign In or Register to comment.