Custom animation system not working, no reason why

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.
SpeedySloth
Prole
Posts: 9
Joined: Thu Jul 19, 2018 7:52 pm

Custom animation system not working, no reason why

Post by SpeedySloth »

So I'm trying to add animations to my project, and recently I've noticed a number of issues that seem to make no sense, however I'm only going to mention one here, because this one in particular has literally (as far as I know) no reason to occur. Basically, when I assign an animation to a variable, and use that as the player's animation, the animation is distorted, but when I just create a new animation, everything's fine.

Here's my code:

Code: Select all

function gamestate.loadimages()
    gamestate.playerupanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerUpAnim.png")
    gamestate.playerdownanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerDownAnim.png")
    gamestate.playerleftanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerLeftAnim.png")
    gamestate.playerrightanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerRightAnim.png")

    gamestate.playerswingupanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerSwingDownAnim.png")
    gamestate.playerswingdownanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerSwingDownAnim.png")
    gamestate.playerswingleftanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerSwingDownAnim.png")
    gamestate.playerswingrightanimatlas = love.graphics.newImage("Assets/Graphics/Player Animations/PlayerSwingDownAnim.png")
end

function gamestate.initanims()
    gamestate.playerupanim = animation:new(gamestate.playerupanimatlas, 10, 2, 16, 32)
    gamestate.playerdownanim = animation:new(gamestate.playerdownanimatlas, 10, 2, 16, 32)
    gamestate.playerleftanim = animation:new(gamestate.playerleftanimatlas, 10, 2, 16, 32)
    gamestate.playerrightanim = animation:new(gamestate.playerrightanimatlas, 10, 2, 16, 32)

    gamestate.playeranims = 
    {
        moveupanim = gamestate.playerupanim,
        movedownanim = gamestate.playerdownanim,
        moveleftanim = gamestate.playerleftanim,
        moverightanim = gamestate.playerleftanim,
    }

    gamestate.playerswingupanim = animation:new(gamestate.playerswingupanimatlas, 30, 2, 16, 32)
    gamestate.playerswingdownanim = animation:new(gamestate.playerswingdownanimatlas, 30, 2, 16, 32)
    gamestate.playerswingleftanim = animation:new(gamestate.playerswingleftanimatlas, 30, 2, 16, 32)
    gamestate.playerswingrightanim = animation:new(gamestate.playerswingrightanimatlas, 30, 2, 16, 32)

    gamestate.playerswinganims = 
    {
        swingupanim = gamestate.playerswingupanim,
        swingdownanim = gamestate.playerswingdownanim,
        swingleftanim = gamestate.playerswingleftanim,
        swingrightanim = gamestate.playerswingrightanim,
    }
end
And this is the strange part. When I type this:

Code: Select all

player.animations = gamestate.playeranims
player.currentanim = player.animations.moveupanim
everything looks weird, but when I type this:

Code: Select all

player.animations = gamestate.playeranims
player.currentanim = animation:new(gamestate.playerupanimatlas, 10, 2, 16, 32)
everything works. You'll notice that the animation used in the latter example is the exact same animation used in the former, so why are they yielding different results? Is this a known but (I'm new to Love2D). Any insight is appreciated!
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Custom animation system not working, no reason why

Post by pgimeno »

Hello, welcome to the forums. Without any code to examine, all we can do is guess. My guess here is that you may be altering table contents through references. Consider this:

Code: Select all

$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> a = {x=1}
> b = a
> b.x = 2
> print(a.x)
2
Tables are mutable objects that exist in memory. A variable is a reference to the object, and if you assign a variable to another, you're copying the reference, not the object. After the line 'b=a' there's only one table object, but there are two references to it, and if it's altered through one reference, the results become visible through the other reference.

Or I may be wrong in my guess, in which case it would help if you can attach a .love file that we can examine, to try to find out where the problem can be rather than guessing.
SpeedySloth
Prole
Posts: 9
Joined: Thu Jul 19, 2018 7:52 pm

Re: Custom animation system not working, no reason why

Post by SpeedySloth »

