Initial commit from version 1e-99
[beatscape.git] / fx.py
1 import pygame
2 import math
3 import os, os.path
4
5 ALIGN_LEFT = 0
6 ALIGN_RIGHT = 1
7
8 # FX is the abstract base class for all "effects" objects. They have two
9 # defining features:
10 #
11 # 1) The FX base class sets up self.screen so that you can draw to the
12 #    screen. It is then important to call FX.__init__(self) in your
13 #    __init__ routine.
14 # 2) Each FX object has a draw(self,t) method that draws itself to the
15 #    screen (possibly with appearance based on the current time).
16
17 class FX:
18         def __init__(self):
19                 self.screen = pygame.display.get_surface()
20
21         def draw(self,t):
22                 pass
23
24 class Blank(FX):
25         def draw(self,t):
26                 self.screen.fill((0,0,0))
27
28 class Image(FX):
29         align = ALIGN_LEFT
30
31         def __init__(self,file,location=(0,0)):
32                 FX.__init__(self)
33                 self.surface = pygame.image.load(file).convert_alpha()
34                 self.location = location
35
36         def draw(self,t):
37                 if self.align == ALIGN_RIGHT:
38                         rl = (self.location[0] - self.surface.get_width(),self.location[1])
39                         self.screen.blit(self.surface,rl)
40                 else:
41                         self.screen.blit(self.surface,self.location)
42
43 class Text(Image):
44         def __init__(self,text,font,size,location=(0,0),color=(255,255,255)):
45                 FX.__init__(self)
46                 self.font = pygame.font.Font(font,size)
47                 self.location = location
48                 self.color = color
49                 self.settext(text)
50
51         def settext(self,text):
52                 f = self.font.render(text,True,(0,0,0))
53                 self.surface = pygame.surface.Surface((f.get_width()+2,f.get_height()+2)).convert_alpha()
54                 self.surface.fill((0,0,0,0))
55                 self.surface.blit(f,(2,2))
56                 f = self.font.render(text,True,self.color)
57                 self.surface.blit(f,(0,0))
58
59 textglyphs = {}
60
61 class GlyphText(FX):
62         def __init__(self,location=(0,0),glyphdir='gfx/glyph'):
63                 FX.__init__(self)
64                 if not textglyphs:
65                         l = os.listdir(glyphdir)
66                         for g in l:
67                                 c = g.split('.')[0]
68                                 textglyphs[c] = pygame.image.load(os.path.join(glyphdir,g)).convert_alpha()
69                 self.location = location
70                 self.text = ''
71
72         def settext(self,str):
73                 self.text = str
74
75         def draw(self,t):
76                 (x,y) = self.location
77                 for c in self.text:
78                         if textglyphs.has_key(c):
79                                 self.screen.blit(textglyphs[c],(x,y))
80                                 x += textglyphs[c].get_width()
81
82 class PulseLine(FX):
83         r = -0.02
84
85         def __init__(self, pointlist, color, period, maxwidth = 8, minwidth = 1):
86                 FX.__init__(self)
87                 self.period = period
88                 self.color = color
89                 if maxwidth:
90                         self.maxwidth = maxwidth
91                 if minwidth:
92                         self.minwidth = minwidth
93                 self.pointlist = pointlist
94                 self.location = (0,0)
95
96         def draw(self,t):
97                 w = (self.maxwidth - 1) * math.exp(self.r * (t % self.period)) + self.minwidth
98                 pl = map(lambda x: (x[0] + self.location[0],x[1] + self.location[1]),self.pointlist)
99                 pygame.draw.lines(self.screen,self.color, 0, pl, int(w))
100
101 class ColumnPulse(FX):
102         r = -0.03
103
104         def __init__(self,rect,color):
105                 FX.__init__(self)
106                 self.rect = rect
107                 self.color = color
108                 self.st = 0
109                 self.surf = []
110                 t = 0
111                 a = 1.0
112                 while a > 0.01:
113                         s = pygame.Surface(self.rect.size).convert_alpha()
114                         s.lock()
115                         s.fill( (0,0,0,0) )
116                         for n in range(0,self.rect.height):
117                                 c = (self.color[0],self.color[1],self.color[2],float(n) / self.rect.height * a * 255.0)
118                                 w = (self.rect.width / 2) * (1.0 - a)
119                                 pygame.draw.line(s,c,(w,n),(self.rect.width-w,n))
120                                 #s.fill(c,(0,n,self.rect.width,1))
121                         s.unlock()
122                         self.surf.append(s)
123                         t += 16
124                         a = math.exp(self.r * t)
125
126                 self.hit = 0
127
128         def down(self):
129                 self.hit = 1
130
131         def up(self):
132                 self.st = pygame.time.get_ticks()
133                 self.hit = 0
134
135         def draw(self):
136                 dt = pygame.time.get_ticks() - self.st
137                 if self.hit:
138                         self.screen.blit(self.surf[0],self.rect)
139                 else:
140                         n = dt / 16
141                         if n > len(self.surf) - 1:
142                                 return
143                         self.screen.blit(self.surf[n],self.rect)
144
145 class PlaneScroll(FX):
146         surface = None
147
148         def __init__(self,file,direction,zoom=1.0,alpha=1.0):
149                 FX.__init__(self)
150                 ts = pygame.image.load(file)
151                 if zoom != 1.0:
152                         ts = pygame.transform.rotozoom(ts, 0.0, zoom)
153                 self.surface = ts.convert()
154                 del ts
155                 if alpha < 1.0 and alpha >= 0.0:
156                         self.surface.set_alpha(int(alpha * 255))
157                 self.direction = direction
158
159         def draw(self,t):
160                 w = self.surface.get_width()
161                 h = self.surface.get_height()
162                 location = self.surface.get_rect()
163                 location.size = (640,480)
164                 location.move_ip((t * self.direction[0]) % w, (t * self.direction[1]) % h)
165                 self.screen.blit(self.surface,(0,0),location)
166                 if location.right > w:
167                         x = 640 - (location.right - w)
168                         self.screen.blit(self.surface,(x,0),(0,location.top,640,480))
169                 if location.bottom > h:
170                         y = 480 - (location.bottom - h)
171                         self.screen.blit(self.surface,(0,y),(location.left,0,640,480))
172                 if location.bottom > h and location.right > w:
173                         # x and y must be calculated from above two tests
174                         self.screen.blit(self.surface,(x,y),(0,0,640,480))