I need help with animation script...

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
PixelHero
Prole
Posts: 45
Joined: Sat Apr 16, 2022 3:16 am

I need help with animation script...

Post by PixelHero »

Hello. I am making a fighter game, and I need help... I am having problems with my graphics file for the first player. Here is my code:

Code: Select all

local g1  = { k = { anim1 = 'idle', attackTime = 0, animdone = true }, i = {},  a1  = {}, m = { i = 1 },  }
g1.l = require 'Modules/LocationF1'


function g1.load()

    --Idle
    g1.i.F1i_1  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-1.png')
    g1.i.F1i_2  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-2.png')
    g1.i.F1i_3  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-3.png')
    g1.i.F1i_4  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-4.png')
    g1.i.F1i_5  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-5.png')
    g1.i.F1i_6  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-6.png')
    g1.i.F1i_7  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-7.png')
    g1.i.F1i_8  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-8.png')
    --Attack #1
    g1.a1.F1A_1 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-1.png')
    g1.a1.F1A_2 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-2.png')
    g1.a1.F1A_3 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-3.png')
    g1.a1.F1A_4 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-4.png')
    g1.a1.F1A_5 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-5.png')
    g1.a1.F1A_6 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-6.png')
    g1.a1.F1A_7 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-7.png')
    g1.a1.F1A_8 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-8.png')

	g1.F1 = g1.i.F1i_1
end

function g1.attack(key)
	g1.m.i = 1
	while g1.m.i <= 8.8 do
		g1.m.i = g1.m.i + (dt/10)
		g1.m.i_floored = math.floor(g1.m.i)
		
		if g1.m.i_floored == 1 then
			g1.frame = g1.i.F1A_1
		elseif g1.m.i_floored == 2 then
			g1.frame = g1.i.F1A_2
		elseif g1.m.i_floored == 3 then
			g1.frame = g1.i.F1A_3
		elseif g1.m.i_floored == 4 then
			g1.frame = g1.i.F1A_4
		elseif g1.m.i_floored == 5 then
			g1.frame = g1.i.F1A_5
		elseif g1.m.i_floored == 6 then
			g1.frame = g1.i.F1A_6
		elseif g1.m.i_floored == 7 then
			g1.frame = g1.i.F1A_7
		elseif g1.m.i_floored == 8 then
			g1.frame = g1.i.F1A_8
		end
		
		g1.F1 = g1.frame
		if g1.m.i == 8.8 then break end
	end
end

function g1.idle(key)
	g1.m.i = 1
	
	while g1.m.i <= 8.8 do
		g1.m.i = g1.m.i + 0.2
		g1.m.i_floored = math.floor(g1.m.i)
		
		if g1.m.i_floored == 1 then
			g1.frame = g1.i.F1i_1
		elseif g1.m.i_floored == 2 then
			g1.frame = g1.i.F1i_2
		elseif g1.m.i_floored == 3 then
			g1.frame = g1.i.F1i_3
		elseif g1.m.i_floored == 4 then
			g1.frame = g1.i.F1i_4
		elseif g1.m.i_floored == 5 then
			g1.frame = g1.i.F1i_5
		elseif g1.m.i_floored == 6 then
			g1.frame = g1.i.F1i_6
		elseif g1.m.i_floored == 7 then
			g1.frame = g1.i.F1i_7
		elseif g1.m.i_floored == 8 then
			g1.frame = g1.i.F1i_8
		end
		g1.F1 = g1.frame
		if g1.m.i == 8.8 then break end
	end
end

function g1.update(dt)
	g1.l.update(dt) --line 92----------------------------------------------------------
end


function g1.draw()
	--love.graphics.print(g1.m.i, 400, 400)
    love.graphics.draw( g1.F1, g1.l.x, g1.l.y )

end

return g1

And here's the code for LocationF1:

Code: Select all

--this file is for movement and positioning of Fighter 1
local l = { x, y, xv, yv, px, py }

function l.load()
	
	l.x = 300
	l.y = 500
	
	l.xv = 0
	l.yv = 0
	
end

function l.update(dt)
	
	l.px = l.x
	l.py = l.y
	
	if love.keyboard.isDown('d') then
		if l.xv < 5	then
			l.xv = l.xv + 0.5
			if l.xv > 5 then
				l.xv = 5
			end
		end
	end
	
	if love.keyboard.isDown('a') then
		if l.xv > -5 then
			l.xv = l.xv + -0.5
			if l.xv < -5 then
				l.xv = -5
			end
		end
	end
	
	if l.px <= 800 and l.px >= 0 then
		l.x = l.x +l.xv * dt
	end
	--if l.py <= 800 and l.py >= 0 then
	--	l.y = l.y +l.yv * dt
	--end
end

