Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Code by Anthony Cook
- # fb.com/groups/pygame
- # TESTER NOTES:
- # use 'a' and 'd' to more the character left and right
- # 'space' to jump
- # mouse and left mouse button to place platforms
- import pygame
- import pygame.gfxdraw
- import sys, os, time, math, random
- import collections
- import lzma, base64
- # Pygame contants
- W = 1280
- H = 720
- HW = int(W / 2)
- HH = int(H / 2)
- FPS = 60
- # Define some colors
- FUCHSIA = [255, 0, 255]
- PURPLE = [128, 0, 128]
- TEAL = [ 0, 128, 128]
- LIME = [ 0, 255, 0]
- GREEN = [ 0, 128, 0]
- OLIVE = [128, 128, 0]
- DOLIVE = [ 64, 64, 0]
- YELLOW = [255, 255, 0]
- ORANGE = [255, 165, 0]
- RED = [255, 0, 0]
- MAROON = [128, 0, 0]
- SILVER = [192, 192, 192]
- GRAY = [128, 128, 128]
- BLUE = [ 0, 0, 255]
- NAVY = [ 0, 0, 128]
- AQUA = [ 0, 255, 255]
- WHITE = [255, 255, 255]
- BLACK = [ 0, 0, 0]
- FONT_DATA = b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4Aw9AW5dAACO8kOjEfa2JjD81EffSaUPknD93Eph1Fsy7hNTgvcZJxKO8vuqgc3XN\
- 3Lz2F/+rT9w9iuzsmBXzqTvbkREQ7Io0T/ALfy6MU/6BR7cC0iyLG9bk6y+A7e4DJDb86aloX9r2qeu1DnBUOu7ie8Y+Z8hOQg9rNd4bu5wlIPL\
- UIejdSo0RcIJiS5w1xmTlmFEI8n7isSpL+Zl3NNk/Hgrd+ajfx+dJ2r/+ENsaRYWNLJ8ZRkUMl3ECYmC9pzK5cMH9EZ/CTJLhNIFZq3EpapLc7+\
- dRZOMN3uxtEshysWcJJHip5CTAkjAoFbu4Tl0J8gtke66of1u/gv69rGbru0lbd0eY5MdQfHs1U1WtrBgJ7Di9mSu7h1YHvm07W8DhcOkb26+NG\
- 0/kV7JyQMczTE6VV6qN2FAK8JnjpkCh40xg63Dxi2m7N3JiKvl1tE/gPOvSJkGQIus7HQFHXjc6DouLaw3zh81ra8HDg4ZRQAvLAAAALI4wzJkk\
- ZgtAAGKA74YAADSUkbUscRn+wIAAAAABFla'
- FONT_CHARMAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.!-"
- GRAVITY = 0.5
- def gradient(rgb1, rgb2, frames):
- rStep = (rgb2[0] - rgb1[0]) / frames
- gStep = (rgb2[1] - rgb1[1]) / frames
- bStep = (rgb2[2] - rgb1[2]) / frames
- return [[int(rgb1[0] + rStep * i), int(rgb1[1] + gStep * i), int(rgb1[2] + bStep * i)] for i in range(frames)] + [rgb2]
- def imgUnzip(lz64):
- data = lzma.decompress(base64.b64decode(lz64))
- imageW = int.from_bytes(data[0:2], "big")
- imageH = int.from_bytes(data[2:4], "big")
- paletteLength = int.from_bytes(data[4:5], "big")
- palette = [int.from_bytes(data[5 + index * 3:8 + index * 3], "big") for index in range(paletteLength)]
- pixelDataStart = 5 + paletteLength * 3
- surface = pygame.Surface((imageW, imageH))
- pixelArray = pygame.PixelArray(surface)
- for index in range(0, len(data) - pixelDataStart):
- pixelArray[index % imageW][int(index / imageW)] = palette[data[pixelDataStart + index]]
- pixelArray.close()
- del pixelArray
- return surface
- class gameTime:
- def __init__(s, fps):
- s.timeStamp = time.time()
- s.time = 0
- s.fps = fps
- s.tpf = 1 / fps
- s.paused = False
- def secs(s, seconds):
- return s.fps * seconds
- def tick(s):
- while time.time() - s.timeStamp < s.tpf:
- pass
- s.timeStamp = time.time()
- if not s.paused:
- s.time += 1
- class event:
- def __init__(s, obj, start, interval, maxCount):
- s.obj = obj
- s.start = start
- s.interval = interval
- s.maxCount = maxCount
- s.count = 0
- class rect:
- def __init__(s, rect, active = True):
- s.x = rect[0]
- s.y = rect[1]
- s.w = rect[2]
- s.h = rect[3]
- s.active = active
- s.collisionActive = True
- s.dead = False
- def setXY(s, coords):
- s.x = coords[0]
- s.y = coords[1]
- def testObj(s, obj):
- if s.x <= obj.RECT.x2() and s.x2() >= obj.RECT.x and s.y <= obj.RECT.y2() and s.y2() >= obj.RECT.y:
- return True
- return False
- def testRect(s, rect):
- if s.x <= rect[0] + rect[2] and s.x2() >= rect[0] and s.y <= rect[1] + rect[3] and s.y2() >= rect[1]:
- return True
- return False
- def testEdges(s, obj, fXY):
- for edgeIndex in range(4):
- if not obj.EDGE_COLLISION[edgeIndex]: continue
- if edgeIndex == 0:
- if s.y2() <= obj.RECT.y and fXY[1] + s.h >= obj.RECT.y and s.x2() >= obj.RECT.x and s.x <= obj.RECT.x2():
- return 0
- elif edgeIndex == 1:
- if s.x >= obj.RECT.x2() and fXY[0] < obj.RECT.x2() and s.y2() >= obj.RECT.y and s.y <= obj.RECT.y2():
- return 1
- elif edgeIndex == 2:
- if s.y >= obj.RECT.y2() and fXY[1] <= obj.RECT.y2() and s.x2() >= obj.RECT.x and s.x <= obj.RECT.x2():
- return 2
- elif edgeIndex == 3:
- if s.x2() <= obj.RECT.x and fXY[0] + s.w >= obj.RECT.x and s.y2() >= obj.RECT.y and s.y <= obj.RECT.y2():
- return 3
- return None
- def intRect(s):
- return [int(s.x), int(s.y), int(s.w), int(s.h)]
- def intXY(s):
- return [int(s.x), int(s.y)]
- def x1(s):
- return int(s.x)
- def y1(s):
- return int(s.y)
- def x2(s):
- return int(s.x + s.w)
- def y2(s):
- return int(s.y + s.h)
- def intXYOffset(s, x, y):
- return [int(s.x + x), int(s.y + y)]
- def center(s):
- return [int(s.x + s.w / 2), int(s.y + s.h / 2)]
- def xCenter(s):
- return int(s.x + s.w / 2)
- def yCenter(s):
- return int(s.y + s.h / 2)
- class stage:
- class placeHolder:
- ID = "placeholder"
- def __init__(s, r, ownID):
- s.RECT = rect(r)
- s.ownerID = ownID
- def reset(s):
- s.timeStamp = s.time.time
- s.paused = False
- s.score = 0
- s.previousScore = 0
- s.lives = 0
- s.gameOver = False
- s.tempAddObjects = []
- s.tempRemoveObjects = []
- s.container = []
- s.objectCounts = {}
- s.timeEvents = []
- s.scoreEvents = []
- s.layers = collections.OrderedDict()
- s.setupLayers()
- s.setupObjects()
- def setupLayers(s):
- for name in s.layerNames:
- s.layers[name] = []
- def setupObjects(s):
- for obj in s.objects:
- if hasattr(obj, "LAYER") and hasattr(obj, "ADD_IMMEDIATELY"):
- newObj = obj(s)
- s.layers[obj.LAYER].append(newObj)
- s.container.append(newObj)
- s.objectCounts[newObj.ID] = 1
- if hasattr(obj, "TIME_EVENT"):
- s.timeEvents.append(event(obj, obj.EVENT_START, obj.EVENT_INTERVAL, obj.EVENT_MAXCOUNT))
- if hasattr(obj, "SCORE_EVENT"):
- s.scoreEvents.append(event(obj, obj.EVENT_START, obj.EVENT_INTERVAL, obj.EVENT_MAXCOUNT))
- def setFont(s, font):
- s.font = font
- def setObjects(s, objects):
- s.objects = objects
- def setTimer(s, gameTimeObject):
- s.time = gameTimeObject
- def setLayers(s, layerNames):
- s.layerNames = layerNames
- def setAllVars(s, font, layerNames, objects, gameTimeObject):
- s.font = font
- s.layerNames = layerNames
- s.objects = objects
- s.time = gameTimeObject
- def do(s):
- s.draw()
- s.time.tick()
- s.move()
- s.purgeObjects()
- s.collisions()
- s.events()
- s.addObjects()
- def draw(s):
- for layer in s.layers:
- for obj in s.layers[layer]:
- if obj.RECT.active:
- obj.draw()
- pygame.display.update()
- def move(s):
- for layer in s.layers:
- for obj in s.layers[layer]:
- if obj.RECT.active:
- if not s.paused:
- obj.do(s)
- elif hasattr(obj, "DO_WHILE_PAUSED"):
- obj.do(s)
- if obj.RECT.dead: s.tempRemoveObjects += [obj]
- def collisions(s):
- for obj in s.container:
- if obj.RECT.active and obj.RECT.collisionActive and not obj.RECT.dead and hasattr(obj, 'COLLISION_DETECTION'):
- for colObj in s.container:
- if obj != colObj and colObj.RECT.active and not colObj.RECT.dead and colObj.RECT.collisionActive:
- if hasattr(colObj, 'EDGE_COLLISION'):
- edgeIndex = obj.RECT.testEdges(colObj, obj.futureMove())
- if edgeIndex != None:
- obj.collision(s, colObj, edgeIndex)
- else:
- if obj.RECT.testObj(colObj):
- obj.collision(s, colObj)
- def events(s):
- now = s.time.time
- for timeEvent in s.timeEvents:
- if now < timeEvent.start: continue
- if now == timeEvent.start or (now - timeEvent.start) % timeEvent.interval == timeEvent.interval - 1:
- if s.objectCounts[timeEvent.obj.ID] < timeEvent.maxCount:
- s.addObject(timeEvent.obj(s))
- for scoreEvent in s.scoreEvents:
- if s.score < scoreEvent.start: continue
- if s.score >= scoreEvent.start and not scoreEvent.count:
- scoreEvent.count += 1
- s.addObject(scoreEvent.obj(s))
- elif (s.score - scoreEvent.start) >= scoreEvent.interval * scoreEvent.count and s.objectCounts[scoreEvent.obj.ID] < scoreEvent.maxCount:
- s.addObject(scoreEvent.obj(s))
- scoreEvent.count += 1
- def purgeObjects(s):
- while s.tempRemoveObjects:
- obj = s.tempRemoveObjects.pop()
- s.container.remove(obj)
- s.objectCounts[obj.ID] -= 1
- if hasattr(obj, "LAYER"):
- s.layers[obj.LAYER].remove(obj)
- def addObjects(s):
- while s.tempAddObjects:
- obj = s.tempAddObjects.pop()
- s.container.append(obj)
- if obj.ID in s.objectCounts:
- s.objectCounts[obj.ID] += 1
- else:
- s.objectCounts[obj.ID] = 1
- if hasattr(obj, "LAYER"):
- s.layers[obj.LAYER].append(obj)
- def addObject(s, obj):
- s.tempAddObjects.append(obj)
- return obj
- def addPlaceHolder(s, rect, id):
- obj = s.placeHolder(rect, id)
- s.tempAddObjects.append(obj)
- return obj
- def delPlaceHolder(s, ph):
- s.tempRemoveObjects.append(ph)
- # rect is potential location for object s = stage
- def testAllRect(s, rect, invalidIDs = [], validIDs = []):
- for colObj in s.container:
- if colObj.ID in invalidIDs or not colObj.RECT.active or colObj.RECT.dead or not colObj.RECT.collisionActive: continue
- if validIDs:
- if colObj.ID in validIDs:
- if colObj.RECT.testRect(rect): return True
- else:
- if colObj.RECT.testRect(rect): return True
- return False
- class font:
- def __init__(s, img, charMap, spacing):
- s.surfaceWidth, s.surfaceHeight = img.get_size()
- s.fontSurface = img.copy()
- s.monochromeFonts = {}
- s.cols = len(charMap)
- s.charWidth = int(s.surfaceWidth / s.cols)
- s.spacing = spacing
- s.charMap = charMap
- def text(s, text, scale = None, colorName = None):
- surfaceWidth = len(text) * s.charWidth + s.spacing * (len(text) - 1)
- surface = pygame.Surface((surfaceWidth, s.surfaceHeight))
- charPosX = 0
- for c in text:
- charIndex = s.charMap.find(c)
- if charIndex == -1:
- charPosX += s.charWidth + s.spacing
- continue
- charOffsetX = charIndex * s.charWidth
- if colorName:
- surface.blit(s.monochromeFonts[colorName], (charPosX, 0), (charOffsetX, 0, s.charWidth, s.surfaceHeight))
- else:
- surface.blit(s.fontSurface, (charPosX, 0), (charOffsetX, 0, s.charWidth, s.surfaceHeight))
- charPosX += s.charWidth + s.spacing
- if scale != None:
- return pygame.transform.scale(surface, (surfaceWidth * scale, s.surfaceHeight * scale))
- return surface
- def newMonochromeFont(s, name, color):
- global DS
- monochromeSurface = s.fontSurface.copy()
- monochromePA = pygame.PixelArray(monochromeSurface)
- for x in range(s.surfaceWidth):
- for y in range(s.surfaceHeight):
- if monochromePA[x][y] != 0: monochromePA[x][y] = DS.map_rgb(color)
- monochromePA.close()
- del monochromePA
- s.monochromeFonts[name] = monochromeSurface
- def size(s, text, scale = 1):
- w = len(text) * s.charWidth + s.spacing * (len(text) - 1)
- h = s.surfaceHeight
- return [w * scale, h * scale]
- BACKGROUND_COLOR_TOP = [0, 35, 35]
- BACKGROUND_COLOR_BOTTOM = [0, 32, 32]
- class background:
- ID = "background"
- LAYER = "background"
- ADD_IMMEDIATELY = True
- class backgroundPoint:
- def __init__(s, x):
- global HH
- s.p = [x, 0]
- s.r = random.randint(50, HH - 50)
- s.a = random.uniform(0, 6.283185307179586)
- s.s = random.uniform(0.01, 0.035)
- def calc(s):
- global HH
- s.p[1] = HH + int(math.cos(s.a) * s.r)
- s.a += s.s
- def __init__(s, S):
- global W, H
- s.RECT = rect((0, 0, W, H))
- s.RECT.collisionActive = False
- s.points = [s.backgroundPoint(x) for x in range(0, W, int(W / 10))] + [s.backgroundPoint(W)]
- s.poly1 = [[W, 0], [0, 0]] + [bp.p for bp in s.points]
- s.poly2 = [[W, H], [0, H]] + [bp.p for bp in s.points]
- def draw(s):
- global DS
- global BACKGROUND_COLOR_TOP, BACKGROUND_COLOR_BOTTOM
- pygame.draw.polygon(DS, BACKGROUND_COLOR_TOP, s.poly1)
- pygame.draw.polygon(DS, BACKGROUND_COLOR_BOTTOM, s.poly2)
- def do(s, S):
- for bp in s.points: bp.calc()
- s.draw()
- PLATFORM_BLOCK_SIZE = 10
- PLATFORM_BLOCK_MAX_STATIC_TIME = 0.5 # secs
- PLATFORM_BLOCK_MAX_STATIC_FRAMES = int(FPS * PLATFORM_BLOCK_MAX_STATIC_TIME)
- PLATFORM_BLOCK_FALL_TIME = 0.25 # secs
- PLATFORM_BLOCK_FALL_FRAMES = int(FPS * PLATFORM_BLOCK_FALL_TIME)
- PLATFORM_BLOCK_GRAVITY = GRAVITY * 1.25
- PLATFORM_WIDTH_IN_BLOCKS = 10
- PLATFORM_HEIGHT_IN_BLOCKS = 3
- PLATFORM_WIDTH = PLATFORM_BLOCK_SIZE * PLATFORM_WIDTH_IN_BLOCKS
- PLATFORM_HALF_WIDTH = int(PLATFORM_WIDTH / 2)
- PLATFORM_HEIGHT = PLATFORM_BLOCK_SIZE * PLATFORM_HEIGHT_IN_BLOCKS
- PLATFORM_HALF_HEIGHT = int(PLATFORM_HEIGHT / 2)
- PLATFORM_STATIC_POS = [10, H - PLATFORM_HEIGHT - 10]
- PLATFORM_COLOR = DOLIVE
- PLATFORM_SOLID_TIME = 3 # secs before desintergration starts
- PLATFORM_SOLID_FRAMES = int(FPS * PLATFORM_SOLID_TIME)
- class platform:
- ID = "platform"
- LAYER = "platforms"
- EDGE_COLLISION = [True, True, True ,True] # edges = [top, right, bottom, left]
- ADD_IMMEDIATELY = True
- class block:
- def __init__(s, S, x, y, w, instantFall = False):
- global PLATFORM_BLOCK_SIZE
- global PLATFORM_BLOCK_MAX_STATIC_FRAMES
- s.timeStamp = S.time.time
- if not instantFall:
- s.staticTime = random.randint(0, PLATFORM_BLOCK_MAX_STATIC_FRAMES)
- else:
- s.staticTime = 0
- s.x = x
- s.y = y
- s.w = w
- s.yv = 0 # y velocity
- s.opacity = 255
- s.dead = False
- def draw(s):
- global PLATFORM_BLOCK_SIZE
- global PLATFORM_COLOR
- global DS
- pygame.gfxdraw.box(DS, [s.x, int(s.y), s.w, PLATFORM_BLOCK_SIZE], PLATFORM_COLOR + [int(s.opacity)])
- def do(s, S):
- global PLATFORM_BLOCK_GRAVITY, PLATFORM_BLOCK_FALL_TIME
- now = S.time.time
- if now >= s.timeStamp + s.staticTime:
- fallingTime = now - (s.timeStamp + s.staticTime)
- if fallingTime >= PLATFORM_BLOCK_FALL_FRAMES:
- s.dead = True
- return
- percentage = fallingTime / PLATFORM_BLOCK_FALL_FRAMES
- s.opacity = 255 - percentage * 255
- s.y += s.yv
- s.yv += PLATFORM_BLOCK_GRAVITY
- def __init__(s, S):
- global PLATFORM_WIDTH, PLATFORM_HEIGHT, PLATFORM_HEIGHT_IN_BLOCKS, PLATFORM_HALF_WIDTH, PLATFORM_HALF_HEIGHT
- if len(S.layers[s.LAYER]):
- mx, my = pygame.mouse.get_pos()
- s.RECT = rect([mx - PLATFORM_HALF_WIDTH, my - PLATFORM_HALF_HEIGHT, PLATFORM_WIDTH, PLATFORM_HEIGHT])
- s.staticPlatform = False # Platform will not dissintergrate if True
- else:
- s.RECT = rect([10, H - 10 - PLATFORM_HEIGHT, PLATFORM_WIDTH, PLATFORM_HEIGHT])
- s.staticPlatform = True
- s.blockHeight = PLATFORM_HEIGHT_IN_BLOCKS
- s.blockContainer = []
- s.timeStamp = S.time.time
- s.dead = False
- def draw(s):
- global PLATFORM_COLOR
- global DS
- if not s.dead:
- pygame.gfxdraw.box(DS, s.RECT.intRect(), PLATFORM_COLOR)
- for block in s.blockContainer:
- block.draw()
- def do(s, S):
- global PLATFORM_BLOCK_SIZE
- global PLATFORM_SOLID_FRAMES, PLATFORM_WIDTH
- s.RECT.h = s.blockHeight * PLATFORM_BLOCK_SIZE
- if s.staticPlatform: return
- deadBlocks = []
- for block in s.blockContainer:
- block.do(S)
- if block.dead: deadBlocks.append(block)
- for thisBlock in deadBlocks:
- s.blockContainer.remove(thisBlock)
- now = S.time.time
- if now - s.timeStamp >= PLATFORM_SOLID_FRAMES:
- if not s.blockContainer:
- if s.blockHeight > 1:
- s.blockContainer = [s.block(S, s.RECT.x + index * PLATFORM_BLOCK_SIZE, s.RECT.y2() - PLATFORM_BLOCK_SIZE, PLATFORM_BLOCK_SIZE) for index in range(PLATFORM_WIDTH_IN_BLOCKS)]
- s.blockHeight -= 1
- else:
- if not s.dead:
- s.blockContainer = [s.block(S, s.RECT.x, s.RECT.y, PLATFORM_WIDTH, True)]
- s.dead = True
- s.RECT.collisionActive = False
- else:
- s.RECT.dead = True
- def die(s):
- s.timeStamp = 0
- PLATFORM_POINTER_COLOR = WHITE
- PLATFORM_POINTER_OPACITY = 128 # 0 - 255; 0 = invisible
- class platformPointer:
- ID = "pointer"
- LAYER = ID
- ADD_IMMEDIATELY = True
- DO_WHILE_PAUSED = True
- def __init__(s, S):
- global PLATFORM_WIDTH, PLATFORM_HEIGHT
- s.RECT = rect([0, 0, PLATFORM_WIDTH + 1, PLATFORM_HEIGHT + 1])
- s.RECT.collisionActive = False
- s.mousePressed = False
- def draw(s):
- global PLATFORM_POINTER_COLOR, PLATFORM_POINTER_OPACITY
- global DS
- pygame.gfxdraw.rectangle(DS, s.RECT.intRect(), PLATFORM_POINTER_COLOR + [PLATFORM_POINTER_OPACITY])
- def do(s, S):
- global PLATFORM_HALF_WIDTH, PLATFORM_HALF_HEIGHT
- mx, my = pygame.mouse.get_pos()
- s.RECT.setXY([mx - PLATFORM_HALF_WIDTH, my - PLATFORM_HALF_HEIGHT])
- if not S.paused:
- mb = pygame.mouse.get_pressed()[0]
- if mb and not s.mousePressed:
- S.addObject(platform(S))
- s.mousePressed = True
- elif not mb and s.mousePressed:
- s.mousePressed = False
- PLAYER_SIZE = 10
- PLAYER_SIZE_HALF = int(PLAYER_SIZE / 2)
- PLAYER_SIZE_QUARTER = int(PLAYER_SIZE / 4)
- PLAYER_RESPAWN_POS = [10 + PLATFORM_HALF_WIDTH - PLAYER_SIZE_HALF, -PLAYER_SIZE]
- PLAYER_GOT_FOOD_COLOR = gradient(ORANGE, RED, FPS)
- PLAYER_DEAD_COLOR = gradient(WHITE, ORANGE, FPS)
- PLAYER_X_VELOCITY = 3 # pixels
- PLAYER_JUMP_HEIGHT = 100 # pixels
- PLAYER_JUMP_TIME = 0.75 # secs
- PLAYER_JUMP_FRAMES = int(FPS * PLAYER_JUMP_TIME / 2)
- PLAYER_JUMP_GRAVITY = 2 * PLAYER_JUMP_HEIGHT / (PLAYER_JUMP_FRAMES * (PLAYER_JUMP_FRAMES - 1))
- PLAYER_JUMP_VELOCITY = -(PLAYER_JUMP_GRAVITY * (PLAYER_JUMP_FRAMES - 1))
- PLAYER_DEAD_GRAVITY = 0.1
- PLAYER_LEG_SHOW_PERCENTAGE = 0.9 # pecentage of upward velocity
- PLAYER_HAT_WIDTH = 20 # pixels
- PLAYER_HAT_COLOR = RED
- PLAYER_HAT_X_OFFSET = int((PLAYER_SIZE - PLAYER_HAT_WIDTH) / 2) # ideally the hat should bigger than PLAYER_SIZE
- PLAYER_HAT_RIM_HEIGHT = 2 # pixels
- PLAYER_HAT_CROWN_HEIGHT = 5 # pixels
- class player:
- ID = "player"
- LAYER = ID
- ADD_IMMEDIATELY = True
- COLLISION_DETECTION = True
- def __init__(s, S):
- global PLAYER_SIZE
- s.RECT = rect([0, 0, PLAYER_SIZE, PLAYER_SIZE])
- s.reset()
- def reset(s):
- global PLAYER_RESPAWN_POS
- global PLAYER_GOT_FOOD_COLOR
- s.RECT.setXY(PLAYER_RESPAWN_POS)
- s.RECT.collisionActive = True
- s.yv = 0.00001 # falling velocity
- s.xv = 0 # horizontal velocity
- s.hatPosY = 0
- s.hatOffsetY = 0
- s.dead = False
- s.colorIndex = 0
- s.color = PLAYER_GOT_FOOD_COLOR[0]
- s.colorGradient = PLAYER_GOT_FOOD_COLOR
- s.legDirection = 0
- s.legRect = None
- s.bodyRect = s.RECT.intRect()
- def draw(s):
- global PLAYER_HAT_WIDTH, PLAYER_HAT_RIM_HEIGHT, PLAYER_HAT_CROWN_HEIGHT # dimensions
- global PLAYER_HAT_X_OFFSET # position
- global PLAYER_HAT_COLOR # color
- global DS
- hx, hy = s.bodyRect[0:2]
- # Player's hat
- pygame.gfxdraw.box(DS, (hx + PLAYER_HAT_X_OFFSET, hy - PLAYER_HAT_RIM_HEIGHT + s.hatOffsetY, PLAYER_HAT_WIDTH, PLAYER_HAT_RIM_HEIGHT), PLAYER_HAT_COLOR)
- pygame.gfxdraw.box(DS, (hx, hy - PLAYER_HAT_RIM_HEIGHT - PLAYER_HAT_CROWN_HEIGHT + s.hatOffsetY, 10, PLAYER_HAT_CROWN_HEIGHT), PLAYER_HAT_COLOR)
- # Player's body
- pygame.gfxdraw.box(DS, s.bodyRect, s.color)
- # player's leg
- if s.legRect:
- pygame.gfxdraw.box(DS, s.legRect, s.color)
- def do(s, S):
- global PLAYER_SIZE, PLAYER_SIZE_HALF, PLAYER_SIZE_QUARTER
- global PLAYER_X_VELOCITY, PLAYER_JUMP_VELOCITY, PLAYER_JUMP_GRAVITY, PLAYER_DEAD_GRAVITY
- global PLAYER_LEG_SHOW_PERCENTAGE
- global W, H
- # position the player's hat
- if s.yv > 0:
- s.hatOffsetY = int((s.hatPosY - s.RECT.y) / 0.8)
- else:
- s.hatOffsetY = 0
- s.hatPosY = s.RECT.y
- # if gradient is active
- if s.colorIndex:
- s.colorIndex -= 1
- s.color = s.colorGradient[s.colorIndex]
- # moving body parts
- if not s.dead:
- if s.yv < 0 and s.yv >= PLAYER_JUMP_VELOCITY * PLAYER_LEG_SHOW_PERCENTAGE:
- s.legRect = [s.RECT.x1() + (s.legDirection * PLAYER_SIZE_HALF), s.RECT.y2(), PLAYER_SIZE_HALF, PLAYER_SIZE_HALF]
- else:
- if s.yv == 0:
- if s.xv > 0:
- s.legRect = [s.RECT.x1() - PLAYER_SIZE_QUARTER, s.RECT.yCenter(), PLAYER_SIZE_QUARTER, PLAYER_SIZE_HALF]
- elif s.xv < 0:
- s.legRect = [s.RECT.x2(), s.RECT.yCenter(), PLAYER_SIZE_QUARTER, PLAYER_SIZE_HALF]
- else:
- s.legRect = [s.RECT.x1() - PLAYER_SIZE_QUARTER, s.RECT.yCenter(), PLAYER_SIZE + PLAYER_SIZE_HALF - 1, PLAYER_SIZE_HALF]
- else:
- s.legRect = None
- else:
- s.legRect = [s.RECT.x1() + int(PLAYER_SIZE_HALF / 2), s.RECT.y2(), PLAYER_SIZE_HALF, int(PLAYER_SIZE_HALF / 2)]
- # body
- s.bodyRect = s.RECT.intRect()
- # keys
- k = pygame.key.get_pressed()
- if k[pygame.K_a]:
- if s.xv > -PLAYER_X_VELOCITY:
- s.xv -= GRAVITY
- s.legDirection = 1
- elif k[pygame.K_d]:
- if s.xv < PLAYER_X_VELOCITY:
- s.xv += GRAVITY
- s.legDirection = 0
- else:
- if s.xv < 0: s.xv += GRAVITY
- elif s.xv > 0: s.xv -= GRAVITY
- if k[pygame.K_SPACE] and s.yv == 0:
- s.yv = PLAYER_JUMP_VELOCITY
- # movement
- reset = False
- s.RECT.x += s.xv
- if s.RECT.x >= W or s.RECT.x <= -PLAYER_SIZE:
- reset = True
- s.RECT.y += s.yv
- if not s.dead:
- s.yv += PLAYER_JUMP_GRAVITY
- else:
- s.yv -= PLAYER_DEAD_GRAVITY
- if s.RECT.y > H:
- S.score -= 1000
- if S.score < 0:
- S.score = 0
- reset = True
- if s.RECT.y + PLAYER_SIZE <= 0 and s.dead:
- reset = True
- if reset:
- s.reset()
- def futureMove(s):
- return [s.RECT.x + s.xv, s.RECT.y + s.yv]
- def collision(s, S, obj, edgeIndex = None):
- global PLAYER_SIZE, PLAYER_X_VELOCITY
- global PLAYER_GOT_FOOD_COLOR
- global FOOD_EXISTS_FRAMES
- if obj.ID == "platform":
- if edgeIndex == 0 and s.yv >= 0:
- s.RECT.y = obj.RECT.y - PLAYER_SIZE
- s.yv = 0
- if obj.ID == "food":
- s.colorIndex = len(PLAYER_GOT_FOOD_COLOR) - 1
- obj.RECT.dead = True
- if S.time.time - obj.timeStamp <= FOOD_EXISTS_FRAMES * 0.25:
- S.addObject(star(s, s.xv))
- S.score += FOOD_EXISTS_FRAMES - (S.time.time - obj.timeStamp)
- else:
- S.score += int((FOOD_EXISTS_FRAMES - (S.time.time - obj.timeStamp)) / 2)
- S.addObject(food(S))
- if obj.ID == "wall":
- if edgeIndex == 0 and s.yv >= 0:
- s.RECT.y = obj.RECT.y - PLAYER_SIZE
- s.yv = 0
- elif edgeIndex == 1:
- s.RECT.x = obj.RECT.x2() + PLAYER_X_VELOCITY# + 1
- s.xv = 0
- elif edgeIndex == 2 and s.yv < 0:
- s.RECT.y = obj.RECT.y2()
- s.yv = 0.00001
- elif edgeIndex == 3:
- s.RECT.x = obj.RECT.x - PLAYER_SIZE - PLAYER_X_VELOCITY # - 1
- s.xv = 0
- if obj.ID == "bumper":
- if edgeIndex == 0:
- s.yv = -20
- if edgeIndex == 1:
- s.xv = 20
- if edgeIndex == 2:
- s.yv = 20
- if edgeIndex == 3:
- s.xv = -20
- obj.shake()
- def die(s):
- global PLAYER_DEAD_COLOR
- s.dead = True
- s.RECT.collisionActive = False
- s.yv = 0.00001
- s.colorGradient = PLAYER_DEAD_COLOR
- s.colorIndex = len(PLAYER_DEAD_COLOR) - 1
- STAR_POINTS = [[10, 0], [13, 7], [20, 7], [15, 13], [18, 20], [10, 15], [2, 20], [5, 13], [0, 7], [7, 7]]
- STAR_SIZE = 20
- STAR_SIZE_HALF = int(STAR_SIZE / 2)
- STAR_JUMP_VELOCITY = -10
- STAR_X_VELOCITY = 4
- STAR_DIRECTION_POLARITY = [-1, 1]
- STAR_FADE_TIME = 0.5
- STAR_FADE_FRAMES = int(FPS * STAR_FADE_TIME)
- STAR_OPACITY_CHUNK = 255 / STAR_FADE_FRAMES
- STAR_COLOR = YELLOW
- class star:
- ID = "star"
- LAYER = "stars"
- def __init__(s, obj, velocity):
- global STAR_SIZE, STAR_SIZE_HALF
- global STAR_DIRECTION_POLARITY, STAR_JUMP_VELOCITY
- s.RECT = rect([obj.RECT.xCenter() - STAR_SIZE_HALF, obj.RECT.yCenter() - STAR_SIZE_HALF, STAR_SIZE, STAR_SIZE])
- s.RECT.collisionActive = False
- if velocity != 0:
- direction = velocity / abs(velocity)
- else:
- direction = STAR_DIRECTION_POLARITY[random.randint(0, 1)]
- s.xv = STAR_X_VELOCITY * direction
- s.yv = STAR_JUMP_VELOCITY
- s.opacity = 255
- def makePoints(s):
- global STAR_POINTS
- return [[p[0] + s.RECT.x1(), p[1] + s.RECT.y1()] for p in STAR_POINTS]
- def draw(s):
- global STAR_COLOR
- global DS
- pygame.gfxdraw.filled_polygon(DS, s.makePoints(), STAR_COLOR + [int(s.opacity)])
- def do(s, S):
- global STAR_OPACITY_CHUNK
- global GRAVITY
- s.RECT.x += s.xv
- s.RECT.y += s.yv
- s.yv += GRAVITY
- if s.opacity:
- s.opacity -= STAR_OPACITY_CHUNK
- if s.opacity < 0:
- s.RECT.dead = True
- FOOD_SIZE = 10
- FOOD_SIZE_HALF = int(FOOD_SIZE / 2)
- FOOD_SPAWN_BORDER = 30 # pixels
- FOOD_SPAWN_AREA = [FOOD_SPAWN_BORDER, FOOD_SPAWN_BORDER, W - FOOD_SPAWN_BORDER -FOOD_SIZE, H - FOOD_SPAWN_BORDER - FOOD_SIZE]
- FOOD_DROP_TIME = 1 # second
- FOOD_DROP_FRAMES = int(FPS * FOOD_DROP_TIME)
- FOOD_EXISTS_TIME = 20 # secs
- FOOD_EXISTS_FRAMES = (FPS * FOOD_EXISTS_TIME)
- FOOD_WARNING_FRAMES = (FPS * 3) # frames
- FOOD_MAX_SHAKE_DISTANCE = 3 # pixels
- FOOD_SHAKE_CHUNK = FOOD_MAX_SHAKE_DISTANCE / FOOD_WARNING_FRAMES
- FOOD_COLOR = RED
- FOOD_CLOCK_SIZE = FOOD_SIZE + FOOD_SIZE_HALF
- FOOD_CLOCK_TICK_CHUNK = 360 / (FPS * FOOD_EXISTS_TIME)
- FOOD_CLOCK_OPACITY_TIME = 1 # secs
- FOOD_CLOCK_OPACITY_FRAMES = int(FPS * FOOD_CLOCK_OPACITY_TIME)
- FOOD_CLOCK_OPACITY_CHUNK = 255 / FOOD_CLOCK_OPACITY_FRAMES
- FOOD_CLOCK_COLOR = GRAY
- class food:
- global FPS
- ID = "food"
- LAYER = "objects"
- ADD_IMMEDIATELY = True
- TIME_EVENT = True
- EVENT_START = 5 * 60 * FPS
- EVENT_INTERVAL = EVENT_START
- EVENT_MAXCOUNT = 3
- def __init__(s, S):
- s.reset(S)
- def reset(s, S):
- global FOOD_SIZE # dimensions
- global FOOD_SPAWN_AREA # position
- global FOOD_DROP_FRAMES, FOOD_CLOCK_OPACITY_FRAMES, FOOD_CLOCK_TICK_CHUNK # time
- noSpaceFoundYet = True
- attempts = 25
- while noSpaceFoundYet and attempts:
- s.x = random.randint(FOOD_SPAWN_AREA[0], FOOD_SPAWN_AREA[2])
- s.y = random.randint(FOOD_SPAWN_AREA[1], FOOD_SPAWN_AREA[3])
- newRect = [s.x, s.y, FOOD_SIZE, FOOD_SIZE]
- noSpaceFoundYet = S.testAllRect(newRect, ["platform"])
- attempts -= 1 # if attempts to find a space for the food fails then place it anywhere
- s.RECT = rect([s.x, -FOOD_SIZE, FOOD_SIZE, FOOD_SIZE])
- s.placeHolder = S.addPlaceHolder(newRect, s.ID)
- s.gravity = 2 * (s.y + FOOD_SIZE) / (FOOD_DROP_FRAMES * (FOOD_DROP_FRAMES - 1))
- s.yv = s.gravity * (FOOD_DROP_FRAMES - 1)
- s.clockOpacity = 0
- s.clockTime = 360 - FOOD_CLOCK_TICK_CHUNK * FOOD_DROP_FRAMES
- s.stopped = False
- s.warning = False
- s.dead = False
- s.timeStamp = S.time.time
- def draw(s):
- global FOOD_CLOCK_SIZE
- global FOOD_COLOR, FOOD_CLOCK_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), FOOD_COLOR)
- pygame.gfxdraw.arc(DS, s.RECT.xCenter(), s.RECT.yCenter(), FOOD_CLOCK_SIZE, 270 - int(s.clockTime), -90, FOOD_CLOCK_COLOR + [int(s.clockOpacity)])
- def do(s, S):
- global FOOD_EXISTS_FRAMES, FOOD_WARNING_FRAMES # time
- global FOOD_COLOR, FOOD_CLOCK_OPACITY_CHUNK # color
- global FOOD_CLOCK_TICK_CHUNK # movement
- global GRAVITY
- global H
- if not s.stopped:
- s.RECT.y += s.yv
- s.yv -= s.gravity
- if s.RECT.y1() == s.y - 1:
- s.yv = 0
- s.stopped = True
- S.delPlaceHolder(s.placeHolder)
- S.addObject(beacon(s, FOOD_COLOR))
- now = S.time.time
- if s.stopped:
- if s.clockOpacity < 255:
- s.clockOpacity += FOOD_CLOCK_OPACITY_CHUNK
- if s.clockOpacity > 255: s.clockOpacity = 255
- if s.clockTime:
- s.clockTime -= FOOD_CLOCK_TICK_CHUNK
- if s.clockTime < 0:
- s.clockTime = 0
- if now - s.timeStamp >= FOOD_EXISTS_FRAMES - FOOD_WARNING_FRAMES and not s.dead:
- if not s.warning:
- S.addObject(beacon(s, FOOD_COLOR))
- s.warning = True
- distance = FOOD_SHAKE_CHUNK * (now - s.timeStamp - FOOD_EXISTS_FRAMES + FOOD_WARNING_FRAMES)
- s.RECT.setXY([s.x + random.uniform(-distance, distance), s.y + random.uniform(-distance, distance)])
- if now - s.timeStamp >= FOOD_EXISTS_FRAMES:
- if not s.dead:
- s.RECT.setXY((s.x, s.y))
- s.dead = True
- s.RECT.y += s.yv
- s.yv += GRAVITY
- if s.RECT.y >= H:
- S.lives -= 1
- s.reset(S)
- WALL_WIDTH = 30 # pixels
- WALL_HEIGHT = HH - 25
- WALL_BORDER = 30
- WALL_SPAWN_AREA = [10 + PLATFORM_WIDTH + 10, W - WALL_BORDER - WALL_WIDTH]
- WALL_STARTING_POSY = [-WALL_HEIGHT, H]
- WALL_EXISTS_TIME = 20 # secs
- WALL_EXISTS_FRAMES = WALL_EXISTS_TIME * FPS
- WALL_DROP_TIME = 1 # sec
- WALL_DROP_FRAMES = int(FPS * WALL_DROP_TIME)
- WALL_GRAVITY = 2 * WALL_HEIGHT / (WALL_DROP_FRAMES * (WALL_DROP_FRAMES - 1))
- WALL_VELOCITY = WALL_GRAVITY * (WALL_DROP_FRAMES - 1)
- WALL_VELOCITY_POLARITY = [1, -1]
- WALL_COLOR = PURPLE
- class wall:
- ID = "wall"
- LAYER = "objects"
- EDGE_COLLISION = [True, True, True, True]
- SCORE_EVENT = True
- EVENT_START = 10000
- EVENT_INTERVAL = 10000
- EVENT_MAXCOUNT = 5
- def __init__(s, S):
- s.reset(S)
- def reset(s, S):
- global WALL_WIDTH, WALL_HEIGHT # dimensions
- global WALL_SPAWN_AREA, WALL_STARTING_POSY # position
- global WALL_DROP_FRAMES # time
- global WALL_VELOCITY_POLARITY, WALL_GRAVITY # movement
- global H
- noSpaceFoundYet = True
- attempts = 25
- while noSpaceFoundYet and attempts:
- x = random.randint(WALL_SPAWN_AREA[0], WALL_SPAWN_AREA[1])
- s.alignment = random.randint(0, 1) # 0 = top, 1 = bottom
- s.y = (H - WALL_HEIGHT) * s.alignment
- newRect = [x, s.y, WALL_WIDTH, WALL_HEIGHT]
- noSpaceFoundYet = S.testAllRect(newRect, ["platform"])
- attempts -= 1
- s.placeHolder = S.addPlaceHolder(newRect, s.ID)
- s.RECT = rect([x, WALL_STARTING_POSY[s.alignment], WALL_WIDTH, WALL_HEIGHT])
- s.yv = WALL_VELOCITY * WALL_VELOCITY_POLARITY[s.alignment]
- s.gravity = WALL_GRAVITY * WALL_VELOCITY_POLARITY[s.alignment]
- s.stopped = False
- s.timeStamp = S.time.time
- def draw(s):
- global WALL_COLOR # color
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), WALL_COLOR)
- def do(s, S):
- global WALL_HEIGHT # dimensions
- global WALL_EXISTS_FRAMES # time
- global WALL_GRAVITY, WALL_VELOCITY_POLARITY # movement
- global H
- if not s.stopped:
- s.RECT.y += s.yv
- s.yv -= s.gravity
- if s.RECT.y1() == s.y:
- s.yv = 0
- s.stopped = True
- S.delPlaceHolder(s.placeHolder)
- S.addObject(beacon(s, WALL_COLOR))
- now = S.time.time
- if s.stopped and now - s.timeStamp >= WALL_EXISTS_FRAMES:
- s.RECT.y += s.yv
- s.yv += -s.gravity
- if s.RECT.y1() == WALL_STARTING_POSY[s.alignment]:
- s.reset(S)
- BOUNCER_SIZE = 25
- BOUNCER_SPEED = 3
- BOUNCER_BORDER_SIZE = 30
- BOUNCER_SPAWN_AREA = [10 + PLATFORM_WIDTH + 10, BOUNCER_BORDER_SIZE, W - BOUNCER_BORDER_SIZE - BOUNCER_SIZE, H - BOUNCER_BORDER_SIZE - BOUNCER_SIZE]
- BOUNCER_APPEAR_TIME = 0.5 # seconds
- BOUNCER_APPEAR_FRAMES = int(FPS * BOUNCER_APPEAR_TIME)
- BOUNCER_APPEAR_OPACITY_CHUNK = 255 / BOUNCER_APPEAR_FRAMES
- BOUNCER_COLOR = TEAL
- class bouncer:
- ID = "bouncer"
- LAYER = "objects"
- COLLISION_DETECTION = True
- SCORE_EVENT = True
- EVENT_START = 65000
- EVENT_INTERVAL = 100000
- EVENT_MAXCOUNT = 5
- def __init__(s, S):
- global BOUNCER_SIZE, BOUNCER_SPEED, BOUNCER_SPAWN_AREA
- global W, H
- noSpaceFoundYet = True
- attempts = 25
- while noSpaceFoundYet and attempts:
- x = random.randint(BOUNCER_SPAWN_AREA[0], BOUNCER_SPAWN_AREA[2])
- y = random.randint(BOUNCER_SPAWN_AREA[1], BOUNCER_SPAWN_AREA[3])
- noSpaceFoundYet = S.testAllRect([x, y, BOUNCER_SIZE, BOUNCER_SIZE], ["platform"])
- attempts -= 1 # if attempts to find a space for the food fails then place it anywhere
- s.RECT = rect([x, y, BOUNCER_SIZE, BOUNCER_SIZE])
- r = math.radians(random.randint(0, 360))
- s.dx = math.cos(r) * BOUNCER_SPEED
- s.dy = math.sin(r) * BOUNCER_SPEED
- s.opacity = 0
- def draw(s):
- global BOUNCER_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), BOUNCER_COLOR + [s.opacity])
- def do(s, S):
- global BOUNCER_SIZE
- global BOUNCER_APPEAR_OPACITY_CHUNK
- global W, H
- if s.opacity < 255:
- s.opacity += BOUNCER_APPEAR_OPACITY_CHUNK
- if s.opacity > 255: s.opacity = 255
- s.RECT.x += s.dx
- s.RECT.y += s.dy
- if s.RECT.x2() > W:
- s.RECT.x = W - BOUNCER_SIZE
- s.dx = -s.dx
- elif s.RECT.x < 0:
- s.RECT.x = 0
- s.dx = -s.dx
- if s.RECT.y2() > H:
- s.RECT.y = H - BOUNCER_SIZE
- s.dy = -s.dy
- elif s.RECT.y < 0:
- s.RECT.y = 0
- s.dy = -s.dy
- def futureMove(s):
- return([s.RECT.x + s.dx, s.RECT.y + s.dy])
- def collision(s, S, obj, edgeIndex = None):
- global BOUNCER_SIZE, BOUNCER_COLOR
- if obj.ID == "wall" or obj.ID == "bumper":
- if edgeIndex == 0:
- s.RECT.y = obj.RECT.y - BOUNCER_SIZE
- s.dy = -s.dy
- elif edgeIndex == 1:
- s.RECT.x = obj.RECT.x2()
- s.dx = -s.dx
- elif edgeIndex == 2:
- s.RECT.y = obj.RECT.y2()
- s.dy = -s.dy
- elif edgeIndex == 3:
- s.RECT.x = obj.RECT.x - BOUNCER_SIZE
- s.dx = -s.dx
- S.addObject(beacon(s, BOUNCER_COLOR))
- if obj.ID == "platform":
- if not obj.dead: obj.die()
- if obj.ID == "player":
- if not obj.dead:
- S.lives -= 1
- S.addObject(beacon(s, BOUNCER_COLOR))
- BUMPER_SIZE = 100
- BUMPER_SPAWN_BORDER = 30
- BUMPER_SPAWN_AREA = [10 + PLATFORM_WIDTH + 10, BUMPER_SPAWN_BORDER, W - BUMPER_SIZE - BUMPER_SPAWN_BORDER, H - BUMPER_SIZE - BUMPER_SPAWN_BORDER]
- BUMPER_DROP_TIME = 1 # secs
- BUMPER_DROP_FRAMES = int(FPS * BUMPER_DROP_TIME)
- BUMPER_COLOR = gradient(GRAY, WHITE, int(FPS / 2))
- BUMPER_COLOR_MAX_INDEX = len(BUMPER_COLOR) - 1
- BUMPER_EXIST_TIME = 20 # secs
- BUMPER_EXIST_FRAMES = BUMPER_EXIST_TIME * FPS
- class bumper:
- ID = "bumper"
- LAYER = "objects"
- EDGE_COLLISION = [True, True, True, True]
- SCORE_EVENT = True
- EVENT_START = 50000
- EVENT_INTERVAL = 50000
- EVENT_MAXCOUNT = 5
- def __init__(s, S):
- s.reset(S)
- def reset(s, S):
- global BUMPER_SIZE, BUMPER_SPAWN_AREA
- global BUMPER_COLOR_MAX_INDEX
- global BUMPER_DROP_FRAMES
- noSpaceFoundYet = True
- attempts = 25
- while noSpaceFoundYet and attempts:
- s.x = random.randint(BUMPER_SPAWN_AREA[0], BUMPER_SPAWN_AREA[2])
- s.y = random.randint(BUMPER_SPAWN_AREA[1], BUMPER_SPAWN_AREA[3])
- newRect = [s.x, s.y, BUMPER_SIZE, BUMPER_SIZE]
- noSpaceFoundYet = S.testAllRect(newRect, ["platform"])
- attempts -= 1
- s.placeHolder = S.addPlaceHolder(newRect, s.ID)
- s.RECT = rect([s.x, -BUMPER_SIZE, BUMPER_SIZE, BUMPER_SIZE])
- s.RECT.collisionActive = False
- s.gravity = 2 * (s.y + BUMPER_SIZE) / (BUMPER_DROP_FRAMES * (BUMPER_DROP_FRAMES - 1))
- s.yv = s.gravity * (BUMPER_DROP_FRAMES - 1)
- s.colorIndex = 0
- s.stopped = False
- s.dead = False
- s.timeStamp = S.time.time
- def draw(s):
- global BUMPER_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), BUMPER_COLOR[s.colorIndex])
- def do(s, S):
- global BUMPER_EXIST_FRAMES
- global BUMPER_COLOR
- global GRAVITY
- global H
- if s.colorIndex:
- s.colorIndex -= 1
- s.RECT.setXY([s.x + random.randint(-5, 5), s.y + random.randint(-5, 5)])
- if not s.stopped:
- s.RECT.y += s.yv
- s.yv -= s.gravity
- if s.RECT.y1() == s.y - 1:
- s.yv = 0
- s.RECT.collisionActive = True
- s.stopped = True
- S.delPlaceHolder(s.placeHolder)
- S.addObject(beacon(s, BUMPER_COLOR[0]))
- now = S.time.time
- if s.stopped:
- if now - s.timeStamp >= BUMPER_EXIST_FRAMES:
- s.RECT.y += s.yv
- s.yv += GRAVITY
- if s.RECT.y >= H:
- s.reset(S)
- if not s.dead:
- s.dead = True
- s.RECT.collisionActive = False
- def shake(s):
- global BUMPER_COLOR, BUMPER_COLOR_MAX_INDEX
- s.colorIndex = BUMPER_COLOR_MAX_INDEX
- FIRE_SIZE = 4
- FIRE_SIZE_HALF = int(FIRE_SIZE / 2)
- FIRE_SPEED = 1.3
- FIRE_COLOR = RED
- FIRE_BURN_TIME = 0.5 # secs
- FIRE_FRAMES = int(FPS * FIRE_BURN_TIME)
- FIRE_OPACITY_CHUNK = 255 / FIRE_FRAMES
- BULLET_SIZE = 6
- BULLET_SIZE_HALF = int(BULLET_SIZE / 2)
- BULLET_SPEED = 5
- BULLET_COLOR = SILVER
- class bullet:
- ID = "bullet"
- LAYER = "bullets"
- COLLISION_DETECTION = True
- class fire:
- ID = "fire"
- LAYER = ID
- def __init__(s, b):
- global FIRE_SIZE, FIRE_SIZE_HALF
- global FIRE_SPEED
- s.xv = b.xv / FIRE_SPEED
- s.yv = b.yv / FIRE_SPEED
- bx, by = b.RECT.center()
- s.RECT = rect([bx - FIRE_SIZE_HALF, by - FIRE_SIZE_HALF, FIRE_SIZE, FIRE_SIZE])
- s.RECT.collisionActive = False
- s.opacity = 255
- def draw(s):
- global FIRE_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), FIRE_COLOR + [int(s.opacity)])
- def do(s, S):
- global FIRE_SIZE, FIRE_SIZE_HALF
- global W, H
- global DS
- if s.opacity:
- s.opacity -= FIRE_OPACITY_CHUNK
- if s.opacity < 0:
- s.RECT.dead = True
- s.RECT.x += s.xv
- s.RECT.y += s.yv
- if s.RECT.x <= -FIRE_SIZE or s.RECT.y <= -FIRE_SIZE or s.RECT.x >= W or s.RECT.y >= H:
- s.RECT.dead = True
- return
- def __init__(s, gun, victim):
- global BULLET_SIZE, BULLET_SIZE_HALF
- global BULLET_SPEED
- s.gun = gun
- tx, ty = victim.RECT.center()
- gx, gy = gun.RECT.center()
- angle = math.atan2(ty - gy, tx - gx)
- s.xv = math.cos(angle) * BULLET_SPEED
- s.yv = math.sin(angle) * BULLET_SPEED
- x = gx + math.cos(angle) * gun.RECT.w / 2
- y = gy + math.sin(angle) * gun.RECT.h / 2
- s.RECT = rect([x - BULLET_SIZE_HALF, y - BULLET_SIZE_HALF, BULLET_SIZE, BULLET_SIZE])
- s.fireFlames = None
- def draw(s):
- global BULLET_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), BULLET_COLOR)
- def do(s, S):
- global FIRE_FRAMES
- global BULLET_SIZE
- global BULLET_COLOR
- global W, H
- global DS
- if s.fireFlames == None:
- s.fireFlames = S.addObject(s.fire(s))
- elif s.fireFlames.opacity <= 128:
- s.fireFlames = S.addObject(s.fire(s))
- s.RECT.x += s.xv
- s.RECT.y += s.yv
- if s.RECT.x <= -BULLET_SIZE or s.RECT.y <= -BULLET_SIZE or s.RECT.x >= W or s.RECT.y >= H:
- s.RECT.dead = True
- return
- def futureMove(s):
- return [s.RECT.x + s.xv, s.RECT.y + s.yv]
- def collision(s, S, obj, edgeIndex = None):
- global BULLET_SIZE
- global ORANGE
- if obj.ID == "player":
- S.lives -= 1
- s.RECT.dead = True
- s.gun.dead = True
- S.addObject(beacon(s, ORANGE))
- SHOOTER_SIZE = 25
- SHOOTER_SPAWN_BORDER = 30
- SHOOTER_SPAWN_AREA = [10 + PLATFORM_WIDTH + 10, SHOOTER_SPAWN_BORDER, W - SHOOTER_SPAWN_BORDER - SHOOTER_SIZE, H - SHOOTER_SPAWN_BORDER - SHOOTER_SIZE]
- SHOOTER_DROP_TIME = 2 #secs
- SHOOTER_DROP_FRAMES = int(FPS * SHOOTER_DROP_TIME)
- SHOOTER_FIRE_DELAY = (2 * FPS) #frames
- SHOOTER_COLOR = GREEN
- class shooter:
- ID = "shooter"
- LAYER = "objects"
- SCORE_EVENT = True
- EVENT_START = 100000
- EVENT_INTERVAL = 100000
- EVENT_MAXCOUNT = 5
- def __init__(s, S):
- global SHOOTER_SIZE # dimensions
- global SHOOTER_SPAWN_AREA # position
- global SHOOTER_DROP_FRAMES # time
- noSpaceFoundYet = True
- attempts = 25
- while noSpaceFoundYet and attempts:
- s.x = random.randint(SHOOTER_SPAWN_AREA[0], SHOOTER_SPAWN_AREA[2])
- s.y = random.randint(SHOOTER_SPAWN_AREA[1], SHOOTER_SPAWN_AREA[3])
- newRect = [s.x, s.y, SHOOTER_SIZE, SHOOTER_SIZE]
- noSpaceFoundYet = S.testAllRect(newRect, ["platform"])
- attempts -= 1
- s.placeHolder = S.addPlaceHolder(newRect, s.ID)
- s.RECT = rect([s.x, -SHOOTER_SIZE, SHOOTER_SIZE, SHOOTER_SIZE])
- s.gravity = 2 * (s.y + SHOOTER_SIZE) / (SHOOTER_DROP_FRAMES * (SHOOTER_DROP_FRAMES - 1))
- s.yv = s.gravity * (SHOOTER_DROP_FRAMES - 1)
- s.stopped = False
- s.timeStamp = S.time.time
- s.bulletCount = 3
- s.bulletTimeStamp = 0
- def draw(s):
- global SHOOTER_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), SHOOTER_COLOR)
- def fireBullet(s, S):
- S.addObject(bullet(s, S.layers["player"][0]))
- s.bulletTimeStamp = S.time.time
- s.bulletCount -= 1
- def die(s):
- s.bulletCount = 0
- def do(s, S):
- global SHOOTER_COLOR
- global SHOOTER_FIRE_DELAY
- global GRAVITY
- if not s.stopped:
- s.RECT.y += s.yv
- s.yv -= s.gravity
- if s.RECT.y1() == s.y - 1:
- s.yv = 0
- s.stopped = True
- S.delPlaceHolder(s.placeHolder)
- S.addObject(beacon(s, SHOOTER_COLOR))
- s.fireBullet(S)
- now = S.time.time
- if s.stopped:
- if now - s.bulletTimeStamp >= SHOOTER_FIRE_DELAY and s.bulletCount:
- s.fireBullet(S)
- elif not s.bulletCount:
- s.RECT.y += s.yv
- s.yv += GRAVITY
- if s.RECT.y >= H:
- s.RECT.dead = True
- BEACON_MAX_SIZE = 100
- BEACON_DURATION = 0.5 # secs
- BEACON_FRAMES = int(FPS * BEACON_DURATION)
- BEACON_GROW_PER_FRAME = int(BEACON_MAX_SIZE / BEACON_FRAMES)
- BEACON_OPACITY_CHUNK = 128 / BEACON_FRAMES
- class beacon:
- ID = "beacon"
- LAYER = "beacons"
- def __init__(s, obj, color):
- s.RECT = rect(obj.RECT.intRect())
- s.RECT.collisionActive = False
- s.objRect = obj.RECT
- s.color = color
- s.opacity = 128
- def draw(s):
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), s.color + [s.opacity])
- def do(s, S):
- global BEACON_GROW_PER_FRAME, BEACON_OPACITY_CHUNK
- s.RECT.x -= BEACON_GROW_PER_FRAME
- s.RECT.y -= BEACON_GROW_PER_FRAME
- s.RECT.w += BEACON_GROW_PER_FRAME * 2
- s.RECT.h += BEACON_GROW_PER_FRAME * 2
- if s.opacity > 0:
- s.opacity -= BEACON_OPACITY_CHUNK
- if s.opacity <= 0:
- s.opacity = 0
- s.RECT.dead = True
- SCORE_SCALE = 5
- SCORE_SHAKE_SIZE = 3
- SCORE_SHAKE_TIME = 0.5 # secs
- SCORE_SHAKE_FRAMES = int(FPS * SCORE_SHAKE_TIME)
- SCORE_BACKGROUND_COLOR = BLACK
- SCORE_PREVIEW_DROP_HEIGHT = H - 100 # pixels
- SCORE_PREVIEW_DROP_TIME = 1 # secs
- SCORE_PREVIEW_DROP_FRAMES = int(FPS * SCORE_PREVIEW_DROP_TIME)
- SCORE_PREVIEW_GRAVITY = 2 * SCORE_PREVIEW_DROP_HEIGHT / (SCORE_PREVIEW_DROP_FRAMES * (SCORE_PREVIEW_DROP_FRAMES - 1))
- SCORE_PREVIEW_VELOCITY = SCORE_PREVIEW_GRAVITY * (SCORE_PREVIEW_DROP_FRAMES - 1)
- SCORE_PREVIEW_OPACITY_CHUNK = 255 / SCORE_PREVIEW_DROP_FRAMES
- SCORE_PREVIEW_SCALE = 3
- class score:
- ID = "score"
- LAYER = ID
- ADD_IMMEDIATELY = True
- class preview:
- def __init__(s, S, value, score):
- global SCORE_SCALE
- global SCORE_PREVIEW_SCALE
- global SCORE_PREVIEW_DROP_HEIGHT, SCORE_PREVIEW_VELOCITY
- global SCORE_BACKGROUND_COLOR
- global W, H
- s.surface = S.font.text(str(value), SCORE_PREVIEW_SCALE) #.convert_alpha()
- s.surface.set_colorkey(SCORE_BACKGROUND_COLOR)
- #s.surface.set_alpha(0)
- s.w, s.h = s.surface.get_size()
- s.x = W - 10 - s.w
- s.y = H - 10 - (S.font.size("A", SCORE_SCALE)[1] / 2) - SCORE_PREVIEW_DROP_HEIGHT - s.h
- s.yv = 0
- s.opacity = 0
- s.score = score
- s.dead = False
- def draw(s):
- global DS
- DS.blit(s.surface, (s.x, int(s.y)))
- def do(s):
- global SCORE_PREVIEW_OPACITY_CHUNK, SCORE_PREVIEW_GRAVITY
- s.y += s.yv
- s.yv += SCORE_PREVIEW_GRAVITY
- s.opacity += SCORE_PREVIEW_OPACITY_CHUNK
- if s.opacity >= 255:
- s.opacity = 255
- s.dead = True
- s.surface.set_alpha(int(s.opacity))
- def __init__(s, S):
- global SCORE_SCALE
- global SCORE_BACKGROUND_COLOR
- s.RECT = rect([0, 0, 0 ,0])
- s.RECT.collisionActive = False
- s.previews = []
- s.shake = False
- s.shakeX = 0
- s.shakeY = 0
- s.shakeTimeStamp = 0
- s.prevScore = 0
- s.surface = S.font.text(str(S.score), SCORE_SCALE)
- s.width, s.height = s.surface.get_size()
- s.surface.set_colorkey(SCORE_BACKGROUND_COLOR)
- def draw(s):
- global W, H
- global DS
- DS.blit(s.surface, (W - 10 - s.width + s.shakeX, H - 10 - s.height + s.shakeY))
- for preview in s.previews:
- preview.draw()
- def do(s, S):
- global SCORE_SCALE
- global SCORE_SHAKE_FRAMES
- global SCORE_BACKGROUND_COLOR
- if S.score != s.prevScore:
- value = S.score - s.prevScore
- if value > 0:
- s.previews.append(s.preview(S, value, S.score))
- else:
- s.surface = S.font.text(str(S.score), SCORE_SCALE)
- s.width, s.height = s.surface.get_size()
- s.surface.set_colorkey(SCORE_BACKGROUND_COLOR)
- s.prevScore = S.score
- deadPreviews = []
- for preview in s.previews:
- preview.do()
- if preview.dead:
- deadPreviews.append(preview)
- s.surface = S.font.text(str(preview.score), SCORE_SCALE)
- s.width, s.height = s.surface.get_size()
- s.surface.set_colorkey(SCORE_BACKGROUND_COLOR)
- s.shake = True
- s.shakeTimeStamp = S.time.time
- for deleteThis in deadPreviews:
- s.previews.remove(deleteThis)
- if s.shake:
- if S.time.time - s.shakeTimeStamp < SCORE_SHAKE_FRAMES:
- s.shakeX = random.randint(-SCORE_SHAKE_SIZE, SCORE_SHAKE_SIZE)
- s.shakeY = random.randint(-SCORE_SHAKE_SIZE, SCORE_SHAKE_SIZE)
- else:
- s.shake = False
- s.shakeX, s.shakeY = 0, 0
- LIFE_SIZE = 20
- LIFE_COLOR = [255, 186, 97]
- LIFE_FALL_TIME = 0.5 # seconds
- LIFE_FALL_FRAMES = int(FPS * LIFE_FALL_TIME)
- LIFE_FALL_HEIGHT = 100
- LIFE_FALL_GRAVITY = 2 * LIFE_FALL_HEIGHT / (LIFE_FALL_FRAMES * (LIFE_FALL_FRAMES - 1))
- LIFE_OPACITY_CHUNK = 255 / LIFE_FALL_FRAMES
- LIVES_AT_START = 3
- class lives:
- ID = "lives"
- LAYER = ID
- ADD_IMMEDIATELY = True
- class life:
- def __init__(s, x, y):
- global LIFE_SIZE
- s.RECT = rect([x, y, LIFE_SIZE, LIFE_SIZE])
- s.opactiy = 255
- s.yv = 0
- s.dead = False
- def draw(s):
- global LIFE_COLOR
- global DS
- pygame.gfxdraw.box(DS, s.RECT.intRect(), LIFE_COLOR + [int(s.opactiy)])
- def do(s):
- global GRAVITY
- s.RECT.y += s.yv
- s.yv += LIFE_FALL_GRAVITY
- if s.opactiy:
- s.opactiy -= LIFE_OPACITY_CHUNK
- if s.opactiy < 0:
- s.dead = True
- def __init__(s, S):
- global LIFE_SIZE
- global LIVES_AT_START
- global W
- s.RECT = rect([0, 0, 0 ,0])
- s.RECT.collisionActive = False
- S.lives = LIVES_AT_START
- s.prevLives = LIVES_AT_START
- startPos = W - (LIFE_SIZE + 10) * LIVES_AT_START
- s.container = [s.life(startPos + index * (LIFE_SIZE + 10), 10) for index in range(0, LIVES_AT_START)]
- s.deadContainer = []
- def draw(s):
- global DS
- for life in s.container + s.deadContainer:
- life.draw()
- def do(s, S):
- if S.lives != s.prevLives:
- s.prevLives = S.lives
- s.deadContainer.append(s.container.pop(0))
- S.layers["player"][0].die()
- if not S.lives and not S.layers["player"][0].dead:
- S.gameOver = True
- deleteLives = []
- for deadLife in s.deadContainer:
- deadLife.do()
- if deadLife.dead: deleteLives.append(deadLife)
- for deleteThis in deleteLives:
- s.deadContainer.remove(deleteThis)
- pygame.init()
- DS = pygame.display.set_mode((W, H))
- TIME = gameTime(FPS)
- FONT = font(imgUnzip(FONT_DATA), FONT_CHARMAP, 1)
- TITLE_LAYERS = ["background", "other"]
- TITLE_OBJECT_LIST = [background]
- GAME_STAGE_LAYERS = [
- "background",
- "beacons",
- "score",
- "lives",
- "platforms",
- "objects",
- "player",
- "fire",
- "bullets",
- "stars",
- "pointer"
- ]
- GAME_OBJECTS = [background, platform, player, platformPointer, score, lives, food, bouncer, bumper, shooter, wall]
- GAME_STAGE = stage()
- GAME_STAGE.setTimer(TIME)
- GAME_STAGE.setLayers(GAME_STAGE_LAYERS)
- GAME_STAGE.setObjects(GAME_OBJECTS)
- GAME_STAGE.setFont(FONT)
- GAME_STAGE.reset()
- # Main loop
- while not GAME_STAGE.gameOver:
- e = pygame.event.get()
- if pygame.key.get_pressed()[pygame.K_ESCAPE]: break
- GAME_STAGE.do()
- pygame.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement