import pygame, sys, os from pygame.locals import * from eduGames import * import random class Paint(Game): (INITIAL, WAITING, BAD_CHOICE, GOOD_CHOICE, WAITING_PAINT, PAINTING, END) = (0,1,2,3,4,5, 6) def __init__(self, screen, uiMgr, sndMgr, screenMgr, path): Game.__init__(self, screen, uiMgr, sndMgr, screenMgr, path) self.finished = False self.puzzleElements = None self.paintBoxes = None self.currentElementIndex = 0 self.state = Paint.INITIAL self.puzzleElementControls = None self.selectedColor = "" self.soundIcon = None self.soundsDir = "" #set later by the Games class self.xMargin = 0 self.yMargin = 0 self.masterResourcesDir = None self.brush = None self.fakeMouse = None self.isHelp = False self.onNavigationPortion = False self.xStartBrushZone = 0 self.yStartBrushZone = 0 self.xEndBrushZone = 1030 + self.xMargin self.yEndBrushZone = 0 def getCurrentPuzzleElement(self): return self.puzzleElements[self.currentElementIndex] def getCurrentPuzzleElementControl(self): return self.puzzleElements[self.currentElementIndex].control def pause(self): self.getUiMgr().removeControl(self.brush) pygame.mouse.set_visible(True) def unPause(self): self.getUiMgr().addControl(self.brush) pygame.mouse.set_visible(False) def initializeGameData(self): self.brush = Brush(self, "") self.alert = os.path.join(self.soundsDir, "chord.ogg") self.ding = os.path.join(self.soundsDir, "ding.ogg") (self.puzzleElements, self.paintBoxes, backgroundPath, backgroundX, backgroundY) = self.readInfo() self.showElements() self.showPaintBoxes() if backgroundPath != "": self.showBackgroundImage(backgroundPath, backgroundX, backgroundY) fakeMouse = [c for c in self.getUiMgr().controls if c.type == "fakeMouse"] self.fakeMouse = None if not len(fakeMouse) == 0: self.fakeMouse = fakeMouse[0] self.brush.trackControl(self.fakeMouse) self.fakeMouse.setLayer(20) self.getUiMgr().addControl(self.brush) if not self.isHelp: pygame.mouse.set_visible(False) def showBackgroundImage(self, backgroundPath, x, y): path = os.path.join(self.resourcesDir, backgroundPath) ic = ImageControl(self, x, y, path, "", 1) ic.setLayer(9) self.getUiMgr().addControl(ic) def getShuffledElements(self): shuffledElements = [] for element in self.puzzleElements: shuffledElements.append(element) random.shuffle(shuffledElements) return shuffledElements def showElements(self): shuffledElements = self.getShuffledElements() x = self.settings["xFirstElement"] + self.xMargin y = self.settings["yFirstElement"] + self.yMargin distanceBetweenElements = -1 if self.settings.has_key("distanceBetweenElements"): distanceBetweenElements = self.settings["distanceBetweenElements"] self.puzzleElementControls = [] counter = 1 for element in shuffledElements: if counter > self.settings["elementsPerRow"] and counter % self.settings["elementsPerRow"] == 1: xLastRow = self.settings["xFirstElementLastRow"] + self.xMargin x = xLastRow y = y + self.settings["spaceBetweenRows"] if element.x > -1: x = element.x y = element.y ic = ImageControl(self, x, y, os.path.join(self.resourcesDir, element.image), "", element.getNumberOfStates()) ic.setLayer(6) ic.type = "drawing" ic.setAsUnclickable() element.control = ic if distanceBetweenElements > -1: x += distanceBetweenElements else: x += ic.getWidth() self.getUiMgr().addControl(ic) self.puzzleElementControls.append(ic) counter += 1 def showPaintBoxes(self): x = self.settings["paintBoxesX"] + self.xMargin y = self.settings["paintBoxesY"] + self.yMargin watercolor = ImageControl(self, x, y, os.path.join(self.masterResourcesDir, "_acuarelas.png")) watercolor.setLayer(5) self.soundIcon = GrowsAndShrinksAnimatedControl(self, self.settings["soundIconX"] + self.xMargin, self.settings["soundIconY"] + self.yMargin, os.path.join(self.masterResourcesDir, "sound.png"), "", 2) self.soundIcon.setLayer(5) self.soundIcon.type = "soundIcon" self.getUiMgr().addControl(watercolor) self.getUiMgr().addControl(self.soundIcon) x = self.settings["paintBoxesX"] + self.xMargin + 75 y = self.settings["paintBoxesY"] + self.yMargin + 25 for element in self.paintBoxes: ic = Control(self, x, y, 50, 50) ic.color = element ic.setLayer(4) ic.type = "paint" x += 7 + ic.getWidth() self.getUiMgr().addControl(ic) self.yEndBrushZone = watercolor.getY() + watercolor.getHeight() def readInfo(self): fileName = os.path.join(self.path, self.settings["infoFile"]) file = open(fileName, "r") fileText = file.read() reader = ScreensReader() file.close() return reader.read(fileText) def on_mouse_hover(self, clickedControl): if clickedControl == self.soundIcon: self.soundIcon.setImageDivisionIndex(1) self.onNavigationPortion = True else: if self.soundIcon.getImageDivisionIndex() == 1: #might improve performance. self.soundIcon.setImageDivisionIndex(0) mousePos = pygame.mouse.get_pos() mousePosX = mousePos[0] mousePosY = mousePos[1] if mousePosX < self.xStartBrushZone or mousePosY < self.yStartBrushZone or mousePosX > self.xEndBrushZone or mousePosY > self.yEndBrushZone: self.onNavigationPortion = True else: self.onNavigationPortion = False try: if self.onNavigationPortion: if self.brush.isVisible(): self.brush.makeInvisible() else: if not self.brush.isVisible(): self.brush.makeVisible() except: pass def on_mouse_button_down(self, clickedControl): if self.state == Paint.WAITING: if clickedControl.type == "paint": self.selectedColor = clickedControl.color elif clickedControl == self.soundIcon: self.state = Paint.INITIAL if self.state == Paint.WAITING_PAINT: if clickedControl.type == "drawing" and clickedControl is self.getCurrentPuzzleElementControl(): self.state = Paint.PAINTING self.playSoundSequentially(self.ding) else: self.playSound(self.alert) def paintCurrentElement(self): self.getCurrentPuzzleElementControl().setImageDivisionIndex(self.getCurrentPuzzleElement().getCurrentIndex()+1) def playSoundSequentially(self, sound): self.getSoundMgr().addSoundForPlayback(sound, False, True) def playSound(self, sound): self.getSoundMgr().addSoundForPlayback(sound) def updateState(self): mouseVisible = self.isHelp or self.isPaused or self.onNavigationPortion pygame.mouse.set_visible(mouseVisible) if self.state == Paint.INITIAL: soundPath = os.path.join(self.soundsDir, self.getCurrentPuzzleElement().currentAudio()) self.getSoundMgr().addSoundForPlayback(soundPath) self.soundIcon.delay = 15 self.soundIcon.playAnimation() self.soundIcon.stopAnimation() self.state = Paint.WAITING currentControl = self.getCurrentPuzzleElementControl() currentControl.setAsClickable() return if self.state == Paint.WAITING: #Actually two states: with and without a selected color. if self.selectedColor != "": if self.selectedColor == self.getCurrentPuzzleElement().currentColor(): self.state = Paint.GOOD_CHOICE self.getUiMgr().removeControl(self.brush) self.brush = Brush(self, self.selectedColor, self.fakeMouse) self.getUiMgr().addControl(self.brush) else: self.state = Paint.BAD_CHOICE self.selectedColor = "" return if self.state == Paint.BAD_CHOICE: self.playSound(self.alert) self.state = Paint.WAITING return if self.state == Paint.GOOD_CHOICE: self.playSound(self.ding) self.state = Paint.WAITING_PAINT return if self.state == Paint.PAINTING: self.paintCurrentElement() self.getCurrentPuzzleElement().moveOn() self.getUiMgr().removeControl(self.brush) self.brush = Brush(self) self.brush.trackControl(self.fakeMouse) self.getUiMgr().addControl(self.brush) self.state = Paint.INITIAL if self.getCurrentPuzzleElement().solved(): self.getCurrentPuzzleElementControl().setAsUnclickable() self.currentElementIndex += 1 if self.currentElementIndex >= len(self.puzzleElements): self.state = Paint.END return if self.state == Paint.END: self.finished = True if not self.fakeMouse: pygame.mouse.set_visible(True) if not self.isHelp: self.saveAsDone() return def endGame(self): self.finished = True if not self.fakeMouse: pygame.mouse.set_visible(True) class ScreensReader: def read(self, text): lines = text.splitlines() self.elements = [] self.paintCollection = [] self.backgroundPath = "" self.backgroundX = 0 self.backgroundY = 0 state = "initial" for line in lines: if line.strip() != "" and not line.startswith("#"): if line.strip() == "paint:": state = "paint" continue if line.strip() == "elements:": state = "elements" continue if line.strip().startswith("background"): state = "background" info = line.split(":")[1].strip() infoPieces = info.split() self.backgroundPath = infoPieces[0] self.backgroundX = int(infoPieces[1]) self.backgroundY = int(infoPieces[2]) if state == "paint": self.paintCollection.append(line.strip()) if state == "elements": elemData = line.split() element = PaintPuzzleItem(elemData[0]) counter = 1 while(counter < len(elemData)): if not elemData[counter].isdigit(): part = PaintPuzzlePart(elemData[counter], elemData[counter+1]) element.parts.append(part) else: element.x = int(elemData[counter]) element.y = int(elemData[counter+1]) counter = counter + 2 self.elements.append(element) return (self.elements, self.paintCollection, self.backgroundPath, self.backgroundX, self.backgroundY) class PaintPuzzleItem: def __init__(self, image): self.image = image self.parts = [] self.__currentIndex = 0 self.x = -1 self.y = -1 def getNumberOfStates(self): return len(self.parts) + 1 def getCurrentIndex(self): return self.__currentIndex def moveOn(self): self.__currentIndex = self.__currentIndex + 1 def solved(self): return self.__currentIndex == len(self.parts) def currentAudio(self): return self.parts[self.__currentIndex].audio def currentColor(self): return self.parts[self.__currentIndex].color class PaintPuzzlePart: def __init__(self, audio, color): self.audio = audio self.color = color class Brush(ImageControl): def __init__(self, game, color="", controlToTrack=None): if color == "": imageFilePath = os.path.join(game.masterResourcesDir, "pincel.png") else: imageFilePath = os.path.join(game.masterResourcesDir, "pincel_" + color + ".png") if controlToTrack is None: (mouseX, mouseY) = pygame.mouse.get_pos() else: (mouseX, mouseY) = (controlToTrack.getX(), controlToTrack.getY()) ImageControl.__init__(self, game, mouseX, mouseY, imageFilePath, "", 1) self.__controlToTrack = controlToTrack def update(self): if self.getLayer() != 0: self.setLayer(0) ImageControl.update(self) if not self.__controlToTrack: (mouseX, mouseY) = pygame.mouse.get_pos() else: mouseX = self.__controlToTrack.getX() mouseY = self.__controlToTrack.getY() self.setX(mouseX) self.setY(mouseY) def isClickable(self): return False def trackControl(self, controlToTrack): self.__controlToTrack = controlToTrack def stopTrackingControl(self): self.__controlToTrack = None