import pygame, sys, os from pygame.locals import * from eduGames import * from pygame.font import * class DragnDrop(Game): def __init__(self, screen, uiMgr, sndMgr, screenMgr, path): Game.__init__(self, screen, uiMgr, sndMgr, screenMgr, path) self.binControls = [] #necessary only to place crayons in their places self.solvedItems = 0 self.finished = False self.hoveredOnControl = None self.soundsDir = "" self.fakeMouse = None #used in demo self.xo = None #idem self.xMargin = 0 self.yMargin = 0 self.isHelp = False self.successSound = "" try: self.maxX = self.settings["gameAreaMaxX"] self.minX = self.settings["gameAreaMinX"] self.maxY = self.settings["gameAreaMaxY"] self.minY = self.settings["gameAreaMinY"] except: self.maxX = screen.get_width() self.maxY = screen.get_height() self.minX = 0 self.minY = 0 def initializeGameData(self): self.alert = os.path.join(self.soundsDir, "chord.ogg") (self.screens, self.bins) = self.readInfo() self.currentScreenIndex = -1 self.moveToNextScreen = True self.createBinObjects() fakeMouse = [c for c in self.getUiMgr().controls if c.type == "fakeMouse"] if not len(fakeMouse) == 0: self.fakeMouse = fakeMouse[0] #self.xo = ImageControl(self, 500 + self.xMargin, 300 + self.yMargin, os.path.join(self.resourcesDir, "xo.png"), "", 2) #self.xo.setColorKey((255,255,255)) self.successSound = os.path.join(self.soundsDir, "bing.ogg") def showCurrentScreen(self): self.solvedItems = 0 self.getUiMgr().deleteGameControls(self) self.createCrayons() self.addBinObjects() self.moveToNextScreen= False if self.xo: self.getUiMgr().addControl(self.xo) def addBinObjects(self): for ctrl in self.binControls: self.getUiMgr().addControl(ctrl) def createBinObjects(self): x = self.settings["leftMargin"] + self.xMargin y = self.settings["yOddBins"] + self.yMargin for bin in self.bins: #binObj = ImageControl(self, x, y, bin.image, "", imageDivisions = 6) binObj = HighlightedControl(self, x, y, bin.image, "", 1) binObj.bin = bin binObj.type = "bin" binObj.setLayer(5) self.binControls.append(binObj) x = x + binObj.getWidth() + self.settings["spaceBetweenBins"] if y == self.settings["yOddBins"] + self.yMargin: y = self.settings["yEvenBins"] + self.yMargin else: y = self.settings["yOddBins"] + self.yMargin def createCrayons(self): fontPath = os.path.join(self.resourcesDir, "Helvetica LT Condensed Black.ttf") font = Font(fontPath, 30) y = self.settings["yOddCrayons"] + self.yMargin tieCrayonsToBins = True distanceBetweenCrayons = 40 if self.settings.has_key("xFirstCrayon"): x = self.settings["xFirstCrayon"] tieCrayonsToBins = False if self.settings.has_key("distanceBetweenCrayons"): distanceBetweenCrayons = self.settings["distanceBetweenCrayons"] counter = 0 for crayon in self.screens[self.currentScreenIndex]: if tieCrayonsToBins: x = self.binControls[counter].getX() + self.binControls[counter].getWidth()/2 else: if counter > 0: x = x + distanceBetweenCrayons crayonObj = HighlightedControl(self, x, y, crayon.image, crayon.audio, 1) crayonObj.type = "crayon" crayonObj.crayon = crayon crayonObj.setLayer(4) crayonObj.originalPosition = (x,y) if self.fakeMouse: crayonObj.setDemoMode(self.fakeMouse) txt = crayon.text letterWidth = 14 if self.settings.has_key("letterWidth"): letterWidth = self.settings["letterWidth"] xText = crayonObj.getX() + crayonObj.getWidth()/2 - len(txt)*(letterWidth/2) labelWidth = 20 if self.settings.has_key("useCenterOfCrayonForText"): if self.settings["useCenterOfCrayonForText"]: xText = crayonObj.getX() + crayonObj.getWidth()/2 - len(txt)*(letterWidth/2) yText = crayonObj.getY() + crayonObj.getHeight() text = Label(self, xText, yText, labelWidth, 10, font, txt, 5) text.color = (0,0,0) text.background = None crayonObj.label = text self.getUiMgr().addControl(text) self.getUiMgr().addControl(crayonObj) counter = counter + 1 def readInfo(self): fileName = os.path.join(self.path, self.settings["infoFile"]) file = open(fileName, "r") fileText = file.read() reader = ScreensReader(self.resourcesDir, self.soundsDir) file.close() return reader.read(fileText) def on_mouse_hover(self, clickedControl): if clickedControl.type == "crayon": if not self.hoveredOnControl is None: self.hoveredOnControl.filterOff() if not clickedControl.isBeingDragged(): self.hoveredOnControl = clickedControl else: underlyingBin = self.getBinThatCollidesWithCrayon(clickedControl) if not underlyingBin is None: self.hoveredOnControl = underlyingBin (x,y) = pygame.mouse.get_pos() if x > self.maxX: x = self.maxX if y > self.maxY: y = self.maxY if x < self.minX: x = self.minX if y < self.minY: y = self.minY pygame.mouse.set_pos((x,y)) if not self.hoveredOnControl is None: self.hoveredOnControl.filterOn() else: if not self.hoveredOnControl is None: self.hoveredOnControl.filterOff() def getBinThatCollidesWithCrayon(self, crayonControl): crayonRect = crayonControl.getRect() for binControl in self.binControls: if crayonRect.colliderect(binControl.getRect()): return binControl def on_mouse_button_up(self, clickedControl): if clickedControl.type == "crayon" and clickedControl.isBeingDragged(): self.getUiMgr().dropDraggingControl() selectedBin = None if self.xo: self.xo.setImageDivisionIndex(0) if self.fakeMouse: self.fakeMouse.setImageDivisionIndex(0) if self.hoveredOnControl.type == "bin": selectedBin = self.hoveredOnControl if not selectedBin is None: if clickedControl.crayon.bin == selectedBin.bin: self.getUiMgr().removeControl(clickedControl) self.getUiMgr().removeControl(clickedControl.label) self.solvedItems = self.solvedItems + 1 self.getSoundMgr().addSoundForPlayback(self.successSound, False, True) if self.solvedItems == len(self.screens[self.currentScreenIndex]): self.moveToNextScreen = True else: self.triggerAlert() self.getUiMgr().dropDraggingControl() self.moveBinToOriginalPosition(clickedControl) else: self.getUiMgr().dropDraggingControl() self.moveBinToOriginalPosition(clickedControl) def moveBinToOriginalPosition(self, crayon): #"crayon" must be a crayon. crayon.startMovement(crayon.originalPosition, self.settings["speed"]) def on_mouse_button_down(self, clickedControl): if clickedControl.type == "crayon": self.getUiMgr().dragControl(clickedControl) clickedControl.filterOff() self.getSoundMgr().addSoundForPlayback(clickedControl.soundFilePath, False) if self.xo: self.xo.setImageDivisionIndex(1) if self.fakeMouse: self.fakeMouse.setImageDivisionIndex(1) def triggerAlert(self): self.getSoundMgr().addSoundForPlayback(self.alert, False) def updateState(self): if self.moveToNextScreen: self.currentScreenIndex = self.currentScreenIndex + 1 if self.currentScreenIndex < len(self.screens): self.showCurrentScreen() else: self.endGame() if not self.isHelp: self.saveAsDone() def endGame(self): self.finished = True self.getUiMgr().dropDraggingControl() class ScreensReader: def __init__(self, resourcesDir, soundsDir): self.resourcesDir = resourcesDir self.soundsDir = soundsDir def read(self, text): lines = text.splitlines() self.screens = [] self.bins = [] state = "bins" currentScreen = [] for line in lines: if line.strip() != "" and not line.startswith("#"): if line.upper().startswith("SCREEN"): state = "screens" if state == "bins": if line.upper().strip() == "BINS:": continue else: binInfo = line.split(":") binName = binInfo[0] binImage = binInfo[1] self.bins.append(Bin(binName, binImage, self.resourcesDir)) else: if line.upper().startswith("SCREEN"): currentScreen = [] self.screens.append(currentScreen) else: splitData = line.split() crayon = Crayon(splitData[0], splitData[1], splitData[2], self.getBin(splitData[3]), self.resourcesDir, self.soundsDir) currentScreen.append(crayon) return self.screens, self.bins def getBin(self, name): for bin in self.bins: if bin.name == name: return bin class Bin: def __init__(self, name, image, resourcesDir): self.image = os.path.join(resourcesDir, image) self.name = name class Crayon: def __init__(self, image, audio, text, bin, resourceDir, soundsDir): (self.image, self.audio, self.text, self.bin) = (os.path.join(resourceDir,image), os.path.join(soundsDir,audio), text, bin)