~facundo/enjuewemela/trunk

« back to all changes in this revision

Viewing changes to cocos/sprite.py

  • Committer: facundo at com
  • Date: 2010-11-20 01:41:24 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: facundo@taniquetil.com.ar-20101120014124-zjyxkchmvili5m2u
Project reorder!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ----------------------------------------------------------------------------
 
2
# cocos2d
 
3
# Copyright (c) 2008 Daniel Moisset, Ricardo Quesada, Rayentray Tappa, Lucio Torre
 
4
# All rights reserved.
 
5
#
 
6
# Redistribution and use in source and binary forms, with or without
 
7
# modification, are permitted provided that the following conditions are met:
 
8
#
 
9
#   * Redistributions of source code must retain the above copyright
 
10
#     notice, this list of conditions and the following disclaimer.
 
11
#   * Redistributions in binary form must reproduce the above copyright
 
12
#     notice, this list of conditions and the following disclaimer in
 
13
#     the documentation and/or other materials provided with the
 
14
#     distribution.
 
15
#   * Neither the name of cocos2d nor the names of its
 
16
#     contributors may be used to endorse or promote products
 
17
#     derived from this software without specific prior written
 
18
#     permission.
 
19
#
 
20
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
21
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
22
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 
23
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 
24
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 
25
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
26
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
27
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
28
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
30
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
31
# POSSIBILITY OF SUCH DAMAGE.
 
32
# ----------------------------------------------------------------------------
 
33
'''Sprite
 
34
 
 
35
Animating a sprite
 
36
==================
 
37
 
 
38
To execute any action you need to create an action::
 
39
 
 
40
    move = MoveBy( (50,0), 5 )
 
41
 
 
42
In this case, ``move`` is an action that will move the sprite
 
43
50 pixels to the right (``x`` coordinate) and  0 pixel in the ``y`` coordinate
 
44
in 5 seconds.
 
45
 
 
46
And now tell the sprite to execute it::
 
47
 
 
48
    sprite.do( move )
 
49
'''
 
50
 
 
51
__docformat__ = 'restructuredtext'
 
52
import math
 
53
 
 
54
import pyglet
 
55
from pyglet import image
 
56
from pyglet.gl import *
 
57
 
 
58
import cocosnode
 
59
from batch import *
 
60
import rect
 
61
 
 
62
import euclid
 
63
import math
 
64
 
 
65
__all__ = [ 'Sprite',                     # Sprite class
 
66
            ]
 
67
 
 
68
 
 
69
 
 
70
class Sprite( BatchableNode, pyglet.sprite.Sprite):
 
71
    '''Sprites are sprites that can execute actions.
 
72
 
 
73
    Example::
 
74
 
 
75
        sprite = Sprite('grossini.png')
 
76
    '''
 
77
 
 
78
    def __init__( self, image, position=(0,0), rotation=0, scale=1, opacity = 255, color=(255,255,255), anchor = None ):
 
79
        '''Initialize the sprite
 
80
 
 
81
        :Parameters:
 
82
                `image` : string or image
 
83
                    name of the image resource or a pyglet image.
 
84
                `position` : tuple
 
85
                    position of the anchor. Defaults to (0,0)
 
86
                `rotation` : float
 
87
                    the rotation (degrees). Defaults to 0.
 
88
                `scale` : float
 
89
                    the zoom factor. Defaults to 1.
 
90
                `opacity` : int
 
91
                    the opacity (0=transparent, 255=opaque). Defaults to 255.
 
92
                `color` : tuple
 
93
                    the color to colorize the child (RGB 3-tuple). Defaults to (255,255,255).
 
94
                `anchor` : (float, float)
 
95
                    (x,y)-point from where the image will be positions, rotated and scaled in pixels. For example (image.width/2, image.height/2) is the center (default).
 
96
        '''
 
97
 
 
98
        if isinstance(image, str):
 
99
            image = pyglet.resource.image(image)
 
100
 
 
101
        self.transform_anchor_x = 0
 
