Reputation: 193
I'm trying to make a chess game but i'm just starting to learn corona, and i'm having some difficulty to move the pieces on the board
here is how I do it:
to make the board:
First i make the full board without any special pieces:
local function MakeBoard()
local boardIndex = 0
for i = 1, tilesAcross do
if not boardImg[i] then
boardImg[i] = {};
end
for j = 1, tilesDown do
boardIndex = boardIndex + 1
boardImg[i][j] = spawn({image = images[1].getFile , w = tileWidth, h = tileHeight, objTable = spawnTableBoard}) -- board image
boardImg[i][j].x = (j - 1) * (tileWidth + tileSpacing) + leftSpacing
boardImg[i][j].y = (i - 1) * (tileHeight + tileSpacing) + topSpacing
boardImg[i][j].testx = i
boardImg[i][j].testy = j
boardImg[i][j]boardIndex = boardIndex
end
end
Then I put the piece on the board:
local pieceIndex = 0
for i = 1, tilesAcross do
if not pieceImg[i] then
pieceImg[i] = {};
end
for j = 1, tilesDown do
pieceIndex = pieceIndex + 1
boardIndex = boardIndex + 1
local imagesId = levels[boardIndex]
if imagesId ~= 1 then
pieceImg[i][j] = spawn({image = images[imagesId].getFile , w = tileWidth, h = tileHeight, objTable = spawnTablePiece})
pieceImg[i][j].x = (j - 1) * (tileWidth + tileSpacing) + leftSpacing
pieceImg[i][j].y = (i - 1) * (tileHeight + tileSpacing) + topSpacing
pieceImg[i][j].testx = i
pieceImg[i][j].testy = j
pieceImg[i][j].pieceIndex = pieceIndex
pieceImg[i][j]:addEventListener("tap", select)
end
end
In my select event, I add an event on the board where the piece can move(there is a lot of useless thing and useless stuff because I went in so many direction but this is what the important part look like:
local function select(event)
if selectedpiece == event.target then
for i = 1, #spawnTableBoard do
spawnTableBoard[i]:setFillColor( 255,255 )
end
selectedpiece = nil -- if you click on the same piece as before, we cancel the selection
else
selectedpiece = nil
for i = 1, #spawnTableBoard do
spawnTableBoard[i]:setFillColor( 255,255 )
spawnTableBoard[i]:removeEventListener( "tap", move )
end
selectedpiece = event.target
selectedpiece._x = event.target.testx -- the x value according to the grid
selectedpiece._y = event.target.testy -- the y value according to the grid
if piece[selectedpiece._x][selectedpiece._y].testx == levelImg[selectedpiece._x][selectedpiece._y].testx then -- temporary test to check which piece we clicked
levelImg[levelImg[selectedpiece._x][selectedpiece._y].testx][2]:setFillColor( 255,0,0 ) -- also for testing purpose
levelImg[1][2]:addEventListener("tap", move)
end
end
return true
end
and then comes my move event, and I guess that the problem come from there, i'm doing a transition to move the piece where the player clicked and it works without problem but if I click on the piece that i just move, i have a bug in my select event where the piece object is nil (the piece object is a global : local piece = {} ) and I can't click on it again, but the other piece are still working, so basically i can move every piece only one time.
I guess it's because when I do the transition the image move but the array is not updated correclty or something like that.
local function move(event)
if selectedpiece then
transition.to( selectedpiece, {time = 100, x = spawnTableBoard[event.target.index].x, y = spawnTableBoard[event.target.index].y} )
selectedpiece.playerIndex = event.target.index
piece[selectedpiece._x][selectedpiece._y] = selectedpiece
piece[selectedpiece._x][selectedpiece._y].testx = event.target.testx
piece[selectedpiece._x][selectedpiece._y].testy = event.target.testy
for i = 1, #spawnTableBoard do
spawnTableBoard[i]:setFillColor( 255,255 )
spawnTableBoard[i]:removeEventListener( "tap", move )
spawnTableBoard[i]:removeEventListener( "tap", select )
end
selectedpiece = nil
end
end
Any help would be greatly appreciate! Or if i'm going the wrong way with my logic, please let me know.
Upvotes: 1
Views: 140
Reputation: 29573
I think it is because you remove the tap event listener in the select
function. The code you show doesn't indicate what is spawnTableBoard
, but this is where you remove tap listeners. But there are also several other places where things could go wrong: maybe selectedpiece
remains nil after a piece that has already been moved is selected, so move
does nothing; or maybe select
In terms of logic, you might simplify or clarify your code by thinking in terms of states: after initialization, your game seems to either be in state "waiting for selection", "waiting for destination" or "moving". The 3rd state "moving" implies that until your piece has arrived at destination, your turn is not over. If you have two types of tap listeners, one for pieces, one for squares, then each listener can easily decide what to do based on active state.
For instance, after initialization, the game automatically transitions from "init" to "waiting for piece selection" (set variable currentState='wait for selection'
). The "squares" tap handlers would look something like:
local function someSquare:tap(event)
if currentState == 'wait for piece selection' then
print('square has nothing to do while waiting for piece selection')
elif currentState == 'wait for destination' then
start transition.to with onComplete = function()
if piece there then remove it
set new position, updage grid (undo highlight of from/to squares) etc
transition to 'waiting for piece selection'
end
switch state to 'moving piece'
elif currentState == 'moving piece' then
if tapped square is same as square of selected piece then cancel transition
else
error("BUG: unrecognized state")
end
end
Similarly the piece tap handlers would look like:
local function somePiece:tap(event)
if currentState == 'wait for piece selection' then
transitionObj = transition.to(self, {..., onComplete = function()
if destination has piece then remove it
set new position of piece
updage grid (reset highlights etc)
currentState = 'waiting for piece selection'
end}
currentState = 'moving piece'
elif currentState == 'wait for destination' then
selectedPiece = nil
currentState = 'waiting for piece selection'
inform user that selection cancelled (undo highlight of square, whatever)
elif currentState == 'moving piece' then
transition.cancel(transitionObj)
transitionObj = nil
-- following lines probably identical to 'wait for destination' so probably put in function
selectedPiece = nil
currentState = 'waiting for piece selection'
inform user that selection cancelled (undo highlight of square, whatever)
else
error("BUG: unrecognized state")
end
end
This will dramatically cleanup your logic by virtue of the fact that your game is in a known state, so some things are "impossible" and you don't need to test for them (though asserts are handy as sanity checks).
Upvotes: 2