Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/rayito/RtoPlayer.py
blob: 4e8f5c9c84ec2cbc25194e9489b401b5697c0b1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#! /usr/bin/env python
# Rayito player
# Copyright (C) 2011 Gabriel Eirea
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Contact information:
# Gabriel Eirea geirea@gmail.com
# Ceibal Jam http://ceibaljam.org


import pygame
import RtoObject
import RtoTimeLine


class RtoPlayer():
    """ Class for rayito player.

    RtoPlayer(size, position, timeline, loop = False)
    where:
    size = canvas size
    position = upper-left coordinates in the screen
    timeline = RtoTimeLine object with objects and events
    loop = boolean that indicates whether the player loops or not
    bg_image = pygame surface with background image
    bg_color = background color to use if image not present
    """

    def __init__(self, size, position, timeline, loop = False, 
                 bg_image = None, bg_color = (0, 0, 0)):
        self._size = size
        self._position = position
        self._timeline = timeline
        self._finished = False
        self._canvas = pygame.Surface(size)
        self._last_update = 0
        self._active_objects = list()
        self._tl_index = 0
        self._tl_length = self._timeline.get_length()
        self._loop = loop
        self._loop_time = 0
        self._bg_image = bg_image
        self._bg_color = bg_color
        self._paused = True
        self._pause_time = 0
        self._start_pause = pygame.time.get_ticks()

    def pause(self):
        self._start_pause = pygame.time.get_ticks()
        self._paused = True

    def play(self):
        self._pause_time += pygame.time.get_ticks() - self._start_pause
        self._paused = False

    def is_finished(self):
        return self._finished

    def is_paused(self):
        return self._paused

    def update(self, time):
        """ Update the player at one time step.

        Reads all events between last call and current call, executes
        the actions, updates the objects, and renders all active objects on
        the canvas.
        """
        if self._paused or self._finished:
            return
        # read events between last_update and time
        while self._timeline.get_time(self._tl_index) <= \
                time - self._loop_time - self._pause_time:
            ev = self._timeline.get_event(self._tl_index)
            ob = self._timeline.get_object(self._tl_index)
            pa = self._timeline.get_params(self._tl_index)
            try:
                if pa == None:
                    getattr(ob,ev)()
                else:
                    getattr(ob,ev)(pa)
            except:
                print("Event " + ev + " not defined in object " + str(ob))
            if ev == 'show':
                self._active_objects.append(ob)
                self._active_objects.sort(key=lambda ob:ob.get_layer())
            elif ev == 'hide':
                self._active_objects.remove(ob)
            elif ev == 'pause':
                self.pause()
            # update index and check boundary
            self._tl_index += 1
            if self._tl_index == self._tl_length:
                if self._loop:
                    self._tl_index = 0
                    self._loop_time = time
                else:
                    self._finished = True
                break
        # update all active objects
        for obj in self._active_objects:
            obj.update(time - self._loop_time - self._pause_time)
        # update time and return
        self._last_update = time

    def render(self, screen):
        # erase canvas
        # TODO: can be optimized with dirty rectangles
        if self._bg_image:
            self._canvas.blit(self._bg_image, (0,0))
        else:
            self._canvas.fill(self._bg_color)
        # render active objects on canvas
        for obj in self._active_objects:
            obj.render(self._canvas)
        # render canvas on screen
        screen.blit(self._canvas, self._position)

    def new_timeline(self, timeline, loop = False):
        self._timeline = timeline
        self._finished = False
        self._active_objects = set()
        self._tl_index = 0
        self._tl_length = self._timeline.get_length()
        self._loop = loop
        self._loop_time = 0
        self._paused = True
        self._pause_time = 0
        self._start_pause = pygame.time.get_ticks()

    def pressed(self, pos):
        pos_in_canvas = (pos[0]-self._position[0], pos[1]-self._position[1])
        for obj in self._active_objects:
            if obj.is_pressed(pos_in_canvas):
                return obj # assuming only one object at pos
        return None        


if __name__ == "__main__":
    pass