Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 05-31-2012, 04:46 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
func_tween and func_easing

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 .

I ported the wonderful jQuery easing plugin (BSD license) to GScript.

I present to you: func_tween and func_easing.

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.

To use it, all you do is this:

PHP Code:
temp.callback = function() {
  
player.chat "Done!";
};

this.tween(Ball"y"GraalControl.height Ball.height40temp.easingtemp.callback); 
The parameters of tween are:
  • object - the object to tween
  • property - the property to tween
  • targetValue - the target value at the end of the animation
  • frames - the number of frames the animation should last (20 frames per second)
  • easing - the name of the easing function to use (optional, defaults to "swing")
  • callback - a callback function, called when finished (optional)

You can use any easing available from the easing plugin, plus "linear" (normal, abrupt start and stop), and "swing" (the default, soft stop).

You can see all of the available easings, and try them out, on this site (probably requires a non-ancient browser).

Here's what they look like in game. The video is pretty choppy (sorry), but it looks very smooth in game.



My favorite is probably at 1:38.

Here's the two classes you'll need:

func_tween
PHP Code:
function onCreated() {
  
this.join("func_easing");
}

//#CLIENTSIDE
function tween(temp.objtemp.propertytemp.targetValuetemp.framestemp.easingtemp.callback) {
  if (
temp.easing == null) { // default easing
    
temp.easing "swing";
  }
  
  
temp.startValue temp.obj.(@ temp.property) + 0;
  
this.onTweenStep(temp.objtemp.propertytemp.startValuetemp.targetValuetemp.framestemp.framestemp.easingtemp.callback);
}