102
        self.transform_anchor_y = 0
 
103
        self._image_anchor_x = 0
 
104
        self._image_anchor_y = 0
 
105
 
 
106
        pyglet.sprite.Sprite.__init__(self, image)
 
107
        BatchableNode.__init__(self)
 
108
 
 
109
 
 
110
 
 
111
        if anchor is None:
 
112
            if isinstance(self.image, pyglet.image.Animation):
 
113
                anchor = (image.frames[0].image.width / 2,
 
114
                    image.frames[0].image.height / 2)
 
115
            else:
 
116
                anchor = image.width / 2, image.height / 2
 
117
 
 
118
 
 
119
        self.image_anchor = anchor
 
120
 
 
121
        # group.
 
122
        # This is for batching
 
123
        self.group = None
 
124
 
 
125
        # children group.
 
126
        # This is for batching
 
127
        self.children_group = None
 
128
 
 
129
        #: position of the sprite in (x,y) coordinates
 
130
        self.position = position
 
131
 
 
132
        #: rotation degrees of the sprite. Default: 0 degrees
 
133
        self.rotation = rotation
 
134
 
 
135
        #: scale of the sprite where 1.0 the default value
 
136
        self.scale = scale
 
137
 
 
138
        #: opacity of the sprite where 0 is transparent and 255 is solid
 
139
        self.opacity = opacity
 
140
 
 
141
        #: color of the sprite in R,G,B format where 0,0,0 is black and 255,255,255 is white
 
142
        self.color = color
 
143
 
 
144
 
 
145
    def get_rect(self):
 
146
        '''Get a cocos.rect.Rect for this sprite.'''
 
147
        x = -self.image_anchor_x
 
148
        y = -self.image_anchor_y
 
149
        return rect.Rect(x,y,self.width, self.height)
 
150
 
 
151
    def get_AABB(self):
 
152
        '''Returns a local-coordinates Axis aligned Bounding Box'''
 
153
 
 
154
        v = self._vertex_list.vertices
 
155
        x = v[0], v[2], v[4], v[6]
 
156
        y = v[1], v[3], v[5], v[7]
 
157
        return rect.Rect(min(x),min(y),max(x)-min(x),max(y)-min(y))
 
158
 
 
159
    def _set_rotation( self, a ):
 
160
        pyglet.sprite.Sprite._set_rotation(self, a)
 
161
        BatchableNode._set_rotation(self,a)
 
162
 
 
163
    def _set_scale( self, s ):
 
164
        pyglet.sprite.Sprite._set_scale(self,s)
 
165
        BatchableNode._set_scale(self,s)
 
166
 
 
167
    def _set_position( self, p ):
 
168
        pyglet.sprite.Sprite.position = p
 
169
        BatchableNode._set_position(self,p)
 
170
 
 
171
    def _set_x(self, x ):
 
172
        pyglet.sprite.Sprite._set_x( self, x )
 
173
        BatchableNode._set_x( self, x)
 
174
 
 
175
    def _set_y(self, y ):
 
176
        pyglet.sprite.Sprite._set_y( self, y )
 
177
        BatchableNode._set_y( self, y)
 
178
 
 
179
    def contains(self, x, y):
 
180
        '''Test whether this (untransformed) Sprite contains the pixel coordinates
 
181
        given.
 
182
        '''
 
183
        sx, sy = self.position
 
184
        ax, ay = self.image_anchor
 
185
        sx -= ax
 
186
        sy -= ay
 
187
        if x < sx or x > sx + self.width: return False
 
188
        if y < sy or y > sy + self.height: return False
 
189
        return True
 
190
 
 
191
 
 
192
    def _set_anchor_x(self, value):
 
193
        self._image_anchor_x = value
 
194
        self._update_position()
 
195
 
 
196
    def _get_anchor_x(self):
 
197
        return self._image_anchor_x
 
198
    image_anchor_x = property(_get_anchor_x, _set_anchor_x)
 
199
 
 
200
    def _set_anchor_y(self, value):
 