And here's the code for the drawing file:

Code: Select all

--file for adding effects and the camera...

local d = { g1 = require 'Modules/GraphicsF1', c = require 'Libs/Stalker-X'}


function d.load()
	d.g1.load
	d.camera = d.c()
end

function d.update(dt)
	d.g1.update(dt)
	d.camera:update(dt)
end

function d.draw()
	d.camera:attach()
	d.g1.draw()
	d.camera:detach()
	
	d.camera:draw()
end



return d
Anybody see the problems? The popup says that the problem is at line 92 of the first file, and I made that stick out by commenting that and adding a ton of hyphens after it...
Dragons are great.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: I need help with animation script...

Post by pgimeno »

I think you're missing `return l` in LocationF1.
User avatar
PixelHero
Prole
Posts: 45
Joined: Sat Apr 16, 2022 3:16 am

Re: I need help with animation script...

Post by PixelHero »

pgimeno wrote: Fri Aug 19, 2022 3:01 am I think you're missing `return l` in LocationF1.
Sorry that I didn't see this sooner... You are CORRECT!!!! I saw your post as I was going to post the problem. Do you have any ideas on how to improve my animation script? It doesn't work. All it does is draw the default starting image.
Dragons are great.
User avatar
Gunroar:Cannon()
Party member
Posts: 1088
Joined: Thu Dec 10, 2020 1:57 am

Re: I need help with animation script...

Post by Gunroar:Cannon() »

g1 uses while to change frames, giving love no chance to draw the actual frame. The m.i should be updated through dt in love.update. I didn't do that here (that much) but you should be able to set the frame delay for each animation (cause it seems attack anim is faster).

Code: Select all

local g1  = { k = { anim1 = 'idle', attackTime = 0, animdone = true }, i = {},  a1  = {}, m = { i = 1 , frameDelay = .1},  }
g1.l = require 'Modules/LocationF1'


function g1.load()

    --Idle
    g1.i.F1i_1  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-1.png')
    g1.i.F1i_2  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-2.png')
    g1.i.F1i_3  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-3.png')
    g1.i.F1i_4  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-4.png')
    g1.i.F1i_5  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-5.png')
    g1.i.F1i_6  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-6.png')
    g1.i.F1i_7  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-7.png')
    g1.i.F1i_8  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-8.png')
    --Attack #1
    g1.a1.F1A_1 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-1.png')
    g1.a1.F1A_2 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-2.png')
    g1.a1.F1A_3 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-3.png')
    g1.a1.F1A_4 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-4.png')
    g1.a1.F1A_5 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-5.png')
    g1.a1.F1A_6 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-6.png')
    g1.a1.F1A_7 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-7.png')
    g1.a1.F1A_8 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-8.png')

	g1.F1 = g1.i.F1i_1
end

function g1.attack(key)
	--g1.m.i = 1
	--while g1.m.i <= 8.8 do
		--g1.m.i = g1.m.i + (dt/10)
		g1.m.i_floored = math.floor(g1.m.i/g1.m.frameDelay)
		
		if g1.m.i_floored == 1 then
			g1.frame = g1.i.F1A_1
		elseif g1.m.i_floored == 2 then
			g1.frame = g1.i.F1A_2
		elseif g1.m.i_floored == 3 then
			g1.frame = g1.i.F1A_3
		elseif g1.m.i_floored == 4 then
			g1.frame = g1.i.F1A_4
		elseif g1.m.i_floored == 5 then
			g1.frame = g1.i.F1A_5
		elseif g1.m.i_floored == 6 then
			g1.frame = g1.i.F1A_6
		elseif g1.m.i_floored == 7 then
			g1.frame = g1.i.F1A_7
		elseif g1.m.i_floored == 8 then
			g1.frame = g1.i.F1A_8
		end
		
		g1.F1 = g1.frame
		if g1.m.i == 8.8 then g1.m.i=1 end
	--end
end

function g1.idle(key)
	g1.m.i = 1
	
	--while g1.m.i <= 8.8 do
		--g1.m.i = g1.m.i + 0.2
		g1.m.i_floored = math.floor(g1.m.i/g.m.frameDelay)--?
		
		if g1.m.i_floored == 1 then
			g1.frame = g1.i.F1i_1
		elseif g1.m.i_floored == 2 then
			g1.frame = g1.i.F1i_2
		elseif g1.m.i_floored == 3 then
			g1.frame = g1.i.F1i_3
		elseif g1.m.i_floored == 4 then
			g1.frame = g1.i.F1i_4
		elseif g1.m.i_floored == 5 then
			g1.frame = g1.i.F1i_5
		elseif g1.m.i_floored == 6 then
			g1.frame = g1.i.F1i_6
		elseif g1.m.i_floored == 7 then
			g1.frame = g1.i.F1i_7
		elseif g1.m.i_floored == 8 then
			g1.frame = g1.i.F1i_8
		end
		g1.F1 = g1.frame
		if g1.m.i == 8.8 then g.m.i=1 end
