8eeaf791a5c9c38bae49e929d68021aa89188fdc
[minwii.git] / src / app / widgets / playingscreen.py
1 # -*- coding: utf-8 -*-
2 """
3 Écran de jeu MinWii :
4 bandes arc-en-ciel représentant un clavier.
5
6 $Id$
7 $URL$
8 """
9 import pygame
10 from colorsys import hls_to_rgb
11 from gradients import gradients
12 from math import floor
13 # TODO : positionner cette constance en fonction de la résolution d'affichage
14 # externaliser la conf.
15 BORDER = 5 # 5px
16 FIRST_HUE = 0.6
17 OFF_LUMINANCE = 0.1
18 OFF_SATURATION = 1
19 ON_TOP_LUMINANCE = 0.6
20 ON_BOTTOM_LUMINANCE = 0.9
21 ON_SATURATION = 1
22
23 class _PlayingScreenBase(pygame.sprite.OrderedUpdates) :
24 def __init__(self, distinctNotes=[]) :
25 """
26 distinctNotes : notes disctinctes présentes dans la chanson
27 triées du plus grave au plus aigu.
28 """
29 super(_PlayingScreenBase, self).__init__()
30 self.distinctNotes = distinctNotes
31 self.keyboardLength = 0
32 self.keyboardRects = []
33 self._initRects()
34 self._initColumns()
35
36
37
38 def _initRects(self) :
39 """ création des espaces réservés pour
40 afficher les colonnes.
41 """
42 ambitus = self.distinctNotes[-1].midi - self.distinctNotes[0].midi
43 if ambitus <= 12 :
44 self.keyboardLength = 8
45 else :
46 self.keyboardLength = 11
47
48 screen = pygame.display.get_surface()
49
50 # taille de la zone d'affichage utile (bordure autour)
51 dispWidth = screen.get_width() - 2 * BORDER
52 dispHeight = screen.get_height() - 2 * BORDER
53
54 columnWidth = int(round(float(dispWidth) / self.keyboardLength))
55
56 rects = []
57 for i in range(self.keyboardLength) :
58 upperLeftCorner = (i*columnWidth + BORDER, BORDER)
59 rect = pygame.Rect(upperLeftCorner, (columnWidth, dispHeight))
60 rects.append(rect)
61
62 self.keyboardRects = rects
63
64 def _initColumns(self) :
65
66 hueStep = FIRST_HUE / (self.keyboardLength - 1)
67 for i, rect in enumerate(self.keyboardRects) :
68 hue = FIRST_HUE - hueStep * i
69 c = Column(hue, rect)
70 self.add(c)
71
72
73 def highlightColumn(self, index) :
74 for i, sprite in enumerate(self.sprites()) :
75 sprite.update(i==index)
76 self.draw(pygame.display.get_surface())
77
78
79
80 class SongPlayingScreen(_PlayingScreenBase) :
81
82 def __init__(self, song) :
83 super(SongPlayingScreen, self).__init__(song.distinctNotes)
84 self.song = song
85
86 class SongPlayingScreenTest(_PlayingScreenBase) :
87 def __init__(self) :
88 class C:pass
89 o = C()
90 o.midi=1
91 super(SongPlayingScreenTest, self).__init__([o])
92 self.__running = True
93 #pygame.display.flip()
94 #raw_input('allez ?')
95
96 def run(self):
97 while self.__running :
98 pygame.display.flip()
99 events = pygame.event.get()
100 for event in events:
101 self.input(event)
102
103 def input(self, event) :
104 if event.type == pygame.KEYDOWN:
105 if event.key == pygame.K_q:
106 self.__running = False
107 uni = event.unicode
108 if uni.isdigit() and int(uni) <=8 :
109 self.highlightColumn(int(uni))
110
111
112 # if event.key == pygame.K_i:
113 # self.backToInstrumentChoice = True
114 # self.done = True
115 #
116 # if event.key == pygame.K_w:
117 # self.nextLevel = 0
118 # self.done = True
119 #
120 # if event.key == pygame.K_e:
121 # self.nextLevel = 1
122 # self.done = True
123 #
124 # if event.key == pygame.K_r:
125 # self.nextLevel = 2
126 # self.done = True
127 #
128 # if event.key == pygame.K_t:
129 # self.nextLevel = 3
130 # self.done = True
131
132
133 class Column(pygame.sprite.Sprite) :
134
135 def __init__(self, hue, rect) :
136 pygame.sprite.Sprite.__init__(self)
137 sur = pygame.surface.Surface(rect.size)
138 rgba = hls_to_rgba_8bits(hue, OFF_LUMINANCE, OFF_SATURATION)
139 sur.fill(rgba)
140 self.stateOff = sur
141
142 topRgba = hls_to_rgba_8bits(hue, ON_TOP_LUMINANCE, ON_SATURATION)
143 bottomRgba = hls_to_rgba_8bits(hue, ON_BOTTOM_LUMINANCE, ON_SATURATION)
144 size = rect.inflate(2*rect.width,0).size
145 self.stateOn = gradients.vertical(size, topRgba, bottomRgba)
146
147 self.image = self.stateOff
148 self.rect = rect
149
150 def update(self, state) :
151 if state :
152 self.image = self.stateOn
153 else :
154 self.image = self.stateOff
155
156 def hls_to_rgba_8bits(h, l, s) :
157 #convert to rgb ranging from 0 to 255
158 rgba = [floor(255 * i) for i in hls_to_rgb(h, l, s) + (1,)]
159 return tuple(rgba)
160