1 # -*- coding: utf-8 -*-
4 bandes arc-en-ciel représentant un clavier.
10 from colorsys
import hls_to_rgb
11 from gradients
import gradients
12 from cursors
import WarpingCursor
13 from eventutils
import event_handler
, EventDispatcher
, EventHandlerMixin
14 from math
import floor
16 from musicxml
import Tone
18 from config
import BORDER
19 from config
import FIRST_HUE
20 from config
import OFF_LUMINANCE
21 from config
import OFF_SATURATION
22 from config
import ON_TOP_LUMINANCE
23 from config
import ON_BOTTOM_LUMINANCE
24 from config
import ON_SATURATION
25 from config
import ON_COLUMN_OVERSIZING
26 from config
import ON_COLUMN_ALPHA
27 from config
import FONT
28 from config
import FONT_COLOR
30 class _PlayingScreenBase(pygame
.sprite
.LayeredUpdates
, EventHandlerMixin
) :
32 def __init__(self
, distinctNotes
=[]) :
34 distinctNotes : notes disctinctes présentes dans la chanson
35 triées du plus grave au plus aigu.
37 super(_PlayingScreenBase
, self
).__init
__()
38 self
.distinctNotes
= distinctNotes
39 self
.keyboardLength
= 0
40 self
.keyboardRects
= []
45 self
.draw(pygame
.display
.get_surface())
50 def _initRects(self
) :
51 """ création des espaces réservés pour
52 afficher les colonnes.
54 ambitus
= self
.distinctNotes
[-1].midi
- self
.distinctNotes
[0].midi
56 self
.keyboardLength
= 8
58 self
.keyboardLength
= 11
60 screen
= pygame
.display
.get_surface()
62 # taille de la zone d'affichage utile (bordure autour)
63 dispWidth
= screen
.get_width() - 2 * BORDER
64 dispHeight
= screen
.get_height() - 2 * BORDER
66 columnWidth
= int(round(float(dispWidth
) / self
.keyboardLength
))
69 for i
in range(self
.keyboardLength
) :
70 upperLeftCorner
= (i
*columnWidth
+ BORDER
, BORDER
)
71 rect
= pygame
.Rect(upperLeftCorner
, (columnWidth
, dispHeight
))
74 self
.keyboardRects
= rects
76 def _initColumns(self
) :
78 hueStep
= FIRST_HUE
/ (self
.keyboardLength
- 1)
79 for i
, rect
in enumerate(self
.keyboardRects
) :
80 hue
= FIRST_HUE
- hueStep
* i
81 tone
= self
.distinctNotes
[i
]
82 c
= Column(self
, hue
, rect
, tone
)
85 def _initCursor(self
) :
86 self
.cursor
= WarpingCursor(blinkMode
=True)
87 self
.add(self
.cursor
, layer
=2)
91 clock
= pygame
.time
.Clock()
94 EventDispatcher
.dispatchEvents()
95 dirty
= self
.draw(pygame
.display
.get_surface())
96 pygame
.display
.update(dirty
)
99 @event_handler(pygame
.KEYDOWN
)
100 def handleKeyDown(self
, event
) :
101 if event
.key
== pygame
.K_q
:
102 self
._running
= False
105 @event_handler(pygame
.MOUSEMOTION
)
106 def handleMouseMotion(self
, event
) :
110 class PlayingScreen(_PlayingScreenBase
) :
111 "fenêtre de jeu pour improvisation"
112 scale
= [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]
116 for midi
in self
.scale
:
118 distinctNotes
.append(tone
)
120 super(PlayingScreen
, self
).__init
__(distinctNotes
)
123 class SongPlayingScreen(_PlayingScreenBase
) :
125 def __init__(self
, song
) :
126 super(SongPlayingScreen
, self
).__init
__(song
.distinctNotes
)
129 class SongPlayingScreenTest(_PlayingScreenBase
) :
134 super(SongPlayingScreenTest
, self
).__init
__([o
])
137 class Column(pygame
.sprite
.Sprite
, EventHandlerMixin
) :
139 def __init__(self
, group
, hue
, rect
, tone
) :
140 pygame
.sprite
.Sprite
.__init
__(self
, group
)
141 sur
= pygame
.surface
.Surface(rect
.size
)
142 rgba
= hls_to_rgba_8bits(hue
, OFF_LUMINANCE
, OFF_SATURATION
)
147 topRgba
= hls_to_rgba_8bits(hue
, ON_TOP_LUMINANCE
, ON_SATURATION
, ON_COLUMN_ALPHA
)
148 bottomRgba
= hls_to_rgba_8bits(hue
, ON_BOTTOM_LUMINANCE
, ON_SATURATION
, ON_COLUMN_ALPHA
)
149 onWidth
= rect
.width
* ON_COLUMN_OVERSIZING
150 onLeft
= rect
.centerx
- onWidth
/ 2
151 rectOn
= pygame
.Rect((onLeft
, 0),
152 (onWidth
, rect
.height
))
153 self
.stateOn
= gradients
.vertical(rectOn
.size
, topRgba
, bottomRgba
)
156 self
.image
= self
.stateOff
158 self
.toneName
= FONT
.render(tone
.nom
, True, (0,0,0))
160 def update(self
, state
) :
161 group
= self
.groups()[0]
163 group
.change_layer(self
, 1)
164 self
.image
= self
.stateOn
165 self
.rect
= self
.rectOn
167 group
.change_layer(self
, 0)
168 self
.image
= self
.stateOff
169 self
.rect
= self
.rectOff
171 @event_handler(pygame
.MOUSEBUTTONDOWN
)
172 def onMouseDown(self
, event
) :
173 if self
.rect
.collidepoint(*event
.pos
) :
176 @event_handler(pygame
.MOUSEBUTTONUP
)
177 def onMouseUp(self
, event
) :
180 def raiseNoteOn(self
) :
183 def raiseNoteOff(self
) :
188 def hls_to_rgba_8bits(h
, l
, s
, a
=1) :
189 #convert to rgb ranging from 0 to 255
190 rgba
= [floor(255 * i
) for i
in hls_to_rgb(h
, l
, s
) + (a
,)]