function 
onTweenStep(temp.objtemp.propertytemp.startValuetemp.targetValuetemp.framesRemainingtemp.totalFramestemp.easingtemp.callback) {
  if (
temp.framesRemaining <= 0) {
    
temp.obj.(@ temp.property) = temp.targetValue;
    
    if (
temp.callback != null) {
      
temp.callback(temp.obj);
    }
    
    return;
  }
  
  
temp.= (temp.totalFrames temp.framesRemaining);
  
temp.state temp.temp.totalFrames;
  
  
temp.pos this.ease(temp.easingtemp.statetemp.n01temp.totalFrames);
  
temp.obj.(@ temp.property) = temp.startValue + ((temp.targetValue temp.startValue) * temp.pos);
  
  
this.scheduleEvent(0.05"onTweenStep"temp.objtemp.propertytemp.startValuetemp.targetValuetemp.framesRemaining 1temp.totalFramestemp.easingtemp.callback);

func_easing
PHP Code:
/*
    This is essentially a port of the jQuery easing plugin to
    GScript
    
    jQuery easing plugin:
    http://gsgd.co.uk/sandbox/jquery/easing/
*/

//#CLIENTSIDE
function easeInQuad(xtbcd) {
  return 
* (/= d) * b;
};

function 
easeOutQuad(xtbcd) {
  return -
* (/= d) * (2) + b;
};

function 
easeInOutQuad(xtbcd) {
  if ((
/= 2) < 1) return b;
  return -
* ((--t) * (2) - 1) + b;
};

function 
easeInCubic(xtbcd) {
  return 
* (/= d) * b;
};

function 
easeOutCubic(xtbcd) {
  return 
* ((1) * 1) + b;
};

function 
easeInOutCubic(xtbcd) {
  if ((
/= 2) < 1) return b;
  return 
* ((-= 2) * 2) + b;
};

function 
easeInQuart(xtbcd) {
  return 
* (/= d) * b;
};

function 
easeOutQuart(xtbcd) {
  return -
* ((1) * 1) + b;
};

function 
easeInOutQuart(xtbcd) {
  if ((
/= 2) < 1) return b;
  return -
* ((-= 2) * 2) + b;
};

function 
easeInQuint(xtbcd) {
  return 
* (/= d) * b;
};

function 
easeOutQuint(xtbcd) {
  return 
* ((1) * 1) + b;
};

function 
easeInOutQuint(xtbcd) {
  if ((
/= 2) < 1) return b;
  return 
* ((-= 2) * 2) + b;
};

function 
easeInSine(xtbcd) {
  return -
cos(* (pi 2)) + b;
};

function 
easeOutSine(xtbcd) {
  return 
sin(* (pi 2)) + b;
};

function 
easeInOutSine(xtbcd) {
  return -
* (cos(pi d) - 1) + b;
};

function 
easeInExpo(xtbcd) {
  return (
== 0) ? ^ (10 * (1)) + b;
};

function 
easeOutExpo(xtbcd) {
  return (
== d) ? * (- (^ (-10 d)) + 1) + b;
};

function 
easeInOutExpo(xtbcd) {
  if (
== 0) return b;
  if (
== d) return c;
  if ((
/= 2) < 1) return ^ (10 * (1)) + b;
  return 
* (- (^ (-10 * --t)) + 2) + b;
};

function 
easeInCirc(xtbcd) {
  return -
* ((- (/= d) * t) ^ 0.5 1) + b;
};

function 
easeOutCirc(xtbcd) {
  return 
* (- (1) * t) ^ 0.5 b;
};

function 
easeInOutCirc(xtbcd) {
  if ((
/= 2) < 1) return -* ((t) ^ 0.5 1) + b;
  return 
* ((- (-= 2) * t) ^ 0.5 1) + b;
};

function 
easeInElastic(xtbcd) {
  
1.70158;
  
0;
  
c;
  if (
== 0) return b;
  if ((
/= d) == 1) return c;
  if (!
p.3;
  if (
abs(c)) {
    
c;
    
4;
  } else 
/ (pi) * arcsin(a);
  return -(
^ (10 * (-= 1)) * sin((s) * (pi) / p)) + b;
};

function 
easeOutElastic(xtbcd) {
  
1.70158;
  
0;
  
c;
  if (
== 0) return b;
  if ((
/= d) == 1) return c;
  if (!
p.3;
  if (
abs(c)) {
    
c;
    
4;
  } else 
/ (pi) * arcsin(a);
  return 
^ (-10 t) * sin((s) * (pi) / p) + b;
};

function 
easeInOutElastic(xtbcd) {
  
1.70158;
  
0;
  
c;
  if (
== 0) return b;
  if ((
/= 2) == 2) return c;
  if (!
p* (.3 1.5);
  if (
abs(c)) {
    
c;
    
4;
  } else 
/ (pi) * arcsin(a);
  if (
1) return -.5 * (^ (10 * (-= 1)) * sin((s) * (pi) / p)) + b;
  return 
^ (-10 * (-= 1)) * sin((s) * (pi) / p) * .5 b;
};

function 
easeInBack(xtbcds) {
  if (
s.type() == (- 1)) 1.70158;
  return 
* (/= d) * * ((1) * s) + b;
};

function 
easeOutBack(xtbcds) {
  if (
s.type() == (- 1)) 1.70158;
  return 
* ((1) * * ((1) * s) + 1) + b;
};

function 
easeInOutBack(xtbcds) {
  if (
s.type() == (- 1)) 1.70158;
  if ((
/= 2) < 1) return * (* (((*= (1.525)) + 1) * s)) + b;
  return 
* ((-= 2) * * (((*= (1.525)) + 1) * s) + 2) + b;
};

function 
easeInBounce(xtbcd) {
  return 
this.easeOutBounce(xt0cd) + b;
};

function 
easeOutBounce(xtbcd) {
  if ((
/= d) < (2.75)) {
    return 
* (7.5625 t) + b;
  } else if (
< (2.75)) {
    return 
* (7.5625 * (-= (1.5 2.75)) * .75) + b;
  } else if (
< (2.5 2.75)) {
    return 
* (7.5625 * (-= (2.25 2.75)) * .9375) + b;
  } else {
    return 
* (7.5625 * (-= (2.625 2.75)) * .984375) + b;
  }
};

function 
easeInOutBounce(xtbcd) {
  if (
2) return this.easeInBounce(x20cd) * .5 b;
  return 
this.easeOutBounce(xd0cd) * .5 .5 b;
};

// basic ones
function easeLinear(x) {
  return 
x;
}

function 
easeSwing(x) {
  return (- 
cos(pi) / 2) + 0.5;
}

// helper
function ease(temp.easingxtbcd) {
  return 
this.(@ "ease" temp.easing)(xtbcd);

Hopefully someone finds use out of this .
__________________

Last edited by cbk1994; 05-31-2012 at 09:28 AM.. Reason: links approved
Reply With Quote
  #2  
Old 05-31-2012, 05:14 AM
Fulg0reSama Fulg0reSama is offline
Extrinsical Anomaly
Fulg0reSama's Avatar
Join Date: Sep 2009
Location: Ohio
Posts: 3,049
Fulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant futureFulg0reSama has a brilliant future
Insta-Impressed. (Don't care about this not being a real word)

+rep Chris.
__________________

Careful, thoughts and opinions here scare people.
Reply With Quote
  #3  
Old 05-31-2012, 05:56 AM
Imperialistic Imperialistic is offline
graal player lord
Imperialistic's Avatar
Join Date: Apr 2007
Location: Florida
Posts: 1,094
Imperialistic is a jewel in the roughImperialistic is a jewel in the rough
+rep

very impressive
__________________
" It's been swell, but the swelling's gone down. "
Reply With Quote
  #4  
Old 05-31-2012, 01:23 PM
Hezzy002 Hezzy002 is offline
Registered User
Join Date: Jul 2011
Posts: 247
Hezzy002 is a jewel in the roughHezzy002 is a jewel in the rough
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.

Last edited by Hezzy002; 05-31-2012 at 02:22 PM..
Reply With Quote
  #5  
Old 05-31-2012, 02:03 PM
Chompy Chompy is offline
Ż\(ş_o)/Ż
Chompy's Avatar
Join Date: Sep 2006
Location: Norway
Posts: 2,815
Chompy is just really niceChompy is just really niceChompy is just really nice
Send a message via MSN to Chompy
Quote:
Originally Posted by Hezzy002 View Post
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.
Thumbs up for that.
__________________
Reply With Quote
  #6  
Old 05-31-2012, 02:25 PM
Hezzy002 Hezzy002 is offline
Registered User
Join Date: Jul 2011
Posts: 247
Hezzy002 is a jewel in the roughHezzy002 is a jewel in the rough
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.

Last edited by Hezzy002; 05-31-2012 at 03:02 PM..
Reply With Quote
  #7  
Old 05-31-2012, 05:01 PM
Emera Emera is offline
Delterian Hybrid
Emera's Avatar
Join Date: Mar 2011
Location: Newcastle Upon-Tyne
Posts: 1,704
Emera is a jewel in the roughEmera is a jewel in the rough
This looks great. Good job.
Reply With Quote
  #8  
Old 05-31-2012, 05:02 PM
MattKan MattKan is offline
the KattMan
Join Date: Aug 2010
Location: United States
Posts: 1,325
MattKan is a splendid one to beholdMattKan is a splendid one to beholdMattKan is a splendid one to beholdMattKan is a splendid one to beholdMattKan is a splendid one to behold
Send a message via AIM to MattKan
Is there anything you can't do? +rep
Reply With Quote
  #9  
Old 06-01-2012, 01:42 AM
salesman salesman is offline
Finger lickin' good.
salesman's Avatar
Join Date: Nov 2008
Location: Colorado
Posts: 1,865
salesman has much to be proud ofsalesman has much to be proud ofsalesman has much to be proud ofsalesman has much to be proud ofsalesman has much to be proud ofsalesman has much to be proud ofsalesman has much to be proud of
I hate it, rep-
jk chris plz 4give
__________________
Reply With Quote
  #10  
Old 06-01-2012, 03:34 AM
Tolnaftate2004 Tolnaftate2004 is offline
penguin.
Join Date: Jul 2004
Location: Berkeley, CA
Posts: 534
Tolnaftate2004 is a jewel in the roughTolnaftate2004 is a jewel in the rough
Send a message via AIM to Tolnaftate2004
http://forums.graalonline.com/forums...ad.php?t=79671

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.numNULL);
  }
  return;
}

function 
growl(stitletexticontime) {
  if (
text 0) { time texttext stitlestitle ""icon "alert"; }
  if (
icon 0)  { time iconicon texttext stitlestitle ""; }
  if (
time == 0) { time 10; }
  if (
text == "") { text stitlestitle ""; }
  
  echo(
"[" int(timevar2) @ "] " stitle); echo(text);
  
temp.lines wraptext2(2382/3" -""@verdana@@" text);
  
temp.ys = {};
  
temp.max(3218 * (temp.stitle != "") + 16 temp.lines.size());
  for (
temp.0temp.temp.lines.size(); temp.i++)
    
temp.ys.add(16 * (temp.stitle != "") + 16 temp.i);
  
  for (
temp.this.messages.size(); temp.> -1temp.i--) {
    if (
this.messages[temp.i].objecttype() == "TGraalVar")
      
this.messages.delete(temp.i);
    else 
this.messages[temp.i].duplicate().set("y""+=" @ (temp.10));
  }
  
  
temp.sw screenwidth;
  
temp.bg = $()
    .
images(9200)
    .
set("image"PRE "blackbox.png")
    .
set("layer"7)
    .
set("alpha"1)
    .
set("mode"1)
    .
set("zoom"1)
    .
set("partx", { 01020 })
    .
set("party", { 000101010202020 })
    .
set("partw"10)
    .
set("parth" 10)
    .
set("stretchx", { 128})
    .
set("stretchy", { 111temp.h/10-1temp.h/10-1temp.h/10-111})
    .
set("x", { temp.sw 303temp.sw 158temp.sw 13 })
    .
set("y", { 4444+temp.h/24+temp.h/24+temp.h/24+temp.h4+temp.h4+temp.})
  ;
  if ( 
stitle != "" ) {
    
temp.title = $()
      .
images(1200)
      .
set("text"stitle)
      .
set("zoom"0.7)
      .
set("font""verdana")
      .
set("style""b")
      .
set("layer"8)
      .
set("x"temp.sw 251)
      .
set("y"4)
    ;
  }
  
temp.desc = $()
    .
images(temp.lines.size(), 200)
    .
set("text"temp.lines)
    .
set("zoom"2/3)
    .
set("font""verdana")
    .
set("layer"8)
    .
set("x"temp.sw 251)
    .
set("y"temp.ys)
  ;
  
temp.icon = $()
    .
images(1200)
    .
set("image"PRE "icon_" icon ".png")
    .
set("layer"8)
    .
set("mode"1)
    .
set("x"temp.sw 294)
    .
set("y"temp.h/9)
  ;
  
  (
temp.merged = $());
  
temp.merged
    
.merge({ temp.bgtemp.titletemp.desctemp.icon })
    .
wait(time)
    .
call(
      
this.clear_out = function (args) {
        
temp.args[0];
        
temp.args[1];
        
temp.on false;
        for (
temp.this.messages.size()-1temp.> -1temp.i--) {
          
temp.msg this.messages[temp.i];
          if (
temp.msg.objecttype() == "TGraalVar") continue;
          if (
temp.msg == temp.qtemp.on true;
          elseif (
temp.on) {
            
temp.msg
              
.duplicate()
              .
tween("y""-=" @ (temp.10), 1)
              .
wait(1)
            ;
          }
        }
      }, { 
temp.mergedtemp.}
    )
    .
tween("alpha"01)
    .
wait(1)
    .
end()
  ;
  
  
this.messages.add(temp.merged);
}

public function 
addmsg(titledescicondur) {
  
getlock();
  
growl(titledescicondur);
  
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.
Attached Files
File Type: txt boilerplate.txt (999 Bytes, 167 views)
File Type: txt boilerplate.base.txt (13.6 KB, 188 views)
File Type: txt boilerplate.images.txt (1.1 KB, 170 views)
__________________
◕‿‿◕ · pfa · check yer syntax! · src

Killa Be: when i got that locker in 6th grade the only thing in it was a picture of a midget useing a firehose :/
Reply With Quote
  #11  
Old 06-01-2012, 04:05 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
Quote:
Originally Posted by Tolnaftate2004 View Post
Hah, totally forgot about that. I even replied in the thread.
__________________
Reply With Quote
  #12  
Old 04-21-2013, 05:25 PM
xXziroXx xXziroXx is offline
Master of Puppets
xXziroXx's Avatar
Join Date: May 2004
Location: Sweden
Posts: 5,288
xXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant future
Send a message via AIM to xXziroXx Send a message via MSN to xXziroXx
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
__________________

"A delayed game is eventually good, but a rushed game is forever bad." - Shigeru Miyamoto
Reply With Quote
  #13  
Old 04-22-2013, 01:46 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
Quote:
Originally Posted by xXziroXx View Post
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.
__________________
Reply With Quote
  #14  
Old 04-22-2013, 02:40 AM
xXziroXx xXziroXx is offline
Master of Puppets
xXziroXx's Avatar
Join Date: May 2004
Location: Sweden
Posts: 5,288
xXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant futurexXziroXx has a brilliant future
Send a message via AIM to xXziroXx Send a message via MSN to xXziroXx
Quote:
Originally Posted by cbk1994 View Post
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!
__________________

"A delayed game is eventually good, but a rushed game is forever bad." - Shigeru Miyamoto
Reply With Quote
  #15  
Old 04-22-2013, 03:54 AM
fowlplay4 fowlplay4 is offline
team canada
fowlplay4's Avatar
Join Date: Jul 2004
Location: Canada
Posts: 5,200
fowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond repute
Try tweening another variable and then setting the height/width to that variable.
__________________
Quote:
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 10:38 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.