So, I have made a script that allows a frame to move with WASD and when it moves, an image will cycle through various images to perceive movement. But when I go back and forth and WASD, the animation goes all weird and moves funny. Additionally, when the player stops moving, the animation still continues.
I used a function, an If statement, and a while loop to make the sprite work (Shown below)
local Loop = false
function Animate()
if Loop == true then
while Loop == true do
wait(0.001)
plr.Image = f1
wait(0.001)
plr.Image = f2
wait(0.001)
plr.Image = f3
wait(0.001)
plr.Image = f4
wait(0.001)
plr.Image = f5
wait(0.001)
plr.Image = f6
wait(0.001)
plr.Image = f7
wait(0.001)
plr.Image = f8
wait(0.001)
plr.Image = f9
wait(0.001)
plr.Image = f10
wait(0.001)
plr.Image = f11
wait(0.001)
plr.Image = f12
wait(0.001)
plr.Image = f13
wait(0.001)
plr.Image = f14
wait(0.001)
plr.Image = f15
wait(0.001)
plr.Image = f16
wait(0.001)
plr.Image = f17
wait(0.001)
plr.Image = f18
wait(0.001)
plr.Image = f19
wait(0.001)
plr.Image = f20
wait(0.001)
plr.Image = f21
wait(0.001)
plr.Image = f22
end
end
if Loop == false and plr.Image == f22 or plr.Image == f21 or plr.Image == f20 or plr.Image == f19 or plr.Image == f18 or plr.Image == f17 or plr.Image == f16 or plr.Image == f15 or plr.Image == f14 or plr.Image == f13 or plr.Image == f12 or plr.Image == f11 or plr.Image == f10 or plr.Image == f9 or plr.Image == f8 or plr.Image == f7 or plr.Image == f6 or plr.Image == f5 or plr.Image == f4 or plr.Image == f3 or plr.Image == f2 or plr.Image == f1 then
plr.Image = Idle
end
end
(How the function gets called )
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
--When WASD is pressed
if keys[key] then
pressed[key] = keys[key]
Loop = true
Animate()
end
--When WASD is not pressed
if keys[key] then
pressed[key] = nil
Loop = false
Animate()
end
Well, first of all. The minimun the wait() function can wait is .03 seconds, your code is a little bit messy, and I think you could have made it a lot more effecient. In the infinite loop, there is nothing to check if it should break out of it, so that’s why it continues.
The problem is that the while loop is still going when pressing another key.
You make a new thread which will also be changing the Image because it doesn’t have any command to stop in between all those waits.
You can put the frames in a table like:
local Frames = {f1,f2}
then have a loop which can break if Loop has been set to false.
function Animate()
for i,v in ipairs(Frames) do -- i is the position of the frame in the table and v is the frame itself
if Loop == false then break end-- Stops the loop
plr.Image = v
wait(0.02)-- Probably 5fps animation
end
end
This is meant to be more of an example so I don’t know if it will actually work or be efficient.
I read some posts and it doesn’t seem to say anywhere that the lowest time is 0.03. Only thing I found is that if you don’t provide an argument by just doing wait() it will wait for 0.03 by default.
I’m guessing it’s cause you’re never breaking the loop, so it continues even after it stops animating/being called.
You can use break for that, but I also have something else. Instead of manually animating the player image, you can also use for i = 1, 22 since you have 22 images.
Here’s how to break the loop. (Check the last line before the function ends)
function Animate()
if Loop == true then
while Loop == true do
wait(0.001)
plr.Image = f1
wait(0.001)
plr.Image = f2
wait(0.001)
plr.Image = f3
wait(0.001)
plr.Image = f4
wait(0.001)
plr.Image = f5
wait(0.001)
plr.Image = f6
wait(0.001)
plr.Image = f7
wait(0.001)
plr.Image = f8
wait(0.001)
plr.Image = f9
wait(0.001)
plr.Image = f10
wait(0.001)
plr.Image = f11
wait(0.001)
plr.Image = f12
wait(0.001)
plr.Image = f13
wait(0.001)
plr.Image = f14
wait(0.001)
plr.Image = f15
wait(0.001)
plr.Image = f16
wait(0.001)
plr.Image = f17
wait(0.001)
plr.Image = f18
wait(0.001)
plr.Image = f19
wait(0.001)
plr.Image = f20
wait(0.001)
plr.Image = f21
wait(0.001)
plr.Image = f22
end
end
if Loop == false and plr.Image == f22 or plr.Image == f21 or plr.Image == f20 or plr.Image == f19 or plr.Image == f18 or plr.Image == f17 or plr.Image == f16 or plr.Image == f15 or plr.Image == f14 or plr.Image == f13 or plr.Image == f12 or plr.Image == f11 or plr.Image == f10 or plr.Image == f9 or plr.Image == f8 or plr.Image == f7 or plr.Image == f6 or plr.Image == f5 or plr.Image == f4 or plr.Image == f3 or plr.Image == f2 or plr.Image == f1 then
plr.Image = Idle
break
end
end
The frames idea is very good. The way I would do it is have a global index variable like so:
local frameIdx = 1
local Frames = {f1, f2}
function Animate()
plr.Image = Frames[frameIdx % #Frames]
frameIdx += 1
end
Then call the function By binding to RenderStepped
--When WASD is pressed
if keys[key] then
pressed[key] = keys[key]
RunService:BindToRenderStep("animateSprite", 1, Animate)
end
--When WASD is not pressed
if keys[key] then
pressed[key] = nil
RunService:UnbindFromRenderStep("animateSprite")
frameIdx = 1
end
Here the animation will run at the framerate that the client has. Ideally you would want to use the step to set you framerate appropriately. More here RunService | Roblox Creator Documentation
Just by reading posts, you can’t prove it. The wait has a minimun of 29 milliseconds to wait (0.03), yes it’s right the default would be 0.03, but that’s also the minimum, why wouldn’t it be the minimun wait by default also? Makes no sense. Roblox Globals | Roblox Creator Documentation Scroll down until you find the wait() function
You probably don’t want the animation speed to depend on the frame rate. This code should set the correct image regardless of framerate.
local RunService = game:GetService("RunService")
local ANIM_DURATION = .5 -- Change to whatever you want.
local frames = {f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, f21, f22}
local frameNum = #frames
local frameDuration = ANIM_DURATION / frameNum
local moveAnimLoopRunning = false
local function animateMovement()
moveAnimLoopRunning = true
local animStartTime = os.clock()
while moveAnimLoopRunning do
plr.Image = frames[1 + math.floor((os.clock() - animStartTime) % ANIM_DURATION / frameDuration)]
RunService.RenderStepped:Wait()
end
end
local function stopMovement()
moveAnimLoopRunning = false
end
local function animateIdle()
plr.Image = Idle
end
--When WASD is pressed
if keys[key] then
pressed[key] = keys[key]
if not moveAnimLoopRunning then
animateMovement()
end
end
--When WASD is not pressed
if keys[key] then
pressed[key] = nil
stopMovement()
animateIdle()
end
Hmmm, that error doesn’t sound quite right. Maybe you can DM me a bigger chunk of the code so I can check it? Invalid Argument #3 implies there is a function called on that line, but there is none.
One idea that I have is to change
function Animate()
to
function Animate(step)
Even you don’t use the step. That argument is passed and it might be breaking something there.
Setting ImageLabel.Image to nil gives that error. There’s a problem in the way you calculate the index. If frameIdx is equal to #Frames, frameIdx % #Frames is 0. The code below might work better.