root/src/eventhandler.py @ 267

Revision 267, 26.9 KB (checked in by andefodahl, 23 months ago)

Hopefully revamped hover system

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                    if button.imageRect.collidepoint(event.pos):
183                        currentPage.changeButton(buttonNum)
184                       
185            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
186                for button in visibleButtons:
187                    if button.imageRect.collidepoint(event.pos):
188#                        globalVars.soundPlayer.playSound("click.mp3")
189                        self.mouseDown = True
190                        button.active = True
191                        self.lastClicked = button
192                for clickableObject in currentPage.clickableObjects:
193                    if clickableObject.imageRect.collidepoint(event.pos):
194                        self.mouseDown = True
195                        self.lastClicked = clickableObject
196                       
197            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
198                for button in visibleButtons:
199                    if button == self.lastClicked:
200                        self.lastClicked.active = False
201                        if button.imageRect.collidepoint(event.pos):
202                            self.mouseDown = False
203                            button.clicked = False
204                            if globalVars.menuHandler.transition.isInactive():
205                                self.dest = button.dest
206                for clickableObject in currentPage.clickableObjects:
207                    if clickableObject == self.lastClicked:
208                        if clickableObject.imageRect.collidepoint(event.pos):
209                            clickableObject.clicked()
210                            self.mouseDown = False
211                self.lastClicked = None
212               
213            elif event.type == KEYDOWN:
214                key = pygame.key.name(event.key)
215                if key == "up" or key == "left":
216                    currentPage.selectButton(BBUILDER.BUTTON_PREV)
217                elif key == "down" or key == "right":
218                    currentPage.selectButton(BBUILDER.BUTTON_NEXT)
219                elif (key == "space" or key == "return") and currentPage.selectedButton != None:
220#                    globalVars.soundPlayer.playSound("click.mp3")
221                    self.dest = currentPage.selectedButton.dest
222
223    def processGameEvents(self):
224        """processGameEvents calls the appropriate processing function
225            based on the state of the game. Returns the change in value
226            from toggling blocks"""
227        #Sets currentPuzzles based on mode
228        if self.mode == BBUILDER.STORY:
229            currentPuzzle = self.game.levelDict[
230                self.game.currentLevel].currentPuzzle
231        elif self.mode == BBUILDER.SURVIVAL or self.mode == BBUILDER.BONUS:
232            currentPuzzle = self.game.currentPuzzle
233
234        curState = currentPuzzle.puzzleState
235           
236        if curState == BBUILDER.PUZZLE:
237            return self.processToggleEvents(currentPuzzle)
238        if curState == BBUILDER.INTRO or  curState == BBUILDER.END or curState == BBUILDER.VICTORY:
239            return self.processGameMenuEvents(currentPuzzle)
240        elif curState == BBUILDER.BONUS:
241            return self.processBonusEvents(currentPuzzle)
242        elif curState == BBUILDER.BONUS_INTRO:
243            return self.processGameMenuEvents(self.game.levelDict[
244                self.game.currentLevel])
245           
246
247    def processGameMenuEvents(self, currentPuzzle):
248        """event reader for game menus (if mode is not Puzzle)
249            returns 'Continue' if button is clicked, else 'No'"""
250        if currentPuzzle.puzzleState == BBUILDER.INTRO or currentPuzzle.puzzleState == BBUILDER.BONUS_INTRO:
251            buttonList = currentPuzzle.introButtons
252        elif currentPuzzle.puzzleState == BBUILDER.VICTORY:
253            buttonList = currentPuzzle.victoryButtons
254        else:
255            buttonList = currentPuzzle.endButtons
256
257        for event in pygame.event.get():
258            if event.type == QUIT:
259                self.exit()
260                sys.exit()
261            if event.type == MOUSEMOTION:
262                for button in buttonList:
263                    button.hover = False
264                    button.play = False
265                    if button.imageRect.collidepoint(event.pos):
266                        button.hover = True
267                        button.play = True
268                       
269            if event.type == MOUSEBUTTONDOWN and event.button == 1:
270                for button in buttonList:
271                    if button.imageRect.collidepoint(event.pos):
272#                        globalVars.soundPlayer.playSound("click.mp3")
273                        self.mouseDown = True
274                        button.active = True
275                        self.lastClicked = button
276                if currentPuzzle.puzzleState == BBUILDER.VICTORY and currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
277#                    globalVars.soundPlayer.playSound("click.mp3")
278                    self.mouseDown = True
279                    self.lastClicked = currentPuzzle.exitButton
280                       
281            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
282                for button in buttonList:
283                    if button == self.lastClicked:
284                        self.lastClicked.active = False
285                        self.lastClicked = None
286                        if button.imageRect.collidepoint(event.pos):
287                            self.mouseDown = False
288                            button.clicked = False
289                            return "Continue"
290                if currentPuzzle.puzzleState == BBUILDER.VICTORY and currentPuzzle.exitButton == self.lastClicked:
291                    if currentPuzzle.exitButton.imageRect.collidepoint(
292                        event.pos):
293                        self.mouseDown = False
294                        self.transitioning = True
295                        self.manageScoresTransition()
296                self.lastClicked = None
297
298            elif event.type == KEYDOWN:
299                key = pygame.key.name(event.key)
300                if key == "space" or key == "return":
301#                    globalVars.soundPlayer.playSound("click.mp3")
302                    return "Continue"
303
304        return "No"
305       
306    def processBonusEvents(self, currentPuzzle):
307        for event in pygame.event.get():
308            if event.type == QUIT:
309                self.exit()
310                sys.exit()
311            if event.type == MOUSEMOTION:
312                for toggleNum in range(len(currentPuzzle.choiceList)):
313                    toggle = currentPuzzle.choiceList[toggleNum]
314                    for rect in toggle.rectList:
315                        if rect.collidepoint(event.pos):
316                            currentPuzzle.selectedToggle = toggleNum
317                           
318            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
319                for toggle in currentPuzzle.choiceList:
320                    if not toggle.locked:
321                        for rect in toggle.rectList:
322                            if rect.collidepoint(event.pos):
323                                self.mouseDown = True
324                                self.lastClicked = toggle
325                if currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
326                    self.mouseDown = True
327                    self.lastClicked = currentPuzzle.exitButton
328                       
329            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
330                for toggle in currentPuzzle.choiceList:
331                    if toggle != self.lastClicked:
332                        if toggle.active:
333                            toggle.active = not toggle.active
334                    else:
335                        for rect in toggle.rectList : 
336                            if rect.collidepoint(event.pos):
337                                self.mouseDown = False
338                                if toggle.active:
339                                    valueChange = -1*toggle.value
340                                else: 
341                                    valueChange = toggle.value
342                                    toggle.active = not toggle.active
343                                return valueChange
344                if currentPuzzle.exitButton == self.lastClicked:
345                    if currentPuzzle.exitButton.imageRect.collidepoint(
346                        event.pos):
347                        self.mouseDown = False
348                        self.transitioning = True
349                        self.manageScoresTransition()
350                self.lastClicked = None
351           
352            elif event.type == KEYDOWN:
353                key = pygame.key.name(event.key)
354                if key == "right":
355                    currentPuzzle.selectToggleNext()
356                elif key == "down" or key == "up":
357                    currentPuzzle.selectToggleNext()
358                    currentPuzzle.selectToggleNext()
359                elif key == "left":
360                    currentPuzzle.selectTogglePrev()
361                elif (key == "space" or key == "return") and currentPuzzle.selectedToggle != None:
362#                    globalVars.soundPlayer.playSound("click.mp3")
363                    toggle = currentPuzzle.choiceList[
364                        currentPuzzle.selectedToggle]
365                    if toggle.active:
366                        valueChange = -1*toggle.value
367                    else: valueChange = toggle.value
368                    toggle.active = not toggle.active
369                    return valueChange
370                       
371
372    def processToggleEvents(self, currentPuzzle):
373        """event reader for actually playing the game (mode is Puzzle)
374            returns change in currentcount, else 0"""
375        for event in pygame.event.get():
376            if event.type == QUIT:
377                self.exit()
378                sys.exit()
379            if event.type == MOUSEMOTION:
380                for toggleNum in range(len(currentPuzzle.toggleList)):
381                    toggle = currentPuzzle.toggleList[toggleNum]
382                    for rect in toggle.rectList : 
383                        if rect.collidepoint(event.pos):
384                            currentPuzzle.selectedToggle = toggleNum
385                exitButton = currentPuzzle.exitButton
386                exitButton.hover = False
387                exitButton.play = False
388                if exitButton.imageRect.collidepoint(event.pos):
389                    exitButton.hover = True
390                    exitButton.play = True
391                           
392               
393
394            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
395                for toggle in currentPuzzle.toggleList:
396                    for rect in toggle.rectList : 
397                        if rect.collidepoint(event.pos):
398    #                        globalVars.soundPlayer.playSound("click.mp3")
399                            self.mouseDown = True
400                            self.lastClicked = toggle
401                if currentPuzzle.exitButton.imageRect.collidepoint(event.pos):
402#                    globalVars.soundPlayer.playSound("click.mp3")
403                    self.mouseDown = True
404                    self.lastClicked = currentPuzzle.exitButton
405                       
406            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
407                for toggle in currentPuzzle.toggleList:
408                    if toggle == self.lastClicked:
409                        for rect in toggle.rectList : 
410                            if rect.collidepoint(event.pos):
411                                self.mouseDown = False
412                                if toggle.active and not toggle.locked:
413                                    valueChange = -1*toggle.value
414                                    toggle.active = not toggle.active
415                                elif not toggle.active and currentPuzzle.usedOnes < currentPuzzle.totalOnes:
416                                    valueChange = toggle.value
417                                    toggle.active = not toggle.active
418                                    if currentPuzzle.mode == BBUILDER.STORY:
419                                        currentPuzzle.usedOnes += 1
420                                else:
421                                    valueChange = 0
422                               
423                                return valueChange
424                if currentPuzzle.exitButton == self.lastClicked:
425                    if currentPuzzle.exitButton.imageRect.collidepoint(
426                        event.pos):
427                        self.mouseDown = False
428                        self.transitioning = True
429                        self.manageScoresTransition()
430                self.lastClicked = None
431               
432            elif event.type == KEYDOWN:
433                key = pygame.key.name(event.key)
434                if key == "up" or key == "left":
435                    currentPuzzle.selectToggleNext()
436                elif key == "down" or key == "right":
437                    currentPuzzle.selectTogglePrev()
438                elif (key == "space" or key == "return") and currentPuzzle.selectedToggle != None:
439#                    globalVars.soundPlayer.playSound("click.mp3")
440                    toggle = currentPuzzle.toggleList[
441                        currentPuzzle.selectedToggle]
442                    if toggle.active and not toggle.locked:
443                        valueChange = -1*toggle.value
444                        toggle.active = not toggle.active
445                    elif not toggle.active and currentPuzzle.usedOnes < currentPuzzle.totalOnes:
446                        valueChange = toggle.value
447                        toggle.active = not toggle.active
448                        if currentPuzzle.mode == BBUILDER.STORY:
449                            currentPuzzle.usedOnes += 1
450                    else:
451                        valueChange = 0
452                    return valueChange
453        return 0
454
455    def processInput(self):
456        """processInput reads the necessary input for the input mode.
457            If needed, it will change self.dest in order to change the page"""
458        self.timer += 1
459        currentPage = globalVars.menuHandler.pageLibrary[globalVars.menuHandler.currentPage]
460        for event in pygame.event.get():
461            if event.type == QUIT:
462                self.exit()
463                sys.exit()
464               
465            if event.type == MOUSEMOTION:
466                for buttonNum in range(len(currentPage.menuButtonList)):
467                    button = currentPage.menuButtonList[buttonNum]
468                    if button.imageRect.collidepoint(event.pos):
469                        currentPage.changeButton(buttonNum)
470           
471            elif event.type == MOUSEBUTTONDOWN and event.button == 1:
472                for button in currentPage.menuButtonList:
473                    if button.imageRect.collidepoint(event.pos):
474#                        globalVars.soundPlayer.playSound("click.mp3")
475                        self.mouseDown = True
476                        button.active = True
477                        self.lastClicked = button
478                       
479            elif event.type == MOUSEBUTTONUP and self.mouseDown == True:
480                for button in currentPage.menuButtonList:
481                    if button == self.lastClicked:
482                        self.lastClicked.active = False
483                        if button.imageRect.collidepoint(event.pos):
484                            self.mouseDown = False
485                            button.clicked = False
486                            # Special case for empty input string
487                            if currentPage.inputStr != "" or button.dest == "page0":
488                                self.dest = button.dest
489                            else:
490                                currentPage.textList[4].text = "Please type a name"
491                self.lastClicked = None
492               
493            elif event.type == KEYDOWN:
494                key = pygame.key.name(event.key)
495                if len(key) == 1 or key == "space" or key == "backspace":
496                    caps = pygame.key.get_mods() & (KMOD_CAPS | KMOD_LSHIFT | KMOD_RSHIFT)
497                    currentPage.updateInput(key, caps)
498                elif key == "return":
499                    if currentPage.selectedButton != None:
500#                        globalVars.soundPlayer.playSound("click.mp3")
501                        button = currentPage.menuButtonList[currentPage.selectedButton]
502                        if currentPage.inputStr != "":
503                            self.dest = button.dest
504                            button.clicked = False
505                            self.mouseDown = False
506                            if self.lastClicked != None:
507                                self.lastClicked.active = False
508                        else:
509                            currentPage.textList[4].text = "Please type a name"
510                   
511    def manageTransition(self):
512        if self.transition.isInactive():
513            self.transition.setTransition(BubbleBackground(globalVars.screen, 0, 1))
514            self.transition.incrementTimer()
515            return False
516        elif not self.transition.isInactive() and self.transition.timer == 30:
517            self.transition.drawBackground()
518            if self.game == None and self.mode == BBUILDER.STORY:
519                self.game = Story(self.difficulty)
520            elif self.game == None and self.mode == BBUILDER.SURVIVAL:
521                self.game = Survival(self.difficulty)
522            self.game.draw()
523            self.transition.update(False)
524            self.transition.incrementTimer()
525            return False
526        elif not self.transition.isInactive() and self.transition.timer == 60:
527            self.transition.resetTimer()
528            self.transition.resetTransition()
529            pygame.event.clear()
530            return True
531        elif not self.transition.isInactive() and self.transition.timer != 60:
532            self.transition.drawBackground()
533            if self.game != None:
534                self.game.draw()
535            else:
536                globalVars.menuHandler.draw()
537            self.transition.update(False)   
538            self.transition.incrementTimer()
539            pygame.event.clear()
540            return False
541           
542    def manageScoresTransition(self):
543        if self.transition.isInactive():
544            self.transition.setTransition(BubbleBackground(globalVars.screen, 0, 1))
545            self.transition.incrementTimer()
546            return False
547        elif not self.transition.isInactive() and self.transition.timer == 30:
548            self.transition.drawBackground()
549            self.game.exit = True
550            self.game.draw()
551            self.transition.update(False)
552            self.transition.incrementTimer()
553            return False
554        elif not self.transition.isInactive() and self.transition.timer == 60:
555            self.transition.resetTimer()
556            self.transition.resetTransition()
557            pygame.event.clear()
558            return True
559        elif not self.transition.isInactive() and self.transition.timer != 60:
560            self.transition.drawBackground()
561            if self.transition.timer < 30:
562                self.game.draw()
563            else:
564                globalVars.menuHandler.draw()
565            self.transition.update(False)   
566            self.transition.incrementTimer()
567            pygame.event.clear()
568            return False
569       
570   
571    def exit(self):
572        """exit is called at the end to close stuff nicely"""
573        pygame.quit()
574        self.running = False
575       
Note: See TracBrowser for help on using the browser.