pgimeno wrote: Thu Jul 19, 2018 11:49 pm Hello, welcome to the forums. Without any code to examine, all we can do is guess. My guess here is that you may be altering table contents through references. Consider this:

Code: Select all

$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> a = {x=1}
> b = a
> b.x = 2
> print(a.x)
2
Tables are mutable objects that exist in memory. A variable is a reference to the object, and if you assign a variable to another, you're copying the reference, not the object. After the line 'b=a' there's only one table object, but there are two references to it, and if it's altered through one reference, the results become visible through the other reference.
Thanks for your reply! Sorry for taking so long to respond. I've looked through the code and can't see any rogue references, so I don't thing it's that.
pgimeno wrote: Thu Jul 19, 2018 11:49 pmOr I may be wrong in my guess, in which case it would help if you can attach a .love file that we can examine, to try to find out where the problem can be rather than guessing.
I've attatched the folder. I've never tried uploading a .love file before, so I don't know if it worked. The main files to look in are animation.lua, player.lua, and gamestate.lua (I think the issue is in the gamestate calss).

Please don't feel any obligation to try to find the solution, but I would appreciate it if you did skim through it.
Attachments
test1.love.zip
(10.2 KiB) Downloaded 114 times
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Custom animation system not working, no reason why

Post by pgimeno »

SpeedySloth wrote: Fri Jul 20, 2018 12:04 pm Thanks for your reply! Sorry for taking so long to respond. I've looked through the code and can't see any rogue references, so I don't thing it's that.
Thanks for sharing the code. Yes, it's that. Look at this code:

Code: Select all

animation.properties =
{
    atlas,
    speed,
    framecount,
    framewidth,
    frameheight,
    fields =
    {
        timer = 0,
        framecounter = 0,
    }
}

function animation:new(a, s, fc, fw, fh)
    animation.properties.atlas = a
    animation.properties.speed = s
    animation.properties.framecount = fc
    animation.properties.framewidth = fw
    animation.properties.frameheight = fh

    local self = setmetatable(animation.properties, animation)
    return self
end
You're only creating one animation.properties table object, when the file loads. Then, every time animation:new() is called, you're returning the same table object, rather than a new table object. This means that every time you call animation:new(), you're modifying and returning the same table.

It makes little sense for animation.properties to contain the returned instance, because animation is a class, and classes don't have their instances as fields. It also makes little sense to have class functions such as new() to be defined or called using the colon syntax, because the instance parameter (the 'self' parameter) is never used (pretty much by definition of a class function). In this case you're ignoring it and creating a new local variable with the same name. The colon syntax is used to call methods in instances.

So I suggest to remove the assignment of animation.properties and rewrite animation.new as follows:

Code: Select all

function animation.new(a, s, fc, fw, fh)
    local self = setmetatable({}, animation) -- the {} here creates a brand new table on every call
    self.atlas = a
    self.speed = s
    self.framecount = fc
    self.framewidth = fw
    self.frameheight = fh

    return self
end
Then call it without using the colon syntax, e.g.

Code: Select all

    gamestate.playerupanim = animation.new(gamestate.playerupanimatlas, 10, 2, 16, 32)
SpeedySloth
Prole
Posts: 9
Joined: Thu Jul 19, 2018 7:52 pm

Re: Custom animation system not working, no reason why

Post by SpeedySloth »

pgimeno wrote: Fri Jul 20, 2018 4:10 pm
SpeedySloth wrote: Fri Jul 20, 2018 12:04 pm Thanks for your reply! Sorry for taking so long to respond. I've looked through the code and can't see any rogue references, so I don't thing it's that.
Thanks for sharing the code. Yes, it's that. Look at this code:

Code: Select all

animation.properties =
{
    atlas,
    speed,
    framecount,
    framewidth,
    frameheight,
    fields =
    {
        timer = 0,
        framecounter = 0,
    }
}

function animation:new(a, s, fc, fw, fh)
    animation.properties.atlas = a
    animation.properties.speed = s
    animation.properties.framecount = fc
    animation.properties.framewidth = fw
    animation.properties.frameheight = fh

    local self = setmetatable(animation.properties, animation)
    return self
