help with creating a game sokoban - (solved)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
luislasonbra
Citizen
Posts: 60
Joined: Sun Jun 24, 2012 1:57 pm

help with creating a game sokoban - (solved)

Post by luislasonbra »

hi i am trying to create a game of Sokoban,
but I can not make the collide with other blokes.

eg

block 1 >= block2 == collide.

screenshot

Image

code
Push Box.love
(1.43 KiB) Downloaded 169 times
Last edited by luislasonbra on Mon Aug 26, 2013 4:09 pm, edited 1 time in total.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: help with creating a game sokoban

Post by micha »

Before I come to your specific problem, one general remark:
You can simplify you code a lot. First of all, all boxes have the size of a grid cell, so there is no real need to store width and height of the boxes. The same goes for the player itself. Second, you don't need the generic AABB-Collision check, since you know that all boxes and the player are grid aligned. Third, I very much suggest you store the player's and all other coordinates in grid coordinates, not in screen coordinates (that means e.g. (2,1) instead of (64,32)). Then you can save the math.floor(player.y/32)-part and just use player.y. Only the drawing then needs to know the grid size so for the drawing you write

Code: Select all

love.graphics.rectangle(player.x*32,player.y*32,32,32)
or even better

Code: Select all

love.graphics.rectangle(player.x*dx,player.y*dx,dx,dx)
and you can change dx later, if you decide you want to zoom in more.

Now for the box-box collision: I suggest you put your boxes into the map-array(table) itsself. Your code would then look like this:

Code: Select all

    map = {
        {1, 1, 1, 1},
        {1, 0, 0, 1},
        {1, 0, 0, 1, 1, 1},
        {1, 2, 0, 0, 0, 1},
        {1, 0, 0, 2, 0, 1},
        {1, 0, 0, 1, 1, 1},
        {1, 1, 1, 1},   
    }
I put a 2 for each box.
That way checking should be easy: If the player presses a button, then first check if the new cell is empty. If so-> no problem. Otherwise, if there is a 2 in the cell, check the next cell (the one behind the new cell). If this is empty, then move both player and the box otherwise, don't move.

By the way, I suggest you do not split the movement code into both love.keypressed and love.update. Everything of the collision detection, including the boxes, should be done in the love.keypressed.
User avatar
luislasonbra
Citizen
Posts: 60
Joined: Sun Jun 24, 2012 1:57 pm

Re: help with creating a game sokoban

Post by luislasonbra »

micha wrote:Before I come to your specific problem, one general remark:
You can simplify you code a lot. First of all, all boxes have the size of a grid cell, so there is no real need to store width and height of the boxes. The same goes for the player itself. Second, you don't need the generic AABB-Collision check, since you know that all boxes and the player are grid aligned. Third, I very much suggest you store the player's and all other coordinates in grid coordinates, not in screen coordinates (that means e.g. (2,1) instead of (64,32)). Then you can save the math.floor(player.y/32)-part and just use player.y. Only the drawing then needs to know the grid size so for the drawing you write

Code: Select all

love.graphics.rectangle(player.x*32,player.y*32,32,32)
or even better

Code: Select all

love.graphics.rectangle(player.x*dx,player.y*dx,dx,dx)
and you can change dx later, if you decide you want to zoom in more.

Now for the box-box collision: I suggest you put your boxes into the map-array(table) itsself. Your code would then look like this:

Code: Select all

    map = {
        {1, 1, 1, 1},
        {1, 0, 0, 1},
        {1, 0, 0, 1, 1, 1},
        {1, 2, 0, 0, 0, 1},
        {1, 0, 0, 2, 0, 1},
        {1, 0, 0, 1, 1, 1},
        {1, 1, 1, 1},   
    }
I put a 2 for each box.
That way checking should be easy: If the player presses a button, then first check if the new cell is empty. If so-> no problem. Otherwise, if there is a 2 in the cell, check the next cell (the one behind the new cell). If this is empty, then move both player and the box otherwise, don't move.

By the way, I suggest you do not split the movement code into both love.keypressed and love.update. Everything of the collision detection, including the boxes, should be done in the love.keypressed.

hi sorry for the delay in my response.

thanks for your help achieve make colipciones call in total, plus the code is now cleaner

here I leave the code in case anyone is interested.

Code: Select all

function love.load()
    map = {
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 3, 1},
        {1, 0, 2, 0, 0, 0, 2, 0, 3, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 3, 1},
        {1, 0, 2, 0, 0, 0, 2, 0, 3, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
    }
    
    texto = ""
    ShearTileMap()
    
    totalBlockAcert = 0
    isGameFinish = ""
    
    player = {}
    player.x = 2
    player.y = 2
end

function love.update(dt)
    if totalBlockAcert == 4 then
        isGameFinish = "Juego terminado."
    end
end

function love.keypressed(key)
   if key == "up" then
      if IsPlayerMove(player.x, player.y - 1, "up") and MoveBox(player.x, player.y - 1, "up") then
         player.y = player.y - 1
      end
   elseif key == "down" then
      if IsPlayerMove(player.x, player.y + 1, "down") and MoveBox(player.x, player.y + 1, "down") then
         player.y = player.y + 1
      end
   elseif key == "left" then
      if IsPlayerMove(player.x - 1, player.y, "left") and MoveBox(player.x - 1, player.y, "left") then
         player.x = player.x - 1
      end
   elseif key == "right" then
      if IsPlayerMove(player.x + 1, player.y, "right") and MoveBox(player.x + 1, player.y, "right") then
         player.x = player.x + 1
      end
   end 
end

