Search code examples
luagame-development

My class is a boolean and i don't know why


I start to create a class Button in a file : main.lua with the rest of my code. Everything works but now i want to split my code and create a button.lua file like this :


Button = {}

function Button:new(x, y, width, height, color, text, callback,arg1)
  local button = {
      x = x,
      y = y,
      width = width,
      height = height,
      color = color,
      text = text,
      callback = callback,
      arg1 = arg1,
      state = false,
  }
  setmetatable(button, self)
  self.__index = self
  return button
end

function Button:draw()
  local color = self.hover and {0.8, 0.8, 0.8} or self.color
  love.graphics.setColor(color)
  love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
  if self.hover then
      love.graphics.setColor(1, 1, 1)
      love.graphics.rectangle("line", self.x-1, self.y-1, self.width+2, self.height+2)
  end
  if self.state == true then
      self.callback(self)
  end
  -- Affichage du texte
  love.graphics.setColor(0, 0, 0) -- couleur du texte noir
  local scale = self.height / 50
  local font = love.graphics.newFont(12*scale) 
  love.graphics.setFont(font)
  love.graphics.printf(self.text, self.x, self.y + self.height / 2 - 10, self.width, "center")
end

function Button:update(dt)
  -- On récupère la position de la souris
  local mouseX, mouseY = love.mouse.getPosition()
  -- On vérifie si la souris est dans la zone du bouton
  self.hover = mouseX > self.x and mouseX < self.x + self.width and mouseY > self.y and mouseY < self.y + self.height
  if self.hover and love.mouse.isDown(1) and self.state == false then
      self.state = true
  end
end

and change my main.lua file like this :

-- Définition de la classe Button
local Button = require('button')
local current_text = 1 -- Index du texte courant à afficher
local boxstate = false


function createTextbox(button)
    boxstate = true
    local text = button.arg1[current_text]
    local screen_width, screen_height = love.graphics.getDimensions()
    -- On vérifie si on est à la fin de la liste de textes
    if current_text == #button.arg1 then
        boxstate = false
        button.state = false
        current_text = 1
        return
    end
    -- On définit la couleur verte
    love.graphics.setColor(0, 1, 0)
    -- On dessine le rectangle
    love.graphics.rectangle("fill", 0, screen_height - screen_height/4, screen_width, screen_height/4)
    -- On définit la couleur noire pour le texte
    love.graphics.setColor(0, 0, 0)
    -- On dessine le texte
    love.graphics.print(text, 0, screen_height - screen_height/4)

    draw_arrow_moving()

  end

  local xa = love.graphics.getWidth()-20
local ya = love.graphics.getHeight()
-- amplitude du mouvement de la tête de flèche (en pixels)
local amplitude = 30
-- vitesse de déplacement de la tête de flèche (en cycles par seconde)
local speed = 1

local texts = { "texte1", "texte2", "texte3","end" } -- Liste des textes à afficher

-- fonction pour afficher une tête de flèche mobile
function draw_arrow_moving()
    -- définition de la couleur rouge
    love.graphics.setColor(1, 0, 0)
    -- dessin de la tête de flèche
    love.graphics.polygon("fill", xa, ya, xa+10, ya-10, xa, ya-20)
  end
  
  
-- pour l'utiliser:
-- création d'un tableau de boutons
buttons = {}

-- ajout de deux boutons au tableau
table.insert(buttons, Button:new(200, 10, 200, 100, {0, 0, 1}, "Mon bouton", createTextbox, texts)) -- bouton bleu avec texte "Bouton bleu"

function love.load()
    -- largeur et hauteur de la fenêtre
    love.window.setFullscreen(true)
    -- titre de la fenêtre
    love.window.setTitle("Mon jeu")
  end  

function love.update(dt)
    for _, button in ipairs(buttons) do
        button:update()
    end  
      -- met à jour la position de la tête de flèche
  local t = love.timer.getTime()
  xa = (love.graphics.getWidth() - 70) + amplitude * math.sin(t * speed * 2 * math.pi)
  ya = love.graphics.getHeight() - 20

end

function love.mousepressed(x, y, button, istouch)
    if button == 1 then
        if x > 0 and x < love.graphics.getWidth() and y > love.graphics.getHeight() - love.graphics.getHeight()/4 and y < love.graphics.getHeight() and boxstate == true then
            current_text = current_text + 1
            if current_text > #texts then
                current_text = 1
            end
        end
    end
end


function love.draw()
    -- affichage de tous les boutons
    for _, button in ipairs(buttons) do
      button:draw()
    end
end  

but i have this

Error: main.lua:54: attempt to index local 'Button' (a boolean value)
stack traceback:
    [love "boot.lua"]:345: in function '__index'
    main.lua:54: in main chunk
    [C]: in function 'require'
    [love "boot.lua"]:316: in function <[love "boot.lua"]:126>
    [C]: in function 'xpcall'
    [love "boot.lua"]:355: in function <[love "boot.lua"]:348>
    [C]: in function 'xpcall'

and i don't know why

i already try to combine my two code in my main and it works


Solution

  • Quoting the Lua 5.1 reference manual:

    If the loader returns no value and has not assigned any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the final value of package.loaded[modname].

    This is the reason you get a boolean: You require the module by creating the local variable Button, but in the button.lua module you forgot to return the contents of the module:

    local Button = {}
    
    function Button:new(x, y, width, height, color, text, callback,arg1)
    --
    end
    function Button:draw()
    --
    end
    
    function Button:update(dt)
    --
    end
    
    return Button
    

    PS: it is good practice to declare the Button locally