2 Created on 23 juil. 2009
4 @author: Samuel Benveniste
6 from math
import floor
, ceil
11 from gradients
import gradients
12 from logging
.PickleableEvent
import PickleableEvent
13 from songs
.Song
import Song
14 from songs
.musicxmltosong
import Part
17 class SongPlayingScreen
:
19 The screen on which the game is played
22 The wiimotes used in this session
24 The main display window
26 The main display surface
28 The clock used to animate the screen
30 The background that is painted every time
32 The buffer for painting everything before bliting
34 The width of the window in pixels
36 The height of the window in pixels
38 True if the scale is G to C instead of C to C
40 True if crossing from note to note with a button pressed triggers a new note
42 The size of the scale used
44 The positions of the cursors on the screen, in pixels
49 def __init__(self
, instrumentChoice
, pguconf
):# song, cascade=False, extendedScale=False, easyMode = False, alwaysDown = False, eventLog = None, replay = None, defaultInstrumentChannel = 16, defaultNote = 60):
54 cascade
= pguconf
.cascade
55 extendedScale
= song
.requiresExtendedScale
56 easyMode
= pguconf
.easyMode
57 alwaysDown
= pguconf
.alwaysDown
58 eventLog
= instrumentChoice
.eventLog
59 replay
= instrumentChoice
.replay
60 defaultInstrumentChannel
= 16
63 if isinstance(song
, Song
) :
64 self
.songDurations
= []
65 self
.totalDuration
= None
68 self
.clicksPerMinute
= [0]
69 self
.clicksInPerMinute
= [0]
70 self
.meanTimeBetweenNotes
= []
71 self
.firstClick
= None
72 self
.firstClickIn
= None
74 self
.blinkLength
= 200
75 self
.minimalVelocity
= 90
76 self
.shortScaleSize
= 8
77 self
.longScaleSize
= 11
79 self
.offset
= self
.longScaleSize
- self
.shortScaleSize
83 self
.highlightedNote
= 0
84 self
.highlightedNoteNumber
= 0
86 self
.savedHighlightedNote
= 0
87 self
.alwaysDown
= alwaysDown
90 self
.wiimotes
= instrumentChoice
.wiimotes
91 self
.activeWiimotes
= instrumentChoice
.activeWiimotes
92 self
.window
= instrumentChoice
.window
93 self
.screen
= instrumentChoice
.screen
94 self
.blitOrigin
= instrumentChoice
.blitOrigin
95 self
.clock
= instrumentChoice
.clock
96 self
.width
= instrumentChoice
.width
97 self
.height
= instrumentChoice
.height
98 self
.cursorPositions
= instrumentChoice
.cursorPositions
99 self
.savedScreen
= instrumentChoice
.savedScreen
100 self
.playerScreen
= instrumentChoice
.playerScreen
101 self
.extendedScale
= extendedScale
102 self
.cascade
= cascade
103 self
.joys
= instrumentChoice
.joys
104 self
.portOffset
= instrumentChoice
.portOffset
105 if eventLog
== None :
106 self
.eventLog
= instrumentChoice
.eventLog
108 self
.eventLog
= eventLog
109 self
.cursorPositions
= instrumentChoice
.cursorPositions
111 self
.songIterator
= self
.song
.getSongIterator()
112 self
.midiNoteNumbers
= self
.song
.scale
114 self
.replay
= instrumentChoice
.replay
117 self
.quarterNoteLength
= song
.quarterNoteLength
118 self
.cascadeLockLengthMultiplier
= 1
119 self
.nextCascadeLockLengthMultiplier
= 1
120 self
.cascadeLockLength
= self
.quarterNoteLength
* self
.cascadeLockLengthMultiplier
122 self
.defaultInstrumentChannel
= defaultInstrumentChannel
123 self
.defaultNote
= defaultNote
126 self
.backToInstrumentChoice
= False
127 self
.easyMode
= easyMode
129 #Initializes the highlightedNote and highlightedNoteNumber etc...
130 self
.moveToNextNote()
131 self
.cascadeLockLengthMultiplier
= self
.nextCascadeLockLengthMultiplier
134 self
.savedBlinkOn
= False
135 ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two
136 ##i.e. it guarantees that there will be an attack between two identical consecutive notes
137 self
.highlightIsFree
= True
140 self
.boundingRect
= None
144 self
.velocityLock
= []
146 self
._blinkOffset
= 0
147 self
._cascadeLockTimer
= 0
148 self
.cascadeIsFree
= True
150 self
.font
= pygame
.font
.Font(None,80)
151 self
.renderedNoteNames
= [self
.font
.render(constants
.noteNumberToName(note
),False,(0,0,0)) for note
in self
.midiNoteNumbers
]
153 self
.drawBackground()
154 self
.initializeWiimotes()
156 self
.songStartTime
= self
.eventLog
.getCurrentTime()
159 while not self
.done
:
161 #Clear the cursors from the screen
162 if self
.hasChanged():
163 self
.drawBackground()
164 self
.playerScreen
.blit(self
.savedScreen
, (0, 0))
166 # Limit frame speed to 50 FPS
168 timePassed
= self
.clock
.tick(10000)
170 self
._blinkOffset
+= timePassed
171 if (self
.buttonDown
or self
.alwaysDown
) and not self
.cascadeIsFree
:
172 self
._cascadeLockTimer
+= timePassed
173 if self
._cascadeLockTimer
> self
.cascadeLockLengthMultiplier
*self
.quarterNoteLength
:
174 self
.cascadeIsFree
= True
175 self
.cascadeLockLengthMultiplier
= self
.nextCascadeLockLengthMultiplier
178 if self
._blinkOffset
> self
.blinkLength
:
179 self
._blinkOffset
-= self
.blinkLength
180 self
.blinkOn
= not self
.blinkOn
183 self
.eventLog
.update(timePassed
)
184 pickledEventsToPost
= self
.eventLog
.getPickledEvents()
185 for pickledEvent
in pickledEventsToPost
:
186 pygame
.event
.post(pickledEvent
.event
)
188 events
= pygame
.event
.get()
191 pickledEvents
= [PickleableEvent(event
.type,event
.dict) for event
in events
]
192 if pickledEvents
!= [] :
193 self
.eventLog
.appendEventGroup(pickledEvents
)
198 for i
in range(len(self
.wiimotes
)):
199 if self
.activeWiimotes
[i
]:
200 self
.wiimotes
[i
].cursor
.update(timePassed
, self
.cursorPositions
[i
])
201 if self
.buttonDown
[i
] or self
.alwaysDown
:
202 self
.wiimotes
[i
].cursor
.flash()
203 self
.wiimotes
[i
].cursor
.blit(self
.playerScreen
)
205 self
.screen
.blit(self
.playerScreen
, (0,0))
207 pygame
.display
.flip()
209 for i
in range(len(self
.wiimotes
)):
210 if self
.activeWiimotes
[i
]:
211 self
.wiimotes
[i
].stopNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[i
]])
213 self
.totalDuration
= self
.eventLog
.getCurrentTime()
215 elif isinstance(song
, Part
) :
216 self
.songDurations
= []
217 self
.totalDuration
= None
220 self
.clicksPerMinute
= [0]
221 self
.clicksInPerMinute
= [0]
222 self
.meanTimeBetweenNotes
= []
223 self
.firstClick
= None
224 self
.firstClickIn
= None
226 self
.blinkLength
= 200
227 self
.minimalVelocity
= 90
228 self
.shortScaleSize
= 8
229 self
.longScaleSize
= 11
230 if not extendedScale
:
231 self
.offset
= self
.longScaleSize
- self
.shortScaleSize
235 self
.highlightedNote
= 0
236 self
.highlightedNoteNumber
= 0
238 self
.savedHighlightedNote
= 0
239 self
.alwaysDown
= alwaysDown
240 self
.nextLevel
= None
242 self
.wiimotes
= instrumentChoice
.wiimotes
243 self
.activeWiimotes
= instrumentChoice
.activeWiimotes
244 self
.window
= instrumentChoice
.window
245 self
.screen
= instrumentChoice
.screen
246 self
.blitOrigin
= instrumentChoice
.blitOrigin
247 self
.clock
= instrumentChoice
.clock
248 self
.width
= instrumentChoice
.width
249 self
.height
= instrumentChoice
.height
250 self
.cursorPositions
= instrumentChoice
.cursorPositions
251 self
.savedScreen
= instrumentChoice
.savedScreen
252 self
.playerScreen
= instrumentChoice
.playerScreen
253 self
.extendedScale
= extendedScale
254 self
.cascade
= cascade
255 self
.joys
= instrumentChoice
.joys
256 self
.portOffset
= instrumentChoice
.portOffset
257 if eventLog
== None :
258 self
.eventLog
= instrumentChoice
.eventLog
260 self
.eventLog
= eventLog
261 self
.cursorPositions
= instrumentChoice
.cursorPositions
263 self
.songIterator
= self
.song
.iterNotes()
264 self
.midiNoteNumbers
= self
.song
.scale
266 self
.replay
= instrumentChoice
.replay
269 self
.quarterNoteLength
= song
.quarterNoteLength
270 self
.cascadeLockLengthMultiplier
= 1
271 self
.nextCascadeLockLengthMultiplier
= 1
272 self
.cascadeLockLength
= self
.quarterNoteLength
* self
.cascadeLockLengthMultiplier
274 self
.defaultInstrumentChannel
= defaultInstrumentChannel
275 self
.defaultNote
= defaultNote
278 self
.backToInstrumentChoice
= False
279 self
.easyMode
= easyMode
281 #Initializes the highlightedNote and highlightedNoteNumber etc...
282 self
.moveToNextNote()
283 self
.cascadeLockLengthMultiplier
= self
.nextCascadeLockLengthMultiplier
286 self
.savedBlinkOn
= False
287 ##Will prevent the song to move on if two consecutive notes are identical and the buttons have not been released in between the two
288 ##i.e. it guarantees that there will be an attack between two identical consecutive notes
289 self
.highlightIsFree
= True
292 self
.boundingRect
= None
296 self
.velocityLock
= []
298 self
._blinkOffset
= 0
299 self
._cascadeLockTimer
= 0
300 self
.cascadeIsFree
= True
302 self
.font
= pygame
.font
.Font(None,80)
303 self
.renderedNoteNames
= [self
.font
.render(constants
.noteNumberToName(note
),False,(0,0,0)) for note
in self
.midiNoteNumbers
]
305 self
.drawBackground()
306 self
.initializeWiimotes()
308 self
.songStartTime
= self
.eventLog
.getCurrentTime()
311 while not self
.done
:
313 #Clear the cursors from the screen
314 if self
.hasChanged():
315 self
.drawBackground()
316 self
.playerScreen
.blit(self
.savedScreen
, (0, 0))
318 # Limit frame speed to 50 FPS
320 timePassed
= self
.clock
.tick(10000)
322 self
._blinkOffset
+= timePassed
323 if (self
.buttonDown
or self
.alwaysDown
) and not self
.cascadeIsFree
:
324 self
._cascadeLockTimer
+= timePassed
325 if self
._cascadeLockTimer
> self
.cascadeLockLengthMultiplier
*self
.quarterNoteLength
:
326 self
.cascadeIsFree
= True
327 self
.cascadeLockLengthMultiplier
= self
.nextCascadeLockLengthMultiplier
330 if self
._blinkOffset
> self
.blinkLength
:
331 self
._blinkOffset
-= self
.blinkLength
332 self
.blinkOn
= not self
.blinkOn
335 self
.eventLog
.update(timePassed
)
336 pickledEventsToPost
= self
.eventLog
.getPickledEvents()
337 for pickledEvent
in pickledEventsToPost
:
338 pygame
.event
.post(pickledEvent
.event
)
340 events
= pygame
.event
.get()
343 pickledEvents
= [PickleableEvent(event
.type,event
.dict) for event
in events
]
344 if pickledEvents
!= [] :
345 self
.eventLog
.appendEventGroup(pickledEvents
)
350 for i
in range(len(self
.wiimotes
)):
351 if self
.activeWiimotes
[i
]:
352 self
.wiimotes
[i
].cursor
.update(timePassed
, self
.cursorPositions
[i
])
353 if self
.buttonDown
[i
] or self
.alwaysDown
:
354 self
.wiimotes
[i
].cursor
.flash()
355 self
.wiimotes
[i
].cursor
.blit(self
.playerScreen
)
357 self
.screen
.blit(self
.playerScreen
, (0,0))
359 pygame
.display
.flip()
361 for i
in range(len(self
.wiimotes
)):
362 if self
.activeWiimotes
[i
]:
363 self
.wiimotes
[i
].stopNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[i
]])
365 self
.totalDuration
= self
.eventLog
.getCurrentTime()
367 def drawBackground(self
):
368 self
.savedScreen
.fill((255,255,255))
370 if self
.extendedScale
:
371 self
.scaleSize
= self
.longScaleSize
373 self
.scaleSize
= self
.shortScaleSize
375 self
.noteRects
= [pygame
.Rect(i
* self
.width
/ self
.scaleSize
+self
.blitOrigin
[0], self
.blitOrigin
[1], self
.width
/ self
.scaleSize
+ 1, self
.height
+1) for i
in range(self
.scaleSize
)]
376 #inflate last noteRect to cover the far right pixels
377 self
.noteRects
[-1].width
= self
.noteRects
[-1].width
+ 1
379 self
.noteRects
[self
.highlightedNote
-self
.offset
].inflate_ip(self
.noteRects
[self
.highlightedNote
-self
.offset
].width
*2,0)
381 #create bounding rect
382 self
.boundingRect
= self
.noteRects
[0].unionall(self
.noteRects
)
384 self
.renderedNoteNames
= [self
.font
.render(constants
.noteNumberToName(note
),False,(0,0,0)) for note
in self
.midiNoteNumbers
]
386 #fill the rectangles with a color gradient
388 startingHue
= 0.66666666666666663
390 for rectNumber
in range(self
.scaleSize
):
391 colorRatio
= float(rectNumber
) / (self
.scaleSize
- 1)
392 #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up
393 hue
= startingHue
* (1 - colorRatio
)
394 if rectNumber
+ self
.offset
!= self
.highlightedNote
:
395 #The color of the bottom of the rectangle in hls coordinates
396 bottomColorHls
= (hue
, 0.1, 1)
397 #The color of the top of the rectangle in hls coordinates
398 topColorHls
= (hue
, 0.1, 1)
400 #convert to rgb ranging from 0 to 255
401 bottomColorRgb
= [floor(255 * i
) for i
in colorsys
.hls_to_rgb(*bottomColorHls
)]
402 topColorRgb
= [floor(255 * i
) for i
in colorsys
.hls_to_rgb(*topColorHls
)]
404 bottomColorRgb
.append(255)
405 topColorRgb
.append(255)
407 bottomColorRgb
= tuple(bottomColorRgb
)
408 topColorRgb
= tuple(topColorRgb
)
410 self
.savedScreen
.blit(gradients
.vertical(self
.noteRects
[rectNumber
].size
, topColorRgb
, bottomColorRgb
), self
.noteRects
[rectNumber
])
412 noteNameBlitPoint
= (self
.noteRects
[rectNumber
].left
+(self
.noteRects
[rectNumber
].width
-self
.renderedNoteNames
[rectNumber
+self
.offset
].get_width())/2,
413 self
.noteRects
[rectNumber
].bottom
-self
.renderedNoteNames
[rectNumber
+self
.offset
].get_height())
415 self
.savedScreen
.blit(self
.renderedNoteNames
[rectNumber
+self
.offset
], noteNameBlitPoint
)
417 pygame
.draw
.rect(self
.savedScreen
, pygame
.Color(0, 0, 0, 255), self
.noteRects
[rectNumber
], 2)
419 colorRatio
= float(self
.highlightedNote
-self
.offset
) / (self
.scaleSize
- 1)
420 #hue will go from 0.6666... (blue) to 0 (red) as colorRation goes up
421 hue
= startingHue
* (1 - colorRatio
)
422 #The color of the bottom of the rectangle in hls coordinates
423 bottomColorHls
= (hue
, 0.6, 1)
424 #The color of the top of the rectangle in hls coordinates
425 topColorHls
= (hue
, 0.9, 1)
427 #convert to rgb ranging from 0 to 255
428 bottomColorRgb
= [floor(255 * i
) for i
in colorsys
.hls_to_rgb(*bottomColorHls
)]
429 topColorRgb
= [floor(255 * i
) for i
in colorsys
.hls_to_rgb(*topColorHls
)]
431 bottomColorRgb
.append(255)
432 topColorRgb
.append(255)
434 bottomColorRgb
= tuple(bottomColorRgb
)
435 topColorRgb
= tuple(topColorRgb
)
437 self
.savedScreen
.blit(gradients
.vertical(self
.noteRects
[self
.highlightedNote
-self
.offset
].size
, topColorRgb
, bottomColorRgb
), self
.noteRects
[self
.highlightedNote
-self
.offset
])
439 noteNameBlitPoint
= (self
.noteRects
[self
.highlightedNote
-self
.offset
].left
+(self
.noteRects
[self
.highlightedNote
-self
.offset
].width
-self
.renderedNoteNames
[self
.highlightedNote
].get_width())/2,
440 self
.noteRects
[self
.highlightedNote
-self
.offset
].bottom
-self
.renderedNoteNames
[self
.highlightedNote
].get_height())
442 self
.savedScreen
.blit(self
.renderedNoteNames
[self
.highlightedNote
], noteNameBlitPoint
)
445 renderedSyllabus
= self
.font
.render(self
.syllabus
,False,(0,0,0))
447 syllabusBlitPoint
= (self
.noteRects
[self
.highlightedNote
-self
.offset
].left
+(self
.noteRects
[self
.highlightedNote
-self
.offset
].width
-renderedSyllabus
.get_width())/2,
448 self
.noteRects
[self
.highlightedNote
-self
.offset
].centery
-renderedSyllabus
.get_height()/2)
450 self
.savedScreen
.blit(renderedSyllabus
, syllabusBlitPoint
)
452 pygame
.draw
.rect(self
.savedScreen
, pygame
.Color(0, 0, 0, 255), self
.noteRects
[self
.highlightedNote
-self
.offset
], 2)
454 if self
.song
!= None and self
.blinkOn
:
455 borderSize
= self
.borderSize
456 pygame
.draw
.rect(self
.savedScreen
, pygame
.Color(0, 0, 0, 0), self
.noteRects
[self
.highlightedNote
-self
.offset
].inflate(borderSize
/2,borderSize
/2), borderSize
)
458 def initializeWiimotes(self
):
459 for loop
in self
.wiimotes
:
460 if loop
.port
== None :
461 loop
.port
= pygame
.midi
.Output(loop
.portNumber
)
463 self
.buttonDown
.append(False)
464 self
.velocityLock
.append(False)
466 def updateCursorPositionFromJoy(self
, joyEvent
):
467 joyName
= pygame
.joystick
.Joystick(joyEvent
.joy
).get_name()
468 correctedJoyId
= constants
.joyNames
.index(joyName
)
469 if correctedJoyId
< len(self
.cursorPositions
):
470 if joyEvent
.axis
== 0 :
471 self
.cursorPositions
[correctedJoyId
] = (int((joyEvent
.value
+ 1) / 2 * self
.screen
.get_width()), self
.cursorPositions
[correctedJoyId
][1])
472 if joyEvent
.axis
== 1 :
473 self
.cursorPositions
[correctedJoyId
] = (self
.cursorPositions
[correctedJoyId
][0], int((joyEvent
.value
+ 1) / 2 * self
.screen
.get_height()))
475 def heightToVelocity(self
, pos
, controllerNumber
):
476 if self
.song
!= None:
477 if self
.boundingRect
.collidepoint(pos
) and (self
.highlightedNote
== self
.notes
[controllerNumber
] or self
.velocityLock
[controllerNumber
]):
478 velocity
= int(floor((1 - (float(pos
[1])-self
.blitOrigin
[1]) / self
.height
) * (127-self
.minimalVelocity
))+self
.minimalVelocity
)
485 if self
.boundingRect
.collidepoint(pos
):
486 velocity
= int(floor((1 - (float(pos
[1])-self
.blitOrigin
[1]) / self
.height
) * (127-self
.minimalVelocity
))+self
.minimalVelocity
)
488 velocity
= self
.minimalVelocity
491 def widthToNote(self
, pos
):
494 if self
.noteRects
[self
.highlightedNote
-self
.offset
].collidepoint(pos
) :
495 return self
.highlightedNote
497 while self
.noteRects
[nn
].collidepoint(pos
) == False:
499 return(nn
+ self
.offset
)
505 if self
.firstClick
== None :
506 self
.firstClick
= self
.eventLog
.getCurrentTime()
507 minute
= int(floor((self
.eventLog
.getCurrentTime()-self
.songStartTime
)/60000))
508 if minute
> len(self
.clicksPerMinute
)-1:
509 self
.clicksPerMinute
.append(0)
510 self
.clicksPerMinute
[-1] += 1
512 def logClickIn(self
):
513 self
.clicksIn
[-1] += 1
514 if self
.clicksIn
[-1] > len(self
.song
.notes
)-1 :
515 self
.clicksIn
.append(0)
516 self
.clicks
.append(0)
517 self
.songDurations
.append(self
.eventLog
.getCurrentTime())
518 if self
.firstClickIn
== None :
519 self
.firstClickIn
= self
.eventLog
.getCurrentTime()
520 minute
= int(floor((self
.eventLog
.getCurrentTime()-self
.songStartTime
)/60000))
521 if minute
> len(self
.clicksInPerMinute
)-1:
522 self
.clicksInPerMinute
.append(0)
523 self
.clicksInPerMinute
[-1]+=1
525 def input(self
, event
):
527 if event
.type == pygame
.QUIT
:
528 for loop
in self
.wiimotes
:
533 if event
.type == pygame
.KEYDOWN
:
534 if event
.key
== pygame
.K_q
:
535 self
.nextLevel
= None
538 if event
.key
== pygame
.K_i
:
539 self
.backToInstrumentChoice
= True
542 if event
.key
== pygame
.K_w
:
546 if event
.key
== pygame
.K_e
:
550 if event
.key
== pygame
.K_r
:
554 if event
.key
== pygame
.K_t
:
558 if event
.type == pygame
.JOYAXISMOTION
:
560 joyName
= pygame
.joystick
.Joystick(event
.joy
).get_name()
561 correctedJoyId
= constants
.joyNames
.index(joyName
)
562 if self
.activeWiimotes
[correctedJoyId
]:
563 self
.updateCursorPositionFromJoy(event
)
564 wiimote
= self
.wiimotes
[correctedJoyId
]
565 pos
= self
.cursorPositions
[correctedJoyId
]
567 if (self
.buttonDown
[correctedJoyId
] or self
.alwaysDown
):
568 if self
.notes
[correctedJoyId
] != None:
569 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
570 if velocity
!= None :
571 CCHexCode
= wiimote
.getCCHexCode()
572 wiimote
.port
.write_short(CCHexCode
, 07, velocity
)
573 if self
.cascade
and self
.cascadeIsFree
:
574 n
= self
.widthToNote(pos
)
575 if self
.highlightedNote
== n
:
576 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
577 self
.notes
[correctedJoyId
] = n
578 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
579 self
.velocityLock
[correctedJoyId
] = True
580 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
581 self
.moveToNextNote()
582 self
._cascadeLockTimer
= 0
583 self
.cascadeIsFree
= False
585 if event
.type == pygame
.JOYBUTTONDOWN
:
587 joyName
= pygame
.joystick
.Joystick(event
.joy
).get_name()
588 correctedJoyId
= constants
.joyNames
.index(joyName
)
589 if self
.activeWiimotes
[correctedJoyId
]:
590 wiimote
= self
.wiimotes
[correctedJoyId
]
591 pos
= self
.cursorPositions
[correctedJoyId
]
592 self
.wiimotes
[correctedJoyId
].cursor
.flash()
596 if not (self
.buttonDown
[correctedJoyId
] or self
.alwaysDown
):
597 n
= self
.widthToNote(pos
)
598 if self
.highlightedNote
== n
:
599 self
._cascadeLockTimer
= 0
600 self
.cascadeIsFree
= False
602 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
603 self
.notes
[correctedJoyId
] = n
604 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
605 self
.velocityLock
[correctedJoyId
] = True
606 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
609 self
.moveToNextNote()
611 if not self
.easyMode
:
612 self
._cascadeLockTimer
= 0
613 self
.cascadeIsFree
= False
614 self
.notes
[correctedJoyId
] = n
615 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
616 if velocity
!= None and self
.notes
[correctedJoyId
] != None :
617 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
618 self
.buttonDown
[correctedJoyId
] = True
620 if event
.type == pygame
.JOYBUTTONUP
:
621 joyName
= pygame
.joystick
.Joystick(event
.joy
).get_name()
622 correctedJoyId
= constants
.joyNames
.index(joyName
)
623 if self
.activeWiimotes
[correctedJoyId
]:
624 self
.buttonDown
[correctedJoyId
] = False
625 wiimote
= self
.wiimotes
[correctedJoyId
]
626 if not self
.easyMode
:
627 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
628 self
.velocityLock
[correctedJoyId
] = False
630 if event
.type == pygame
.MOUSEMOTION
:
632 self
.updateCursorPositionFromMouse(event
)
635 while not self
.activeWiimotes
[correctedJoyId
] :
637 wiimote
= self
.wiimotes
[correctedJoyId
]
638 pos
= self
.cursorPositions
[correctedJoyId
]
640 if (self
.buttonDown
[correctedJoyId
] or self
.alwaysDown
):
641 self
.wiimotes
[correctedJoyId
].cursor
.flash()
642 if self
.notes
[correctedJoyId
] != None:
643 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
644 if velocity
!= None :
645 CCHexCode
= wiimote
.getCCHexCode()
646 wiimote
.port
.write_short(CCHexCode
, 07, velocity
)
647 if self
.cascade
and self
.cascadeIsFree
:
648 n
= self
.widthToNote(pos
)
649 if self
.highlightedNote
== n
:
650 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
651 self
.notes
[correctedJoyId
] = n
652 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
653 self
.velocityLock
[correctedJoyId
] = True
654 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
655 self
.moveToNextNote()
656 self
._cascadeLockTimer
= 0
657 self
.cascadeIsFree
= False
659 if event
.type == pygame
.MOUSEBUTTONDOWN
:
661 if event
.button
== 1:
663 while not self
.activeWiimotes
[correctedJoyId
] :
665 wiimote
= self
.wiimotes
[correctedJoyId
]
666 pos
= self
.cursorPositions
[correctedJoyId
]
667 self
.wiimotes
[correctedJoyId
].cursor
.flash()
671 if not (self
.buttonDown
[correctedJoyId
] or self
.alwaysDown
):
672 n
= self
.widthToNote(pos
)
673 if self
.highlightedNote
== n
:
674 self
._cascadeLockTimer
= 0
675 self
.cascadeIsFree
= False
677 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
678 self
.notes
[correctedJoyId
] = n
679 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
680 self
.velocityLock
[correctedJoyId
] = True
681 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
684 self
.moveToNextNote()
686 if not self
.easyMode
:
687 self
._cascadeLockTimer
= 0
688 self
.cascadeIsFree
= False
689 self
.notes
[correctedJoyId
] = n
690 velocity
= self
.heightToVelocity(pos
, correctedJoyId
)
691 if velocity
!= None and self
.notes
[correctedJoyId
] != None :
692 wiimote
.playNoteByNoteNumber(self
.midiNoteNumbers
[self
.notes
[correctedJoyId
]],velocity
)
693 self
.buttonDown
[correctedJoyId
] = True
695 if event
.button
== 2:
699 if event
.type == pygame
.MOUSEBUTTONUP
:
700 if event
.button
== 1 :
702 while not self
.activeWiimotes
[correctedJoyId
] :
704 wiimote
= self
.wiimotes
[correctedJoyId
]
705 self
.buttonDown
[correctedJoyId
] = False
706 if not self
.easyMode
:
707 if self
.notes
[correctedJoyId
] != None :
708 wiimote
.stopNoteByNoteNumber(self
.savedMidiNoteNumbers
[self
.notes
[correctedJoyId
]])
709 self
.velocityLock
[correctedJoyId
] = False
711 def hasChanged(self
):
713 if self
.song
!= None:
714 if self
.blinkOn
!= self
.savedBlinkOn
or self
.highlightedNote
!= self
.savedHighlightedNote
:
715 self
.savedBlinkOn
= self
.blinkOn
716 self
.savedHighlightedNote
= self
.highlightedNote
720 def updateCursorPositionFromMouse(self
, mouseEvent
):
722 while not self
.activeWiimotes
[correctedJoyId
] :
724 self
.cursorPositions
[correctedJoyId
] = mouseEvent
.pos
726 def moveToNextNote(self
):
727 self
.savedMidiNoteNumbers
= self
.midiNoteNumbers
[:]
728 note
, lyricIndex
= self
.songIterator
.next()
729 self
.highlightedNote
= note
.column
730 self
.highlightedNoteNumber
= note
.midi
731 self
.syllabus
= str(note
.lyrics
[lyricIndex
])
732 self
.nextCascadeLockLengthMultiplier
= note
.duration
733 self
.midiNoteNumbers
[self
.highlightedNote
] = self
.highlightedNoteNumber
735 #self.highlightedNote, self.highlightedNoteNumber, self.syllabus, self.nextCascadeLockLengthMultiplier = self.songIterator.next()
736 #self.midiNoteNumbers[self.highlightedNote] = self.highlightedNoteNumber