--- /dev/null
+# -*- coding: utf-8 -*-
+# Molpy Down!
+#
+# Based on Max00355's version of DoodleJump, <https://github.com/Max00355/DoodleJump>
+# Copyright (C) 2015 by Frankie Primerano,
+# written in 120 minutes, see <https://www.reddit.com/r/gamedev/comments/3umhuq/doodle_jump_created_in_120_minutes_with_python/>.
+#
+# Copyright (C) 2018 by Peter Gerwinski <http://www.peter.gerwinski.de>,
+# OTTified in about 120 minutes.
+#
+# Copyright (C) 2018, 2026 by Balthasar SzczepaĆski
+# add arrow, AI, flag save mode,
+# remove off-screen space,
+# gmae mode messages,
+# some optimisation
+# Change into Molpy Down game!
+#
+# This program is Free Software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License (GNU GPL), version 3,
+# as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program, see the file LICENSE. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# The player figure "Molpy" is
+# Copyright (C) 2013 by BlitzGirl, see user "BlitzGirl" at <http://forums.xkcd.com>,
+# released under conditions compatible with both the GNU GPL v3 and the
+# CC BY-NC 2.5 license (see below).
+#
+# All other artwork used by this program is based on xkcd 1190 "Time",
+# Copyright (C) 2013 by Randall Munroe, see <http://xkcd.com/1190>,
+# released under the Creative Commonns Attribution-NonCommercial Generic License,
+# version 2.5 (CC BY-NC 2.5), see <https://creativecommons.org/licenses/by-nc/2.5/>.
+#
+# In particular, the contents of the directory "assets"
+# is NOT subject to the GNU GPL.
+
+import pygame
+from pygame.locals import *
+import sys
+import datetime
+import random
+import math
+
+class MolpyUp:
+
+ platformTypeSand = 0
+ platformTypeGrass = 1
+ platformTypeNormal = platformTypeGrass
+ platformTypeGrapevine = 2
+ platformTypeAfterLucky = 3
+ platformTypeCastle = 4
+ platformTypeWater = 5
+ platformTypeRaftcastle = 6
+ platformTypeFloating = platformTypeRaftcastle
+ platformTypeLucky = 7
+ platformTypeBreaking = 8
+ platformTypeTheEnd = 9
+ platformTypeWonTheGame = 10
+ platformTypeFrame1 = 11
+
+ itemTypeAccelerator = 0
+ itemTypeBeanie = 1
+ itemTypeSnake = 2
+ itemTypePrickly = 3
+ itemTypeSandcastle = 4
+ itemTypeFlag = 5
+ itemTypePlantSand = 6
+ itemTypePlantGrass = 7
+
+ scoreSnake = 1738
+ scorePrickly = 2015
+ scoreGrass = 2193
+ scoreAfterLucky = 2315
+ scoreCastle = 2825
+ scoreLucky = 2976
+ scoreRaftcastle = 3031
+ scoreWater = 3043
+ scoreTheEnd = 3089
+ scoreEpilogue = 3094
+
+ def __init__(self):
+ self.relativeX=0
+ self.sx = 553
+ self.sy = 395
+ self.extrax = self.sx // 16
+ self.screen = pygame.display.set_mode((self.sx, self.sy))
+ pygame.font.init()
+ self.font = pygame.font.SysFont("xkcd,sans", 25)
+ self.clock = pygame.time.Clock()
+ self.xmovementmax = 10
+ self.eternal = False
+ self.eternalFlag = False
+ self.ai = False
+ self.aiDebag = False
+ self.imgPlatformSand = [ pygame.image.load("assets/platformSand1.png").convert_alpha(),
+ pygame.image.load("assets/platformSand2.png").convert_alpha(),
+ pygame.image.load("assets/platformSand3.png").convert_alpha(),
+ pygame.image.load("assets/platformSand4.png").convert_alpha() ]
+ self.imgPlatformGrass = [ pygame.image.load("assets/platformGrass1.png").convert_alpha(),
+ pygame.image.load("assets/platformGrass2.png").convert_alpha(),
+ pygame.image.load("assets/platformGrass3.png").convert_alpha(),
+ pygame.image.load("assets/platformGrass1f.png").convert_alpha(),
+ pygame.image.load("assets/platformGrass2f.png").convert_alpha(),
+ pygame.image.load("assets/platformGrass3f.png").convert_alpha() ]
+ self.imgPlatformWater = [ pygame.image.load("assets/platformWater1.png").convert_alpha(),
+ pygame.image.load("assets/platformWater2.png").convert_alpha(),
+ pygame.image.load("assets/platformWater1f.png").convert_alpha(),
+ pygame.image.load("assets/platformWater2f.png").convert_alpha() ]
+ self.imgPlatformAfterLucky = pygame.image.load("assets/platformAfterLucky.png").convert_alpha()
+ self.imgPlatformCastle = pygame.image.load("assets/platformCastle.png").convert_alpha()
+ self.imgPlatformLuckySleeping = pygame.image.load("assets/platformLuckySleeping.png").convert_alpha()
+ self.imgPlatformLuckyAttacking = pygame.image.load("assets/platformLuckyAttacking.png").convert_alpha()
+ self.imgPlatformRaftcastle = pygame.image.load("assets/platformRaftcastle.png").convert_alpha()
+ self.imgPlatformGrapevine = pygame.image.load("assets/platformGrapevine.png").convert_alpha()
+ self.imgPlatformBreaking = pygame.image.load("assets/platformBreaking.png").convert_alpha()
+ self.imgPlatformBroken = pygame.image.load("assets/platformBroken.png").convert_alpha()
+ self.imgPlatformTheEnd = pygame.image.load("assets/platformTheEnd.png").convert_alpha()
+ self.imgPlatformWonTheGame = pygame.image.load("assets/platformWonTheGame.png").convert_alpha()
+ self.imgPlatformFrame1 = pygame.image.load("assets/platformFrame1.png").convert_alpha()
+ self.imgPlayerRightUp = pygame.image.load("assets/playerRightUp.png").convert_alpha()
+ self.imgPlayerRightDown = pygame.image.load("assets/playerRightDown.png").convert_alpha()
+ self.imgPlayerLeftUp = pygame.image.load("assets/playerLeftUp.png").convert_alpha()
+ self.imgPlayerLeftDown = pygame.image.load("assets/playerLeftDown.png").convert_alpha()
+ self.imgPlayerRightUpBeanie = pygame.image.load("assets/playerRightUpBeanie.png").convert_alpha()
+ self.imgPlayerRightDownBeanie = pygame.image.load("assets/playerRightDownBeanie.png").convert_alpha()
+ self.imgPlayerLeftUpBeanie = pygame.image.load("assets/playerLeftUpBeanie.png").convert_alpha()
+ self.imgPlayerLeftDownBeanie = pygame.image.load("assets/playerLeftDownBeanie.png").convert_alpha()
+ self.imgAccelerator = pygame.image.load("assets/accelerator.png").convert_alpha()
+ self.imgAcceleratorUsed = pygame.image.load("assets/acceleratorUsed.png").convert_alpha()
+ self.imgBeanie = pygame.image.load("assets/beanie.png").convert_alpha()
+ self.imgSnake = pygame.image.load("assets/snake.png").convert_alpha()
+ self.imgSnakeLeft = pygame.image.load("assets/snakeLeft.png").convert_alpha()
+ self.imgSnakeRight = pygame.image.load("assets/snakeRight.png").convert_alpha()
+ self.imgPrickly = pygame.image.load("assets/prickly.png").convert_alpha()
+ self.imgPricklyCurled = pygame.image.load("assets/pricklyCurled.png").convert_alpha()
+ self.imgSandcastle = pygame.image.load("assets/sandcastle.png").convert_alpha()
+ self.imgFlagLeft = pygame.image.load("assets/flagLeft.png").convert_alpha()
+ self.imgFlagLeftDown = pygame.image.load("assets/flagLeftDown.png").convert_alpha()
+ self.imgFlagRight = pygame.image.load("assets/flagRight.png").convert_alpha()
+ self.imgFlagRightDown = pygame.image.load("assets/flagRightDown.png").convert_alpha()
+ self.imgPlantSand = [ pygame.image.load("assets/plantSand1.png").convert_alpha(),
+ pygame.image.load("assets/plantSand2.png").convert_alpha(),
+ pygame.image.load("assets/plantSand3.png").convert_alpha(),
+ pygame.image.load("assets/plantSand4.png").convert_alpha(),
+ pygame.image.load("assets/plantSand5.png").convert_alpha() ]
+ self.imgPlantGrass = [ pygame.image.load("assets/plantGrass1.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass2.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass3.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass4.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass5.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass6.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass7.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass8.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass9.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass10.png").convert_alpha(),
+ pygame.image.load("assets/plantGrass11.png").convert_alpha() ]
+ self.imgMolpArrow = pygame.image.load("assets/molpArrow.png").convert_alpha()
+ self.playerHeight = self.imgPlayerRightUp.get_height()
+ # self.playerHalfHeight = self.playerHeight // 2
+ self.playerWidth = self.imgPlayerRightUp.get_width()
+ self.playerHalfWidth = self.playerWidth // 2
+ self.platformSpeed = self.extrax // 10
+ self.platformSandHeight = self.imgPlatformSand[0].get_height()
+ self.platformSandWidth = self.imgPlatformSand[0].get_width()
+ self.showArrow = True
+
+ def reset(self):
+ self.cameray = 0
+ self.score = self.scoreEpilogue
+ self.sandcastles = 0
+ self.speed = 30
+ self.modeText = ''
+ self.playerx = self.sx // 2 - self.playerHalfWidth
+ self.playery = self.sy * 3 // 4
+ self.direction = 0
+ self.jump = 0
+ self.gravity = 0
+ self.xmovement = 0
+ self.playerWearsBeanie = False
+ self.playerCarriesFlag = False
+ self.hadSnake = False
+ self.hadPrickly = False
+ self.hadAfterLucky = False
+ self.hadCastle = False
+ self.hadLucky = False
+ self.hadTheEnd = False
+ self.raftcastleHasFlag = False
+ self.platforms = [
+ [self.sx // 2 - self.imgPlatformWonTheGame.get_width() // 2, self.playery - self.sy // 2, self.platformTypeWonTheGame, False, False, -1, 0, self.imgPlatformWonTheGame.get_width()],
+ [self.sx // 2 - self.imgPlatformTheEnd.get_width() // 2, self.playery + self.sy // 6, self.platformTypeTheEnd, False, False, -1, 0, self.imgPlatformTheEnd.get_width()]
+ ]
+ self.generateInitialPlatforms()
+ self.items = []
+ self.aiNextPlatformOk = False
+ self.aiNextPlatform=[self.playerx,self.playery]
+ self.oops = False
+ self.pause = False
+ if self.filename:
+ self.restoreGame (self.filename)
+
+ def saveGame(self):
+ self.filename = datetime.datetime.now().strftime("%Y%m%d-%H%M%S.molpyup")
+ with open(self.filename, "w") as file:
+ file.write("MolpyUp!\n")
+ file.write("cameray: " + str(self.cameray) + "\n")
+ file.write("score: " + str(self.score) + "\n")
+ file.write("sandcastles: " + str(self.sandcastles) + "\n")
+ file.write("speed: " + str(self.speed) + "\n")
+ file.write("showArrow: " + str(self.showArrow) + "\n")
+ file.write("playerx: " + str(self.playerx) + "\n")
+ file.write("playery: " + str(self.playery) + "\n")
+ file.write("direction: " + str(self.direction) + "\n")
+ file.write("jump: " + str(self.jump) + "\n")
+ file.write("gravity: " + str(self.gravity) + "\n")
+ file.write("xmovement: " + str(self.xmovement) + "\n")
+ file.write("playerWearsBeanie: " + str(self.playerWearsBeanie) + "\n")
+ file.write("playerCarriesFlag: " + str(self.playerCarriesFlag) + "\n")
+ file.write("hadSnake: " + str(self.hadSnake) + "\n")
+ file.write("hadPrickly: " + str(self.hadPrickly) + "\n")
+ file.write("hadAfterLucky: " + str(self.hadAfterLucky) + "\n")
+ file.write("hadCastle: " + str(self.hadCastle) + "\n")
+ file.write("hadLucky: " + str(self.hadLucky) + "\n")
+ file.write("hadTheEnd: " + str(self.hadTheEnd) + "\n")
+ file.write("raftcastleHasFlag: " + str(self.raftcastleHasFlag) + "\n")
+ file.write("eternal: " + str(self.eternal) + "\n")
+ file.write("eternalFlag: " + str(self.eternalFlag) + "\n")
+ file.write("platforms: " + str(self.platforms) + "\n")
+ file.write("items: " + str(self.items) + "\n")
+
+ def readVariable(self, line, name, var):
+ if line.startswith(name + ": "):
+ return eval (line[len(name) + 2:])
+ else:
+ return var
+
+ def restoreGame(self, filename):
+ try:
+ with open(filename, "r") as file:
+ lines = file.readlines()
+ for line in lines:
+ self.cameray = self.readVariable(line, "cameray", self.cameray)
+ self.score = self.readVariable(line, "score", self.score)
+ self.sandcastles = self.readVariable(line, "sandcastles", self.sandcastles)
+ self.speed = self.readVariable(line, "speed", self.speed)
+ self.showArrow = self.readVariable(line, "showArrow", self.showArrow)
+ self.playerx = self.readVariable(line, "playerx", self.playerx)
+ self.playery = self.readVariable(line, "playery", self.playery)
+ self.direction = self.readVariable(line, "direction", self.direction)
+ self.jump = self.readVariable(line, "jump", self.jump)
+ self.gravity = self.readVariable(line, "gravity", self.gravity)
+ self.xmovement = self.readVariable(line, "xmovement", self.xmovement)
+ self.playerWearsBeanie = self.readVariable(line, "playerWearsBeanie", self.playerWearsBeanie)
+ self.playerCarriesFlag = self.readVariable(line, "playerCarriesFlag", self.playerCarriesFlag)
+ self.hadSnake = self.readVariable(line, "hadSnake", self.hadSnake)
+ self.hadPrickly = self.readVariable(line, "hadPrickly", self.hadPrickly)
+ self.hadAfterLucky = self.readVariable(line, "hadAfterLucky", self.hadAfterLucky)
+ self.hadCastle = self.readVariable(line, "hadCastle", self.hadCastle)
+ self.hadLucky = self.readVariable(line, "hadLucky", self.hadLucky)
+ self.hadTheEnd = self.readVariable(line, "hadTheEnd", self.hadTheEnd)
+ self.raftcastleHasFlag = self.readVariable(line, "raftcastleHasFlag", self.raftcastleHasFlag)
+ self.platforms = self.readVariable(line, "platforms", self.platforms)
+ self.items = self.readVariable(line, "items", self.items)
+ return True
+ except FileNotFoundError:
+ return False
+
+ def findNextPlatform(self):
+ bestPlatformScore = float("-Inf")
+ actualY = self.playery + self.playerHeight
+ actualX = self.playerx + self.playerHalfWidth
+ self.aiNextPlatform = self.platforms[0]
+ if self.jump > 0:
+ maxY = actualY - (self.jump * (self.jump + 1 ) // 2)
+ framesUp = self.jump
+ else:
+ maxY = actualY
+ framesUp = 0
+
+ for p in self.platforms:
+ platformX = p[0] + p[7] //2
+ platformY = p[1]
+ platformScore = 0
+
+ if (platformY < maxY) or (p[2] == self.platformTypeBreaking):
+ platformScore = float("-Inf")
+ p[6] = platformScore
+ continue
+
+ distY = actualY - platformY
+ distDown = platformY - maxY
+ distX = abs(platformX-actualX)
+
+ if self.gravity > 0:
+ framesDown = int(math.floor(math.sqrt(self.gravity * self.gravity + 2 * distDown) - self.gravity))
+ else:
+ framesDown = int(math.floor(math.sqrt(2*distDown)))
+
+ speedX = 9;
+
+ if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+ if (p[4] and platformX > actualX) or (not p[4] and platformX < actualX):
+ speedX -= self.platformSpeed
+ else:
+ speedX += self.platformSpeed
+
+ platformScore += framesUp + framesDown - distX // speedX
+
+ if platformX - actualX > 2 * self.xmovementmax and self.xmovement < 0:
+ platformScore -= (self.xmovementmax - self.xmovement) * (self.xmovementmax - self.xmovement) // 4
+ elif actualX - platformX > 2 * self.xmovementmax and self.xmovement > 0:
+ platformScore -= (-self.xmovementmax - self.xmovement) * (-self.xmovementmax - self.xmovement) // 4
+
+ if platformScore < 0:
+ platformScore = float("-Inf")
+ platformScore *= 4
+
+ if distY > 16:
+ platformScore += distY + distX // 2
+ else:
+ platformScore += 2 * distY - 200 + distX
+
+ if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+ platformScore -= 50 #100
+ elif p[2] == self.platformTypeLucky:
+ platformScore -= 150
+
+ if p[5] == self.itemTypeSnake:
+ platformScore -= 150
+ elif p[5] == self.itemTypeFlag and not self.playerCarriesFlag:
+ platformScore += 70
+ elif p[5] == self.itemTypeSandcastle and self.playerCarriesFlag:
+ platformScore += 70
+ elif p[5] == self.itemTypeBeanie and not self.playerWearsBeanie:
+ platformScore += 50
+
+ p[6] = platformScore
+
+ if platformScore > bestPlatformScore:
+ bestPlatformScore = platformScore
+ self.aiNextPlatform = p
+ self.aiNextPlatformOk = True
+
+ def updatePlayer(self):
+ if ((not self.jump) and (self.playery > self.aiNextPlatform[1])) or (self.aiNextPlatform[1] - self.cameray > self.sy):
+ self.aiNextPlatformOk = False
+
+ if not self.aiNextPlatformOk and self.ai:
+ self.findNextPlatform()
+
+ if not self.jump:
+ self.playery += self.gravity
+ self.gravity += 1
+ else:
+ self.playery -= self.jump
+ self.jump -= 1
+
+ if self.playery - self.cameray > self.sy * 7 // 6:
+ if self.eternal or (self.eternalFlag and self.sandcastles > 0):
+ if self.eternalFlag:
+ self.sandcastles -= 1
+ self.jump = self.gravity
+ self.gravity = 0
+ self.aiNextPlatformOk = False
+ self.playery = self.cameray + self.sy + self.playerHeight
+ else:
+ self.oops = True
+
+ key = pygame.key.get_pressed()
+
+ xdir = 0;
+ actualX = self.playerx + self.playerHalfWidth
+ if key[K_RIGHT]:
+ xdir = 1
+ self.modeText = ''
+ elif key[K_LEFT]:
+ xdir = -1
+ self.modeText = ''
+ elif key[K_PLUS] or key[K_KP_PLUS]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.score += 10
+ self.modeText = "Score +10: " + str(self.score)
+ else:
+ self.speed += 1
+ self.modeText = "Speed: " + str(self.speed)
+ elif key[K_MINUS] or key[K_KP_MINUS]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.score -= 10
+ self.modeText = "Score -10: " + str(self.score)
+ else:
+ self.speed -= 1
+ self.modeText = "Speed: " + str(self.speed)
+ elif self.ai:
+ platformX = self.aiNextPlatform[0] + self.aiNextPlatform[7] // 2
+ if self.aiNextPlatform[2] > self.platformTypeNormal and self.aiNextPlatform[2] <= self.platformTypeFloating:
+ if self.aiNextPlatform[4] == True:
+ self.relativeX = self.xmovement - self.platformSpeed
+ else:
+ self.relativeX = self.xmovement + self.platformSpeed
+ else:
+ self.relativeX = self.xmovement
+
+ if actualX < platformX - 2.5 * self.relativeX:
+ xdir = 1
+ elif actualX > platformX - 2.5 * self.relativeX:
+ xdir = -1
+
+ if xdir > 0:
+ if self.xmovement < self.xmovementmax:
+ self.xmovement += 1
+ elif self.xmovement > self.xmovementmax:
+ self.xmovement -= 1
+ self.direction = 0
+ elif xdir < 0:
+ if self.xmovement > -self.xmovementmax:
+ self.xmovement -= 1
+ elif self.xmovement < -self.xmovementmax:
+ self.xmovement += 1
+ self.direction = 1
+ elif self.xmovement > 0:
+ self.xmovement -= 1
+ elif self.xmovement < 0:
+ self.xmovement += 1
+
+ self.playerx += self.xmovement
+ actualX += self.xmovement
+
+ while actualX < 0:
+ self.playerx += self.sx
+ actualX += self.sx
+ self.aiNextPlatformOk = False
+ while actualX >= self.sx:
+ self.playerx -= self.sx
+ actualX -= self.sx
+ self.aiNextPlatformOk = False
+
+ if self.playery - self.cameray >= self.sy // 3:
+ if self.jump:
+ self.cameray += self.sy // 120
+ else:
+ self.cameray += self.sy // 180
+
+ drawX = self.playerx % self.sx
+ if drawX > self.sx - self.playerWidth:
+ drawX = [drawX, drawX - self.sx]
+ else:
+ drawX = [drawX]
+ drawY = self.playery - self.cameray
+
+ for x in drawX:
+ if (drawY + self.playerHeight) < 0:
+ if self.showArrow:
+ self.screen.blit(self.imgMolpArrow, (x, 2))
+ else:
+ if not self.direction:
+ if self.jump:
+ if self.playerWearsBeanie:
+ self.screen.blit(self.imgPlayerRightDownBeanie, (x, drawY))
+ else:
+ self.screen.blit(self.imgPlayerRightDown, (x, drawY))
+ if self.playerCarriesFlag:
+ self.screen.blit(self.imgFlagLeft, (x + 24, drawY - 10))
+ else:
+ if self.playerWearsBeanie:
+ self.screen.blit(self.imgPlayerRightUpBeanie, (x, drawY))
+ else:
+ self.screen.blit(self.imgPlayerRightUp, (x, drawY))
+ if self.playerCarriesFlag:
+ self.screen.blit(self.imgFlagLeftDown, (x + 22, drawY - 10))
+ else:
+ if self.jump:
+ if self.playerWearsBeanie:
+ self.screen.blit(self.imgPlayerLeftDownBeanie, (x, drawY))
+ else:
+ self.screen.blit(self.imgPlayerLeftDown, (x, drawY))
+ if self.playerCarriesFlag:
+ self.screen.blit(self.imgFlagRight, (x + 13, drawY - 10))
+ else:
+ if self.playerWearsBeanie:
+ self.screen.blit(self.imgPlayerLeftUpBeanie, (x, drawY))
+ else:
+ self.screen.blit(self.imgPlayerLeftUp, (x, drawY))
+ if self.playerCarriesFlag:
+ self.screen.blit(self.imgFlagRightDown, (x + 11, drawY - 10))
+
+ def choosePlatformType(self):
+ platformType = random.randint(0, 999)
+ if self.score > self.scoreWater:
+ if platformType < 900:
+ return self.platformTypeWater
+ else:
+ return self.platformTypeRaftcastle
+ elif platformType < 800:
+ if platformType < 1000 * self.score // self.scoreGrass:
+ if self.score <= self.scoreLucky and not self.hadLucky:
+ self.hadLucky = True
+ return self.platformTypeLucky
+ elif self.score <= self.scoreCastle and not self.hadCastle:
+ self.hadCastle = True
+ return self.platformTypeCastle
+ elif self.score <= self.scoreAfterLucky and not self.hadAfterLucky:
+ self.hadAfterLucky = True
+ return self.platformTypeAfterLucky
+ else:
+ return self.platformTypeGrass
+ else:
+ return self.platformTypeSand
+ elif platformType < 900:
+ return self.platformTypeGrapevine
+ else:
+ return self.platformTypeBreaking
+
+ def generateNewPlatform(self):
+ platform = False
+ platformType = self.choosePlatformType()
+ if platformType == self.platformTypeWater or platformType == self.platformTypeRaftcastle:
+ platform = [random.randint(0, self.sx - self.platformSandWidth), self.platforms[-1][1] + self.sy // 6, platformType, False, False, -1, 0, self.platformSandWidth]
+ elif platformType == self.platformTypeLucky:
+ platform = [0, self.platforms[-1][1] + self.sy // 12, platformType, False, False, -1, False, self.platformSandWidth]
+ else:
+ platform = [random.randint(0, self.sx - self.platformSandWidth), self.platforms[-1][1] + self.sy // 9, platformType, False, False, -1, 0, self.platformSandWidth]
+ if platformType <= self.platformTypeNormal:
+ if platformType == self.platformTypeSand:
+ platform[4] = random.randint(0, len(self.imgPlatformSand) - 1)
+ elif platformType == self.platformTypeGrass:
+ platform[4] = random.randint(0, len(self.imgPlatformGrass) - 1)
+ else:
+ platform[4] = random.randint(0, len(self.imgPlatformWater) - 1)
+ x = platform[0]
+ y = platform[1]
+ if platformType == self.platformTypeGrass and self.score > self.scoreSnake and not self.hadSnake:
+ platform[5]=self.itemTypeSnake
+ self.items.append([x - 10, y + 9, self.itemTypeSnake, False])
+ self.hadSnake = True
+ elif platformType == self.platformTypeGrass and self.score > self.scorePrickly and not self.hadPrickly:
+ platform[5]=self.itemTypePrickly
+ self.items.append([x + self.imgPlatformSand[0].get_width() // 3, y + 8, self.itemTypePrickly, False])
+ self.hadPrickly = True
+ elif self.score > 0:
+ check = random.randint(0, 999)
+ if check > 800:
+ xx = x + random.randint(0, self.platformSandWidth - 40)
+ itemType = random.randint(0,999)
+ if itemType < 50:
+ platform[5]=self.itemTypeBeanie
+ self.items.append([xx, y + 7, self.itemTypeBeanie, False])
+ elif itemType < 150 and platformType == self.platformTypeSand:
+ platform[5]=self.itemTypeSandcastle
+ self.items.append([xx, y + 7, self.itemTypeSandcastle, False])
+ elif itemType < 350 and platformType == self.platformTypeSand:
+ platform[5]=self.itemTypeFlag
+ self.items.append([xx, y + 7, self.itemTypeFlag, False])
+ elif itemType < 950 and platformType == self.platformTypeSand:
+ platform[5]=self.itemTypePlantSand
+ self.items.append([xx, y + 8, self.itemTypePlantSand, itemType % len(self.imgPlantSand)])
+ elif itemType < 100 and platformType == self.platformTypeGrass:
+ platform[5]=self.itemTypeFlag
+ self.items.append([xx, y + 6, self.itemTypeFlag, False])
+ elif itemType < 700 and platformType == self.platformTypeGrass:
+ platform[5]=self.itemTypePlantGrass
+ self.items.append([xx, y + 10, self.itemTypePlantGrass, itemType % len(self.imgPlantGrass)])
+ elif itemType < 850 and platformType == self.platformTypeGrass and self.score > self.scorePrickly:
+ platform[5]=self.itemTypePrickly
+ self.items.append([xx, y + 8, self.itemTypePrickly, False])
+ elif itemType < 950 and platformType == self.platformTypeGrass and self.score > self.scoreSnake:
+ platform[5]=self.itemTypeSnake
+ self.items.append([x - 10, y + 9, self.itemTypeSnake, False])
+ else:
+ platform[5]=self.itemTypeAccelerator
+ self.items.append([xx - 5, y + 10, self.itemTypeAccelerator, False])
+ if platform != False:
+ self.platforms.append(platform)
+
+ def updatePlatforms(self):
+ while True:
+ if len(self.platforms) < 1:
+ return
+ if self.platforms[0][1] - self.cameray >= - self.platformSandHeight - self.sy // 12:
+ break
+ self.generateNewPlatform()
+ self.platforms.pop(0)
+ if self.score > 1:
+ self.score -= 1
+ for p in self.platforms:
+ rect = pygame.Rect(p[0], p[1], p[7], self.platformSandHeight)
+ colX = self.playerx % self.sx
+ player = pygame.Rect(colX + 15, self.playery, self.playerWidth - 30, self.playerHeight)
+ collision = rect.colliderect(player)
+ if colX > self.sx - self.playerWidth:
+ player = pygame.Rect(colX - self.sx + 15, self.playery, self.playerWidth - 30, self.playerHeight)
+ collision = rect.colliderect(player) or collision
+ if collision and self.gravity:
+ if p[2] == self.platformTypeBreaking:
+ p[4] = True
+ else:
+ self.jump = self.sy // 20
+ self.aiNextPlatformOk = False
+ self.gravity = 0
+ if p[2] == self.platformTypeLucky and not (self.playerWearsBeanie and self.playerCarriesFlag) and p[3] <= 0:
+ self.aiNextPlatformOk = False
+ self.xmovement = self.sx // 20
+ self.direction = 0
+ self.cameray -= self.sy // 12
+ p[3] = -1
+ elif (p[2] == self.platformTypeAfterLucky or p[2] == self.platformTypeCastle or p[2] == self.platformTypeLucky) and self.playerCarriesFlag and not p[3]:
+ self.playerCarriesFlag = False
+ p[3] = True
+ self.sandcastles += 1
+ elif p[2] == self.platformTypeRaftcastle and self.playerCarriesFlag and not self.raftcastleHasFlag:
+ self.playerCarriesFlag = False
+ self.raftcastleHasFlag = True
+ self.sandcastles += 1
+ if p[2] > self.platformTypeNormal and p[2] <= self.platformTypeFloating:
+ if p[4]:
+ p[0] += self.platformSpeed
+ if p[0] + p[7] >= self.sx:# + self.extrax:
+ p[4] = False
+ else:
+ p[0] -= self.platformSpeed
+ if p[0] <= 0:
+ p[4] = True
+
+ def drawPlatforms(self):
+ for p in self.platforms:
+ if p[2] == self.platformTypeSand:
+ self.screen.blit(self.imgPlatformSand[p[4]], (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeGrass:
+ self.screen.blit(self.imgPlatformGrass[p[4]], (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeWater:
+ self.screen.blit(self.imgPlatformWater[p[4]], (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeGrapevine:
+ self.screen.blit(self.imgPlatformGrapevine, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeAfterLucky:
+ if p[3]:
+ self.screen.blit(self.imgFlagRight, (p[0] + 47, p[1] - 12 - self.cameray))
+ self.screen.blit(self.imgPlatformAfterLucky, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeCastle:
+ if p[3]:
+ self.screen.blit(self.imgFlagRight, (p[0] + self.imgPlatformCastle.get_width() - 16, p[1] - 4 - self.cameray))
+ self.screen.blit(self.imgPlatformCastle, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeLucky:
+ if p[3]:
+ self.screen.blit(self.imgPlatformLuckyAttacking, (p[0], p[1] - self.imgPlatformLuckyAttacking.get_height() + self.imgPlatformLuckySleeping.get_height() - self.cameray))
+ if p[3] > 0:
+ self.screen.blit(self.imgFlagRight, (p[0] + self.imgPlatformLuckyAttacking.get_width() - 8, p[1] - 11 - self.cameray))
+ else:
+ self.screen.blit(self.imgPlatformLuckySleeping, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeRaftcastle:
+ if self.raftcastleHasFlag:
+ self.screen.blit(self.imgFlagRight, (p[0] + 50, p[1] - 13 - self.cameray))
+ self.screen.blit(self.imgPlatformRaftcastle, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeBreaking:
+ if not p[4]:
+ self.screen.blit(self.imgPlatformBreaking, (p[0], p[1] - self.cameray))
+ else:
+ self.screen.blit(self.imgPlatformBroken, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeTheEnd:
+ self.screen.blit(self.imgPlatformTheEnd, (p[0], p[1] - self.cameray))
+ elif p[2] == self.platformTypeWonTheGame:
+ self.screen.blit(self.imgPlatformWonTheGame, (p[0], p[1] - self.cameray))
+ if self.aiDebag:
+ self.screen.blit(self.font.render(str(p[2])+" "+str(p[5])+" "+str(p[6]), -1, (0, 0x57, 0xaf) if self.ai else (0xbb, 0x66, 0x22)), (p[0], p[1] - self.cameray + 16))
+ if self.aiDebag:
+ self.screen.blit(self.imgMolpArrow, (self.aiNextPlatform[0] + (self.platformSandWidth-self.playerWidth)//2, self.aiNextPlatform[1] - self.cameray + 16))
+
+ def drawAndUpdateItems(self):
+ while self.items and self.items[0][1] - self.cameray > self.sy + self.sy // 12:
+ self.items.pop(0)
+ for item in self.items:
+ if item[2] == self.itemTypeAccelerator:
+ if item[-1]:
+ imgItem = self.imgAcceleratorUsed
+ else:
+ imgItem = self.imgAccelerator
+ elif item[2] == self.itemTypeBeanie:
+ if not item[-1]:
+ imgItem = self.imgBeanie
+ else:
+ imgItem = None
+ elif item[2] == self.itemTypeSnake:
+ if item[-1] == -1:
+ imgItem = self.imgSnakeLeft
+ elif item[-1] == 1:
+ imgItem = self.imgSnakeRight
+ else:
+ imgItem = self.imgSnake
+ elif item[2] == self.itemTypePrickly:
+ if not item[-1]:
+ imgItem = self.imgPrickly
+ else:
+ imgItem = self.imgPricklyCurled
+ elif item[2] == self.itemTypeSandcastle:
+ imgItem = self.imgSandcastle
+ if item[-1]:
+ self.screen.blit(self.imgFlagRight, (item[0] + 4, item[1] - imgItem.get_height() + 2 - self.imgFlagRight.get_height() - self.cameray))
+ elif item[2] == self.itemTypeFlag:
+ if not item[-1]:
+ imgItem = self.imgFlagRight
+ else:
+ imgItem = None
+ elif item[2] == self.itemTypePlantSand:
+ imgItem = self.imgPlantSand[item[-1]]
+ elif item[2] == self.itemTypePlantGrass:
+ imgItem = self.imgPlantGrass[item[-1]]
+ if imgItem:
+ self.screen.blit(imgItem, (item[0], item[1] - imgItem.get_height() - self.cameray))
+ if not item[-1]:
+ if pygame.Rect(item[0], item[1] - imgItem.get_height(), imgItem.get_width(), imgItem.get_height()).colliderect(pygame.Rect(self.playerx, self.playery, self.imgPlayerRightUp.get_width(), self.imgPlayerRightUp.get_height())):
+ if item[2] == self.itemTypeAccelerator:
+ self.aiNextPlatformOk = False
+ self.jump = self.sy // 12
+ self.cameray -= self.sy // 12
+ item[-1] = True
+ elif item[2] == self.itemTypeBeanie and not self.playerWearsBeanie:
+ self.playerWearsBeanie = True
+ item[-1] = True
+ elif item[2] == self.itemTypeSnake:
+ self.aiNextPlatformOk = False
+ if self.playerx + self.imgPlayerRightUp.get_width() // 2 < item[0] + self.imgPlatformGrass[0].get_width() // 2:
+ self.xmovement = -self.sx // 30
+ self.direction = 0
+ self.cameray -= self.sy // 12
+ item[-1] = -1
+ else:
+ self.xmovement = self.sx // 30
+ self.direction = 0
+ self.cameray -= self.sy // 12
+ item[-1] = 1
+ elif item[2] == self.itemTypePrickly:
+ item[-1] = True
+ elif item[2] == self.itemTypeSandcastle and self.playerCarriesFlag:
+ self.playerCarriesFlag = False
+ item[-1] = True
+ self.sandcastles += 1
+ elif item[2] == self.itemTypeFlag and not self.playerCarriesFlag:
+ self.playerCarriesFlag = True
+ item[-1] = True
+
+ def generateInitialPlatforms(self):
+ while self.platforms[-1][1] < self.sy * 10 // 6:
+ self.generateNewPlatform()
+
+ def drawGrid(self):
+ for x in range(80):
+ pygame.draw.line(self.screen, (222,222,222), (x * 12, 0), (x * 12, self.sy))
+ pygame.draw.line(self.screen, (222,222,222), (0, x * 12), (self.sx, x * 12))
+
+ def waitForIt(self, its):
+ run = False
+ while not run:
+ self.clock.tick(self.speed)
+ event = pygame.event.poll()
+ if event.type == KEYDOWN:
+ key = pygame.key.get_pressed()
+ if key[K_ESCAPE]:
+ sys.exit()
+ for it in its:
+ if key[it]:
+ return it
+
+ def showScore(self):
+ line1 = self.font.render("Press ENTER to restart,", -1, (0, 0, 0))
+ line2 = self.font.render("ESC to quit.", -1, (0, 0, 0))
+ w = max(line1.get_width(), line2.get_width())
+ h = line1.get_height() + line2.get_height()
+ dx = 10
+ dy = 5
+ pygame.draw.rect(self.screen, (255,255,255), ((self.sx - w) // 2 - dx, (self.sy - h) // 2 - dy, w + 2 * dx, h + 2 * dy))
+ pygame.draw.rect(self.screen, (0,0,0), ((self.sx - w) // 2 - dx, (self.sy - h) // 2 - dy, w + 2 * dx, h + 2 * dy), 3)
+ self.screen.blit(line1, ((self.sx - line1.get_width()) // 2, self.sy // 2 - line1.get_height()))
+ self.screen.blit(line2, ((self.sx - line2.get_width()) // 2, self.sy // 2))
+ pygame.display.flip()
+ self.waitForIt([K_RETURN])
+
+ def run(self):
+ if len(sys.argv) > 1:
+ self.filename = sys.argv[1]
+ else:
+ self.filename = None
+ self.reset()
+ while True:
+ self.screen.fill((255,255,255))
+ self.clock.tick(self.speed)
+ for event in pygame.event.get():
+ if event.type == QUIT:
+ sys.exit()
+ elif event.type == KEYDOWN:
+ key = pygame.key.get_pressed()
+ if key[K_ESCAPE]:
+ sys.exit()
+ elif key[K_i]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.ai = not self.ai
+ self.aiNextPlatformOk = False
+ self.modeText = "AI " + ('enabled' if self.ai else 'disabled')
+ elif key[K_d]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.aiDebag = not self.aiDebag
+ self.modeText = "AI debug " + ('enabled' if self.aiDebag else 'disabled')
+ elif key[K_e]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.eternal = not self.eternal
+ self.eternalFlag = False
+ self.modeText = "Eternal mode " + ('enabled' if self.eternal else 'disabled')
+ elif key[K_g]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.eternalFlag = not self.eternalFlag
+ self.eternal = False
+ self.modeText = "Eternal (flag) mode " + ('enabled' if self.eternalFlag else 'disabled')
+ elif key[K_f]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.playerCarriesFlag = not self.playerCarriesFlag
+ self.modeText = "Flag " + ('added' if self.playerCarriesFlag else 'removed')
+ elif key[K_b]:
+ if pygame.key.get_mods() & KMOD_CTRL:
+ self.playerWearsBeanie = not self.playerWearsBeanie
+ self.modeText = "Beanie " + ('added' if self.playerWearsBeanie else 'removed')
+ elif key[K_SPACE]:
+ self.modeText = "Wait for it."
+ self.pause = True
+ elif key[K_s]:
+ self.saveGame()
+ self.modeText = "Saved"
+ elif key[K_a]:
+ self.showArrow = not self.showArrow
+ self.modeText = "Arrow " + ('enabled' if self.showArrow else 'disabled')
+ self.drawGrid()
+ self.drawPlatforms()
+ self.drawAndUpdateItems()
+ self.updatePlayer()
+ self.updatePlatforms()
+ self.screen.blit(self.font.render(str(self.score), -1, (0, 0, 0)), (self.sx // 32, self.sy // 24))
+ for i in range(0, self.sandcastles):
+ self.screen.blit(self.imgFlagRight, (self.sx // 32 + 10 * i, self.sy // 8))
+ if self.modeText != '':
+ self.screen.blit(self.font.render(self.modeText, -1, (0, 0, 0)), (self.sx // 32, self.sy - self.sy // 12))
+
+ if self.oops:
+ self.showScore()
+ self.reset()
+ pygame.display.flip()
+
+ if self.pause:
+ self.modeText = "RUN!"
+ while self.waitForIt([K_SPACE, K_s]) == K_s:
+ self.saveGame()
+ self.modeText = "Saved"
+ self.pause = False
+
+MolpyUp().run()