World Structure
From OrbEdit Wiki
Introduction
Orb is made of 5 different types of Elements, WorldSpaces, Bodies, Shapes, Joints, and Sprites. Each WorldSpace is stored in a Layer, which defines its position in the Layer Stack. All these pieces combined together make up the World. The World is organized into an XML-like structure, which allows sets of Elements to be quickly queried by their attributes or placement within the XML structure (see Scripting for more information). If you are familiar with XML schema, you can find the schema that defines the Orb World here.
- The generic term for an Orb type is "Element", with an upper-case 'E'. This is to differentiate between general XML elements, with a lower-case 'e'.
At a very high level, a WorldSpace looks something like this:
At the top of the hierarchy is the WorldSpace. The WorldSpace contains Bodies (gears), which can contain Shapes or Sprites, and can be connected to each other with Joints. Additionally, Shapes can also contain Sprites, and Sprites can contain other Sprites. These relationships are strictly enforced, you cannot, for example, add a Body to a Shape, it must always be the other way around.
Element Types
All Elements share the following common properties. Some of these properties have different meanings for different Element types, those differences are discussed below.
- ID: A unique, numerical identifier of the Element. IDs are assigned at the time that the Element is created and cannot be changed. The Element type can be determined by the range of its ID, see below for ranges. The range of each Element type is 1000000, meaning one million of each type of Element can be created during any one game session.
- Name: The name of the Element, to be used as a way of grouping and retrieving Elements for scripting purposes. Names do not need to be unique, but set them to something descriptive to make it easier to identify the Element. Names are initially blank.
- Meta: A user-definable field that can be used to store any string data, generally used for scripting. No default.
- Locked: Locked Elements cannot be clicked on. Locking is a quick way to get an Element out of you way so you don't accidentally change it.
- Visible: Specifies whether or not the Element is visible. All child Elements of an invisible Element are also invisible.
- Position: The X, Y coordinate of the Element, relative to its parent. Position is used in slightly different ways for different Element types:
- WorldSpace: Defines the center of the WorldSpace's viewport. Only Elements that fall within their WorldSpace's viewport are actually drawn.
- Line Segment: Refers to one of a Line Segment's 2 endpoints.
- Joint: Refers to one of a Joint's 2 endpoints, relative to the Body that end is attached to.
- Defaults to 0, 0.
- Size: The "size" of the Element, as an X, Y vector. Size is used in slightly different ways for different Element types:
- WorldSpace: Defines the dimensions of the WorldSpace's viewport.
- Line Segment Indicates the other endpoint of the Line Segment.
- Circle: Specifies the radius of the Circle. Uses only the X component to do this, Y component is unused.
- Joint: Indicates the other endpoint of the Joint, relative to the Body that end is attached to.
- Defaults to 0, 0.
All Elements also share the following Events:
- OnLoad: Fired when the Element is first loaded.
- OnUnload: Fired when the Element is removed from the World.
- OnSize: Fired when the Element's size changes. For incremental change operations, such as
grow(), this Event is fired only once, when the function is first called.
- See the Events section for more information.
|
The WorldSpace ID: 0 - 999999
| |
|
|
A WorldSpace is a big container that holds all of the Elements which make up your game. Each WorldSpace is held in its own Layer which defines some extra information about the WorldSpace, such as its position in the Layer Stack. All Elements inside a WorldSpace are referred to as the children of the WorldSpace. As indicated in the diagram above, the only direct children of WorldSpaces are Bodies - a single Static Body and any number of dynamic Bodies. Terminology can sometimes get confusing! World refers to the collection of all Layers, but is also sometimes called the Layer Stack or more commonly, the Level. The term WorldSpace however, always refers to the physical space in which Bodies and Shapes exist.
Each WorldSpace has its own viewport, based on its position and size. A viewport is like a sub-window within the WorldSpace; child Elements that fall outside of this viewport are not drawn. Generally, this viewport covers the entire window, but it can be resized smaller for letterboxing or screen-transition effects. A WorldSpace has several of its own properties.
|
- BodiesID: 1000000 - 1999999
A Body represents a physical object within a WorldSpace. Bodies have no form, only a mass. You can apply forces to Bodies to move them around and they will fall under the effects of gravity. By themselves, Bodies are not very interesting. However, once you give them a form by attaching Shapes to them, they can collide with each other and cool things start to happen.
Within OrbEdit, Bodies are represented by the Gear icon seen to the left. Resizing the icon only changes how it looks and has no effect on game mechanics, since Bodies have no form by themselves.
Bodies have the following unique properties:
- Mass: The mass, or weight of the Body. A heavier Body takes more force to move. Defaults to 1.0.
- Mass has a special value of Infinity you can set to give a Body an infinite mass.
- Moment: Short for Moment of Inertia. This is the amount of force it will take to rotate this Body about its center point. This value is automatically calculated unless AutoMoment is set to false. Defaults to 1.0.
- Moment has a special value of Infinity you can set to give a Body an infinite moment of inertia.
- Angle: The angle of rotation of the Body. As this Body collides with other Bodies, it will likely spin, which is reflected by this value. Defaults to 0.
- AutoMoment: Indicates whether or not this Body's moment of inertia should be automatically calculated as Shapes are added to it. If you want to fix its moment of inertia at a certain value, set this to false. Defaults to true.
- Manual: Indicates whether this Body should be influenced by its WorldSpace or not. Normally, a WorldSpace automatically calculates the position of all the Bodies contained within it. If you wish to perform this calculation on your own, set this value to true. Defaults to false.
- The Static Body
Each WorldSpace has a single Body called the Static Body. This is a regular Body with an infinite mass and infinite moment of inertia, which is to say, it cannot be moved. As such, the Static Body is not affected by gravity. Just like regular Bodies, the Static Body has no form, you must attach Shapes to it before it can do anything useful. Think of the Static Body as the ground, walls, and ceiling of your WorldSpace.
The Static Body has no graphic within OrbEdit, it is "everywhere". When you add a Shape or Sprite to a blank area of OrbEdit, you are adding it to the Static Body.
As the name suggests, Static Bodies have no extra properties that you can change. While it is possible to change a Static Body's common properties through scripting, doing so will have no effect.
- ShapesID: 2000000- 2999999
Shapes are what give form to Bodies. Shapes can only be attached to Bodies, both regular and Static. Shapes can collide with other Shapes, bounce, roll, and spin. A Shape's position in the World is always relative to the Body it's attached to, you can think of a Body as the center of gravity of the Shapes that are attached to it.
When you attach a Shape to a Body, the Body's moment of inertia will be automatically adjusted if its AutoMoment property is set to true. The further you move a Shape away from its Body, the higher the moment of inertia for that Body will be, as that Body becomes "harder to spin". Shapes have no effect on a Body's mass.
There are 3 specific types of Shapes which are discussed below.
Shapes have several unique properties which effect how they collide with one another:
- CollisionGroup: Shapes with the same non-zero collision group will not collide with one another. For example, if Shape A and Shape B are both in collision group 3, they will not collide with each other. However, if Shape A is in collision group 3 and Shape B is in collision group 2, they will collide with each other. Also, if either has a collision group of 0, regardless of the collision group of the other, they will collide with each other. Defaults to 0.
- CollisionLayers: Each Shape has up to 30 collision layers to which it can belong. Shapes will only collide with one another if they share at least one collision layer. For example, if Shape A is in collision layers 1,5,9 and Shape B is in collision layers 2,3, they will not collide. However, if Shape B is in collision layer 9, they will collide. Defaults to 1.
- Shapes attached to the same Body will never collide with each other, regardless of their collision group or layers.
Shapes also have several unique properties that affect their behavior:
- Elasticity: The "bounciness" of the Shape. The higher the value, the more the Shape will bounce when it collides with another Shape. To speak in math terms, the velocity of each Shape involved in a collision is multiplied by each Shape's elasticity. Thus, if the elasticity of either Shape is 0, both Shapes will stop dead in their tracks when they collide, since the velocity of both will go to 0. If both have an elasticity of 1, then no energy will be lost in the collision and they will bounce off each other with the same force with which they collided. If both have an elasticity greater than 1, then they will gain energy by colliding and will rebound faster than they were going when they collided. Be careful with values greater than 1, they can quickly lead to out-of-control Shapes. Defaults to 1.
- Friction: The "stickiness" of the Shape. A Shape with 0 friction will "slide", whereas a shape with higher friction will "roll". When Shapes with non-zero friction collide, some of the energy is lost to friction, which translates into rotational energy imparted to each other. Friction acts like elasticity, in that the friction of each Shape involved in a collision is used to calculate their resultant velocities. If one Shape has a friction of 0, it will cancel out the friction of the other Shape. Defaults to 0.
- Surface Velocity: Specifies the velocity which which the surface of the Shape is moving. Think of it like a conveyor belt - a Shape with a surface velocity will impart a force equal to its surface velocity to any other Shapes that come into contact with it. Defaults to 0, 0.
Shapes have one additional event type:
- OnCollide: Fired whenever the Shape collides with another Shape.
- The velocity or rotation of a Shape really refers the velocity or rotation of the Body the Shape is attached to.
- Line Segment
The Line Segment is the most basic type of Shape. A Line Segment is made up of 2 endpoints connected by a segment. Just like all Shapes, their endpoints are relative to the position of the Body they are attached to.
Line Segments are meant as a Static Shape, that is, their behavior is best behaved when they are attached to a Static Body. They will still perform in limited ways when attached to a regular Body, but you are advised to experiment with them. There is likely no reason why you will want to use them as a Dynamic Shape, they are meant to act as the "ground" or "walls" of your World.
- Circle
Of all the Shapes, the Circle are the easiest to perform collision on. A Circle is made up of a position and a radius. Like all Shapes, their position is relative to the position of the Body they are attached to.
Circles can be used equally well as Static or Dynamic Shapes. They have the added advantage of being able to roll along surfaces and behave nicely even over rough terrain. If you're trying to create that nice "sliding around corners" feel to your collision detection, Circles are your best choice.
Circles should be thought of as "solid", more of a disc than a circle. That is, another Shape cannot be "inside" a Circle; it will be immediately pushed to the outside.
- Polygon
The Polygon is the most complicated type of Shape. OrbEdit allows for triangles, rectangles, pentagons, and hexagons, but there is no hard restriction on the amount of sides a Polygon can have. Like all Shapes, their position is relative to that of the Body they are attached to.
The sides of a Polygon can be moved around into any configuration, with the following 2 restrictions:
- The Polygon must remain simple, that is, no sides can overlap each other.
- The Polygon must remain convex, that is, no internal angle between any 2 sides can be greater than 180ยบ.
Additionally, Polygons must always remain right-handed, that is, when constructed, their sides must be be added in a clockwise fashion.
All Polygons created by OrbEdit meet all 3 of these requirements, but if you create additional Polygons in your scripts, take care that they also meet these requirements. Polygons that fail one or more of these conditions will collide in very erratic ways, if at all.
- OrbEdit provides a Constrain Polygons option from the View menu that will keep you from moving the sides of your Polygons in such a manner to make the non-convex. However, if you've already created one or more non-convex Polygons before enabling this option, they will remain non-convex.
- JointsID: 3000000- 3999999
Joints are the connecting rods between Bodies. They constrain how far a Body can move away from another Body, or define how those Bodies can rotate relative to one another. A Body's mass and moment of inertia both come into play as it pushes and pulls around other Bodies connected to it. The best way to see this behavior is to try it out!
Joints always connect exactly 2 Bodies, however, any given Body can be connected to any number of other Bodies by an equal number of Joints. Although there is no restriction on the number of Joints that can connect any two Bodies, you will likely see some strange behavior if you connect two Bodies with multiple Joints.
The life of a Joint is tied to the life of both of its Bodies. If either of its Bodies is deleted, the Joint will be deleted as well.
- Although Joints can be attached to the Static Body, OrbEdit gives no way of doing this, since the Static Body cannot be selected. If you wish to create a "fixed point", you can create a regular Body with a mass and moment of 'Infinity, and hook other Bodies to it via Joints. This provides an easier interface for attaching Joints to fixed points than dealing with the Static Body.
Joints in general have no extra properties that can be set. However, several specific Joint types do, as described below.
- Pin Joint
The Pin Joint is the simplest type of Joint. A Pin Joint represents a rigid connector that keeps its Bodies a constant distance apart. This distance is fixed to the distance between its Bodies at the time that the Pin Joint is created and cannot be changed.
Pin Joints have no additional unique properties that can be set.
- Slide Joint
The Slide Joint is a very useful type of Joint. A Slide Joint represents a telescoping connector that allows its Bodies to "slide" between a minimum and maximum distance apart. Slide Joints can be used to create a "chain", since each link in a chain can move freely up to a certain distance within its neighboring links.
Slide Joints have the following unique properties:
- Min: The minimum distance allowed between the Slide Joint's Bodies. Defaults to the distance between the two Bodies at the time that the Slide Joint is created.
- Max: The maximum distance allowed between the Slide Joint's Bodies. Defaults to Min + 100.
- Pivot Joint
The Pivot Joint is a "hinge" Joint. A Pivot Joint is similar to a Pin Joint, with the addition of a pivot in its center. This pivot allows a Pivot Joint to fold in the middle, allowing its Bodies to pivot about that point.
Pivot Joints have the following unique property:
- Pivot: The coordinates of the Pivot Joint's pivot point, in World coordinates (that is, relative to the World, as opposed to relative to either of the Bodies). Defaults to the center point between the connecting Bodies.
- Groove Joint
The Groove Joint is the most complicated type of Joint. A Groove Joint is also similar to a Pin Joint, but with a "groove" on one end in which that end can slide freely. Groove Joints impose a minimum distance between their Bodies, but the length and orientation of the groove is also factored into this minimum.
Groove Joints have the following unique property:
- Groove: The coordinates of the end of the groove, in Body coordinates (that is, relative to the Body on which the groove lies). Defaults to 50, 50.
- SpritesID: 4000000- 4999999
The Sprite is what makes up all graphics within Orb. Sprites are the only thing visible when playing a game made with Orb, it is only through OrbEdit that you can see Bodies, Shapes, and Joints.
- You can turn on the In-Game rendering mode through OrbEdit either from the View menu, or the shortcut Alt+1. This will turn off the rendering of everything except Sprites so you can see how your game will actually look.
Sprites do not collide with anything and have no effect on physics; they are purely graphical. They can be attached to both Bodies, Shapes, and other Sprites and will stay attached to them as they move around. You can attach Sprites to the Static Body to create backgrounds and other pieces of scenery that aren't intended to move. Since Sprites don't collide, they should generally be attached to Shapes, in a way that provides good feedback to the user as to where the collision areas are. For example, you wouldn't want to attach a Sprite that looks like a box to a Circle, you should make sure your collision Shape looks as much like your Sprite as possible.
Attaching Sprites to other Sprites allows you to make logical groups, such as a menu. The main background of the menu is a single sprite and all the widgets on the menu are children of it. Thus, when you move the menu around, all the widgets stay attached to it and move with it. You can create some complicated movement functions this way too. For example, if you attach a moving Sprite to a spinning Sprite, the result is a very nice spiral movement effect.
Sprites can be textured, colored, scaled, rotated, and have pixel shaders applied to them. They can display any type of text and are highly scriptable. However, this means that they have quite a few properties:
- Scale: The factor by which the Sprite is scaled, in the X and Y directions. The Sprite's size is multiplied by its scaling factor to determine its final size on the screen. For example, a Sprite that is 50 x 50 pixels in size, with a scaling factor of 2 x 2 will be rendered as 100 x 100 pixels. Sprites scale outwards from their pivot point. Defaults to 1, 1.
- Rotation: The angle of rotation of the Sprite. All Sprites rotate around their pivot point. Defaults to 0.
- Pivot: The "center" of the Sprite, in the X and Y direction. Pivots are defined from 0 to 1, meaning the percentage of the way from one side of the Sprite to the other. Within OrbEdit, pivots are marked with a red "x". Each Sprite rotates around and scales outwards from its pivot point. Defaults to 0.5, 0.5.
- Color: The color of the Sprite, in Red, Green, Blue, and Alpha (RGBA). All values are from 0 to 1. For example, an RGBA value of "1, 0, 0, 1" would be a completely opaque red, and "0, 1, 0, 0.5" would be a half-transparent green. Only the alpha value of a Sprite's color applies to its text; text color is controlled independentally from its Sprite's color. Defaults to 1, 1, 1, 1.
- Texture: The name of an image file with which to texture the Sprite. Must be a .bmp, .jpg, .tga, .gif, or .png file of any dimensions. No default.
- TextureTile: Specifies how many times to tile the Sprite's texture, in the X and Y directions. For example, if TextureTile is set to 5, 3.5, the Sprite will have its texture repeated 5 times across and 3.5 times down. Tiling should always be favored over multiple Sprites for faster performance. Defaults to 1, 1.
- Shader: The name of a Shader, as defined in Shaders/shader_registry.xml to apply to the Sprite. See the section on Shaders for more information. No default.
- BlendingMode: The mix of alpha blending that will be applied to the Sprite. Mixes are generally either additive or subtractive, play around with different mixes to get a feel for what they do.
- FlipHorizontal: Indicates whether or not to render the Sprite as if flipped over its Y axis. Only the Sprite's texture is effected by being flipped, Shaders are not. Defaults to false.
- FlipVertical: Indicates whether or not to render the Sprite as if flipped over its X axis. Only the Sprite's texture is effected by being flipped, Shaders are not. Defaults to false.
- Text: The text to be rendered over the Sprite. Text is rendered in the upper-left corner of the Sprite, in the font specified by the Sprite's Font property, with a small shadow underneath it to add to its readability. The color of the text is determined by the Sprite's Color property. No default.
- An invisible Sprite will also have invisible text. If you want the text to still be visible, but the Sprite to be invisible (such as for building menus), you can texture the sprite with an "invisible" texture, that is, a texture with only an alpha channel, but no color channels. Orb comes with a special texture for this purpose, Images/Invisible.png.
- Font: The name of a Font, as defined in Fonts/font_registry.xml, with which to render the Sprite's text. See the section on Fonts for more information. Defaults to "Arial12", a 12-point Arial font.
- TextAlign: The position on the Sprite to render its text. This property allows text to be left, center, or right justified.
- TextScaling: Specifies whether or not the Sprite's text will scale with it. For example, if a Sprite's scale value is set to 2,2, its text will be twice as large as normal too. However, when TextScaling is set to false, the Sprite will still be twice its normal size, but its text will remain its default size. This can be useful for constructing menus that tend to become distorted as the resolution changes.