function love.draw()
    DrawMap()
    
    PlayerDraw()
    
    love.graphics.print(texto, 400, 32)
    
    love.graphics.print("Blokes Colocados: " .. totalBlockAcert, 0, 0)
    love.graphics.print("GameState: " .. isGameFinish, 150, 0)
end

local count = 0
function ShearTileMap()
    texto = ""
    count = 0
    for y = 1, #map do
       for x = 1, #map[y] do
           
           if count == #map then texto = texto .. "\n"; count = 0 end
           if count < #map - 1 then texto = texto .. map[y][x] .. ", " else texto = texto .. map[y][x] end
           count = count + 1
           
       end 
    end
end

function DrawMap()
    for y = 1, #map do
       for x = 1, #map[y] do
           
           if map[y][x] == 1 then love.graphics.rectangle("line", x * 32, y * 32, 32, 32) end
           
           love.graphics.setColor(255, 0, 0)
           if map[y][x] == 2 then love.graphics.rectangle("line", x * 32, y * 32, 32, 32) end
           love.graphics.setColor(255, 255, 255)
           
           love.graphics.setColor(88, 90, 234)
           if map[y][x] == 3 then love.graphics.rectangle("line", x * 32, y * 32, 32, 32) end
           love.graphics.setColor(255, 255, 255)
           
           love.graphics.setColor(0, 195, 254)
           if map[y][x] == 4 then love.graphics.rectangle("line", x * 32, y * 32, 32, 32) end
           love.graphics.setColor(255, 255, 255)
           
       end 
    end 
end

function PlayerDraw()
    love.graphics.rectangle("fill", player.x * 32, player.y * 32, 32, 32)
end

function IsPlayerMove(ax, ay, direct)
    if direct == "up" then
       if map[ay][ax] == 1 then return false end
    elseif direct == "down" then
       if map[ay][ax] == 1 then return false end
    elseif direct == "left" then
       if map[ay][ax] == 1 then return false end
    elseif direct == "right" then
       if map[ay][ax] == 1 then return false end
    end
    
    return true
end

function CheckFinishBlock()
    totalBlockAcert = 0
    for y = 1, #map do
       for x = 1, #map[y] do
          if map[y][x] == 4 and totalBlockAcert <= 3 then
             totalBlockAcert = totalBlockAcert + 1
          end
       end 
    end
end

-- Function para saber si hay collipcion entre las cajas....
function MoveBox(ax, ay, direct)
    if direct == "up" then
        if map[ay][ax] == 2 or map[ay][ax] == 4 then
           
           if (map[ay-1][ax] == 4) or (map[ay-1][ax] == 2) or (map[ay-1][ax] == 1) then return false end
           if map[ay-1][ax] == 3 then map[ay-1][ax] = 4 else map[ay-1][ax] = 2 end
           if map[ay][ax] == 4 then map[ay][ax] = 3 else map[ay][ax] = 0 end
           
           ShearTileMap() -- Actualiza el texto que aparece al lado derecho.....
           CheckFinishBlock()
           
           return true
        end
    elseif direct == "down" then
        if map[ay][ax] == 2 or map[ay][ax] == 4 then
           
           if (map[ay+1][ax] == 4) or (map[ay+1][ax] == 2) or (map[ay+1][ax] == 1) then return false end
           if map[ay+1][ax] == 3 then map[ay+1][ax] = 4 else map[ay+1][ax] = 2 end
           if map[ay][ax] == 4 then map[ay][ax] = 3 else map[ay][ax] = 0 end
           
           ShearTileMap() -- Actualiza el texto que aparece al lado derecho.....
           CheckFinishBlock()
           
           return true
        end
    elseif direct == "left" then
        if map[ay][ax] == 2 or map[ay][ax] == 4 then
           
           if (map[ay][ax-1] == 4) or (map[ay][ax-1] == 2) or (map[ay][ax-1] == 1) then return false end
           if map[ay][ax-1] == 3 then map[ay][ax-1] = 4 else map[ay][ax-1] = 2 end
           if map[ay][ax] == 4 then map[ay][ax] = 3 else map[ay][ax] = 0 end
           
           ShearTileMap() -- Actualiza el texto que aparece al lado derecho.....
           CheckFinishBlock()
           
           return true
        end
    elseif direct == "right" then
        if map[ay][ax] == 2 or map[ay][ax] == 4 then
            
           if (map[ay][ax+1] == 4) or (map[ay][ax+1] == 2) or (map[ay][ax+1] == 1) then return false end
           if map[ay][ax+1] == 3 then map[ay][ax+1] = 4 else map[ay][ax+1] = 2 end
           if map[ay][ax] == 4 then map[ay][ax] = 3 else map[ay][ax] = 0 end
           
           ShearTileMap() -- Actualiza el texto que aparece al lado derecho.....
           CheckFinishBlock()
           
           return true
        end
    end
    
    return true
end
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: help with creating a game sokoban - (solved)

Post by Ranguna259 »

Are you Portuguese or Spanish ?
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
luislasonbra
Citizen
Posts: 60
Joined: Sun Jun 24, 2012 1:57 pm

Re: help with creating a game sokoban - (solved)

Post by luislasonbra »

Ranguna259 wrote:Are you Portuguese or Spanish ?
Spanish
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: help with creating a game sokoban - (solved)

Post by Ranguna259 »

Welcome to the forum :)
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
luislasonbra
Citizen
Posts: 60
Joined: Sun Jun 24, 2012 1:57 pm

Re: help with creating a game sokoban - (solved)

Post by luislasonbra »

Ranguna259 wrote:Welcome to the forum :)
Thanks
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 4 guests