--	end
end

function g1.update(dt)
	g1.l.update(dt) --line 92----------------------------------------------------------
    g1.m.I = g.m.i+dt
   if g1.do_idle then
        g1.idle()
   else
        g1.attack()
    end
end


function g1.draw()
	--love.graphics.print(g1.m.i, 400, 400)
    love.graphics.draw( g1.F1, g1.l.x, g1.l.y )

end

return g1
Untested. I just edited it to work to the bare minimum.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
RNavega
Party member
Posts: 245
Joined: Sun Aug 16, 2020 1:28 pm

Re: I need help with animation script...

Post by RNavega »

Hi PixelHero. There's that saying, "a good programmer doesn't repeat themselves". I think there's a lot of repetition in your code that could be cut down. That's part of the fun in fact: finding out patterns that repeat a lot in your own code and then creating something generic out of it.

Look at this section here:

Code: Select all

    --Idle
    g1.i.F1i_1  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-1.png')
    g1.i.F1i_2  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-2.png')
    g1.i.F1i_3  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-3.png')
    g1.i.F1i_4  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-4.png')
    g1.i.F1i_5  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-5.png')
    g1.i.F1i_6  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-6.png')
    g1.i.F1i_7  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-7.png')
    g1.i.F1i_8  = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1i-8.png')
    --Attack #1
    g1.a1.F1A_1 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-1.png')
    g1.a1.F1A_2 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-2.png')
    g1.a1.F1A_3 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-3.png')
    g1.a1.F1A_4 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-4.png')
    g1.a1.F1A_5 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-5.png')
    g1.a1.F1A_6 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-6.png')
    g1.a1.F1A_7 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-7.png')
    g1.a1.F1A_8 = love.graphics.newImage('Assets/Sprites/FightersBlowup/F1/F1A-8.png')
Basically what you're doing is storing the Image object for file "...\F1i-n.png" inside the table key "F1i_n".
You can reduce all of that to using a FOR loop and then building the filename for each frame based on the frame number. You can then pack this logic all inside a function so you can call it for different animation sequences.

Code: Select all

function loadPNGSequence(pathTemplate, totalFrames)
    local allFrames = {length = totalFrames}
    for frameIndex = 1, totalFrames do
        local imagePath = pathTemplate .. tostring(frameIndex) .. '.png'
        allFrames[frameIndex] = love.graphics.newImage(imagePath)
    end
    return allFrames
end
So now you can load both the Idle and Attack-1 sequences like this:

Code: Select all

g1.sequences = {
    -- Idle sequence has 8 frames.
    idle = loadPNGSequence('Assets/Sprites/FightersBlowup/F1/F1i-', 8),
    -- Attack #1 sequence has 8 frames.
    attack1 = loadPNGSequence('Assets/Sprites/FightersBlowup/F1/F1A-', 8)
}
Another place where there's a lot of repetition is your g1.idle() and g1.attack() functions.
See this:

Code: Select all

if g1.m.i_floored == 1 then
    g1.frame = g1.i.F1A_1
elseif g1.m.i_floored == 2 then
    g1.frame = g1.i.F1A_2
elseif g1.m.i_floored == 3 then
    g1.frame = g1.i.F1A_3
elseif g1.m.i_floored == 4 then
    g1.frame = g1.i.F1A_4
elseif g1.m.i_floored == 5 then
    g1.frame = g1.i.F1A_5
elseif g1.m.i_floored == 6 then
    g1.frame = g1.i.F1A_6
elseif g1.m.i_floored == 7 then
    g1.frame = g1.i.F1A_7
elseif g1.m.i_floored == 8 then
    g1.frame = g1.i.F1A_8
end

Notice the pattern? You store the animation frame of the same number as i_floored, into g1.frame.
That all can be reduced to this:

Code: Select all

-- Index the 'g1.sequences.idle' table using the 'g1.m.i_floored' value.
g1.frame = g1.sequences.idle[g1.m.i_floored]

There are other ways to reduce repetition in your code, like not having a g1.attack() and g1.idle() functions, but rather a g1.updateSequence() function that both advances the floored frame number and grabs the frame image from the sequence that's playing, whatever it is -- it doesn't care what sequence it is, you can store it in g1.currentSequence and it'll play that, and you know how many frames it has because it was stored in the 'length' key of the sequence table in that loadPNGSequence() function (so whatever sequence it is, it'll play from frame 1 to frame currentSequence.length).
Post Reply

Who is online

Users browsing this forum: No registered users and 59 guests