Log In  


Caution

This posts acts also as a kind of documentation for the tool, its usage and the integration of the data. It's not final and might probably change in the future, to improve the writing style, fix mistakes or add more explanations. Please do report any feedback you desire so I can improve the documentation.

Anim Editor

Hello! From starting a project, I ended up going on a tangent for weeks and had been making a frame-based animation editor for the last few weeks with an intent of making my own internal mini animation library to make sprite animations as easy as drawing -or at least, for me-.

Cart #eyn_anim_editor-7 | 2024-05-01 | Embed ▽ | License: CC4-BY-NC-SA
27

Changelog

0.0

  • Initial version

0.1

Additions

  • Added a right-click menu on animations with delete and duplicate options.
  • Added ability to cycle between frames of the current animation by pressing left and right.

Changes

  • TAE will sort alphabetically the animations in the editor.
  • Changed BBS mode detection and added some failsafes to make it work.

Fixes

  • Fixed looping checkbox not updated on animation change
  • Fixed handling of GFX files. Those shouldn't change the reported current file anymore, which caused saving issues when using TAE as a dev editor like Picotron's.
  • Prevents animation info from staying visible after loading a file. Prevents possible crash when fetching an animation's data when no animation is selected after loading.
  • Fixed loss of ability to use space to play the animation after activating a rename field.

Using the tool

The animation editor is trying to follow the philosophy of Picotron's builtin editors. While it can't enjoy the same integration than the tools provided with the OS (like not having its own file open intent), it'll still aiming to feel at home when next to the other tool. Thus it's working at its best when opened while a cart is mounted/loaded to work on the cart's files.

The editor is split in three parts : the view, the timeline and the sidebar, each of which is going to have its own section. There's also going to be one for using the data generated by the animation editor.

The sidebar

The sidebar has buttons to open or save an animation, save as another file, replace the currently loaded GFX file, a button to create animations and undo/redo actions. You can right click the open button to open up a recent file list instead of Picotron's open dialog for a faster access.

Note that saving and opening are disabled in the BBS because there's no persistence nor demo files. This is planned for when I'll the energy to.

Then is presented to you the animation list. Once you created one or more animations, they'll be listed there. Click on one of them to select it and double click an animation to rename it. The X button allows you to delete animations. Don't worry, deleting an animation is undoable.

Following down is the sprite selector. It should work like the GFX editor except that you have an extra button to reload the GFX if you edited it externally. You can click & drag a sprite from the grid to drop it on the view to add it on the current frame in the current animation.

Note that the reload button is going to go away as soon as I'll replicate the map editor's automatic GFX reload mechanism. Another planned "when in the mood for" feature.

The timeline

Once you create and selected an animation, you'll see there its frames in the bottom bar and two buttons crossing over its border. The first button will create more frames at the end of the animation and the second button toggle playing the animation, this is also doable by pressing space.

Click on a frame to select it. Drag it to move it in the timeline. More options are hidden a right-click on a frame, like copy & paste or duplicate the frame. The small circle on the top right corner will delete the frame. Again, it's one undo away from you.

Note that most actions are disabled during playback, for your convenience (and to avoid a plethora of bugs). The grid will disappear and you'll be pretty much limited to change the playback speed (left editable for your convenience) and pausing the playback.

The scene view

Finally, the rest of the owl: the scene view. The scene view will display the current animation's current frame by overlaying the sprites from first to last inserted. Drag a sprite from the sprite selector to the view to add it to the frame. Once dropped, you can continue interacting with them by dragging them to reposition them or right-click for more options, like applying the currently selected sprite on the selected sprite. You can drag the view by click and dragging the middle mouse button to pan in the scene.

Note that the two blue and green lines are the main axises of the animations and the point where they meet will be the origin of the animation. You might want to use that point as a reference when integrating your animations, the latter being the main topic of the next section. Nice segue, eh?

Using the animation data

Now that you made your animations, you might want to use them in your game or project, right? This is the section that will explain the inner details to help you getting to it.

Like any POD file, an .anim file is just a serialized Lua table. You can introspect the .anim files by opening them with podtree, that's always a good trick to keep around in case you want to figure something or edit them.

Animation structure

An animation file (.anim), once loaded with fetch or unpod, contains two main elements at its root: a reference to the GFX file used during the creation of the file and a table named anims.

anims contains your animations, indexed by the name you put in the editor. So my_anim will be accessible by getting my_loaded_file.anims["my_anim"] or my_loaded_file.anims.my_anim; the former syntax allows for spaces in the name.

