OLPCities/Sprites: Difference between revisions
No edit summary |
|||
(20 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
This library is part of the <b>Gamelib</b>, created by Scott Porter and updated by Brent Silby. Gamelib is available under the terms of the [http://www.gnu.org/copyleft/lgpl.html GNU Library General Public Licence]. |
|||
By definition the sprite has "frames" (horizontal frames) and "animations" (vertical frames). It can have only one frame so it will have 1 "frame" and 1 "animation" that are the same. |
|||
By definition a sprite has "frames" (horizontal frames) and "animations" (vertical frames). It can have only one frame so it will have 1 "frame" and 1 "animation" that are the same. |
|||
To understand this better take a look at the many sprites at: |
To understand this better take a look at the many sprites at: |
||
*[[Floors]] |
*[[OLPCities/Floors|Floors]] |
||
*[[Avatares]] |
*[[OLPCities/Avatares|Avatares]] |
||
*[[3D objects]] |
*[[OLPCities/3D objects|3D objects]] |
||
*[[Hard objects]] |
*[[OLPCities/Hard objects|Hard objects]] |
||
*[[Animated objects]] |
*[[OLPCities/Animated objects|Animated objects]] |
||
*[[Links]] |
*[[OLPCities/Links|Links]] |
||
To use this library (this Class) add |
To use this library (this Class) add one line to the <HEAD> section of the web page of the Lot. |
||
<pre> |
|||
You need to click this link and "save" the library at the same folder of the web page or put it at another folder at the same server and make a reference: |
|||
<script language="Javascript" src="http://www.dmu.com/olpc/gamelib_sprites.js"></script> |
|||
</pre> |
|||
Better to click this link and "save" the library at the same folder of the web page or put it at another folder at the same server and make a reference: |
|||
[http://www.dmu.com/olpc/gamelib_sprites.js gamelib_sprites.js ] |
[http://www.dmu.com/olpc/gamelib_sprites.js gamelib_sprites.js ] |
||
If you put it at the same folder, the line would be: |
|||
<pre> |
<pre> |
||
<script language="Javascript" src="gamelib_sprites.js"></script> |
<script language="Javascript" src="gamelib_sprites.js"></script> |
||
Line 47: | Line 47: | ||
destroy() Will "destroy" the sprite object. |
destroy() Will "destroy" the sprite object. |
||
setCollisionArea(n,n,n,n) |
setCollisionArea(n,n,n,n) Setsa the collision area for a sprite. The parameters passed are the distances |
||
from the left, right, top and bottom . |
from the left, right, top and bottom . |
||
Line 73: | Line 73: | ||
setImage(String,n,n,n,n) Sets the sprite image. The arguments to this method are passed in the |
setImage(String,n,n,n,n) Sets the sprite image. The arguments to this method are passed in the |
||
following order: the image src (eg "mypicture.gif"); width of each frame; |
following order: the image src (eg "mypicture.gif"); width of each frame; |
||
height of each |
height of each frame; number of "frames"; number of "animations". |
||
setFrame(n) Sets the sprite's frame (horizontal). Each frame can have a number |
|||
</pre> |
|||
of animations (vertical). Using this resets to the first animation for |
|||
the frame (animation position 0). You must set a frame for a sprite before it |
|||
will be displayed at all. If a sprite only has one frame/animation, |
|||
use setFrame(0). |
|||
setFrameByDirection (n,n,n...) This method is used to specify which frames the sprite should use when it's |
|||
==TO BE EDITED SOON== |
|||
heading in different directions. The arguments are in sets of 3, and are of |
|||
the form degree,degree,frame, degree,degree,frame etc etc. So if you wanted |
|||
a sprite to use frame 0 when it was moving in the direction between 50 and |
|||
70 degrees, and frame 1 when it was moving between 71 and 100 degrees, you |
|||
could use something like this: |
|||
mySprite.setFrameByDirection(50,70,0,71,100,1); |
|||
setAnimation(n) Sets one of the sprite's animations |
|||
swapImage String Swaps the sprite's image to a new passed as the argument. You must use setImage() to set the sprite's initial image. This method will not resize the image currently in use, and so should only be used to swap between images of the same size unless you don't mind the scaling. On the other hand though, it's very fast! |
|||
setFrame Numeric This sets the sprite's frame. Each frame can have a number of animations. Using this resets the animation position for a sprite to the first animation for the frame (animation position 0). You must set a frame for a sprite before it will be displayed at all. If a sprite only has one frame, and no animation, use setFrame(0) |
|||
setAnimationLoop(n,n) Sets the animation limits for a frame between the first and second arguments. |
|||
setFrameByDirection Numeric, Numeric, Numeric [...] This method is used to specify which frames the sprite should use when it's heading in different directions. The arguments are in sets of 3, and are of the form degree,degree,frame, degree,degree,frame etc etc. So if you wanted a sprite to use frame 0 when it was moving in the direction between 50 and 70 degrees, and frame 1 when it was moving between 71 and 100 degrees, you could use something like this: |
|||
This is used when using a canvas image with animations of varying lengths |
|||
(for example, 2 stages of animation for one frame, 5 for another frame etc) |
|||
setAnimationRepeat(n) When this is set to a value above -1, the sprite will animate x times. |
|||
A value of -1 means "keep animating indefinately". |
|||
setAnimationSpeed(n [,String]) The first argument sets the sprites animation speed (number of frames |
|||
mySprite.setFrameByDirection(50,70,0,71,100,1); |
|||
between animation changes) A value of 0 means |
|||
no animation. The optional second argument is either "forward" |
|||
or "backward" (case insensitive). 3 is the usual for avatares walking. |
|||
2 is faster than 3. |
|||
setSpeed(n) Sets the sprite speed. |
|||
Easy huh? :-) You can specify up to 360 degrees for a sprite's frames. Sprites are intelligent enough to translate between degrees and absolute directions too, so if you set the direction to (1,-1), the sprite knows to use the frame that covers 45 degrees! |
|||
setFalling Numeric You can use this in any way you feel appropriate. Perhaps set to 1 if the sprite is falling, then 0 if the sprite is not falling. For example: |
|||
mySprite.setFalling(1); |
|||
getXYdegs() This method will return the sprite's current direction as degrees, an |
|||
setFallingSpeed Numeric This is another useful property. You can use this to keep a record of the sprite's falling speed. |
|||
integer between 0 and 359. |
|||
mySprite.setFallingSpeed(8); |
|||
Note: At this time there are no falling functions provided in the sprite module. You will have to handle this yourself. FallingSpeed, setFalling, setJumpSpeed etc are simply properties that you can use in whatever way you choose. |
|||
setXYdegs(n) Sets the sprite direction between 0 and 359 degrees. |
|||
setFinishPos Numeric It is often useful to calculate a finish position for a sprite when it is falling. |
|||
mySprite.setFinishPos(278); |
|||
setZ(n) Sets the sprite z-index. Sprites with higher values move over |
|||
those with lower ones |
|||
switchOn() Switches the sprite on. When a sprite is created, it is off by |
|||
default, and so not visible. |
|||
mySprite.setJumping(1); |
|||
switchOff() Switches the sprite off |
|||
dragType (n) Defines how the sprite can be dragged (see makeDraggable() method |
|||
which must be used first). The dragType can be one of the following: |
|||
0 = normal dragging (default). |
|||
1 = Sprite can only be dragged in the y axis. |
|||
2 = Sprite can only be dragged in the x axis. |
|||
follow(Object,n,n) Causes the sprite to follow another sprite or the mouse object, remaining |
|||
at distance n,n from the object it's following. A sprite can only follow one |
|||
object at a time, so you MUST use the stopFollowing() method before you make |
|||
a sprite follow something else! Good to be used for a bullet of |
|||
an avatar's gun. At the shoot you liberate it and change it's speed. |
|||
makeDraggable() Makes the sprite draggable! * Note: You must have the mouse module |
|||
linked in to use this |
|||
makeUndraggable() Stops the sprite from being draggable! |
|||
setCollide(Boolean) If true, the sprite will register collisions. If this is false, then the |
|||
hit events will not work (default=false) |
|||
stopFollowing() Causes the sprite to stop following another sprite or the mouse |
|||
useHitEvents(Boolean) If true, then sprite will use hit events (and hard hit events) as defined below. |
|||
setHitEvent(Object,String) String argument is function name or any legitimate JavaScript statement) |
|||
to be called when this sprite hits another. |
|||
target (Object,n,n) The sprite will now move toward the Sprite Object, offset from its top left |
|||
corner by x,y pixels (passed as the second and third arguments. Whether it |
|||
catches a moving sprite or not depends on the speeds of the two sprites. |
|||
A sprite can only target one object at a time, so use the stopTargetting() |
|||
method before you make a sprite target a new object. |
|||
stopTargetting(String) Stops the sprite from targetting another sprite. If the String 'drift' is |
|||
passed (ie mySprite.stopTargetting('drift')) then the sprite will continue |
|||
moving in the direction it was before it stopped targetting. |
|||
makeHard () Makes the sprite "hard" for collisons. |
|||
setHardHitEvent(String) The string argument is a function or JavaScript statement to be called when this |
|||
sprite hits ANY hard sprite. You must enable hit events for the sprite to use |
|||
this (see useHitEvents() method) |
|||
</pre> |
|||
==Properties== |
|||
Read only if not especified differently |
|||
<pre> |
|||
on Use this to determine whether the sprite is on/off. |
|||
When off, it's not on screen. |
|||
x Sprite's X position |
|||
y Sprite's Y position |
|||
setJumpSpeed This is another useful property. You can use this to keep a record of the sprite's jumping speed. You can change it in your script if you want to make the sprite's jump speed slow down to 0 to make it look realistic. Perhaps once it reaches 0 you can setJumping(0), then setFalling(1) and define a fallingSpeed (see above). |
|||
mySprite.setFallingSpeed(8); |
|||
z Sprite's z position. Sprites with higher value will pass over sprites with lower. |
|||
xmin The minumum allowed x position for sprite. |
|||
ymin The minimum allowed y position for sprite. |
|||
setAnimation Numeric This sets the sprite's animation stage for the frame |
|||
setAnimationLoop Numeric, Numeric This sets the animation limits for a frame between the first and second arguments. This is used when using a canvas image with animations of varying lengths (for example, 2 stages of animation for one frame, 5 for another frame etc) |
|||
You cannot set the animation limits below 0, or above the maximum amount of animations specified when canvas was loaded into the sprite using setImage(). Also, the first argument cannot be greater than the second. The method checks for these things and adjusts the values to correct limits. This is useful if you wish to revert to the default animation limits for a sprite, just set the first argument to 0 and the second to a large number! |
|||
xmax The maximum allowed x position for sprite. |
|||
setAnimationRepeat Numeric When this is set to a value above -1, the sprite will animate x times. A value of -1 means "keep animating indefinately". Once the sprite stops animating, you can start it animating again by either using this method again, or using the setAnimationSpeed() method |
|||
setAnimationSpeed Numeric [,String] The first argument sets the sprites animation speed. A value of 0 means no animation. Any other value means how many frames between animation changes. So 1 would mean every frame, 2 would mean every other frame etc. When animating, the sprite keeps the same frame but loops through the animations for that frame (between the default limits of animation when the setImage() method was called, or the limits imposed by setAnimationLoop()). 0 is the default speed for animations (no animation). |
|||
ymax The maximum allowed y position for sprite. |
|||
The optional second argument is either "forward" or "backward" (case insensitive). "forward" means loop through animation stages from top to bottom of the image you gave the sprite, "backward" loops up from bottom to top. "forward" is the default setting. If this argument is omitted, the sprite will continue to animate in its current direction. |
|||
width The width of sprite |
|||
height The height of sprite |
|||
xdir The direction of sprite in x axis |
|||
ydir The direction of sprite in y axis |
|||
xydegs The current direction of sprite as 0-359 degrees |
|||
speed The speed of sprite. |
|||
hard True if an sprite is hard |
|||
frame The current frame being used by an animated sprite. |
|||
animpos The current animation position for a frame. |
|||
animdir The direction of animation, either "forward" or "backward". |
|||
setShootDelay Numeric A useful property. The gamelib engine doesn't do anything with this. You can use it in whatever way you wish. A suggestion is to use it in shooting games. Only let a sprite fire if it's shoot delay is <0. Then set the sprite's shoot delay to, say, 5 when it shoots. On every loop reduce the sprite's shoot delay e.g mySprite.setShootDelay(mySprite.shootDelay-1). |
|||
setSpeed Numeric Sets the sprite speed |
|||
getXYdegs (none) This method will return the sprite's current direction as degrees of a circle. So if you had set the direction to (1,0) for example, this method would return 90. The return value is always an integer between 0 and 359. |
|||
setValue Numeric This sets the sprite's value. See the value property for details. |
|||
setXYdegs Numeric This sets the sprite direction between 0 and 359 degrees. wraps so that 360 degs=0, 370 degs=10 etc |
|||
setZ Numeric This sets the sprite z-index. Sprites with higher values move over those with lower ones |
|||
switchOn (none) This switches the sprite on. When a sprite is created, it is off by default, and so not visible |
|||
switchOff (none) This switches the sprite off (default) |
|||
resize Numeric, Numeric This resizes the sprite to x,y size. Note: this is not the size of the canvas, but the size of the individual frames/animations in the canvas. Any collision area settings are retained. Be aware that Netscape 4 has difficulties resizing images, so although it will work, there will be some flickering if sprites are being resized constantly. |
|||
dragType Numeric/String Defines how the sprite can be dragged (see makeDraggable() method which must be used first). The dragType can be one of the following: |
|||
0 or "normal" =normal dragging (default). |
|||
1 or "vertical" =Sprite can only be dragged in the y axis. |
|||
2 or "horizontal" =Sprite can only be dragged in the x axis. |
|||
animspd The number of frames between animation changes. 0 means no animation. |
|||
* Note: sprites cannot be dragged outside their x and y limits (xmin,xmax,ymin,ymax) |
|||
onmouseover [=String] Is R/W The string is the function name to be called when the mouse |
|||
pointer has moved over the sprite. This CAN include arguments so |
|||
mySprite.onmouseover="dosomething(x,y,z)" would pass the variables x,y,z |
|||
to the function dosomething |
|||
onmouseout [=String} Is R/W. The string is the function name to be called |
|||
onclickdown [=String] Is R/W The string is the function name to be called |
|||
onclickup [=String] Is R/W The string is the function name to be called |
|||
</pre> |
|||
<b>***IMPORTANT: To use the last four properties you need to create an object of the Class [[OLPCities/Mouse|Mouse]] </b> |
|||
<pre> |
|||
bounces [=Boolean] Is R/W The sprite will collide and do not stops, reverting the direction |
|||
draggable Whether the sprite is draggable or not. |
|||
hitevents Whether this sprite is using hit events (see setHitEvent() method |
|||
beingfollowed True if sprite is being followed by another object |
|||
following The sprite this sprite is following |
|||
follow Sprite Object, Numeric, Numeric As with the layer object (see layer docs), this causes the sprite to follow another sprite or the mouse object, remaining at distance x,y (where x is the second argument, y the third) from the object it's following. A sprite can only follow one object at a time, so you MUST use the stopFollowing() method before you make a sprite follow something else! |
|||
groupHit (none) This will cause a groupHit event for this sprite's group. If the group this sprite belongs to has a trigger set, and this hit, added to the current total of hits in the group has reached the group's trigger value, then the group's trigger event will fire, and the groups hit count will be reset to zero. (see global group functions section for more details about sprite groups) |
|||
followingx The x offset to sprite this sprite is following |
|||
groupSet Numeric This will add the sprite to a group. If a group with the ID passed as the parameter does not exist, it will be created and the hitCount for the group set to zero. (see global group functions section for more details about sprite groups) |
|||
makeDraggable (none) Makes the sprite draggable! * Note: You must have the mouse module linked in to use this |
|||
followingy The y offset to sprite this sprite is following |
|||
makeUndraggable (none) Stops the sprite from being draggable! * Note: You must have the mouse module linked in to use this |
|||
setCollide Boolean If true, the sprite will register collisions. If this is false, then the hit events will not work (default=false) |
|||
</pre> |
|||
stopFollowing (none) Calling this method causes the sprite to stop following another sprite or the mouse |
|||
useHitEvents Boolean If true, then sprite will use hit events (and hard hit events) as defined below. Using these events does not have much impact upon performance, and can greatly simplify your own code! Don't enable them unless you're actually going to use them though... |
|||
[[Category:OLPCities_JavaScript_Libraries]] |
|||
setHitEvent Sprite Object,String String argument is function name (usually, but can be any legitimate javascript statement) to be called when this sprite hits the Sprite Object. You cannot set a hit event for the mouse since there are already 4 mouse events for that! |
|||
target Sprite Object, Numeric, Numeric The sprite will now move toward the Sprite Object, offset from its top left corner by x,y pixels (passed as the second and third arguments. Whether it catches a moving sprite or not depends on the speeds of the two sprites. A sprite can only target one object at a time, so use the stopTargetting() method before you make a sprite target a new object. |
|||
stopTargetting String This stops the sprite from targetting another sprite. If the String 'drift' is passed (ie mySprite.stopTargetting('drift')) then the sprite will continue moving in the direction it was before it stopped targetting. |
|||
makeHard (none) This makes sprite hard (fnaa fnaa :). See hard property for details |
|||
setHardHitEvent String The string argument is a function (usually, but can be any legitimate javascript statement) to be called when this sprite hits ANY hard sprite. You must enable hit events for the sprite to use this (see useHitEvents() method) |
|||
setOpacity Numeric Sets the opacity of the sprite. Range is from 0 to 100, with 0 being invisible. It's probably not a good idea to use this too much in a game, as it affects performance when there are a lot of semi-transparent objects flying around (looks nice though!) This function has no effect with Netscape 4 (browser does not support transparency.) |
Latest revision as of 06:51, 2 June 2009
This library is part of the Gamelib, created by Scott Porter and updated by Brent Silby. Gamelib is available under the terms of the GNU Library General Public Licence.
By definition a sprite has "frames" (horizontal frames) and "animations" (vertical frames). It can have only one frame so it will have 1 "frame" and 1 "animation" that are the same.
To understand this better take a look at the many sprites at:
To use this library (this Class) add one line to the <HEAD> section of the web page of the Lot.
You need to click this link and "save" the library at the same folder of the web page or put it at another folder at the same server and make a reference:
If you put it at the same folder, the line would be:
<script language="Javascript" src="gamelib_sprites.js"></script>
To create an "object" of the Class:
someName = new Sp_Sprite();
Due to the continuing rendering problems under Linux platforms, add the following statement to your script before creating the sprites:
Sp_linuxcompatible=true;
Methods
clearCollisionArea() Removes the collision area from a sprite. See the setCollisionArea(). clearRoute() Stops sprite from following a route. See setRoute(). clearRouteLoop() Stops the sprite from looping through a route. It will continue following its current route until the end. destroy() Will "destroy" the sprite object. setCollisionArea(n,n,n,n) Setsa the collision area for a sprite. The parameters passed are the distances from the left, right, top and bottom . setCollisionZTest(n) Sets the maximum distance another sprite can be within in the Z axis to be able to collide with this sprite. See the setZ(n). setRoute (Boolean,n,n,...) sets a route for the sprite to follow. The first argument specifies whether the sprite should loop (true means loop, false means don't) through the route. After the first argument, any number of numeric x,y values which specify the co-ordinates the sprite should visit during the route. getHits() Will return an array containing references to all the sprites this sprite hit during the last gameloop. hasHit(Object) Test if the sprite has hit another. moveTo(n,n) Moves sprite to position on screen. setDir(n,n) Sets sprite directions. setXlimits(n,n) Limits the sprite x movement. setYlimits(n,n) Limits the sprite y movement. setImage(String,n,n,n,n) Sets the sprite image. The arguments to this method are passed in the following order: the image src (eg "mypicture.gif"); width of each frame; height of each frame; number of "frames"; number of "animations". setFrame(n) Sets the sprite's frame (horizontal). Each frame can have a number of animations (vertical). Using this resets to the first animation for the frame (animation position 0). You must set a frame for a sprite before it will be displayed at all. If a sprite only has one frame/animation, use setFrame(0). setFrameByDirection (n,n,n...) This method is used to specify which frames the sprite should use when it's heading in different directions. The arguments are in sets of 3, and are of the form degree,degree,frame, degree,degree,frame etc etc. So if you wanted a sprite to use frame 0 when it was moving in the direction between 50 and 70 degrees, and frame 1 when it was moving between 71 and 100 degrees, you could use something like this: mySprite.setFrameByDirection(50,70,0,71,100,1); setAnimation(n) Sets one of the sprite's animations setAnimationLoop(n,n) Sets the animation limits for a frame between the first and second arguments. This is used when using a canvas image with animations of varying lengths (for example, 2 stages of animation for one frame, 5 for another frame etc) setAnimationRepeat(n) When this is set to a value above -1, the sprite will animate x times. A value of -1 means "keep animating indefinately". setAnimationSpeed(n [,String]) The first argument sets the sprites animation speed (number of frames between animation changes) A value of 0 means no animation. The optional second argument is either "forward" or "backward" (case insensitive). 3 is the usual for avatares walking. 2 is faster than 3. setSpeed(n) Sets the sprite speed. getXYdegs() This method will return the sprite's current direction as degrees, an integer between 0 and 359. setXYdegs(n) Sets the sprite direction between 0 and 359 degrees. setZ(n) Sets the sprite z-index. Sprites with higher values move over those with lower ones switchOn() Switches the sprite on. When a sprite is created, it is off by default, and so not visible. switchOff() Switches the sprite off dragType (n) Defines how the sprite can be dragged (see makeDraggable() method which must be used first). The dragType can be one of the following: 0 = normal dragging (default). 1 = Sprite can only be dragged in the y axis. 2 = Sprite can only be dragged in the x axis. follow(Object,n,n) Causes the sprite to follow another sprite or the mouse object, remaining at distance n,n from the object it's following. A sprite can only follow one object at a time, so you MUST use the stopFollowing() method before you make a sprite follow something else! Good to be used for a bullet of an avatar's gun. At the shoot you liberate it and change it's speed. makeDraggable() Makes the sprite draggable! * Note: You must have the mouse module linked in to use this makeUndraggable() Stops the sprite from being draggable! setCollide(Boolean) If true, the sprite will register collisions. If this is false, then the hit events will not work (default=false) stopFollowing() Causes the sprite to stop following another sprite or the mouse useHitEvents(Boolean) If true, then sprite will use hit events (and hard hit events) as defined below. setHitEvent(Object,String) String argument is function name or any legitimate JavaScript statement) to be called when this sprite hits another. target (Object,n,n) The sprite will now move toward the Sprite Object, offset from its top left corner by x,y pixels (passed as the second and third arguments. Whether it catches a moving sprite or not depends on the speeds of the two sprites. A sprite can only target one object at a time, so use the stopTargetting() method before you make a sprite target a new object. stopTargetting(String) Stops the sprite from targetting another sprite. If the String 'drift' is passed (ie mySprite.stopTargetting('drift')) then the sprite will continue moving in the direction it was before it stopped targetting. makeHard () Makes the sprite "hard" for collisons. setHardHitEvent(String) The string argument is a function or JavaScript statement to be called when this sprite hits ANY hard sprite. You must enable hit events for the sprite to use this (see useHitEvents() method)
Properties
Read only if not especified differently
on Use this to determine whether the sprite is on/off. When off, it's not on screen. x Sprite's X position y Sprite's Y position z Sprite's z position. Sprites with higher value will pass over sprites with lower. xmin The minumum allowed x position for sprite. ymin The minimum allowed y position for sprite. xmax The maximum allowed x position for sprite. ymax The maximum allowed y position for sprite. width The width of sprite height The height of sprite xdir The direction of sprite in x axis ydir The direction of sprite in y axis xydegs The current direction of sprite as 0-359 degrees speed The speed of sprite. hard True if an sprite is hard frame The current frame being used by an animated sprite. animpos The current animation position for a frame. animdir The direction of animation, either "forward" or "backward". animspd The number of frames between animation changes. 0 means no animation. onmouseover [=String] Is R/W The string is the function name to be called when the mouse pointer has moved over the sprite. This CAN include arguments so mySprite.onmouseover="dosomething(x,y,z)" would pass the variables x,y,z to the function dosomething onmouseout [=String} Is R/W. The string is the function name to be called onclickdown [=String] Is R/W The string is the function name to be called onclickup [=String] Is R/W The string is the function name to be called
***IMPORTANT: To use the last four properties you need to create an object of the Class Mouse
bounces [=Boolean] Is R/W The sprite will collide and do not stops, reverting the direction draggable Whether the sprite is draggable or not. hitevents Whether this sprite is using hit events (see setHitEvent() method beingfollowed True if sprite is being followed by another object following The sprite this sprite is following followingx The x offset to sprite this sprite is following followingy The y offset to sprite this sprite is following