2DCharacterControlLib for AS3
From WorkCDN
Summary
Current Status: writing design doc
This is a library for use in ActionScript3 (AS3).
AS3 is the language behind Adobe Flash, Flex, and Air.
This library will allow a user to control characters in a 2D video game.
With a few adjustments to the code, it can be customized for various "perspectives" such as
- side-view platformer or fighting game
- top-down action/arcade
- isometric RPG
In theory, if a game had various perspectives in it, or mini-games with differing perspectives,
this one library could handle all of them.
The scope of this project does not include environments, or being able to go in front of or behind things. It is strictly character control but will account for common events that effect a character like collision, and common events that a character must perform at a certain frame like shooting a projectile, or playing a sound.
Theory
Definitions:
- animation frame -- this is one frame of animation for a character. It could be part of a walk-cycle, or just standing still, or a jump animation. It has both images and variables associated with it. (bitmap instantiations and properties of where to get the bitmap from, where to place it, and what draw order it has)
- action -- this is a series of one or more animation frames such as a walk cycle, overhead chop, or some gesture like wave goodbye. Practically speaking, this can be referred to as an animation. But for purposes of artificial intelligence and coding, it seems easier to call it an action.
- activity -- this is a series of one or more actions. An activity might be a sword combination: chop, chop, parry, or a series of pathfinding commands: turn right, walk ahead, turn left, walk ahead, walk ahead, stop.
unorganized ramblings
If the game has a few simple actions like move, shoot, and jump, then there is not a need to have the frames take care of character movement and AI. But if there are many possibilities branching from each other, like fight combos, pathfinding, and gestures, then this should be alot easier than having functions upon functions to take care of every possibility.
Some changes to a character are handled by user interaction and in-game stimuli from other NPCs, projectiles, etc. Other changes are instinctual to the character and should be handled internally within the animation/action. For instance, the new X and Y position of the character can many times be determined by the frame of animation being shown. If the character is in mid-jump, we know he's going to be continuing along that jump path. But if collision occurs, this is best handled at the highest level of the character object, because it can occur at any frame. Some animation frames are interruptable by user interaction and some are not. But all animation frames are interruptable by collision. So when creating these animations for the game, each frame has booleans attached to it, allowing it to be interruptable by certain other actions, and all frames are susceptable to higher-governing code, unless elsewise stated.
And considering a jump, there is the issue of a super jump, common in lots of games. The dev might opt to use the same art assets. In the common/current way of doing things, a function takes care of the trajectory of the normal jump, and it is altered in code for the super jump. Then there's need to check for collision and if another button is pushed, segwey into a flying kick, flying punch, flip, etc. In my proposed way of controlling a character, a new animation is set up, called super jump. It is an action. Each frame of a jump or super jump can have permission to branch off into flying jump, flying kick, flying flip, land or whatever. Perhaps the dev decides that only 1 frame of animation can branch off into a super flying combo attack or something. Also, the end of the jump can end in a fall action, where the character plummets down an endless pit, say, in a platformer.
Another consideration is in the case of collision avoidance. There is an instinctual part and a pre-meditated part. If a character is venturing along a path-finding path, and encounters another NPC walking into him (something that path-finding can't take into consideration), the actions within the character's activity should alter, but the character's directive should remain the same: that is, to get to the destination, this time by a slightly different path. So in this case, it shouldn't be handled frame by frame, nor should path finding be calculated each iteration, but the character's current action should be checking for potential nearby collisions and if so, refer to the path-finding function, a higher-level function.
This collision avoidance is the same technique that some engines use, where there are varying degrees of collision: if the character is on screen, then turn on proximity. If another character enters that proximity then turn on collision (and in our case, collision avoidance). If collision occurs, then bounce the characters away from each other.
I'm currently working on a game where two worlds are depicted simultaneously. The characters of each world interract physically (collide, fight, etc.) within their own world, but not with characters of the other world. There is interaction from one world to another but it is not instantaneous (not instinctual or immediate). It is a reaction purely handled by AI: activities are changed and not animation frames.
The idea is to allow instinctual behaviors to be handled within the animation frames themselves, higher levels of reaction (AI) tied to activities, and things in between to actions.
Technical Specifics
WIP
Each frame of animation needs to be identified by the character's action, direction, and ???
Usually each frame has only one image associated with it. But in some cases, several images are used to create the character, like head, hair, arms, jacket, pants, shoes, etc. Because of this, an ArrayCollection is associated with the character which has the draw order of the images. Additionally, each image of each frame has an offsetX and offsetY which place the images off-center from the characterX,Y. For instance, the image for a piece of hair should be very small, and drawn way above the character's feet. Obviously, the Image class in AS3 needs to be extended to include these offsets
Considering a simpler 2D game which uses only one image per frame of animation for a character, there will be quite a bit of usused variables for each frame of animation.
Not only should the individual paperDoll pieces have offsetX,Y, but the entire frame should have offsetX,Y, to be able to adjust it so that the in-game animation is fluid, no feet slipping, etc. The frame's offsetX,Y is actually the thing which will increase the characterX,Y. characterX += frame.offsetX
Additionally, the character has a varySpeed which is added to characterX,Y. If varySpeed is set to zero, there is no variation in the character's speed. It's a number between 0 and 1, a percentage in decimal form, like .4 or .75
varySpeed is multiplied to frame.offsetX before being added to characterX. characterX += (frame.offsetX * varySpeed)
For random NPC character generation, this varySpeed can be randomized.
A tool will need to be made to set all these variables for characters which the dev wants to create specifically. The varySpeed can be displayed as a percentage (64%) or a decimal (.64), depending on the target user group for this lib. This lib will basically be useless without a tool to use it.
So, it seems that every frame needs an ArrayCollection associated to it, which contains a number of Images associated to it, each of which has an offsetX,Y and all the inheritance of a normal Image in AS3, like alpha, width, height, colorTransform (tint), etc.
variables needed
Character class
Public Properties
x: Number
The character's position along the x-axis in the game world.
y: Number
The character's position along the y-axis in the game world.
z: Number
The character's position along the z-axis in the game world.
region: int
The character's current region in the game world.
- This is a way to further break up the game world into managable pieces.
- Could be used for various regions in a perpetual world map, or for levels in a side scroller.
- There could be regionX, Y, Z but a region could be a node, or a coordinate on a grid, or part of a linear level progression in a platformer, so it might be better left to modding after the library is written.
varySpeed: Number
The percentage increase/decrease in the character's game world speed.
- This is applied to the offsetX, Y, Z of each frame before being added to character.x, y, z.
speed: Number
The character's game world speed.
- This replaces the offsetX,Y,Z of each frame during runtime, according to their respective ratios, before being added to character.x, y, z. The vector angle of offsetX, Y, Z is preserved, but the vector magnitude is altered.
maxSpeed: Number
The character's maximum allowed game world speed.
- triggered by a change in varySpeed or speed.
minSpeed: Number
The character's minimum allowed game world speed.
- triggered by a change in varySpeed or speed.
facing: int
A number cooresponding to an art asset which depicts the character facing a certain direction in the game world.
direction: Number
The direction that the character is facing, in degrees, in the game world.
movesOrtho: Boolean
Default is "true", which means that direction is quantized to facing. The character moves orthogonally, or cartologically. If set to "false" then the character can move at any angle.
- If set to false, the offsetX, Y, Z of each frame is replaced during runtime, according to their respective ratios, before being added to character.x, y, z. The vector magnitude of offsetX,Y,Z is preserved, but the vector angle is defined by direction.
directionRateOfChange: Number
The amount of time in milliseconds that must pass before a change in direction can occur.
directionQuantityOfChange: Number
The amount of degrees that are added to or subtracted from the character's current direction
- If directionQuantityOfChange were set to a multiple of 360 (like 45), the effect would be the same as setting movesOrtho to true, and facing to 8. The only difference between the two is that in one case, the character's # of possible directions is determined by the number of art assets available, and in the other case, the art asset to be displayed is determined by the character's direction.
maxFacing: int
The number of angles that the character can face; the the number of art assets which are available to depict the character facing certain directions.
- Ideally, it should be 2,4,8,16, or 32. But numbers like 5 will also work.
- Each frame of animation has in it the offsetX, Y, Z which is applied to character.x, y, z, thus taking care of the perspective angles.
- A tool will be used to position offsetX,Y,Z correctly.
paperDoll: Object
This contains all the graphical information to create the character on screen.
Character.paperDoll
rotation: Number
The rotation of the image(s) contained within paperDoll with respect to the screen.
