Fixed: Code behavior difference between Love and Lua Interpreter

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
Zahren
Prole
Posts: 1
Joined: Sat Feb 08, 2025 3:13 am

Fixed: Code behavior difference between Love and Lua Interpreter

Post by Zahren »

Update

This was caused by arg being deprecated in 5.1. In my local environment a compatibility setting enabled ... to be automatically sent to arg, this setting was off in love2d.

Setting ... to a local arg table solves the issue.

Related stack exchange https://stackoverflow.com/questions/482 ... g-variable

Original Post

Hello, I've been working through a bug with a class implementation I'm using for my game. When initializing an object in love the init function will fail to set values for objects, but still be able to create empty objects for the instance. When the same init function is run through an interpreter in the command line it has no issues updating values in the call to new.

The interpreter is running Lua 5.1.5

As an example calling the below won't set self.entity within PLAYER_HEALTH_BAR

Code: Select all


-- initializing won't work by itself when using love
PLAYER_HEALTH_BAR = cHealthBar:new(CHARACTER)

-- errors out if run in love, but a comparable print in the interpreter works fine
-- health is null despite health being set by CHARACTER in call to new
love.graphics.print(PLAYER_HEALTH_BAR:test_get().health)

but if you set self.entity separately it works fine

Code: Select all

PLAYER_HEALTH_BAR = cHealthBar:new(CHARACTER)
PLAYER_HEALTH_BAR:set_entity(CHARACTER)
-- everything across the globe is great, the health prints!
love.graphics.print(PLAYER_HEALTH_BAR:test_get().health)
Would love some suggestions for what's going on here and how I can get initialization working in love, thanks!

Class implementation (pulled from http://lua-users.org/wiki/ClassesAndMethodsExample):

Code: Select all

BaseObject = {
  super = nil,
  name = "Object",
  new = 
    function(class)
        local obj = {class = class}
        local meta = {
            __index = function(self,key) return class.methods[key] end 
        }            
        setmetatable(obj, meta)
        return obj
    end,
  methods = {classname = function(self) return(self.class.name) end},
  data = {}
}

function setclass(name, super)
  if (super == nil) then
    super = BaseObject
  end

  local class = {
    super = super; 
    name = name; 
    new =
        function(self, ...) 
            local obj = super.new(self, "___CREATE_ONLY___")
            -- check if calling function init
            -- pass arguments into init function
            if (super.methods.init) then
                obj.init_super = super.methods.init
            end

            if (self.methods.init) then
                if (tostring(arg[1]) ~= "___CREATE_ONLY___") then
                    obj.init = self.methods.init
                    if obj.init then
                      obj:init(unpack(arg))
                    end
                end
            end

            return obj
        end,  
    methods = {}
  }
    
  -- if class slot unavailable, check super class
  -- if applied to argument, pass it to the class method new        
  setmetatable(class, {
    __index = function(self,key) return self.super[key] end,
    __call  = function(self,...) return self.new(self,unpack(arg)) end 
  })

  -- if instance method unavailable, check method slot in super class    
  setmetatable(class.methods, {
    __index = function(self,key) return class.super.methods[key] end
  })
  return class
end

HealthBar implementation:

Code: Select all

require("baseClass")

cHealthBar = setclass("HealthBar")

function cHealthBar.methods:init(entity, options)
    if entity == nil then
        error('Missing argument.')
    end

    if options == nil then
        options = {}
    end
    if options.x == nil then
        options.x = 0
    end
    if options.y == nil then
        options.y = 0
    end
    if options.offset == nil then
        options.offset = 20
    end

    --self:set_entity(entity)
    ---self.entity = entity
    self.x = options.x
    self.y = options.y
    self.height = 10
    self.width = 100
end

function cHealthBar.methods:set_entity(entity)
    self.entity = entity
end

function cHealthBar.methods:draw()
    local name = tostring(self.entity.name)
    local health = tostring(self.entity.health)
    local max_health = tostring(self.entity.max_health)
    local health_percentage = self.entity.health / self.entity.max_health

    -- Print text information
    love.graphics.setColor(255, 0, 0)
    love.graphics.print(name .. health .. '/' .. max_health, self.x, self.y)

    -- Draw health bar
    love.graphics.rectangle('fill', self.x, self.y, health_percentage*self.width, 10)
    love.graphics.rectangle('line', self.x, self.y, self.width, 10)
end

function cHealthBar.methods:test_get()
    return self.entity.health, self.entity.max_health
end
Post Reply

Who is online

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