Page 1 of 1

[Résolu] Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:19
by GameLy
Bonjour tout le monde,
J'ai un problème avec mon code en lua. C'est sensé être un "Bejeweld" (un genre de candy crush pour ceux qui ne connaissent pas). Le voici :

Code: Select all
-- Gemme --
Gemme = class()
function Gemme:init(color, y)
  self.color = {255*(color%2), 255*(math.floor(color/2)%2), 255*(math.floor(color/4)%4)}
  self.color2 = color
  self.y = y
end

function Gemme:fall()
  self.y = self.y - 0.2
end

function Gemme:paint(gc, x, y)
  gc:setColorRGB(unpack(self.color))
  gc:fillArc(11+20*(x-1), 8+20*(y-1), 17, 17, 0, 360)
end

-- Curseur --
Curs = {
  x = 0,
  y = 0,
  color = {c1, c2, c3}
}

function Curs:paint(gc)
  gc:setColorRGB(unpack(Curs.color))
  gc:drawRect(10+20*self.x, 7+20*self.y, 18, 18)
end

function Curs:move(dx, dy)
  Curs.x = Curs.x + dx
  Curs.y = Curs.y + dy
  platform.window:invalidate()
end

-- Selection --
Select = {
  crd = {}
}

function Select:Enter(cx, cy)
  local gemLink1, gemLink2 = {{}, {}}, {{}, {}}
  if self.crd[1] == nil and self.crd[2] == nil then
    self.crd = {cx, cy}
  elseif cx == self.crd[1] and cy == self.crd[2] then
    self.crd = {}
  elseif (cx+1 == self.crd[1] and cy == self.crd[2]) or (cx == self.crd[1] and cy+1 == self.crd[2]) or (cx-1 == self.crd[1] and cy == self.crd[2]) or (cx == self.crd[1] and cy-1 == self.crd[2]) then
    gemme_mat[cx+1][cy+1], gemme_mat[self.crd[1]+1][self.crd[2]+1] = gemme_mat[self.crd[1]+1][self.crd[2]+1], gemme_mat[cx+1][cy+1]
    local continue1, continue2, continue3, continue4, continue5, continue6, continue7, continue8 = true, true, true, true, true, true, true, true
    for i=1, 2 do
      if cx+i > 9 then
        continue1 = false
      elseif gemme_mat[cx+1+i][cy+1].color2 == gemme_mat[cx+1][cy+1].color2 and continue1 then
        table.insert(gemLink1[1], cx+i)
      else
        continue1 = false
      end
      if cx-i < 0 then
        continue2 = false
      elseif gemme_mat[cx-i+1][cy+1].color2 == gemme_mat[cx+1][cy+1].color2 and continue2 then
        table.insert(gemLink1[1], cx-i)
      else
        continue2 = false
      end
      if cy+i > 9 then
        continue3 = false
      elseif gemme_mat[cx+1][cy+1+i].color2 == gemme_mat[cx+1][cy+1].color2 and continue3 then
        table.insert(gemLink1[2], cy+i)
      else
        continue3 = false
      end
      if cy-i < 0 then
        continue4 = false
      elseif gemme_mat[cx+1][cy+1-i].color2 == gemme_mat[cx+1][cy+1].color2 and continue4 then
        table.insert(gemLink1[2], cy-i)
      else
        continue4 = false
      end
      if self.crd[1]+i > 9 then
        continue5 = false
      elseif gemme_mat[self.crd[1]+1+i][self.crd[2]+1].color2 == gemme_mat[self.crd[1]+1][self.crd[2]+1].color2 and continue5 then
        table.insert(gemLink2[1], self.crd[1]+i)
      else
        continue5 = false
      end
      if self.crd[1]-i < 0 then
        continue6 = false
      elseif gemme_mat[self.crd[1]-i+1][self.crd[2]+1].color2 == gemme_mat[self.crd[1]+1][self.crd[2]+1].color2 and continue6 then
        table.insert(gemLink2[1], self.crd[1]-i)
      else
        continue6 = false
      end
      if self.crd[2]+i > 9 then
        continue7 = false
      elseif gemme_mat[self.crd[1]+1][self.crd[2]+1+i].color2 == gemme_mat[self.crd[1]+1][self.crd[2]+1].color2 and continue7 then
        table.insert(gemLink2[2], self.crd[2]+i)
      else
        continue7 = false
      end
      if self.crd[2]-i < 0 then
        continue8 = false
      elseif gemme_mat[self.crd[1]+1][self.crd[2]+1-i].color2 == gemme_mat[self.crd[1]+1][self.crd[2]+1].color2 and continue8 then
        table.insert(gemLink2[2], self.crd[2]-i)
      else
        continue8 = false
      end
    end
    if #gemLink1[1] >= 2 then
      for k, v in ipairs(gemLink1[1]) do
        gemme_mat[v+1][cy+1] = false
      end
      gemme_mat[cx+1][cy+1] = false
    end
    if #gemLink1[2] >= 2 then
      for k, v in ipairs(gemLink1[2]) do
        gemme_mat[cx+1][v+1] = false
      end
      gemme_mat[cx+1][cy+1] = false
    end
    if #gemLink2[1] >= 2 then
      for k, v in ipairs(gemLink2[1]) do
        gemme_mat[v+1][self.crd[2]+1] = false
      end
      gemme_mat[self.crd[1]+1][self.crd[2]+1] = false
    end
    if #gemLink2[2] >= 2 then
      for k, v in ipairs(gemLink2[2]) do
        gemme_mat[self.crd[1]+1][v+1] = false
      end
      gemme_mat[self.crd[1]+1][self.crd[2]+1] = false
    end
    if #gemLink1[1] < 2 and #gemLink1[2] < 2 and #gemLink2[1] < 2 and #gemLink2[2] < 2 then
      gemme_mat[cx+1][cy+1], gemme_mat[self.crd[1]+1][self.crd[2]+1] = gemme_mat[self.crd[1]+1][self.crd[2]+1], gemme_mat[cx+1][cy+1]
    else
      Fall({unpack(gemLink1), unpack(gemLink2)})
    end
  end
  platform.window:invalidate()