The GFX reference is used by the editor to determine which GFX file to load when loading the .anim, but you can also use it to identify yourself what to load, for situations like having a specific GFX file for a specific animations or anything, really, it's up to you.

Animations

An animation contains a list of frames, a tick member and a loop flag.

  • ticks: The system currently being based on rendering frames (or game logic ticks) as a measure of time, that member indicates how many ticks should be spent between two frames - so, in other words, a bit like the speed of the animation. Think of SFX' speed
  • loop: This value is currently not used in the editor but you can use it in your code to determine if your animation should stop or not

Each frame contains a list of sprites, which each stores an ID mapped to the loaded GFX file's sprite list(so like spr does too) and a position offset (relative to center of the scene in the editor). Those sprites should be rendered from first to last in the array to reflect what you'll see in the editor

Sample code

This is not fully tested, I just ripped off my project and tried to remove what was speicfic to it, but the general idea is there.

local player_anims = fetch "anim/player.anim"
player = {
	...
	anims = player_anims.anims
}

function player:set_anim(anim)
	self.curanim = anim
	local a=self.anims[self.curanim]
	self.animticks = a.ticks
	self.curframe = 1
end

function player:update_animation()
	self.animtick-=1
	if self.animtick<=0 then
		self.curframe+=1
		local a=self.anims[self.curanim]
		self.animtick=a.ticks--reset timer
		if self.curframe>#a.frames then
			if a.loop then
				self.curframe=1--loop
			else
				-- Here I had something else in my code to transition into another animation if needed.
				-- Another element I'll probably add in the editor when I'll feel the need for.
				self.curframe = #a.frames
			end
		end
	end
end

function player:draw_animation()
	local a=self.anims[self.curanim]
	local frame=a.frames[self.curframe]
	-- Here, the animation's origin will be placed on (cx,cy), so the center of the player object.
	-- That's one way to of doing it, you could also use the middle point on the bottom, a corner, etc.
	local cx, cy = self.x-(self.w/2), self.y-(self.h/2)
	local flp_x = self.flipx and -1 or 1
	for sprite in all(frame) do
		spr(sprite.gfx_index,
		cx + (sprite.x * flp_x),
		cy + sprite.y,
		self.flipx,
		false)
	end
end

About the tool's future

I'm probably going to plug more features as I'll need them in the future, like having a timeline for hitboxes or triggers. I'll probably go back to this tool only when I'll really feel the need for it.

Also, I'd like to be honest and say in advance I don't really plan on making the most versatile tool ever, but I'd like to make it a tool one could remix to their own needs. I made this small tool when building for another project in mind (or two, maybe???) and I'd not want it to take most of my time. I hope you'll understand.

That said, I'll also add the task of trying to improve the source code to make it more open for customization in the "maybe later" task list.

Resources used

  • Zep's GUI lib and wrangler utility (forked the latter into a custom version). I also borrowed his save icon I recolorized. I hope you don't mind. :°
  • Surt's take on Kenney's Platformer Kit. Licence: CC0
27


you can use Picotron in the entirety with this don't tell Zep


I really really really (x200) love this!
Keep us updated on the project.

@FallBreak8203 Lmao I opened the terminal but return doesn't work


As I'm working with the tool, I found some things to add or fix. Here's a WIP changelog for the next version (0.1). I'll edit this post and the main post as soon as I'll publish this version.

0.1

Additions

  • Added a right-click menu on animations with delete and duplicate options.
  • Added ability to cycle between frames of the current animation by pressing left and right.

    Changes

  • NOw TAE will sort alphabetically the animations in the editor.

    Fixes

  • Fixed looping checkbox not updated on animation change
  • Fixed handling of GFX files. Those shouldn't change the reported current file anymore, which caused saving issues when using TAE as a dev editor like Picotron's.
  • Prevents animation info from staying visible after loading a file. Prevents possible crash when fetching an animation's data when no animation is selected after loading.
  • Fixed loss of ability to use space to play the animation after activating a rename field.

Regarding the current state of tool:

  • I'm currently in the need of tracking stuff like hitboxes. I haven't totally decided what and how I should add to implement generic per-frame data yet, but that's something I might think about in the future.
  • I'm also thinking of changing the loop toggle into a smaller toggle button or something in the sort. Do you have any thoughts on that?
  • I also am considering changing the UX for scene edition, moving to a select & move system instead of just dragging sprites without having selection. It might help for moving multiple sprites at once. Just a heads up in case I'm doing that change

EDIT: I noticed that the BBS detection code is not working anymore, sorry for the annoyance. I'll try to fix that for the 0.1. Fixed

EDIT2 : 0.1 landed, check it out on the main post!



[Please log in to post a comment]