def __init__(self, position, spriteSize): """initializes a ring zap object""" direction = random.randint(1, 10) self._movement = { pygame.K_LEFT: False, pygame.K_RIGHT: False, pygame.K_UP: False } #randomly determines direction of movement if direction < 5: self._movement[pygame.K_LEFT] = True position = Vector2(position.x - spriteSize.x, position.y + spriteSize.y // 2 - 16) elif direction < 8: self._movement[pygame.K_RIGHT] = True position = Vector2(position.x + spriteSize.x, position.y + spriteSize.y // 2 - 16) else: self._movement[pygame.K_UP] = True position = Vector2(position.x + 6, position.y - 6) super().__init__("bubble_enemies.png", position, (2, 10)) #a vector2 of its velocity self._originalPosition = position self._velocity = Vector2(MAX_VELOCITY, MAX_VELOCITY) self._active = True self._notActiveCount = 0 self._zapTimer = 0 self._zapTime = 0.75 self._start = True
def getText(self, fileContents): """gets the image for each letter in the text given in the layout file""" fileStuff = fileContents.split("\n") #text,xval,yval,words #line 0 starts at A (first letter): ascii 65 #lint 1 starts at N (13th letter) selectionCount = 0 for line in fileStuff: info = line.split(",") if info[0] == "text": text = info[3].upper() #xCenter = (self._worldsize[0] + int(info[1]))/4 - (len(text)//2 * 8) if self._filename == "startmenu.txt": xCenter = 10 else: xCenter = 15 for i in range(len(text)): if text[i] != " ": if text[i] == "!": self._text.append(Drawable("exclamation.png", Vector2(int(xCenter) + 8 * i, int(info[2])), (0,0))) else: aVal = ord(text[i]) numInAlph = aVal - 65 offsetY = numInAlph // 13 offsetX = numInAlph - 13*offsetY self._text.append(Drawable("font.png", Vector2(int(xCenter) + 8 * i, int(info[2])), (2 + offsetX, 7 + offsetY)))
def __init__(self, filename): """intializes an animation""" self._filename = filename self._background = Drawable(self.getBackground(), Vector2(0, 0), (0, 0)) self._frame = Drawable("animation_frame.png", Vector2(0, 0), (0, 0)) self._worldsize = (400, 400) self._text = [] self._animationTimer = 0 self._animationTime = 10 self._ready = False
def __init__(self, filename): """intializes a menu""" self._filename = filename self._background = Drawable(self.getBackground(), Vector2(0,0), (0,0)) self._accent = Drawable("menu_accent.png", Vector2(0,45), (0,0)) self._worldsize = (400, 400) self._selectionAreas = [] self._blobs = [] self._text = [] self._selectedBlob = None self._ready = False self._startButton = None
def __init__(self, position, spriteSize): """intializes an arrow object""" #adjust position correctly before creating it position = Vector2(position.x - spriteSize.x // 2, position.y) super().__init__("gaston.png", position, (0, 1)) self._originalPosition = position self._velocity = Vector2(MAX_VELOCITY, MAX_VELOCITY) self._active = True self._notActiveCount = 0 self._zapTimer = 0 self._zapTime = 0.8 self._start = True
def handleDestroy(self): """handle the animation of a violent collision""" newSpriteSize = Vector2(22, 22) self._velocity = Vector2(0, 0) self._imageName = "bubble_enemies.png" fullImage = pygame.image.load(os.path.join("images", self._imageName)).convert() rect = pygame.Rect(newSpriteSize.x * 4, newSpriteSize.y * 2, newSpriteSize.x, newSpriteSize.y) self._image = pygame.Surface((rect.width, rect.height)) self._image.blit(fullImage, (0, 0), rect) self._image.set_colorkey(self._image.get_at((0, 0))) self._active = False
def handleEnd(self): """handle a casual inactive moment""" newSpriteSize = Vector2(22, 22) self._velocity = Vector2(0, 0) self._imageName = "bubble_enemies.png" fullImage = pygame.image.load(os.path.join("images", self._imageName)).convert() rect = pygame.Rect(newSpriteSize.x * 5, newSpriteSize.y * 2, newSpriteSize.x, newSpriteSize.y) self._image = pygame.Surface((rect.width, rect.height)) self._image.blit(fullImage, (0, 0), rect) self._image.set_colorkey(self._image.get_at((0, 0))) self._active = False
def getOtherBlobs(self, fileContents): """determines if this is a level that has other blobs in it that don't move""" fileStuff = fileContents.split("\n") for line in fileStuff: info = line.split(",") if info[0] == "otherblobs": self._otherblobs.append( Blob(Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y - 50), color=info[1])) if len(self._otherblobs) != 0: self._otherblobsCollideRect = pygame.Rect(300, 234, 100, 66) self._block = Drawable("block.png", Vector2(300, 250), (0, 0)) self._spot = Drawable("ground.png", Vector2(250, 300), (0, 0))
def getBlobSelectionAreas(self, fileContents): """loads in the selection areas for choosing a blob to play with on a menu""" SELECTION_SIZE = Vector2(112, 112) BLOB_SIZE = Vector2(64, 64) fileStuff = fileContents.split("\n") selectionCount = 0 for line in fileStuff: info = line.split(",") if info[0] == "selection": if self._filename == "blobmenu.txt": self._selectionAreas.append(Drawable("blob_selection.png", Vector2(int(info[1]), int(info[2])), (selectionCount,0))) blobXpos = int(info[1]) + SELECTION_SIZE.x//2 - BLOB_SIZE.x//2 blobYpos = int(info[2]) + SELECTION_SIZE.y//2 - BLOB_SIZE.y//2 - 14 self._blobs.append(Drawable("menu_blobs.png", Vector2(blobXpos, blobYpos), (selectionCount + 1,0))) selectionCount += 1
def __init__(self, position, color="pink"): """initializes a blob object""" self._color = color #determines which blob image to grab based on the color if color == "pink": self._offset = (0,0) elif color == "blue": self._offset = (1,0) elif color == "green": self._offset = (2,0) elif color == "orange": self._offset = (3,0) super().__init__("blobs.png", position, self._offset) #a vector2 of its velocity self._velocity = Vector2(0,0) self._maxVelocity = MAX_VELOCITY self._acceleration = ACCELERATION self._movement = {pygame.K_UP: False, pygame.K_DOWN: False, pygame.K_LEFT: False, pygame.K_RIGHT: False} self._jumpTimer = 0 self._jumpTime = STANDARD_JUMP self._vSpeed = 100 self._jSpeed = 80 self._zaps = [] self._alive = True self._forcefield = False self._forcefieldTime = 5 self._forcefieldTimer = 0 self._higher = False self._highTime = 10 self._highTimer = 0 self._endLevel = False
def adjustMousePos(cls, mousePos): """adjusts the mouse position on screen to coordinates within the wider world""" adjustedPos = [ mousePos[0] + Drawable.WINDOW_OFFSET[0], mousePos[1] + Drawable.WINDOW_OFFSET[1] ] return Vector2(adjustedPos[0], adjustedPos[1])
def plantFlowers(self): """plants flowers randomly for decoration""" flowerSize = 16 for xPos in range(0, 2400, 20): randomNumber = random.randint(10, 13) self._decorations.append( Drawable("nuts_and_milk.png", Vector2(xPos, self._worldsize[1] - 100 - flowerSize), (randomNumber, 8)))
def getStartButton(self, fileContents): """creates a start button with the given position""" fileStuff = fileContents.split("\n") #selection,xval,yval selectionCount = 0 for line in fileStuff: info = line.split(",") if info[0] == "start": xPos = (self._worldsize[0] - int(info[1]))//2 - 64//2 self._startButton = Drawable("startbutton.png", Vector2(xPos, int(info[2])), (0,0))
def handleEvent(self, event): """manage state based on key presses""" #arrow keys to move and spacebar to spawn a zap if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: self._movement[pygame.K_LEFT] = True self._FSM.manageState("left") elif event.key == pygame.K_RIGHT: self._movement[pygame.K_RIGHT] = True self._FSM.manageState("right") # Check for jumping keypress elif event.key == pygame.K_UP: self._movement[pygame.K_UP] = True self._FSM.manageState("jump") self.updateVisual() elif event.key == pygame.K_SPACE: if self._FSM.isFacing("left"): zap = BlobZap(Vector2(self._position.x - SPRITE_SIZE.x, self._position.y + SPRITE_SIZE.y//2 - 6)) else: zap = BlobZap(Vector2(self._position.x + SPRITE_SIZE.x, self._position.y + SPRITE_SIZE.y//2 - 6)) self._zaps.append(zap) SoundManager.getInstance().playSound("heart.ogg") zap.handleEvent(self._FSM.isFacing("left")) elif event.type == pygame.KEYUP: if event.key in [pygame.K_LEFT, pygame.K_RIGHT]: if event.key == pygame.K_LEFT: self._movement[pygame.K_LEFT] = False if event.key == pygame.K_RIGHT: self._movement[pygame.K_RIGHT] = False self._FSM.manageState("stopMoving") # check for release of jumping keypress elif event.key == pygame.K_UP: self._movement[pygame.K_UP] = False self._FSM.manageState("fall") elif event.key == pygame.K_DOWN: self._movement[pygame.K_DOWN] = False if self._position.y + 32 >= 300: self._FSM.manageState("collideGround") else: self._FSM.manageState("collidePlatform") self.updateVisual()
def loadLevel(self): """controls the loading of the level""" file = open(os.path.join("resources", "levels", self._filename)) fileContents = file.read() file.close() self.getWorldSize(fileContents) self._ground = Drawable(self.getGround(), Vector2(0, self._worldsize[1] - 100), (0, 0)) if self._filename != "level6.txt": self._blob = Blob(Vector2( 0, self._worldsize[1] - 100 - CHAR_SPRITE_SIZE.y), color=self._blob._color) self.plantFlowers() self.getPlatforms(fileContents) self.getOtherBlobs(fileContents) self.getActiveBlobs() self.getPowerUps(fileContents) self.getTraps(fileContents) self.getEnemies(fileContents) self.getWorldSize(fileContents)
def getPowerUps(self, fileContents): """parses the level layout file for the powerups and saves them to a dictionary""" fileStuff = fileContents.split("\n") for line in fileStuff: info = line.split(",") if info[0] == "powerup": if info[1] == "floppy": self._powerups["floppy"].append( Floppy( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y))) elif info[1] == "sign": self._powerups["sign"].append( Sign( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y))) elif info[1] == "vote": self._powerups["vote"].append( Vote( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y)))
def __init__(self, position): """initializes a blob zap""" super().__init__("nuts_and_milk.png", position, (11, 1)) #a vector2 of its velocity self._originalPosition = position self._velocity = Vector2(MAX_VELOCITY, 0) self._active = True self._notActiveCount = 0 self._zapTimer = 0 self._zapTime = 0.75 self._movement = {pygame.K_LEFT: False, pygame.K_RIGHT: True} self._start = True
def getTraps(self, fileContents): """parses the level layout file for the traps and saves them to a dictionary""" fileStuff = fileContents.split("\n") for line in fileStuff: info = line.split(",") if info[0] == "trap": if info[1] == "bra": self._traps[info[1]].append( Bra( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y))) elif info[1] == "ring": self._traps[info[1]].append( Ring( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y))) elif info[1] == "pan": self._traps[info[1]].append( Pan( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y)))
def __init__(self, position, worldHeight): """initializes an elevator object""" self._position = position self._parts = {"back": [], "front": [], "doors": [], "top": []} totalHeight = worldHeight - (50 + MAIN_SPRITE_SIZE.x) for i in range(0, totalHeight, MAIN_SPRITE_SIZE.y): self._parts["back"].append( Drawable("elevator_back.png", Vector2(self._position.x, i), (0, 0))) for j in range(0, totalHeight - 60, MAIN_SPRITE_SIZE.y): self._parts["front"].append( Drawable("elevator_front.png", Vector2(self._position.x, j), (0, 0))) for k in range(totalHeight - 60, totalHeight, MAIN_SPRITE_SIZE.y): self._parts["doors"].append( Drawable("elevator_doors.png", Vector2(self._position.x, k), (0, 0))) self._parts["top"].append( Drawable("elevator_top.png", Vector2(self._position.x, totalHeight - 60), (0, 0))) self._ranInto = False
def __init__(self, position, final=False): """initializes ceiling object""" super().__init__("ceiling.png", position, (0, 0)) self._hp = {"left": 0, "right": 0} self._final = final self._hitby = { "pink": False, "blue": False, "green": False, "orange": False } self._velocity = Vector2(0, 0)
def update(self, worldInfo, ticks): """updates the boss animation and the positions of its spawns""" super().update(ticks, True) for blob in self._spawns: blob.update(worldInfo, ticks) self._spawnTimer += ticks if self._spawnTimer > self._spawnTime: spawn = Spawn( Vector2(self._position.x, self._position.y + 32 + 25 - 9), SPRITE_SIZE) self._spawns.append(spawn) self._spawnTimer = 0
def getActiveBlobs(self): """determines if this is a level that the player can switch their controls between""" if self._filename == "level6.txt": self._activeBlobs.append( Blob(Vector2(25, 100 - CHAR_SPRITE_SIZE.y), color="pink")) self._activeBlobs.append( Blob(Vector2(25, self._worldsize[1] - 100 - CHAR_SPRITE_SIZE.y), color="blue")) self._activeBlobs.append( Blob(Vector2(200, self._worldsize[1] - 100 - CHAR_SPRITE_SIZE.y), color="green")) self._activeBlobs.append( Blob(Vector2(300, self._worldsize[1] - 100 - CHAR_SPRITE_SIZE.y), color="orange")) self._blob = self._activeBlobs[0] self._downbar = Drawable("downbar.png", Vector2(0, self._worldsize[1] - 28), (0, 0)) for i in range(4): self._downbarSelections.append( Drawable("downbarselection.png", Vector2(i * 28, self._worldsize[1] - 28), (0, 0)))
def __init__(self, filename): """intializes a level""" self._filename = filename self._background = Drawable(self.getBackground(), Vector2(0, 0), (0, 0)) self._ground = Drawable(self.getGround(), Vector2(0, 300), (0, 0)) self._blob = Blob(Vector2(0, 300 - CHAR_SPRITE_SIZE.y)) self._decorations = [] self._platforms = [] self._traps = {"bra": [], "pan": [], "ring": []} self._enemies = {"devil": [], "gaston": [], "boss": []} self._powerups = {"floppy": [], "sign": [], "vote": []} self._worldsize = (2400, 400) self._elevator = elevator = Elevator( Vector2(self._worldsize[0] - 50, 300), self._worldsize[1]) if self._filename == "level3.txt": self._ceiling = Ceiling(Vector2(0, 0), final=False) elif self._filename == "level6.txt": self._ceiling = Ceiling(Vector2(0, 0), final=True) else: self._ceiling = None self._deathCycle = 0 self._keydown = {1: False, 2: False, 3: False} self._otherblobs = [] self._otherblobsCollideRect = None self._block = None self._spot = None self._activeBlobs = [] self._downbar = None self._downbarSelections = [] self._selectCount = 0 self._samePlat = 0
def getEnemies(self, fileContents): """parses the level layout file for the enemies and saves them to a dictionary""" fileStuff = fileContents.split("\n") for line in fileStuff: info = line.split(",") if info[0] == "enemy": if info[1] == "devil": self._enemies[info[1]].append( Devil( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y), int(info[4]))) elif info[1] == "gaston": self._enemies[info[1]].append( Gaston( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y))) elif info[1] == "boss": self._enemies[info[1]].append( Boss( Vector2(int(info[2]), int(info[3]) - CHAR_SPRITE_SIZE.y - 25)))
def __init__(self, position, spriteSize): """initializes a spawn object""" position = Vector2(position.x - spriteSize.x // 2, position.y) randomColor = random.randint(0, 12) #randomizes the colors of the spawns if randomColor < 3: self._offsetX = 0 elif randomColor < 6: self._offsetX = 1 elif randomColor < 9: self._offsetX = 2 else: self._offsetX = 3 super().__init__("blob_spawns.png", position, (self._offsetX, 0)) #a vector2 of its velocity self._originalPosition = position self._velocity = Vector2(MAX_VELOCITY, MAX_VELOCITY) self._active = True self._notActiveCount = 0 self._zapTimer = 0 self._zapTime = 0.8 self._start = True self._opposite = False
def updateOffset(cls, trackingObject, screenSize, worldSize): """updates the WINDOW_OFFSET class variable""" offset = Vector2( min( max( 0, trackingObject.getX() + (trackingObject.getWidth() // 2) - (screenSize[0] // 2)), worldSize[0] - screenSize[0]), min( max( 0, trackingObject.getY() + (trackingObject.getHeight() // 2) - (screenSize[1] // 2)), worldSize[1] - screenSize[1])) # update the WINDOW_OFFSET class variable Drawable.WINDOW_OFFSET = offset
def __init__(self, position, patrolUnit): """initializes a devil object""" super().__init__("dizzy_devil.png", position, (0, 1)) #a vector2 of its velocity self._velocity = Vector2(MAX_VELOCITY, 0) self._startPosition = position self._maxVelocity = MAX_VELOCITY self._acceleration = ACCELERATION self._patrolLength = patrolUnit * 50 - SPRITE_SIZE.x self._vSpeed = 100 self._waitTime = 0.75 self._waitTimer = 0 self._right = True self._patrolRect = pygame.Rect(self._position.x, self._position.y, self._patrolLength, SPRITE_SIZE.y) self._hp = 50
def getPlatforms(self, fileContents): """returns the appropriate platform tile image""" if self._filename == "level1.txt": platformImage = "platform.png" elif self._filename == "level2.txt": platformImage = "platform2.png" elif self._filename == "level3.txt" or self._filename == "level6.txt": platformImage = "platform3.png" elif self._filename == "level4.txt" or self._filename == "level5.txt": platformImage = "platform4.png" fileStuff = fileContents.split("\n") for line in fileStuff: info = line.split(",") if info[0] == "platform": for i in range(int(info[3])): self._platforms.append( Drawable(platformImage, Vector2(int(info[1]) + 50 * i, int(info[2])), (0, 0)))
def updateVisual(self): """updates the cracks in the ceiling and if it is broken or not based on the hitpoints""" if (self._hp["left"] > 2 or self._hp["right"] > 2): if self._hp["left"] > 2 and self._hp["right"] < 2: self._imageName = "ceiling3.png" elif self._hp["right"] > 2 and self._hp["left"] < 2: self._imageName = "ceiling4.png" elif self._hp["left"] + self._hp["right"] < 8: self._imageName = "ceiling5.png" elif self._hp["left"] + self._hp["right"] < 12 and self._final: self._imageName = "ceiling6.png" elif self._hp["left"] + self._hp["right"] <= 16 and self._final: self._imageName = "ceiling7.png" elif self._hp["left"] + self._hp["right"] > 17 and self._final: self._imageName = "broken.png" self._velocity = Vector2(0, 100) else: self._imageName = "ceiling.png" self._image = FRAMES.getFrame(self._imageName, (0, 0))
def __init__(self, position): super().__init__("", position) self._width = 30 self._height = 30 self._image = pygame.Surface((self._width,self._height)) self._image.fill((255,255,255,255)) pygame.draw.circle(self._image, (0,0,0), (15,15), 15) self._image.set_colorkey(self._image.get_at((0,0))) self._velocity = Vector2(0,0) self._maxVelocity = 150 self._movement = {pygame.K_LEFT:False, pygame.K_RIGHT:False, pygame.K_UP:False, pygame.K_DOWN:False} self._keys = [] states = ["standing","jumping","falling","walking"] transitions = [Rule("standing","jump","jumping"), Rule("jumping","fall","falling"), Rule("falling","stop","standing"), Rule("standing","walk","walking"), Rule("walking","stop","standing"), Rule("walking","jump","jumping"), Rule("walking","fall","falling"), Rule("standing","fall","falling")] self._fsm = FSM("standing", states, transitions) self._onGround = False self._jumpTime = 0.5 self._jumpTimer = 0 self._jumpCount = 0 self._gravity = 2 self._friction = 0.3 self._jumpPower = 125 self._shrunk = False