If you've used jQuery for simple animations, you know it's easy to make simple tweens look nice by using the variety of available easing options.
Whenever I try to do some nice effect in Graal, I end up writing the tweening code from scratch for that particular case, which is ridiculous.
Tweening is pretty easy, but to make it look nice, you need some form of easing. Animations that start and stop abruptly look bad; it's usually better for there to be some kind of slow stop, fast start, or even bouncing .
func_tween is just a couple functions that makes it easy to change the property of an object over time. You can use any object; images, GUIs, players, NPCs, etc.
function easeInOutQuad(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; };
function easeInCubic(x, t, b, c, d) { return c * (t /= d) * t * t + b; };
function easeOutCubic(x, t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; };
function easeInOutCubic(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; return c / 2 * ((t -= 2) * t * t + 2) + b; };
function easeInQuart(x, t, b, c, d) { return c * (t /= d) * t * t * t + b; };
function easeOutQuart(x, t, b, c, d) { return -c * ((t = t / d - 1) * t * t * t - 1) + b; };
function easeInOutQuart(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b; return -c / 2 * ((t -= 2) * t * t * t - 2) + b; };
function easeInQuint(x, t, b, c, d) { return c * (t /= d) * t * t * t * t + b; };
function easeOutQuint(x, t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; };
function easeInOutQuint(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; };
function easeInSine(x, t, b, c, d) { return -c * cos(t / d * (pi / 2)) + c + b; };
function easeOutSine(x, t, b, c, d) { return c * sin(t / d * (pi / 2)) + b; };
function easeOutCirc(x, t, b, c, d) { return c * (1 - (t = t / d - 1) * t) ^ 0.5 + b; };
function easeInOutCirc(x, t, b, c, d) { if ((t /= d / 2) < 1) return -c / 2 * ((1 - t * t) ^ 0.5 - 1) + b; return c / 2 * ((1 - (t -= 2) * t) ^ 0.5 + 1) + b; };
function easeInElastic(x, t, b, c, d) { s = 1.70158; p = 0; a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < abs(c)) { a = c; s = p / 4; } else s = p / (2 * pi) * arcsin(c / a); return -(a * 2 ^ (10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b; };
function easeOutElastic(x, t, b, c, d) { s = 1.70158; p = 0; a = c; if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (a < abs(c)) { a = c; s = p / 4; } else s = p / (2 * pi) * arcsin(c / a); return a * 2 ^ (-10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b; };
function easeInOutElastic(x, t, b, c, d) { s = 1.70158; p = 0; a = c; if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5); if (a < abs(c)) { a = c; s = p / 4; } else s = p / (2 * pi) * arcsin(c / a); if (t < 1) return -.5 * (a * 2 ^ (10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p)) + b; return a * 2 ^ (-10 * (t -= 1)) * sin((t * d - s) * (2 * pi) / p) * .5 + c + b; };
function easeInBack(x, t, b, c, d, s) { if (s.type() == (- 1)) s = 1.70158; return c * (t /= d) * t * ((s + 1) * t - s) + b; };
function easeOutBack(x, t, b, c, d, s) { if (s.type() == (- 1)) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; };
function easeInOutBack(x, t, b, c, d, s) { if (s.type() == (- 1)) s = 1.70158; if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; };
function easeInBounce(x, t, b, c, d) { return c - this.easeOutBounce(x, d - t, 0, c, d) + b; };
function easeOutBounce(x, t, b, c, d) { if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b; } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } };
function easeInOutBounce(x, t, b, c, d) { if (t < d / 2) return this.easeInBounce(x, t * 2, 0, c, d) * .5 + b; return this.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b; };
// basic ones function easeLinear(x) { return x; }
One of the features of jQuery's animation lib is daisy-chaining animations.
item.animate().animate().animate();
Then they execute in that order. You can rig that up in GS2, should look into it.
In my engine, tweening is part of the built-in scripting features. I accomplish daisy chaining by having the first call return an animation object, which is then built upon by the member functions of the animation object. That way, you can animate multiple variables concurrently and with some nice synactic sugar, too.
I edited my post with a way to implement it in GS2. Edit was supposed to be right after but I didn't have time, had to go off to school.
You should also rig a percentage of tweening to use as a variable, it's useful. For instance, in my implementation there's some preset types of easing, with each one being able to be modified by a scalar value. A value between -infinity and infinity. A value > 0 will make it start quickly, and end slowly. A value < 0 does the opposite, while a value of 0 will make it run at the same pace the entire time, with it all being relative to the distance from 0. Flash does the same thing. All it takes for that is a little multiplication against the value you input into the easing type function.
Also with regards to chaining, I've been hanging on to this because I wanted to make it more extensible (like jQuery), but I've yet to devise an elegant solution. Anyway, you can check out the attachments. It includes some tweening functionality (specifically, linear and sinusiodal). Here's an example, the Zenkou message system.
PHP Code:
// Zenkou Messaging System (Growl Edition!)
// Styled after Growl (http://growl.info)
// v0.1
function onCreated() { this.join("boilerplate"); }
//#CLIENTSIDE
const PRE = "zen_messages_";
function getlock() {
if (this.lock) {
while (!waitfor(this.name, "onMessage" @ this.num));
this.num++;
}
this.lock = true;
return;
}
function release() {
if (this.lock) {
this.lock = false;
this.trigger("Message" @ this.num, NULL);
}
return;
}
function growl(stitle, text, icon, time) {
if (text > 0) { time = text; text = stitle; stitle = ""; icon = "alert"; }
if (icon > 0) { time = icon; icon = text; text = stitle; stitle = ""; }
if (time == 0) { time = 10; }
if (text == "") { text = stitle; stitle = ""; }
public function addmsg(title, desc, icon, dur) {
getlock();
growl(title, desc, icon, dur);
release();
}
Of course I was aiming for something a little more sophisticated than a series of chained set()s for image manipulation when I started writing it but meh.
Hey Chris, I've been using this to tween the x & y of GUI controls successfully a few times, but it doesn't seem to like tweening the width/height of them at all. The GUI control disappears, and reappears with the target width/height on the last frame.
Is it your code not supporting it or is it just another beautiful day in GScript? If there's anything you could on your end to "fix" it, I'd much appreciate it
Hey Chris, I've been using this to tween the x & y of GUI controls successfully a few times, but it doesn't seem to like tweening the width/height of them at all. The GUI control disappears, and reappears with the target width/height on the last frame.
Is it your code not supporting it or is it just another beautiful day in GScript? If there's anything you could on your end to "fix" it, I'd much appreciate it
I don't think I ever tried it in that manner but I don't see why it wouldn't work. If it doesn't, my guess would be it's one of the many quirks of Graal. I don't have access to any server to test on now, though.
I don't have access to any server to test on now, though.
I'd be more than happy to give you whatever rights you need on Maloria if you need a server to test code on. It's classic enabled, so shouldn't be any problems with that. If it's something you'd be interested in, let me know!