Tititesouris

Trash Rolling Turtle

Apr 28th, 2014
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.41 KB | None | 0 0
  1. '''
  2. Game made by @Tititesouris
  3. Graphics made by @_Inaar
  4. 28/04/2014 - 29/04/2014
  5. Ludum Dare - Beneath the surface
  6. '''
  7. from math import *
  8. import pygame, os, time, random, sys, json
  9. from pygame.locals import *
  10. from cx_Freeze import setup, Executable
  11. pygame.mixer.pre_init(44100, -16, 2, 2048) #Initialise the mixer
  12. pygame.init() #Initialise Pygame
  13. os.environ["SDL_VIDEO_WINDOW_POS"] = "{0}, {1}".format(50, 50) #Window origin
  14. windowSize = [800, 600] #Window size
  15. window = pygame.display.set_mode((windowSize[0], windowSize[1])) #Creating window
  16. pygame.display.set_caption("Window") #Window title
  17. font = pygame.font.SysFont("Lucida Console", 18) #Font
  18. bigFont = pygame.font.SysFont("Lucida Console", 30) #Font
  19.  
  20. '''
  21. Global functions
  22. '''
  23. def getTime(): #Returns the current timestamp
  24.    return int(round(time.time()*1000))
  25.  
  26. def isTime(time): #Is time a past timestamp
  27.    if getTime() > time:
  28.       return True
  29.    else:
  30.       return False
  31.  
  32. def randNb(min=0, max=1): #Returns a random integer between min and max inclusive
  33.    return random.randint(min, max)
  34.  
  35. def randItem(list): #Returns a random element from list
  36.    return random.choice(list)
  37.  
  38. def write(window, font, text, coords, colour=(0, 0, 0)):
  39.    window.blit(font.render(str(text), 1, colour), coords)
  40.  
  41. def drawRect(window, rectangle, colour=(255, 255, 255), thickness=1):
  42.    pygame.draw.rect(window, colour, rectangle, thickness)
  43.  
  44. def drawCircle(window, coords, radius, colour=(255, 255, 255), thickness=1):
  45.    pygame.draw.circle(window, colour, coords, radius, thickness)
  46.  
  47. def play(sound): #Play sound
  48.    sound.set_volume(0.5)
  49.    sound.play()
  50.  
  51. def playMusic(music, loop=-1): #Play music
  52.    music.set_volume(0.5)
  53.    music.play(loop)
  54.  
  55. '''
  56. Images and sounds
  57. '''
  58. backgroundImage = pygame.image.load("images/background.png")
  59. turtleImage = [pygame.image.load("images/turtles.png").subsurface(140*i, 0, 140, 80) for i in range(6)]
  60. deadTurtleImage = pygame.image.load("images/deadturtle.png")
  61. barrelRollImage = pygame.image.load("images/barrelroll.png")
  62. junkImages = {junk.split(".png")[0]: pygame.image.load("images/junks/{0}".format(junk)) for junk in os.listdir("images/junks")}
  63. music = pygame.mixer.Sound("sounds/music.wav") #Easy Lemon incompetech.com
  64. sadMusic = pygame.mixer.Sound("sounds/sadmusic.wav") #Virtutes Instrumenti incompetech.com
  65. deathSound = pygame.mixer.Sound("sounds/death.wav")
  66. barrelRollSound = pygame.mixer.Sound("sounds/barrelroll.wav")
  67.  
  68. '''
  69. Global variables
  70. '''
  71. press = {
  72.    "up": False,
  73.    "right": False,
  74.    "down": False,
  75.    "left": False,
  76. }
  77. isGameRunning = True
  78.  
  79. '''
  80. Classes
  81. '''
  82. class engine:
  83.    def __init__(self):
  84.       self.startTime = getTime()+3000
  85.       self.moveInterval = 5
  86.       self.nextMove = self.startTime
  87.       self.gravityPullInterval = 50
  88.       self.nextGravityPull = self.startTime
  89.       self.moveJunkInterval = 4
  90.       self.nextMoveJunk = self.startTime
  91.       self.spawnInterval = 2000
  92.       self.nextSpawn = self.startTime+1000
  93.       self.levelInterval = 10000
  94.       self.nextLevel = self.startTime+self.levelInterval
  95.       self.staminaInterval = 300
  96.       self.nextStamina = self.startTime+self.staminaInterval
  97.       self.barrelRollTime = 2000
  98.       self.endBarrelRoll = 0
  99.       self.paused = False
  100.    
  101.    def tick(self):
  102.       if isTime(self.startTime) and not self.paused:
  103.          if not GAME.gameOver:
  104.             if not pygame.key.get_focused(): #Window loses focus
  105.                self.paused = True
  106.                GAME.pausedTime = getTime()
  107.             if isTime(self.nextMove): #Turtle move
  108.                if press["up"] and not press["down"]:
  109.                   TURTLE.move("up")
  110.                elif press["down"] and not press["up"]:
  111.                   TURTLE.move("down")
  112.                if press["right"] and not press["left"]:
  113.                   TURTLE.move("right")
  114.                elif press["left"] and not press["right"]:
  115.                   TURTLE.move("left")
  116.                self.nextMove = getTime()+self.moveInterval
  117.             if isTime(self.nextMoveJunk): #Junk move
  118.                JUNK.move()
  119.                self.nextMoveJunk = getTime()+self.moveJunkInterval
  120.             if isTime(self.nextSpawn): #Junk spawn
  121.                JUNK.spawn()
  122.                JUNK.destroy()
  123.                self.nextSpawn = getTime()+self.spawnInterval
  124.             if isTime(self.nextLevel): #Level up
  125.                GAME.level += 1
  126.                JUNK.speed += 1
  127.                TURTLE.swimming = max(10, TURTLE.swimming-20)
  128.                GAME.waveSpeed = max(1, GAME.waveSpeed-2)
  129.                self.spawnInterval = max(600, self.spawnInterval - 500)
  130.                self.levelInterval += GAME.level*10000
  131.                self.nextLevel = getTime()+self.levelInterval
  132.             if TURTLE.barrelRolling and isTime(self.endBarrelRoll):
  133.                TURTLE.barrelRolling = False
  134.             elif isTime(self.nextStamina) and TURTLE.stamina < 100:
  135.                TURTLE.stamina += 1
  136.                self.nextStamina = getTime()+self.staminaInterval
  137.             TURTLE.contact()
  138.          if isTime(self.nextGravityPull):
  139.             if GAME.gameOver or (not GAME.gameOver and TURTLE.position[1] < windowSize[1]-TURTLE.size[1]):
  140.                TURTLE.position[1] += 1
  141.                self.nextGravityPull = getTime()+self.gravityPullInterval
  142. ENGINE = engine()
  143.  
  144. class turtle:
  145.    def __init__(self):
  146.       self.size = [140, 80]
  147.       self.position = [windowSize[0]//2-self.size[0], windowSize[1]//2]
  148.       self.speed = 6
  149.       self.barrelRolling = False
  150.       self.stamina = 100
  151.       self.swimming = 100
  152.    
  153.    def move(self, direction):
  154.       if not self.barrelRolling:
  155.          if direction == "up" and self.position[1] > GAME.surface:
  156.             self.position[1] -= self.speed
  157.          elif direction == "right" and self.position[0] < windowSize[0]-self.size[0]:
  158.             self.position[0] += self.speed
  159.          elif direction == "down" and self.position[1] < windowSize[1]-self.size[1]:
  160.             self.position[1] += self.speed
  161.          elif direction == "left" and self.position[0] > 0:
  162.             self.position[0] -= self.speed
  163.    
  164.    def contact(self):
  165.       if not self.barrelRolling:
  166.          touch = False
  167.          for junk in JUNK.junks:
  168.             if junk["position"][0]+JUNK.size[0] > self.position[0] > junk["position"][0]-self.size[0] and junk["position"][1]+JUNK.size[1] > self.position[1] > junk["position"][1]-self.size[1]:
  169.                touch = True
  170.                break
  171.          if touch:
  172.             GAME.gameOver = True
  173.             GAME.finishTime = getTime()-GAME.time
  174.             pygame.mixer.stop()
  175.             play(deathSound)
  176.             playMusic(sadMusic)
  177.    
  178.    def barrelRoll(self):
  179.       if not self.barrelRolling and self.stamina == 100 and isTime(ENGINE.startTime) and not ENGINE.paused:
  180.          self.barrelRolling = True
  181.          self.stamina = 0
  182.          ENGINE.endBarrelRoll = getTime()+ENGINE.barrelRollTime
  183.          play(barrelRollSound)
  184. TURTLE = turtle()
  185.  
  186. class junk:
  187.    def __init__(self):
  188.       self.junks = []
  189.       self.size = [55, 55]
  190.       self.speed = 4
  191.    
  192.    def spawn(self):
  193.       spawnPoints = [i for i in range(((windowSize[1]-self.size[1])-GAME.surface)//TURTLE.size[1]+1)]
  194.       for i in range(randItem([1]*(GAME.level+1)+[randNb(1, max(1, min(6, GAME.level)))])):
  195.          spawnPoint = randItem(spawnPoints)
  196.          spawnPoints.remove(spawnPoint)
  197.          self.junks.append({
  198.             "name": randItem(["Plastic Bag", "Water Bottle", "Coke Bottle", "Can", "Cigarette Pack"]),
  199.             "position": [windowSize[0], GAME.surface+TURTLE.size[1]*spawnPoint],
  200.          })
  201.    
  202.    def move(self):
  203.       self.junks = [{"name": junk["name"], "position": [junk["position"][0]-self.speed, junk["position"][1]]} for junk in self.junks]
  204.    
  205.    def destroy(self):
  206.       self.junks = [junk for junk in self.junks if junk["position"][0] >= -self.size[0]]
  207. JUNK = junk()
  208.  
  209. class facts:
  210.    def __init__(self):
  211.       self.facts = [
  212.          "More than 3 billion kilograms (7 billion pounds)\nof non-recyclable plastic is created every year.",
  213.          "Only 7% of the plastic in the U.S.A. is recycled.\nLess than 5% of the plastic worldwide is recycled.",
  214.          "Consider picking up every plastic debris you spot\nin the street, before they end up in the sea.",
  215.          "All the junk in the oceans conglomerates\nto form 'Great Garbage Patches' or 'Trash Vortexes'.",
  216.          "It's impossible to measure the size of a garbage patch\nbut using samples it's estimated that the Great Pacific Garbage Patch\nis twice the size of Texas.",
  217.          "In the Great Pacific Garbage Patch there is\nmore plastic than plankton, the main food for many marine animals.",
  218.          "Even the Mediterranean sea is full of junk\nwith 500 tonnes of trash floating around.",
  219.          "If you played this game with realistic trash proportions\nyou wouldn't last more than 3 seconds.",
  220.          "Hundreds of thousands of marine mammals and more than\n1 million seabirds die each year from ocean pollution.",
  221.          "Sea turtles and other marine creatures mistake\nplastic bags for jellyfish. When ingesting them, it causes\nblockages in their digestive systems, leading to death.",
  222.          "The plastic toxins end up in fish, which end up in our plates.",
  223.          "More than 80% of the oceans' junk is plastic.",
  224.       ]
  225.       self.fact = 0
  226.    
  227.    def new(self):
  228.       if self.fact < len(self.facts)-1:
  229.          self.fact += 1
  230.       else:
  231.          self.fact = 0
  232. FACTS = facts()
  233.  
  234. class game:
  235.    def __init__(self):
  236.       self.gameOver = False
  237.       self.time = ENGINE.startTime
  238.       self.level = 0
  239.       self.highscore = 0
  240.       self.waveAmplitude = 10 #Amplitude of the wave in pixel
  241.       self.waveSpeed = 10 #Speed of the wave moving left, the lower the greater
  242.       self.waveStrength = 400 #Speed of the wave moving up and down, the lower the greater
  243.       self.wavePeriod = 50 #Spacial period in pixel
  244.       self.surface = 100
  245.       self.pausedTime = 0
  246.       self.finishTime = 0
  247.    
  248.    def reset(self):
  249.       if self.finishTime > self.highscore:
  250.          json.dump(self.finishTime, open("save.txt", "w"))
  251.       ENGINE.__init__()
  252.       TURTLE.__init__()
  253.       JUNK.__init__()
  254.       GAME.__init__()
  255.       self.highscore = json.load(open("save.txt", "r"))
  256.       pygame.mixer.stop()
  257.       playMusic(music)
  258.    
  259.    def display(self):
  260.       window.blit(backgroundImage, (0, 0)) #Background
  261.       write(window, font, "Stamina", (windowSize[0]-font.size("Stamina")[0]-35, 26)) #Stamina
  262.       drawRect(window, (windowSize[0]-154, 0, 204, 24), (0, 0, 0), 0) #Stamina gauge border
  263.       drawRect(window, (windowSize[0]-152, 2, TURTLE.stamina*1.5, 20), (0, 150, 50), 0) #Stamina gauge
  264.       if not self.gameOver:
  265.          if not TURTLE.barrelRolling:
  266.             window.blit(turtleImage[floor(getTime()/TURTLE.swimming%6)], (TURTLE.position[0], TURTLE.position[1])) #Turtle
  267.          else:
  268.             middlePoint = ENGINE.endBarrelRoll-ENGINE.barrelRollTime//2
  269.             distanceToMiddle = getTime()-middlePoint
  270.             newSize = [round(TURTLE.size[0]*max(0.75, abs(sin(distanceToMiddle/(ENGINE.barrelRollTime/2))))), round(TURTLE.size[1]*max(0.75, abs(sin(distanceToMiddle/(ENGINE.barrelRollTime/2)))))]
  271.             window.blit(pygame.transform.scale(barrelRollImage, (newSize[0], newSize[1])), (TURTLE.position[0]+(TURTLE.size[0]-newSize[0])//2, TURTLE.position[1]+(TURTLE.size[1]-newSize[1])//2)) #Barrel rolling turtle
  272.          if isTime(ENGINE.startTime):
  273.             for junk in JUNK.junks: #Junks
  274.                window.blit(junkImages[junk["name"]], (junk["position"][0], junk["position"][1]))
  275.             if not ENGINE.paused:
  276.                write(window, bigFont, round((getTime()-self.time)/1000, 2), (0, 0)) #Time
  277.             else:
  278.                write(window, bigFont, round((self.pausedTime-self.time)/1000, 2), (0, 0)) #Time
  279.                write(window, bigFont, "Press escape to unpause the game", (windowSize[0]//2-bigFont.size("Press escape to unpause the game")[0]//2, windowSize[1]//2), (190, 100, 10)) #Instructions
  280.          else:
  281.             write(window, bigFont, "Trash Rolling Turtle", (windowSize[0]//2-bigFont.size("Trash Rolling Turtle")[0]//2, windowSize[1]//2-4*bigFont.size("A")[1]), (190, 100, 10)) #Title
  282.             write(window, bigFont, round((ENGINE.startTime-getTime())/1000), (TURTLE.position[0]+TURTLE.size[0]+50, TURTLE.position[1]+TURTLE.size[1]//2-bigFont.size("A")[1]//2)) #Countdown
  283.             write(window, bigFont, "Press space to do a barrel roll", (windowSize[0]//2-bigFont.size("Press space to do a barrel roll")[0]//2, windowSize[1]//2-2*bigFont.size("A")[1])) #Instructions
  284.             write(window, bigFont, "Survive as long as possible", (windowSize[0]//2-bigFont.size("Survive as long as possible")[0]//2, windowSize[1]//2+4*bigFont.size("A")[1])) #Instructions
  285.       else:
  286.          window.blit(deadTurtleImage, (TURTLE.position[0], TURTLE.position[1])) #Dead turtle
  287.          if self.finishTime > self.highscore:
  288.             write(window, bigFont, "New Record!", (windowSize[0]//2-bigFont.size("New Record!")[0]//2, windowSize[1]//2-4*bigFont.size("A")[1]), (190, 100, 10)) #New record
  289.             write(window, bigFont, "Best: {0} seconds".format(round(self.finishTime/1000, 2)), (windowSize[0]//2-bigFont.size("Best: {0} seconds".format(round(self.finishTime/1000, 2)))[0]//2, windowSize[1]//2-3*bigFont.size("A")[1])) #Highscore
  290.          else:
  291.             write(window, bigFont, "Best: {0} seconds".format(round(self.highscore/1000, 2)), (windowSize[0]//2-bigFont.size("Best: {0} seconds".format(round(self.highscore/1000, 2)))[0]//2, windowSize[1]//2-3*bigFont.size("A")[1])) #Highscore
  292.          write(window, bigFont, "{0} seconds".format(round(self.finishTime/1000, 2)), (windowSize[0]//2-bigFont.size("{0} seconds".format(round(self.finishTime/1000, 2)))[0]//2, windowSize[1]//2-2*bigFont.size("A")[1])) #Time
  293.          fact = FACTS.facts[FACTS.fact].split("\n")
  294.          for i in range(len(fact)):
  295.             write(window, font, fact[i], (windowSize[0]//2-font.size(fact[i])[0]//2, windowSize[1]//2+i*font.size("A")[1])) #Fact
  296.          write(window, bigFont, "Press space to retry", (windowSize[0]//2-bigFont.size("Press space to retry")[0]//2, windowSize[1]//2+(i+2)*font.size("A")[1]), (190, 100, 10)) #Instructions
  297.          write(window, font, "Game made by @Tititesouris", (0, windowSize[1]-2*font.size("A")[1])) #Credits game
  298.          write(window, font, "Graphics made by @_Inaar", (0, windowSize[1]-font.size("A")[1])) #Credits art
  299.          write(window, font, "Music from incompetech.com", (windowSize[0]-font.size("Music from incompetech.com")[0], windowSize[1]-font.size("A")[1])) #Credits music
  300.       for x in range(windowSize[0]+round(2*pi*self.wavePeriod)): #Waves
  301.          drawCircle(window, (round(x-getTime()/self.waveSpeed%(2*pi*self.wavePeriod)), round(self.surface+(abs(sin(getTime()/self.waveStrength%(2*pi*self.wavePeriod)))+1)*self.waveAmplitude*sin(x/self.wavePeriod))), 1, (255, 255, 255), 0)
  302. GAME = game()
  303. '''
  304. Infinite loop
  305. '''
  306. GAME.reset()
  307. while isGameRunning:
  308.    posMouse = pygame.mouse.get_pos() #Cursor position
  309.    ### Events ###
  310.    for event in pygame.event.get():
  311.       if event.type == QUIT: #Closing window
  312.          isGameRunning = False #Terminate programme
  313.       if event.type == KEYDOWN: #Pushing key
  314.          if event.key in [K_UP, K_w]:
  315.             press["up"] = True
  316.          if event.key in [K_RIGHT, K_d]:
  317.             press["right"] = True
  318.          if event.key in [K_DOWN, K_s]:
  319.             press["down"] = True
  320.          if event.key in [K_LEFT, K_a]:
  321.             press["left"] = True
  322.          if event.key == K_SPACE:
  323.             if not GAME.gameOver:
  324.                TURTLE.barrelRoll()
  325.             else:
  326.                GAME.reset()
  327.                FACTS.new()
  328.          if event.key == K_ESCAPE and isTime(ENGINE.startTime):
  329.             if ENGINE.paused:
  330.                ENGINE.paused = False
  331.                GAME.time += getTime()-GAME.pausedTime
  332.                ENGINE.nextSpawn += getTime()-GAME.pausedTime
  333.             else:
  334.                ENGINE.paused = True
  335.                GAME.pausedTime = getTime()
  336.       if event.type == KEYUP: #Releasing key
  337.          if event.key in [K_UP, K_w]:
  338.             press["up"] = False
  339.          if event.key in [K_RIGHT, K_d]:
  340.             press["right"] = False
  341.          if event.key in [K_DOWN, K_s]:
  342.             press["down"] = False
  343.          if event.key in [K_LEFT, K_a]:
  344.             press["left"] = False
  345.    ENGINE.tick()
  346.    GAME.display()
  347.    pygame.display.update() #Display everything!
Add Comment
Please, Sign In to add comment