end
You're only creating one animation.properties table object, when the file loads. Then, every time animation:new() is called, you're returning the same table object, rather than a new table object. This means that every time you call animation:new(), you're modifying and returning the same table.

It makes little sense for animation.properties to contain the returned instance, because animation is a class, and classes don't have their instances as fields. It also makes little sense to have class functions such as new() to be defined or called using the colon syntax, because the instance parameter (the 'self' parameter) is never used (pretty much by definition of a class function). In this case you're ignoring it and creating a new local variable with the same name. The colon syntax is used to call methods in instances.

So I suggest to remove the assignment of animation.properties and rewrite animation.new as follows:

Code: Select all

function animation.new(a, s, fc, fw, fh)
    local self = setmetatable({}, animation) -- the {} here creates a brand new table on every call
    self.atlas = a
    self.speed = s
    self.framecount = fc
    self.framewidth = fw
    self.frameheight = fh

    return self
end
Then call it without using the colon syntax, e.g.

Code: Select all

    gamestate.playerupanim = animation.new(gamestate.playerupanimatlas, 10, 2, 16, 32)
Thanks so much! I was pulling my hair out over this!

Sorry to drop another thing on you, but for some reason only 1 image seems to be available at a time. So the only image that is used is the last one that was loaded. If you don't know why this is, please don't spend ages looking for the answer, you've already helped me more than enough! :awesome:
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Custom animation system not working, no reason why

Post by pgimeno »

Can you be more specific? What do you expect where, and what do you get instead?
SpeedySloth
Prole
Posts: 9
Joined: Thu Jul 19, 2018 7:52 pm

Re: Custom animation system not working, no reason why

Post by SpeedySloth »

pgimeno wrote: Fri Jul 20, 2018 5:00 pm Can you be more specific? What do you expect where, and what do you get instead?
Basically, even though I'm loading 2 images , only the last one that was loaded is being used, even when I specify the other to be used. It's like the animations, only the last one to be initialised is being used. I'm guessing this is because I'm editing the references (Like with the animations), but I can't see why, as they're all under different variable names, and I'm using the default method (love.graphics.newImage()) to load the images.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Custom animation system not working, no reason why

Post by pgimeno »

Sorry to insist but this is still not specific enough. For me to see the same problem you see, what line(s) should I change in what file(s)?

In the previous case, based on your problem statement, I did a text search and located a line commented out that looked like the one you posted, and deduced that that was the problematic point. In this case, I have no idea what to look at or what to change.
SpeedySloth
Prole
Posts: 9
Joined: Thu Jul 19, 2018 7:52 pm

Re: Custom animation system not working, no reason why

Post by SpeedySloth »

pgimeno wrote: Fri Jul 20, 2018 5:12 pm Sorry to insist but this is still not specific enough. For me to see the same problem you see, what line(s) should I change in what file(s)?

In the previous case, based on your problem statement, I did a text search and located a line commented out that looked like the one you posted, and deduced that that was the problematic point. In this case, I have no idea what to look at or what to change.
In gamestate lines 46-49 you'll notice movement animations are loaded (Currently all the same), and in lines 51-54 a sword swing animation is loaded. For some reason, whatever is loaded in line 18 (Where image1 is defined, and the last image to be loaded) is assigned to all images, so if a movement animation atlas is loaded, even the swing animations will use that image as an atlas, and vice versa.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Custom animation system not working, no reason why

Post by pgimeno »

There must be some communication problem. What I'm asking is, what are you changing in order to get the result you expect (but doesn't work)?

An example of an answer to that question would be something like along these lines:
  • I'm editing gamestates.lua, and in the function gamestate.load I'm changing this line:

    Code: Select all

        player.texture = image1
    
    to this:

    Code: Select all

        player.texture = gamestate.playerswingupanimatlas
    
    but it's showing the movement texture instead of the swing texture.
(I tried, it's indeed showing the swing texture, so that's not it for sure, but it's an example of a possible answer)

player.texture is the image that is ultimately drawn to the screen. It's defined in States/gamestate.lua and used in Sprites/sprite.lua. Are you changing player.texture? How? Where?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 43 guests