Moving graphical interface

Skylark
Posts: 46
Joined: Mon Feb 22, 2010 12:38 am

Moving graphical interface

Post by Skylark »

There are a bunch of useful applications of being able to depict motion with interface elements. While I don't believe labels, gauges, and other such things were never meant to be used as such, I've tried moving them around rapidly to simulate motion. However even on a fast computer I start running into problems refreshing their position quickly enough to maintain a good illusion of motion. I was wondering if anyone had any good workarounds / knew of faster graphical API. Even something as simple as a moving rectangle would do. Thanks for reading.

Edit: Meant to stick this in a different board, my bad. While I'm at it:

Is there a way to make gauges vertical?

User avatar
Oneymus
Posts: 321
Joined: Thu Sep 17, 2009 5:24 am

Re: Moving graphical interface

Post by Oneymus »

I suppose it would be most helpful to have some concrete examples of what you're trying to accomplish.

Currently, I have a package that can dynamically update the sizes of 4 (technically 5, but one's virtual) labels as I resize the Mudlet window. These labels occupy the border space surrounding the main console, calculated with every update call. It works flawlessly, and I experience no discernible, detrimental slowdown (offline testing).

Perhaps there is an issue with the manner in which you update your label positions? With more details, we can work through this.

Also, there is no other API. Are you using Geyser? Geyser wraps around the raw Mudlet API; I have not used Geyser much, but I can't imagine it would add too much overhead.

Gauges: I'm not sure if there's a pre-baked Gauge function for vertical gauges, but it's fairly simple. The trick is just in moving the gauge appropriately.
Code: [show] | [select all] lua
-- Helps to have these defined outside of the creation functions, so they can be referenced.
label = {
    x = 0,
    y = 0,
    width = 50,
    height = 100
}

-- Background. Not necessary, but looks nicer. Is static.
createLabel( "gauge_back", label.x, label.y, label.width, label.height, 1 )
setBackgroundColor( "gauge_back", 50, 50, 50, 255 )

-- This is the actual gauge. Resized.
createLabel( "gauge_front", label.x, label.y, label.width, label.height, 1 )
setBackgroundColor( "gauge_front", 200, 200, 200, 255 )

-- We create this so the text doesn't move, even as we update the size of
-- the front gauge.
createLabel( "gauge_text", label.x, label.y, label.width, label.height, 0 )
-- Make it transparent so we can see the gauges beneath.
setBackgroundColor( "gauge_text", 0, 0, 0, 0 )
-- Or however you record your stats...
echo( "gauge_text", string.format( "%d/%d", stat.current, stat.max ) )

function updateGauges ()
    local gauge_percent = stat.current / stat.max
    local new_height = label.height * gauge_percent
    local new_y = label.y + (label.height - new_height)
    -- First we resize the gauge...
    resizeWindow( "gauge_front", label.width, new_height )
    -- Now we move the window, if want it to empty downward.
    -- If you want it to empty upward, then omit the movement.
    moveWindow( "gauge_front", label.x, new_y )
    -- Echo the new stats.
    echo( "gauge_text", string.format( "%d/%d", stat.current, stat.max ) )
end
This was written off the cuff, though tested. Should be taken as educational, rather than functional. These gauges could be made prettier using Stylesheets, but this works.

Skylark
Posts: 46
Joined: Mon Feb 22, 2010 12:38 am

Re: Moving graphical interface

Post by Skylark »

Thanks for the response. I won't be able to give you the code I used or run more tests until tomorrow when I get back to my computer, but here's what I was doing.

In IRE games there are a lot of balances being used simultaneously (salve, herb, etc). I wrote a guitar hero-esque interface that created a relationship between pixels and time (easy to understand visually). So I had a thin, wide label at the bottom of this interface that represented the present. When a balance was used (say, sipping an elixir), a label would be created a distance above the 'now' point proportional to how long it would take to regain the balance. I then used a timer to call an update function that moved the label down one increment. It became very obvious that I was getting some slowdown because the moving label was hitting the zero point significantly after it should have.

I added a counter to the timer and used it to get data on the slowdown, measuring how many times the timer managed to fire before the duration of the balance was up. If everything was working, it should have been the number I determined earlier in the script. For example, running it at 30fps, the timer was set to fire every .033ms. Over a time of 4.5 seconds it should have fired close to 135 times. However, in practice it was only updating the label's position 95-97 times in 4.5 seconds, resulting in the label being significantly out of position. I tried this technique at varying FPS, going as far down as 10fps, and while the slowdown decreased it never completely disappeared.

I did something similar with Gauges and encountered the same issue. The only difference was that I updated the gauges instead of moving them.

User avatar
Vadi
Posts: 4867
Joined: Sat Mar 14, 2009 3:13 pm

Re: Moving graphical interface

Post by Vadi »

What you're looking at are animations. There've been several things for that - http://www.youtube.com/watch?v=Sa0_W9AAQJI (I -think- you might find code for those on Aetolian forums), http://www.youtube.com/watch?v=SoAyIqQW2sY, and look around the forums as well. I made an animations demo somewhere that used all 3 possible methods of rendering - either using a permanent timer (I believe this was the most efficient, but I don't remember for sure - so check that animations demo and try), pre-creating tempTimers for every frame that there'll be, or using a recursive tempTimer (that creates the next in itself).

It'd be great to have something standardized and included in Mudlet by default if you can work it out.

Skylark
Posts: 46
Joined: Mon Feb 22, 2010 12:38 am

Re: Moving graphical interface

Post by Skylark »

Sweet, thanks. I'll let you know what I come up with. My coding skills are pretty much just the result of messing around in Lua, though, so be warned that anything I produce will be pretty ungainly.

User avatar
Oneymus
Posts: 321
Joined: Thu Sep 17, 2009 5:24 am

Re: Moving graphical interface

Post by Oneymus »

I tried to find those demos, Vadi. Are they on the wiki, by chance? If not, it'd be a good place for them if you find them.

User avatar
Vadi
Posts: 4867
Joined: Sat Mar 14, 2009 3:13 pm

Re: Moving graphical interface

Post by Vadi »

No, here on forums


Skylark
Posts: 46
Joined: Mon Feb 22, 2010 12:38 am

Re: Moving graphical interface

Post by Skylark »

Alright, I didn't have nearly as much time today as I'd hoped, but I got some stuff done. I took Vadi's demo as a base and made it a little more general, creating an animateWindow() function that allows you to designate start & finish coordinates, fps, and duration. A couple issues and thoughts.

As vadi mentioned earlier, polluting the GUI is kind of an issue. Currently the function adds the permanent timers to a folder named "Animation Timers" which should keep it somewhat under control. However, I'm not sure how to create said folder without doing it manually. If you want to test it out you'll need to create the folder yourself or edit the function.

Before creating the timer, the script first checks to see if one already exists for the window you're animating. This is another step towards avoiding polluting the GUI. If you wish to animate a window in more than one way, however, IDs have to be added onto the timer names to differentiate between them. It's that or create a new timer every time you animate it, which tend to limit the function's usefulness. It'd be much easier if it was possible to delete permanent timers; we could just toss old timers and create a new one for every animation.

For now you have to manually delete the timer if you wish to run a different animation on the same window, I didn't get around to adding in a way to generate IDs.
Code: [show] | [select all] lua
function animateWindow( name, fps, duration, xInitial, yInitial, xFinal, yFinal)
	local t = {}
	t.fps, t.anim_time = fps, duration

	t.frame_count = fps * t.anim_time
	t.time_per_frame = 1/fps
	t.x_gain_per_frame = (xFinal - xInitial) / t.frame_count
	t.y_gain_per_frame = (yFinal - yInitial) / t.frame_count

	display(t)

	_G["timer_frame_" ..name] = 1
	if exists("animation timer_" ..name, "timer") == 0 then
		permTimer("animation timer_" ..name, "Animation Timers", t.time_per_frame, [[moveWindow("]] ..name .. [[",]] ..xInitial.. [[ + timer_frame_]] ..name.. [[*]] .. t.x_gain_per_frame .. [[,]] ..yInitial.. [[ + timer_frame_]] ..name.. [[*]].. t.y_gain_per_frame..[[) timer_frame_]] ..name.. [[ = timer_frame_]] ..name.. [[+1 if timer_frame_]]..name.. [[ >= ]] .. t.frame_count .. [[ then disableTimer("animation timer_]] ..name .. [[") end]])
	end
	enableTimer("animation timer_" ..name)
end
Oh, and I'm still getting slowdown. Testing by activating an animateWindow() set to 4 seconds and a simple echo timer set to the same duration shows slowdown scaling with fps; it's noticeable even at 10-20fps.

User avatar
Vadi
Posts: 4867
Joined: Sat Mar 14, 2009 3:13 pm

Re: Moving graphical interface

Post by Vadi »

There is a permGroup function on recent Mudlets that allows creating folders: http://wiki.mudlet.org/w/Manual:Lua_Functions#permGroup

Post Reply