201
        self._image_anchor_y = value
 
202
        self._update_position()
 
203
 
 
204
    def _get_anchor_y(self):
 
205
        return self._image_anchor_y
 
206
    image_anchor_y = property(_get_anchor_y, _set_anchor_y)
 
207
 
 
208
    def _set_anchor(self, value):
 
209
        self._image_anchor_x = value[0]
 
210
        self._image_anchor_y = value[1]
 
211
        self._update_position()
 
212
 
 
213
    def _get_anchor(self):
 
214
        return (self._get_anchor_x(), self._get_anchor_y())
 
215
 
 
216
    image_anchor = property(_get_anchor, _set_anchor)
 
217
 
 
218
    def draw(self):
 
219
        self._group.set_state()
 
220
        if self._vertex_list is not None:
 
221
            self._vertex_list.draw(GL_QUADS)
 
222
        self._group.unset_state()
 
223
 
 
224
    def _update_position(self):
 
225
        if not self._visible:
 
226
            self._vertex_list.vertices[:] = [0, 0, 0, 0, 0, 0, 0, 0]
 
227
            return
 
228
 
 
229
        img = self._texture
 
230
        if self.transform_anchor_x == self.transform_anchor_y == 0:
 
231
 
 
232
            if self._rotation:
 
233
                x1 = -self._image_anchor_x * self._scale
 
234
                y1 = -self._image_anchor_y * self._scale
 
235
                x2 = x1 + img.width * self._scale
 
236
                y2 = y1 + img.height * self._scale
 
237
                x = self._x
 
238
                y = self._y
 
239
 
 
240
                r = -math.radians(self._rotation)
 
241
                cr = math.cos(r)
 
242
                sr = math.sin(r)
 
243
                ax = int(x1 * cr - y1 * sr + x)
 
244
                ay = int(x1 * sr + y1 * cr + y)
 
245
                bx = int(x2 * cr - y1 * sr + x)
 
246
                by = int(x2 * sr + y1 * cr + y)
 
247
                cx = int(x2 * cr - y2 * sr + x)
 
248
                cy = int(x2 * sr + y2 * cr + y)
 
249
                dx = int(x1 * cr - y2 * sr + x)
 
250
                dy = int(x1 * sr + y2 * cr + y)
 
251
 
 
252
                self._vertex_list.vertices[:] = [ax, ay, bx, by, cx, cy, dx, dy]
 
253
            elif self._scale != 1.0:
 
254
                x1 = int(self._x - self._image_anchor_x * self._scale)
 
255
                y1 = int(self._y - self._image_anchor_y * self._scale)
 
256
                x2 = int(x1 + img.width * self._scale)
 
257
                y2 = int(y1 + img.height * self._scale)
 
258
                self._vertex_list.vertices[:] = [x1, y1, x2, y1, x2, y2, x1, y2]
 
259
            else:
 
260
                x1 = int(self._x - self._image_anchor_x)
 
261
                y1 = int(self._y - self._image_anchor_y)
 
262
                x2 = x1 + img.width
 
263
                y2 = y1 + img.height
 
264
                self._vertex_list.vertices[:] = [x1, y1, x2, y1, x2, y2, x1, y2]
 
265
        else:
 
266
            x1 = int(- self._image_anchor_x)
 
267
            y1 = int(- self._image_anchor_y)
 
268
            x2 = x1 + img.width
 
269
            y2 = y1 + img.height
 
270
            m = self.get_local_transform()
 
271
            p1 = m * euclid.Point2(x1, y1)
 
272
            p2 = m * euclid.Point2(x2, y1)
 
273
            p3 = m * euclid.Point2(x2, y2)
 
274
            p4 = m * euclid.Point2(x1, y2)
 
275
 
 
276
            self._vertex_list.vertices[:] = [
 
277
                int(p1.x), int(p1.y), int(p2.x), int(p2.y),
 
278
                int(p3.x), int(p3.y), int(p4.x), int(p4.y)]
 
279
 
 
280
Sprite.supported_classes = Sprite