end

function Fall(crdVide)
  for i=1, 5 do
    for k, v in ipairs(crdVide) do
        gemme_mat[v[1]][v[2]]:fall() -- La ligne qui pose problème !
    end
  end
end

function Select:paint(gc)
  gc:setColorRGB( (255+Curs.color[1])/3, (255+Curs.color[2])/3, (255+Curs.color[3])/3)
  if self.crd[1] and self.crd[2] then
    gc:drawRect(10+20*self.crd[1], 7+20*self.crd[2], 18, 18)
  end
end

gemme_mat = {}

function Randomize()
  for i=1,10,1 do
    col = {}
    for j=1,10,1 do
      table.insert(col, Gemme(math.floor( math.random(1, 6) ), j))
    end
    table.insert(gemme_mat, col)
  end
end

function on.create()
  local score = 0
  if not(hscore) then
    hscore = 0
  end
  Randomize()
end

function on.paint(gc)
  for i=1,10,1 do
    gc:drawRect(9, 6, 20*i, 20*i)
  end
  for i=1,10,1 do
    gc:drawRect(209-20*i, 206-20*i, 20*i, 20*i)
  end
  gc:drawRect(219, 6, 90, 40)
  gc:drawRect(219, 66, 90, 40)
  gc:setFont("sansserif", "r", 10)
  gc:drawString("Score:", 264-gc:getStringWidth("Score:")/2, 8, "top")
  gc:drawString("High-Score:", 264-gc:getStringWidth("High-Score:")/2, 68, "top")
  for k, v in ipairs(gemme_mat) do
    for ka, va in ipairs(v) do
      if va then
        va:paint(gc, k, ka)
      end
    end
  end
  Curs:paint(gc)
  Select:paint(gc)
end

function on.charIn(char)
  if (char == "4") and (Curs.x > 0) then
    Curs:move(-1, 0)
  elseif (char == "6") and (Curs.x < 9) then
    Curs:move(1, 0)
  elseif (char == "8") and (Curs.y > 0) then
    Curs:move(0, -1)
  elseif (char == "2") and (Curs.y < 9) then
    Curs:move(0, 1)
  elseif char == "3" then
    if (Curs.x < 9) and (Curs.y < 9) then
      Curs:move(1, 1)
    elseif (Curs.x == 9) and (Curs.y < 9) then
      Curs:move(0, 1)
    elseif (Curs.x < 9) and (Curs.y == 9) then
      Curs:move(1, 0)
    end
  elseif char == "9" then
    if (Curs.x < 9) and (Curs.y > 0) then
      Curs:move(1, -1)
    elseif (Curs.x == 9) and (Curs.y > 0) then
      Curs:move(0, -1)
    elseif (Curs.x < 9) and (Curs.y == 0) then
      Curs:move(1, 0)
    end
  elseif char == "1" then
    if (Curs.x > 0) and (Curs.y < 9) then
      Curs:move(-1, 1)
    elseif (Curs.x == 0) and (Curs.y < 9) then
      Curs:move(0, 1)
    elseif (Curs.x > 0) and (Curs.y == 9) then
      Curs:move(-1, 0)
    end
  elseif char == "7" then
    if (Curs.x > 0) and (Curs.y > 0) then
      Curs:move(-1, -1)
    elseif (Curs.x == 0) and (Curs.y > 0) then
      Curs:move(0, -1)
    elseif (Curs.x > 0) and (Curs.y == 0) then
      Curs:move(-1, 0)
    end
  end
  if char == "5" then
    Select:Enter(Curs.x, Curs.y)
  end
