OSDN Git Service

first
[opengano/Gano.git] / main.py
1 #!/usr/bin/env python
2 #coding:utf-8
3
4 import pygame
5 import pygame.midi
6 import gutil as gu
7 import os
8 import math
9 import random
10 import threading
11 from pygame.locals import *
12 from OpenGL.GL import *
13 import psyco
14 import time
15 import sys
16
17 CURRENT_DIR = os.path.dirname(__file__)
18 INSTRUMENT = 0
19
20 WIDTH = 1024
21 HEIGHT = 768
22 KEY_MAP = os.path.join(CURRENT_DIR,"key.txt")
23 FPS = 60
24 MIDI_PORT = 2
25
26 #min_note = 46
27 #max_note = 75
28 #number_of_notes = max_note - min_note + 1
29 #theta2r = math.pi / 180
30
31 new_key = [48,50,52,53,54,55,57,59,60,62,64,65,67,69,71,72,74,76]
32 number_of_notes = len(new_key)
33 space = WIDTH / number_of_notes
34
35 class AnoEngine:
36     def __init__(self,writer,output=0):
37         pygame.midi.init()
38         self.midiout = pygame.midi.Output(MIDI_PORT)
39         self.INSTRUMENT = 0 #0:Piano#19:Organ,56:Trympet
40         self.set_instrument(self.INSTRUMENT)
41         self.sustain = False
42         self.default_volume = 128
43         self.writer = writer
44         self.on_notes = []
45         self.keys = {}
46         self.mouse_key = 0
47         #for i in xrange(number_of_notes + 1):
48         #    self.keys[i] = min_note + i
49         self.key_map = self.load_key_map(KEY_MAP)
50
51     def set_instrument(self,instrument):
52         self.INSTRUMENT = instrument
53         self.midiout.set_instrument(instrument)
54
55     def rebus_sustain(self):
56         if self.sustain:
57             self.sustain = False
58         else:
59             self.sustain = True
60
61     def note_on(self,no,vol=100):
62         if not no in self.on_notes:
63             self.midiout.note_on(no,vol)
64             self.on_notes.append(no)
65
66     def note_off(self,no):
67         if no in self.on_notes:
68             self.midiout.note_off(no,0)
69             self.on_notes.remove(no)
70
71     def load_key_map(self,filename):
72         dic = {}
73         for line in open(filename,"r"):
74             if line[0] == "#":
75                 pass
76             else:
77                 [key,no,x,y] = [l.strip() for l in line.split(",")]
78                 dic[eval(key)] = (int(no),(int(x),int(y)))
79         return dic
80
81     def on_event(self,events):
82         for event in events:
83             if event.type == KEYDOWN:
84                 if event.key in self.key_map:
85                     self.note_on(self.key_map[event.key][0])
86                     self.writer.start(self.key_map[event.key][1])
87                 if event.key == K_ESCAPE:
88                     exit()
89             elif event.type == KEYUP:
90                 if event.key in self.key_map:
91                     self.note_off(self.key_map[event.key][0])
92             elif event.type == MOUSEBUTTONDOWN:
93                 if event.button == 1:
94                     (x,y) = pygame.mouse.get_pos()
95                     y = HEIGHT - y
96                     #key = self.keys[x // space]
97                     key = new_key[x // space]
98                     if y < (HEIGHT / 2):
99                         self.note_on(key)
100                         self.writer.start((x,y))
101                         self.mouse_key = key
102                     else:
103                         self.note_on(key)
104                         self.writer.start((x,y))
105                         self.mouse_key = key
106                 elif event.button == 2:
107                     self.rebus_sustain()
108             elif event.type == MOUSEBUTTONUP:
109                 if event.button == 1:
110                     (x,y) = pygame.mouse.get_pos()
111                     y = HEIGHT - y
112                     key = [x // space]
113                     self.note_off(self.mouse_key)
114             elif event.type == QUIT:
115                 exit()
116
117 class Circle:
118     def __init__(self,tex_lis):
119         self.maxrate = 2.0
120         self.tex_lis = tex_lis
121         self.on = False
122         self.x,self.y = (-100,-100)
123         self.ratep = 0.02
124         self.rate = 0
125
126     def draw(self):
127         if self.on:
128             glLoadIdentity()
129             glTranslatef(self.x - self.rate * 500,self.y - self.rate * 500,0)
130             glScale(self.rate,self.rate,0)
131             glCallList(self.tex_lis)
132
133     def start(self,(x,y)):
134         self.on = True
135         self.x,self.y = x,y
136         self.rate = 0
137
138     def update(self):
139         if self.on:
140             self.rate = self.rate + self.ratep
141             if self.rate > self.maxrate:
142                 self.on = False
143                 self.x,self.y = (-100,-100)
144
145 class Line:
146     def __init__(self,tex_lis):
147         self.maxrate = 1.0
148         self.tex_lis = tex_lis
149         self.on = False
150         self.x,self.y = 0,0
151         self.ratep = 0.02
152         self.rate = 0
153         self.theta = 0
154
155     def draw(self):
156         if self.on:
157             glLoadIdentity()
158             glTranslatef(self.x - 750,self.y - 750,0)
159             glTranslatef(750,750,0)
160             glRotatef(self.theta,0,0,1)
161             glTranslatef(-750,-750,0)
162             glCallList(self.tex_lis)
163
164     def start(self,(x,y)):
165         self.on = True
166         self.x,self.y = x,y
167         self.rate = 0
168         self.theta = random.randint(0,360)
169
170     def update(self):
171         if self.on:
172             self.rate = self.rate + self.ratep
173             if self.rate > self.maxrate:
174                 self.on = False
175                 self.x,self.y = 0,0
176
177 class Square:
178     def __init__(self,tex_lis):
179         self.maxrate = 2.0
180         self.tex_lis = tex_lis
181         self.on = False
182         self.x,self.y = (-100,-100)
183         self.ratep = 0.02
184         self.rate = 0
185         self.angle = 0
186         self.anglep = 1
187
188     def draw(self):
189         if self.on:
190             glLoadIdentity()
191             glTranslatef(self.x - self.rate * 500,self.y - self.rate * 500,0)
192             glScale(self.rate,self.rate,0)
193             glTranslatef(500,500,0)
194             glRotatef(self.angle,0,0,1)
195             glTranslatef(-500,-500,0)
196             glCallList(self.tex_lis)
197
198     def start(self,(x,y)):
199         self.on = True
200         self.x,self.y = x,y
201         self.rate = 0
202         self.anglep = random.choice((-1,1))
203         self.angle = random.randint(0,360)
204
205     def update(self):
206         if self.on:
207             self.rate = self.rate + self.ratep
208             self.angle = self.angle + self.anglep
209             if self.rate > self.maxrate:
210                 self.on = False
211                 self.x,self.y = (-100,-100)
212
213 class Triangle:
214     def __init__(self,tex_lis):
215         self.maxrate = 2.0
216         self.tex_lis = tex_lis
217         self.on = False
218         self.x,self.y = (-100,-100)
219         self.ratep = 0.02
220         self.rate = 0
221         self.angle = 0
222         self.anglep = 1
223
224     def draw(self):
225         if self.on:
226             glLoadIdentity()
227             glTranslatef(self.x - self.rate * 500,self.y - self.rate * 500,0)
228             glScale(self.rate,self.rate,0)
229             glTranslatef(500,500,0)
230             glRotatef(self.angle,0,0,1)
231             glTranslatef(-500,-500,0)
232             glCallList(self.tex_lis)
233
234     def start(self,(x,y)):
235         self.on = True
236         self.x,self.y = x,y
237         self.rate = 0
238         self.anglep = random.choice((-1,1))
239         self.angle = random.randint(0,360)
240
241     def update(self):
242         if self.on:
243             self.rate = self.rate + self.ratep
244             self.angle = self.angle + self.anglep
245             if self.rate > self.maxrate:
246                 self.on = False
247                 self.x,self.y = (-100,-100)
248
249
250 class Writer:
251     def __init__(self):
252         circle_tex = gu.create_texture(os.path.join(CURRENT_DIR,"circlet.png"))
253         square_tex = gu.create_texture(os.path.join(CURRENT_DIR,"squaret.png"))
254         line_tex = gu.create_texture(os.path.join(CURRENT_DIR,"line2t.png"))
255         triangle_tex = gu.create_texture(os.path.join(CURRENT_DIR,"trianglet.png"))
256         self.circles = [Circle(circle_tex) for i in xrange(8)]
257         self.squares = [Square(square_tex) for i in xrange(8)]
258         self.lines = [Line(line_tex) for i in xrange(8)]
259         self.triangles = [Triangle(triangle_tex) for i in xrange(8)]
260
261     def draw(self):
262         for c in self.circles:
263             c.draw()
264         for s in self.squares:
265             s.draw()
266         for l in self.lines:
267             l.draw()
268         for t in self.triangles:
269             t.draw()
270
271     def start(self,(x,y)):
272         r = random.choice((0,1,2,3))
273         if r == 0:
274             for c in self.circles:
275                 if not c.on:
276                     c.start((x,y))
277                     return
278         elif r == 1:
279             for s in self.squares:
280                 if not s.on:
281                     s.start((x,y))
282                     return
283         elif r == 2:
284             for l in self.lines:
285                 if not l.on:
286                     l.start((x,y))
287                     return
288         elif r == 3:
289             for t in self.triangles:
290                 if not t.on:
291                     t.start((x,y))
292                     return
293
294     def update(self):
295         for c in self.circles:
296             c.update()
297         for s in self.squares:
298             s.update()
299         for l in self.lines:
300             l.update()
301         for t in self.triangles:
302             t.update()
303
304 def main():
305     psyco.full()
306     screen = gu.init(WIDTH,HEIGHT)
307     pygame.mouse.set_visible(True)
308     writer = Writer()
309     ano = AnoEngine(writer,MIDI_PORT)
310     clock = pygame.time.Clock()
311
312     while True:
313         clock.tick(FPS)
314         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
315         glLoadIdentity()
316         ano.on_event(pygame.event.get())
317         writer.update()
318         writer.draw()
319         pygame.display.flip()
320
321 if __name__ == "__main__":
322     main()