root/src/eventhandler.py @ 253

Revision 253, 27.6 KB (checked in by andefodahl, 22 months ago)
Line 
1"""
2eventhandler.py is the core of the game. It controls what is drawn,
3user input, and changing modes.
4"""
5
6import pygame
7from pygame.locals import QUIT, MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP
8from pygame.locals import KEYDOWN, KMOD_CAPS, KMOD_LSHIFT, KMOD_RSHIFT
9import sys
10from graphics import *
11from sound import *
12from menu import MenuHandler
13from story import *
14from survival import *
15from constants import BBUILDER
16import globalVars
17from transition import *
18
19#set globalVars
20globalVars.screen = pygame.display.set_mode((800, 600))
21globalVars.graphics = Graphics()
22globalVars.menuHandler  = MenuHandler()
23globalVars.soundPlayer = SoundPlayer()
24
25class EventHandler:
26    """The EventHandler class is the overseer for everything that happens in
27        the game. There is a single instance of it."""
28    def __init__(self):
29        """initializes EventHandler"""
30        self.mouseDown = False
31        self.dest = None
32        self.running = True
33        self.lastClicked = None
34        self.game = None
35        self.difficulty = None
36        self.mode = BBUILDER.MENU
37        self.transition = Transition()
38        self.transitionComplete = False
39        self.transitionComplete2 = False
40        self.transitioning = False
41
42    def update(self):
43        """updates the EventHandler. Key function. Acts based on self.mode"""
44        #Menu case
45        if self.mode == BBUILDER.MENU:
46            self.processMenuEvents()
47            if self.dest == "exit":
48                self.exit()
49                sys.exit()
50            elif self.dest != None and "play" in self.dest: #Game mode
51                if self.manageTransition():
52                    self.transitionComplete = True
53                   
54                if "Game" in self.dest:
55                    self.mode = BBUILDER.STORY
56                elif "Survival" in self.dest:
57                    self.mode = BBUILDER.SURVIVAL
58                   
59                if "Easy" in self.dest:
60                    self.difficulty = BBUILDER.EASY
61                elif "Medium" in self.dest:
62                    self.difficulty = BBUILDER.MEDIUM
63                elif "Hard" in self.dest:
64                    self.difficulty = BBUILDER.HARD
65
66                self.dest = None
67               
68            elif self.dest != None: #New Page
69                if globalVars.menuHandler.update(self.dest, globalVars.menuHandler.currentPage):
70                    # Reset keyboard-selected button
71                    self.dest = None
72            globalVars.menuHandler.draw()
73
74        #Story case
75        if self.mode == BBUILDER.STORY and self.transitionComplete:
76            self.transitionComplete2 = False
77            valueChange = self.processGameEvents()
78            score = self.game.update(valueChange)
79            if score == -1:
80                self.game.draw()
81            elif score == "Exit event":
82                self.transitioning = True
83                self.manageScoresTransition()
84            elif (score != -1): #Final score returned
85                globalVars.menuHandler.updateUnlock(self.difficulty, score) 
86                globalVars.menuHandler.currentPage = "enterName"
87                currentPage = globalVars.menuHandler.pageLibrary[
88                    globalVars.menuHandler.currentPage]
89                if self.game.exit:
90                    currentPage.textList[0].text = ""
91                else:
92                    currentPage.textList[0].text = "You win!"
93                currentPage.modeStr = "Story"
94                currentPage.score = int(score)
95                currentPage.textList[1].text = "Your score is "+str(score)
96                currentPage.textList[4].text = ""
97                self.game = None
98                self.transitionComplete = False
99                self.transitioning = True
100                self.mode = BBUILDER.INPUT
101                self.timer = 0
102                self.dest = None
103
104        #Survival case
105        if self.mode == BBUILDER.SURVIVAL and self.transitionComplete:
106            self.transitionComplete2 = False
107            self.game.draw()
108            valueChange = self.processGameEvents()
109            score = self.game.update(valueChange)
110            if score == "Exit event":
111                self.transitioning = True
112                self.manageScoresTransition()
113            elif (score != -1): #Final score returned
114                globalVars.menuHandler.currentPage = "enterName"
115                currentPage = globalVars.menuHandler.pageLibrary[
116                    globalVars.menuHandler.currentPage]
117                if self.game.exit:
118                    currentPage.textList[0].text = ""
119                else:
120                    currentPage.textList[0].text = "Time's up!"
121                currentPage.modeStr = "Survival"
122                currentPage.score = int(score[0])
123                currentPage.textList[1].text = "Your score is "+str(int(
124                    score[0]))
125                currentPage.textList[4].text = ""
126                self.game = None
127                self.transitionComplete = False
128                self.mode = BBUILDER.INPUT
129                self.timer = 0
130                self.dest = None
131       
132        if (self.mode == BBUILDER.SURVIVAL and not self.transitionComplete):
133            self.transitionComplete = self.manageTransition()
134
135        if (self.mode == BBUILDER.STORY and not self.transitionComplete):
136            self.transitionComplete = self.manageTransition()
137           
138        #Input case
139        if self.mode == BBUILDER.INPUT  and self.transitionComplete2:
140            self.processInput()
141            if self.dest == "exit":
142                self.exit()
143                sys.exit()
144            elif self.dest != None: #Mode on from Input
145                if self.dest == "scorePage":
146                    globalVars.menuHandler.pageLibrary[
147                        globalVars.menuHandler.currentPage].registerScore()
148                # Reset keyboard-selected button
149                globalVars.menuHandler.currentPage = self.dest
150                self.dest = None
151                self.mode = BBUILDER.MENU
152            globalVars.menuHandler.draw()
153       
154
155        if not self.transitionComplete2 and self.transitioning:
156            self.transitionComplete2 = self.manageScoresTransition()
157            if self.transitionComplete2:
158                self.transitioning = False
159
160        #Final action is to update screen
161        pygame.display.flip()
162
163    def processMenuEvents(self):
164        """processMenuEvents reads the necessary input for the menu mode.
165            If needed, it will change self.dest in order to change the page"""
166        currentPage = globalVars.menuHandler.pageLibrary[
167            globalVars.menuHandler.currentPage]
168        unlock = globalVars.menuHandler.unlock
169        for event in pygame.event.get():
170            if event.type == QUIT:
171                self.exit()
172                sys.exit()
173           
174            visibleButtons = []
175            for button in currentPage.menuButtonList:
176                if (button.unlock <= unlock):
177                    visibleButtons.append(button)
178                   
179            if event.type == MOUSEMOTION:
180                for buttonNum in range(len(visibleButtons)):
181                    button = visibleButtons[buttonNum]
182                    button.hover = False
183                    button.play = False
184                    if button.imageRect.collidepoint(event.pos):
185                        currentPage.selectedButton = button
186                        button.hover = True
187                        button.play = True
188                       
189            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
190                for button in visibleButtons:
191                    if button.imageRect.collidepoint(event.pos):
192#                        globalVars.soundPlayer.playSound("click.mp3")
193                        self.mouseDown = True
194                        button.active = True
195                        self.lastClicked = button
196                for clickableObject in currentPage.clickableObjects:
197                    if clickableObject.imageRect.collidepoint(event.pos):
198                        self.mouseDown = True
199                        self.lastClicked = clickableObject
200                       
201            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
202                for button in visibleButtons:
203                    if button == self.lastClicked:
204                        self.lastClicked.active = False
205                        if button.imageRect.collidepoint(event.pos):
206                            self.mouseDown = False
207                            button.clicked = False
208                            if globalVars.menuHandler.transition.isInactive():
209                                self.dest = button.dest
210                for clickableObject in currentPage.clickableObjects:
211                    if clickableObject == self.lastClicked:
212                        if clickableObject.imageRect.collidepoint(event.pos):
213                            clickableObject.clicked()
214                            self.mouseDown = False
215                self.lastClicked = None
216               
217            elif event.type == KEYDOWN:
218                key = pygame.key.name(event.key)
219                if key == "up" or key == "left":
220                    currentPage.selectButton(BBUILDER.BUTTON_PREV)
221                elif key == "down" or key == "right":
222                    currentPage.selectButton(BBUILDER.BUTTON_NEXT)
223                elif (key == "space" or key == "return") and currentPage.selectedButton != None:
224#                    globalVars.soundPlayer.playSound("click.mp3")
225                    self.dest = currentPage.selectedButton.dest
226
227    def processGameEvents(self):
228        """processGameEvents calls the appropriate processing function
229            based on the state of the game. Returns the change in value
230            from toggling blocks"""
231        #Sets currentPuzzles based on mode
232        if self.mode == BBUILDER.STORY:
233            currentPuzzle = self.game.levelDict[
234                self.game.currentLevel].currentPuzzle
235        elif self.mode == BBUILDER.SURVIVAL or self.mode == BBUILDER.BONUS:
236            currentPuzzle = self.game.currentPuzzle
237
238        curState = currentPuzzle.puzzleState
239           
240        if curState == BBUILDER.PUZZLE:
241            return self.processToggleEvents(currentPuzzle)
242        if curState == BBUILDER.INTRO or  curState == BBUILDER.END or curState == BBUILDER.VICTORY:
243            return self.processGameMenuEvents(currentPuzzle)
244        elif curState == BBUILDER.BONUS:
245            return self.processBonusEvents(currentPuzzle)
246        elif curState == BBUILDER.BONUS_INTRO:
247            return self.processGameMenuEvents(self.game.levelDict[
248                self.game.currentLevel])
249           
250
251    def processGameMenuEvents(self, currentPuzzle):
252        """event reader for game menus (if mode is not Puzzle)
253            returns 'Continue' if button is clicked, else 'No'"""
254        if currentPuzzle.puzzleState == BBUILDER.INTRO or currentPuzzle.puzzleState == BBUILDER.BONUS_INTRO:
255            buttonList = currentPuzzle.introButtons
256        elif currentPuzzle.puzzleState == BBUILDER.VICTORY:
257            buttonList = currentPuzzle.victoryButtons
258        else:
259            buttonList = currentPuzzle.endButtons
260
261        for event in pygame.event.get():
262            if event.type == QUIT:
263                self.exit()
264                sys.exit()
265            if event.type == MOUSEMOTION:
266                for button in buttonList:
267                    button.hover = False
268                    button.play = False
269                    if button.imageRect.collidepoint(event.pos):
270                        button.hover = True
271                        button.play = True
272                       
273            if event.type == MOUSEBUTTONDOWN and event.button == 1:
274                for button in buttonList:
275                    if button.imageRect.collidepoint(event.pos):
276#                        globalVars.soundPlayer.playSound("click.mp3")
277                        self.mouseDown = True
278                        button.active = True
279                        self.lastClicked = button
280                if currentPuzzle.puzzleState == BBUILDER.VICTORY and currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
281#                    globalVars.soundPlayer.playSound("click.mp3")
282                    self.mouseDown = True
283                    self.lastClicked = currentPuzzle.exitButton
284                       
285            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
286                for button in buttonList:
287                    if button == self.lastClicked:
288                        self.lastClicked.active = False
289                        self.lastClicked = None
290                        if button.imageRect.collidepoint(event.pos):
291                            self.mouseDown = False
292                            button.clicked = False
293                            return "Continue"
294                if currentPuzzle.puzzleState == BBUILDER.VICTORY and currentPuzzle.exitButton == self.lastClicked:
295                    if currentPuzzle.exitButton.imageRect.collidepoint(
296                        event.pos):
297                        self.mouseDown = False
298                        self.transitioning = True
299                        self.manageScoresTransition()
300                self.lastClicked = None
301
302            elif event.type == KEYDOWN:
303                key = pygame.key.name(event.key)
304                if key == "space" or key == "return":
305#                    globalVars.soundPlayer.playSound("click.mp3")
306                    return "Continue"
307
308        return "No"
309       
310    def processBonusEvents(self, currentPuzzle):
311        for event in pygame.event.get():
312            if event.type == QUIT:
313                self.exit()
314                sys.exit()
315            if event.type == MOUSEMOTION:
316                for toggleNum in range(len(currentPuzzle.choiceList)):
317                    toggle = currentPuzzle.choiceList[toggleNum]
318                    toggle.hover = False
319                    toggle.play = False
320                    for rect in toggle.rectList:
321                        if rect.collidepoint(event.pos):
322                            toggle.hover = True
323                            toggle.play = True
324                            currentPuzzle.selectedToggle = toggleNum
325                           
326            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
327                for toggle in currentPuzzle.choiceList:
328                    if not toggle.locked:
329                        for rect in toggle.rectList:
330                            if rect.collidepoint(event.pos):
331                                self.mouseDown = True
332                                self.lastClicked = toggle
333                if currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
334                    self.mouseDown = True
335                    self.lastClicked = currentPuzzle.exitButton
336                       
337            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
338                for toggle in currentPuzzle.choiceList:
339                    if toggle != self.lastClicked:
340                        if toggle.active:
341                            toggle.active = not toggle.active
342                    else:
343                        for rect in toggle.rectList : 
344                            if rect.collidepoint(event.pos):
345                                self.mouseDown = False
346                                if toggle.active:
347                                    valueChange = -1*toggle.value
348                                else: 
349                                    valueChange = toggle.value
350                                    toggle.active = not toggle.active
351                                return valueChange
352                if currentPuzzle.exitButton == self.lastClicked:
353                    if currentPuzzle.exitButton.imageRect.collidepoint(
354                        event.pos):
355                        self.mouseDown = False
356                        self.transitioning = True
357                        self.manageScoresTransition()
358                self.lastClicked = None
359           
360            elif event.type == KEYDOWN:
361                key = pygame.key.name(event.key)
362                if key == "right":
363                    currentPuzzle.selectToggleNext()
364                elif key == "down" or key == "up":
365                    currentPuzzle.selectToggleNext()
366                    currentPuzzle.selectToggleNext()
367                elif key == "left":
368                    currentPuzzle.selectTogglePrev()
369                elif (key == "space" or key == "return") and currentPuzzle.selectedToggle != None:
370#                    globalVars.soundPlayer.playSound("click.mp3")
371                    toggle = currentPuzzle.choiceList[
372                        currentPuzzle.selectedToggle]
373                    if toggle.active:
374                        valueChange = -1*toggle.value
375                    else: valueChange = toggle.value
376                    toggle.active = not toggle.active
377                    return valueChange
378                       
379
380    def processToggleEvents(self, currentPuzzle):
381        """event reader for actually playing the game (mode is Puzzle)
382            returns change in currentcount, else 0"""
383        for event in pygame.event.get():
384            if event.type == QUIT:
385                self.exit()
386                sys.exit()
387            if event.type == MOUSEMOTION:
388                for toggleNum in range(len(currentPuzzle.toggleList)):
389                    toggle = currentPuzzle.toggleList[toggleNum]
390                    toggle.hover = False
391                    toggle.play = False
392                    for rect in toggle.rectList : 
393                        if rect.collidepoint(event.pos):
394                            currentPuzzle.selectedToggle = toggleNum
395                            toggle.hover = True
396                            toggle.play = True
397                exitButton = currentPuzzle.exitButton
398                exitButton.hover = False
399                exitButton.play = False
400                if exitButton.imageRect.collidepoint(event.pos):
401                    exitButton.hover = True
402                    exitButton.play = True
403                           
404               
405
406            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
407                for toggle in currentPuzzle.toggleList:
408                    for rect in toggle.rectList : 
409                        if rect.collidepoint(event.pos):
410    #                        globalVars.soundPlayer.playSound("click.mp3")
411                            self.mouseDown = True
412                            self.lastClicked = toggle
413                if currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
414#                    globalVars.soundPlayer.playSound("click.mp3")
415                    self.mouseDown = True
416                    self.lastClicked = currentPuzzle.exitButton
417                       
418            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
419                for toggle in currentPuzzle.toggleList:
420                    if toggle == self.lastClicked:
421                        for rect in toggle.rectList : 
422                            if rect.collidepoint(event.pos):
423                                self.mouseDown = False
424                                if toggle.active and not toggle.locked:
425                                    valueChange = -1*toggle.value
426                                    toggle.active = not toggle.active
427                                elif not toggle.active and currentPuzzle.usedOnes < currentPuzzle.totalOnes:
428                                    valueChange = toggle.value
429                                    toggle.active = not toggle.active
430                                    if currentPuzzle.mode == BBUILDER.STORY:
431                                        currentPuzzle.usedOnes += 1
432                                else:
433                                    valueChange = 0
434                               
435                                return valueChange
436                if currentPuzzle.exitButton == self.lastClicked:
437                    if currentPuzzle.exitButton.imageRect.collidepoint(
438                        event.pos):
439                        self.mouseDown = False
440                        self.transitioning = True
441                        self.manageScoresTransition()
442                self.lastClicked = None
443               
444            elif event.type == KEYDOWN:
445                key = pygame.key.name(event.key)
446                if key == "up" or key == "left":
447                    currentPuzzle.selectToggleNext()
448                elif key == "down" or key == "right":
449                    currentPuzzle.selectTogglePrev()
450                elif (key == "space" or key == "return") and currentPuzzle.selectedToggle != None:
451#                    globalVars.soundPlayer.playSound("click.mp3")
452                    toggle = currentPuzzle.toggleList[
453                        currentPuzzle.selectedToggle]
454                    if toggle.active and not toggle.locked:
455                        valueChange = -1*toggle.value
456                        toggle.active = not toggle.active
457                    elif not toggle.active and currentPuzzle.usedOnes < currentPuzzle.totalOnes:
458                        valueChange = toggle.value
459                        toggle.active = not toggle.active
460                        if currentPuzzle.mode == BBUILDER.STORY:
461                            currentPuzzle.usedOnes += 1
462                    else:
463                        valueChange = 0
464                    return valueChange
465        return 0
466
467    def processInput(self):
468        """processInput reads the necessary input for the input mode.
469            If needed, it will change self.dest in order to change the page"""
470        self.timer += 1
471        currentPage = globalVars.menuHandler.pageLibrary[globalVars.menuHandler.currentPage]
472        for event in pygame.event.get():
473            if event.type == QUIT:
474                self.exit()
475                sys.exit()
476               
477            elif event.type == MOUSEMOTION:
478                for buttonNum in range(len(currentPage.menuButtonList)):
479                    button = currentPage.menuButtonList[buttonNum]
480                    button.hover = False
481                    button.play = False
482                    if button.imageRect.collidepoint(event.pos):
483                        button.hover = True
484                        button.play = True
485                        currentPage.selectedButton = buttonNum
486           
487            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
488                for button in currentPage.menuButtonList:
489                    if button.imageRect.collidepoint(event.pos):
490#                        globalVars.soundPlayer.playSound("click.mp3")
491                        self.mouseDown = True
492                        button.active = True
493                        self.lastClicked = button
494                       
495            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
496                for button in currentPage.menuButtonList:
497                    if button == self.lastClicked:
498                        self.lastClicked.active = False
499                        if button.imageRect.collidepoint(event.pos):
500                            self.mouseDown = False
501                            button.clicked = False
502                            # Special case for empty input string
503                            if currentPage.inputStr != "" or button.dest == "page0":
504                                self.dest = button.dest
505                            else:
506                                currentPage.textList[4].text = "Please type a name"
507                self.lastClicked = None
508               
509            elif event.type == KEYDOWN:
510                key = pygame.key.name(event.key)
511                if len(key) == 1 or key == "space" or key == "backspace":
512                    caps = pygame.key.get_mods() & (KMOD_CAPS | KMOD_LSHIFT | KMOD_RSHIFT)
513                    currentPage.updateInput(key, caps)
514                elif key == "return":
515                    if currentPage.selectedButton != None:
516#                        globalVars.soundPlayer.playSound("click.mp3")
517                        button = currentPage.menuButtonList[currentPage.selectedButton]
518                        if currentPage.inputStr != "":
519                            self.dest = button.dest
520                            button.clicked = False
521                            self.mouseDown = False
522                            if self.lastClicked != None:
523                                self.lastClicked.active = False
524                        else:
525                            currentPage.textList[4].text = "Please type a name"
526                   
527    def manageTransition(self):
528        if self.transition.isInactive():
529            self.transition.setTransition(BubbleBackground(globalVars.screen, 0, 1))
530            self.transition.incrementTimer()
531            return False
532        elif not self.transition.isInactive() and self.transition.timer == 30:
533            self.transition.drawBackground()
534            if self.game == None and self.mode == BBUILDER.STORY:
535                self.game = Story(self.difficulty)
536            elif self.game == None and self.mode == BBUILDER.SURVIVAL:
537                self.game = Survival(self.difficulty)
538            self.game.draw()
539            self.transition.update(False)
540            self.transition.incrementTimer()
541            return False
542        elif not self.transition.isInactive() and self.transition.timer == 60:
543            self.transition.resetTimer()
544            self.transition.resetTransition()
545            pygame.event.clear()
546            return True
547        elif not self.transition.isInactive() and self.transition.timer != 60:
548            self.transition.drawBackground()
549            if self.game != None:
550                self.game.draw()
551            else:
552                globalVars.menuHandler.draw()
553            self.transition.update(False)   
554            self.transition.incrementTimer()
555            pygame.event.clear()
556            return False
557           
558    def manageScoresTransition(self):
559        if self.transition.isInactive():
560            self.transition.setTransition(BubbleBackground(globalVars.screen, 0, 1))
561            self.transition.incrementTimer()
562            return False
563        elif not self.transition.isInactive() and self.transition.timer == 30:
564            self.transition.drawBackground()
565            self.game.exit = True
566            self.game.draw()
567            self.transition.update(False)
568            self.transition.incrementTimer()
569            return False
570        elif not self.transition.isInactive() and self.transition.timer == 60:
571            self.transition.resetTimer()
572            self.transition.resetTransition()
573            pygame.event.clear()
574            return True
575        elif not self.transition.isInactive() and self.transition.timer != 60:
576            self.transition.drawBackground()
577            if self.transition.timer < 30:
578                self.game.draw()
579            else:
580                globalVars.menuHandler.draw()
581            self.transition.update(False)   
582            self.transition.incrementTimer()
583            pygame.event.clear()
584            return False
585       
586   
587    def exit(self):
588        """exit is called at the end to close stuff nicely"""
589        pygame.quit()
590        self.running = False
591       
Note: See TracBrowser for help on using the browser.