5
|
1 #############################################################################
|
|
2 #
|
|
3 # Copyright (c) 2010 by Casey Duncan and contributors
|
|
4 # All Rights Reserved.
|
|
5 #
|
|
6 # This software is subject to the provisions of the MIT License
|
|
7 # A copy of the license should accompany this distribution.
|
|
8 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
9 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
10 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
11 #
|
|
12 #############################################################################
|
|
13 """Components store all entity data in a given |World|. You can
|
|
14 think of components as tables with entities as their primary keys. Like
|
|
15 database tables, components are defined with a "schema" that specifies
|
|
16 the data fields. Each field in a component has a name and a type.
|
|
17
|
|
18 Component objects themselves have a dict-like interface with entities
|
|
19 as keys and data records as values. An application will typically
|
|
20 interact with components via entity attributes, entity extents or
|
|
21 by joining them. For more information see:
|
|
22
|
|
23 - :class:`~grease.entity.Entity` class.
|
|
24 - :class:`~grease.world.EntityExtent` class.
|
|
25 - :meth:`~grease.world.ComponentParts.join` method of ComponentParts.
|
|
26
|
|
27 See also :ref:`defining custom components in the tutorial <custom-component-example>`.
|
|
28 """
|
|
29
|
|
30 __version__ = '$Id$'
|
|
31
|
|
32 __all__ = ('Component', 'ComponentError', 'Position', 'Transform', 'Movement',
|
|
33 'Shape', 'Renderable', 'Collision')
|
|
34
|
|
35 from grease.component.general import Component
|
|
36 from grease.geometry import Vec2d, Vec2dArray, Rect
|
|
37 from grease import color
|
|
38
|
|
39
|
|
40 class ComponentError(Exception):
|
|
41 """General component error"""
|
|
42
|
|
43
|
|
44 class Position(Component):
|
|
45 """Predefined component that stores position and orientation info for
|
|
46 entities.
|
|
47
|
|
48 Fields:
|
|
49
|
|
50 - **position** (Vec2d) -- Position vector
|
|
51 - **angle** (float) -- Angle, in degrees
|
|
52 """
|
|
53
|
|
54 def __init__(self):
|
|
55 Component.__init__(self, position=Vec2d, angle=float)
|
|
56
|
|
57
|
|
58 class Transform(Component):
|
|
59 """Predefined component that stores offset, shear,
|
|
60 rotation and scale info for entity shapes.
|
|
61
|
|
62 Fields:
|
|
63
|
|
64 - **offset** (Vec2d)
|
|
65 - **shear** (Vec2d)
|
|
66 - **rotation** (float)
|
|
67 - **scale** (float, default 1.0)
|
|
68 """
|
|
69
|
|
70 def __init__(self):
|
|
71 Component.__init__(self, offset=Vec2d, shear=Vec2d, rotation=float, scale=float)
|
|
72 self.fields['scale'].default = lambda: 1.0
|
|
73
|
|
74
|
|
75 class Movement(Component):
|
|
76 """Predefined component that stores velocity,
|
|
77 acceleration and rotation info for entities.
|
|
78
|
|
79 Fields:
|
|
80
|
|
81 - **velocity** (Vec2d) -- Rate of change of entity position
|
|
82 - **accel** (Vec2d) -- Rate of change of entity velocity
|
|
83 - **rotation** (Vec2d) -- Rate of change of entity angle, in degrees/time
|
|
84 """
|
|
85
|
|
86 def __init__(self):
|
|
87 Component.__init__(self, velocity=Vec2d, accel=Vec2d, rotation=float)
|
|
88
|
|
89
|
|
90 class Shape(Component):
|
|
91 """Predefined component that stores shape vertices for entities
|
|
92
|
|
93 - **closed** (bool) -- If the shapes is closed implying an edge between
|
|
94 last and first vertices.
|
|
95 - **verts** (Vec2dArray) -- Array of vertex points
|
|
96 """
|
|
97
|
|
98 def __init__(self):
|
|
99 Component.__init__(self, closed=int, verts=Vec2dArray)
|
|
100 self.fields['closed'].default = lambda: 1
|
|
101
|
|
102
|
|
103 class Renderable(Component):
|
|
104 """Predefined component that identifies entities to be
|
|
105 rendered and provides their depth and color.
|
|
106
|
|
107 - **depth** (float) -- Drawing depth, can be used to determine z-order
|
|
108 while rendering.
|
|
109 - **color** (color.RGBA) -- Color used for entity. The effect of this
|
|
110 field depends on the renderer.
|
|
111 """
|
|
112
|
|
113 def __init__(self):
|
|
114 Component.__init__(self, depth=float, color=color.RGBA)
|
|
115 self.fields['color'].default = lambda: color.RGBA(1,1,1,1)
|
|
116
|
|
117
|
|
118 class Collision(Component):
|
|
119 """Predefined component that stores collision masks to determine
|
|
120 which entities can collide.
|
|
121
|
|
122 Fields:
|
|
123
|
|
124 - **aabb** (Rect) -- The axis-aligned bounding box for the entity.
|
|
125 This is used for broad-phase collision detection.
|
|
126
|
|
127 - **radius** (float) -- The collision radius of the entity, used for narrow-phase
|
|
128 collision detection. The exact meaning of this value depends on the collision
|
|
129 system in use.
|
|
130
|
|
131 - **from_mask** (int) -- A bitmask that determines what entities this object
|
|
132 can collide with.
|
|
133
|
|
134 - **into_mask** (int) -- A bitmask that determines what entities can collide
|
|
135 with this object.
|
|
136
|
|
137 When considering an entity A for collision with entity B, A's ``from_mask`` is
|
|
138 bit ANDed with B's ``into_mask``. If the result is nonzero (meaning 1 or more
|
|
139 bits is set the same for each) then the collision test is made. Otherwise,
|
|
140 the pair cannot collide.
|
|
141
|
|
142 The default value for both of these masks is ``0xffffffff``, which means that
|
|
143 all entities will collide with each other by default.
|
|
144 """
|
|
145 def __init__(self):
|
|
146 Component.__init__(self, aabb=Rect, radius=float, from_mask=int, into_mask=int)
|
|
147 self.fields['into_mask'].default = lambda: 0xffffffff
|
|
148 self.fields['from_mask'].default = lambda: 0xffffffff
|
|
149
|