Initial commit from version 1e-99
[beatscape.git] / keyhandler.py
1 from bmevent import *
2 from keyfile import *
3 from pygame.locals import *
4 from constants import *
5
6 class KeyHandler:
7         keyfile = None
8         li = None
9
10         keymap = None
11         jsbuttonmap = None
12         jsaxismap = None
13         timings = None
14
15         def __init__(self,gameconfig,keyfile):
16                 self.keyfile = keyfile
17                 self.li = BMEListIter(keyfile.bmelist)
18                 self.lastdataref = [0,0,0,0,0,0,0,0]
19                 self.li.goto(0)
20                 for b in self.li.window(1.0):
21                         if b.type == BME_TEMPO:
22                                 self.bpm = b.dataref
23                                 self.adjust_window()
24                                 break
25                 self.keymap = gameconfig['keymap']
26                 self.jsbuttonmap = gameconfig['jsbuttonmap']
27                 self.jsaxismap = gameconfig['jsaxismap']
28                 self.timings = gameconfig['timings']
29
30         def decodekey(self,event):
31                 try: 
32                         if event.type == KEYDOWN:
33                                 return (self.keymap[event.key],1)
34                         elif event.type == KEYUP:
35                                 return (self.keymap[event.key],0)
36                         elif event.type == JOYBUTTONDOWN:
37                                 return (self.jsbuttonmap[event.button],1)
38                         elif event.type == JOYBUTTONUP:
39                                 return (self.jsbuttonmap[event.button],0)
40                         elif event.type == JOYAXISMOTION:
41                                 if event.value == 0.0:
42                                         return (self.jsaxismap[(event.axis,event.value)],0)
43                                 else:
44                                         return (self.jsaxismap[(event.axis,event.value)],1)
45                         else:
46                                 return (None,-1)
47                 except KeyError:
48                         return (None,-1)
49
50         def adjust_window(self):
51                 self.ms_per_beat = 60000.0 / self.bpm
52                 self.tstart = 200.0 / self.ms_per_beat
53                 self.tlength = 2000.0 / self.ms_per_beat
54
55         def setproperties(self,properties):
56                 try:
57                         self.bpm = properties['bpm']
58                         self.adjust_window()
59                 except KeyError:
60                         pass
61
62         def handle(self,event,t):
63                 b = self.keyfile.eval_beatfunc(t)
64                 properties = {}
65                 (k,ud) = self.decodekey(event)
66                 if k == None:
67                         return
68                 properties['key'] = k
69                 properties['ud'] = ud
70                 if ud == 0:
71                         return (None, properties)
72                 self.li.goto(b - self.tstart)
73                 bmelist = filter(lambda x: x.key == k, self.li.window(self.tlength,BME_NOTE1))
74                 if not bmelist:
75                         properties['judgement'] = JUDGE_NA
76                         return (BMEvent(b,BME_HIT,k,self.lastdataref[k]), properties)
77
78                 # Find the closest bme to our event
79                 sd = self.tstart
80                 cbme = None
81                 for bme in bmelist:
82                         d = abs(b - bme.beat)
83                         if d < sd:
84                                 sd = d
85                                 cbme = bme
86                 # Convert back to ms
87                 sd = sd * self.ms_per_beat
88
89                 if cbme:
90                         for bt in self.timings:
91                                 if sd < bt[0]:
92                                         properties['judgement'] = bt[1]
93                                         cbme.type = BME_HIT
94                                         break
95                         self.lastdataref[k] = cbme.dataref
96                 else:
97                         properties['judgement'] = JUDGE_NA
98                         return (BMEvent(b,BME_HIT,k,self.lastdataref[k]),properties)
99                 properties['accuracy'] = (b - cbme.beat) * self.ms_per_beat
100                 return (cbme, properties)