From 9b105877f7d4db2efb215d8b89467d6063c22217 Mon Sep 17 00:00:00 2001 From: b Date: Fri, 27 Mar 2026 00:09:40 +0100 Subject: [PATCH] start with Molpy Down! --- assets/platformFrame1.png | Bin 0 -> 1884 bytes molpydown.py | 856 ++++++++++++++++++++++++++++++++++++++ molpyup.py | 4 +- 3 files changed, 858 insertions(+), 2 deletions(-) create mode 100644 assets/platformFrame1.png create mode 100644 molpydown.py diff --git a/assets/platformFrame1.png b/assets/platformFrame1.png new file mode 100644 index 0000000000000000000000000000000000000000..591ff890515eec01b55c8eb0204826117372fdea GIT binary patch literal 1884 zcma)7YgCg*8vcS@b}1@tT~wl=!N#R%0s@JE1gimqK_d_nWCe7?rBDopi_wTlYOA$k zWZ438m2QD53Abz-5QeCrXtc$5^jP0()FC(v;5gV^UOTwop+x1 zGBaPEI(clPy|X<402@O|#0UVea);-i{>~O2ZH|8U9RS$5g%UraUK*Lvp2&-fLUhdq z72r2W`R{FEOpvple_t#g+(t)Zv@NfZ#qzoLA7bQ%8(_)o*Uftuaw?={Y(u8qwBz(PN2(%gEWd-CJ#I)6`ByD6RUoGn1OMY@co zi@LpI;wokD857EJ>Z_wN_C4v-%;>X{{fdLZ)&e9GvDCw+x_ngXX)|v+*orCSF15771sJBYXqNk zE*~Qc9Jr)j;jzBuq!DD{=6`r1c16ge>Sz=y)))OwP%7!)-f$Rf?5rLP{{&*yvRu~1x?e#<&T5)*0O9D~bl5{skz3hFh`gH2eb~t|>Z2K}%InNA?WK1AxIoX(k_S&& z-P{s=i|n0o$ES!_c`rSWilsM7+gZB+l#LTZB7T3aMZtWOjx)+Mt=GGUZg7(&_V$OX zyN<-BhBJZy0QyKB4g^TjkKO$g5Ws>f8pIBi%?k0#jzE-+Bv%xD}k%&HA4dg->8GoHs z)qrf8Np;h2(718Gx=%+#CV$+lnyBl0t??}9lMqGI0tK40R>v)m3WJwU(^>Nph06go zPSp&{Ivb8d1}qV@@`0a2=FetRbO#3Fo!QT99o@UWsf(hh_?PRv)@&??Wy)DYlNv>} z*4aey?|(v3%x?dUt`a+^r0ck$Y^uo@|i5Yb;Nx9`W| zXsCKT`i;wj)$$L1+7$sfIeQ*MLgz4eBhPQ_AOi}UZ{2N`Z`DNHiY(Kd_dzeYG#J%Q zmqo4p@`5a`t>Edqu=?n755dNnO-lahig1Xid+A_tG#N54Gqfno1#yj=aQa7Qa_;Kb z^gL?3sDpl$eM2P?NDg9~+n0Xt=nky0%LFH8RBF$b&Jl=EHFbgEqCBqKq>(8f$IM4a z8@=x9OV5Q=-`v8l@%xjxnIjb6dU4??S^7~m(6nt>ztg8*@hrPi}brY|sh^GT_YjRhSQM9!N5p!EvKV3 zAsP;1pHix@&BFRzd>;7Z;BrRvLpTZ1-~1xz4PHjxy=C;p)m-WB|Bcgm$87S!-46hb z=D*M!Hp9w3;7G)Gdm#ZBLZPK2o$^ue)>5fq&am}ba5c~sQBTdo>7|FlD}45#Y=ENa z8UtPs5IlQ6?fBzn3U#x3c%e`+TDf_G0T!l0yd9=V15$7T*o?zyqO=6wjW2}W+J}D6 zhNfOsxbm8pmUxS+ZNc_{?C+4kd*9xqx|gC?4+!yBQ(Po8?O=3vRw9Aj&S?@;m!t|8 zPqs>@Qg0nl`_lI8Ouy3eM9zNZYDdg{Aj zB7ZU416*3U@>1hf^o6h&lueDN^wug8TLQri0rz;HaM!fZa==$sz~~4QZw +# Copyright (C) 2015 by Frankie Primerano, +# written in 120 minutes, see . +# +# Copyright (C) 2018 by Peter Gerwinski , +# 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 +# . +# +# The player figure "Molpy" is +# Copyright (C) 2013 by BlitzGirl, see user "BlitzGirl" at , +# 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 , +# released under the Creative Commonns Attribution-NonCommercial Generic License, +# version 2.5 (CC BY-NC 2.5), see . +# +# 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() diff --git a/molpyup.py b/molpyup.py index bd18fe4..4e9f59c 100644 --- a/molpyup.py +++ b/molpyup.py @@ -174,7 +174,7 @@ class MolpyUp: self.sandcastles = 0 self.speed = 30 self.modeText = '' - self.playerx = self.sx // 2 + self.playerx = self.sx // 2 - self.playerHalfWidth self.playery = self.sy * 3 // 4 self.direction = 0 self.jump = 0 @@ -854,4 +854,4 @@ class MolpyUp: self.modeText = "Saved" self.pause = False -MolpyUp().run() \ No newline at end of file +MolpyUp().run() -- 2.30.2