end

function on.enterKey()
  Select:Enter(Curs.x, Curs.y)
end


Il n'y a pas tout le code, juste ce qui peut poser problème.

Il me dit après avoir aligner trois gemmes : "150: attempt to index field '?' (a nil value)" (La ligne qui pose problème est signalé dans le code). Pourtant, gemme_mat est belle et bien définit car dans la fonction précédente, elle fonctionne.
Si quelqu'un a une idée, je suis preneur

P.S. : Pas de critique de mon code svp, je sais qu'il n'est pas optimisé ^^.
P.P.S. : J'adore ce site, il est très complet ;).

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:25
by s0r00t
Note : je n'ai jamais fait de Lua sur Nspire, mais j'en ai fait ailleurs.

Si on prend ton code, ceci est effectué :
Code: Select all
gemme_mat[v[1]][v[2]]:fall()


As-tu vérifié que l'objet gemme_mat contient une valeur à l'index v[1]?
Alors, si gemme_mat[v[1]] n'est pas nil, c'est gemme_mat[v[1]][v[2]] qui est nil.

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:29
by GameLy
Il pense en effet que gemme_mat = nil, or je suis sûr que non. Si tu regardes bien, la fonction Fall est appelé dans une autre fonction : Select:Enter, or dans Select:Enter, la variable fonctionne très bien.

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:32
by s0r00t
En lisant ton code, j'ai vu que gemme_mat était définie après la fonction... C'est peut-être ça?

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:33
by GameLy
Je vais essayer de le mettre avant alors, mais c'est bizarre, encore une fois, il marche dans la fonction précédente.

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:35
by GameLy
Non, ça ne marche pas non plus.

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:37
by Adriweb
Déjà: je vois que tu utilises "on.create". Cet événement n'est plus utilisable dans les APIs récents (depuis plusieurs années en fait). (Si tu as une version antérieur à 4.2, je te conseille d'updater)
Dans ton cas, puisque tu ne fais rien de spécial par rapport à l'API Nspire dans cette fonction, tu peux remplacer ça par "on.construction".

Ensuite, c'est pas gemme_mat qui est nil, mais crdVide qui est pas bon. quand tu itères dessus, v[1] et v[2] sont nil, comme tu peux le voir en faisant print(k, v, v[1], v[2]) par exemple
Donc, en gros, quand tu appelles ça avec {unpack(gemLink1), unpack(gemLink2)}, c'est visiblement pas comme ça qu'il faut faire... (vérifie que gemLink1/2 sont corrects)

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 21:44
by GameLy
Je suis sur TIDE, comment puis-je voir ce qu'affiche print() ?

Mes gemLink1/2 fonctionnent très bien aussi. Il faut que je regarde pour le unpack() alors.

Merci pour le "on.create".

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 31 Mar 2016, 22:11
by Adriweb
TIDE n'est plus à jour depuis longtemps, il me semble, utilise plutôt Jens' Script Editor: https://tiplanet.org/forum/archives_voir.php?id=88209 ?
M'enfin programmer sur le logiciel Nspire ordinateur est tout de même bien plus confortable (et plus encore avec un vrai IDE Lua (je conseille Intellij IDEA + plugin Lua), couplé avec Luna)

Re: Problème "attempt to index field '?' (a nil value)"

Unread postPosted: 01 Apr 2016, 13:44
by GameLy
D'accord, merci pour ces conseils. Je préfère aussi coder sur ordinateur, mais l'avantage d'avoir TIDE est que je peux coder dans n'importe quel endroit. Mais je vais passer sur Jens' alors.