diff --git a/Final_Presentation/doing_battle.png b/Final_Presentation/doing_battle.png new file mode 100644 index 0000000..8177a92 Binary files /dev/null and b/Final_Presentation/doing_battle.png differ diff --git a/Final_Presentation/gladiator.png b/Final_Presentation/gladiator.png new file mode 100644 index 0000000..8aa2ffd Binary files /dev/null and b/Final_Presentation/gladiator.png differ diff --git a/Final_Presentation/midair.png b/Final_Presentation/midair.png new file mode 100644 index 0000000..999a96b Binary files /dev/null and b/Final_Presentation/midair.png differ diff --git a/Final_Presentation/start.png b/Final_Presentation/start.png new file mode 100644 index 0000000..23542c3 Binary files /dev/null and b/Final_Presentation/start.png differ diff --git a/Final_Recording.mp4 b/Final_Recording.mp4 new file mode 100644 index 0000000..28d5094 Binary files /dev/null and b/Final_Recording.mp4 differ diff --git a/HUD.py b/HUD.py new file mode 100644 index 0000000..f5c092b --- /dev/null +++ b/HUD.py @@ -0,0 +1,142 @@ +import math, sys +import pygame +from pygame.locals import * +"""This file contains all the HUD elements. These are all drawn onto the screen itself (not the world) after everything else has been drawn to it. So, +in the current framework, HUD is drawn over characters and spores and terrain. """ + +class HUD_Object(pygame.sprite.Sprite): + """ Base class for parts of the HUD. """ + def __init__(self, view, player): + pygame.sprite.Sprite.__init__(self) + self.view, self.player = view, player + + +class Text(HUD_Object): + """ Text displayed at the bottom of the screen. """ + def __init__(self, view, player, words, duration, speaker): + HUD_Object.__init__(self, view, player) + + # Initialize font and draw it with the given words + drawing_font = pygame.font.Font(pygame.font.get_default_font(), 18) + self.image = drawing_font.render(words, True, pygame.Color('black'), pygame.Color('azure3')) + + # Duration means how long the message stays on the screen in clock ticks + self.timer = duration + + # Set parameters: rectangle for positioning, words for string, and speaker for order of importance + self.rect = self.image.get_rect() + self.speaker = speaker + self.words = words + + def update(self): + """ Keeps the words at the bottom of the screen and keeps track of time. """ + self.rect.center = (400, 550) + self.timer -= 1 + if self.timer <= 1: + self.kill() + + def __cmp__(self, other): + # Ascending order of importance: Monster, Mushroom Hat, Friendly + if self.speaker == other.speaker: + return -1 #This will always make it return the last entry in a list. + elif self.speaker == 'Enemy' and (other.speaker == 'Player' or other.speaker == 'Friend'): + return -1 + elif self.speaker == 'Player' and other.speaker == 'Friend': + return -1 + else: + return 1 + + def __str__(self): + return self.words + +class HealthBar(pygame.sprite.Sprite): + """ A red on black health bar drawn on the left side of the screen. """ + def __init__(self, player): + # Set the height and position of the red surface, + # inner_rect, based on the player's current wound value. + pygame.sprite.Sprite.__init__(self) + self.player = player + self.max = self.player.max_wound/5 + self.current = self.max - self.player.wound/5 + self.health_diff = self.player.wound/5 + + # image is slightly larger than the red bar at max, in order to have a border of 2 px + self.image = pygame.Surface((24, self.max+4)) + self.image.fill((0,0,0)) + + # puts it on the left side of the screen, halfway up the side + self.rect = self.image.get_rect() + self.rect.centery = 300 + self.rect.centerx = 32 + + # creates the red health bar inside the black boundary + self.inner_rect = pygame.Rect(2, 2, 20, self.current) + self.inner_rect.centery = self.rect.centery + self.inner_rect.bottom = self.rect.bottom-2 + + def update(self): + # Update based on changing wound values, blits the new over the old + self.inner_rect.height = self.max - self.player.wound/5 + self.inner_rect.top = 2+self.player.wound/5 + self.image.fill((0, 0, 0)) + self.image.fill((255,0,0), self.inner_rect) + +class Spore_Boxes(pygame.sprite.Sprite): + """ A class that contains all the possible spore indicators. """ + def __init__(self, current_room): + pygame.sprite.Sprite.__init__(self) + + # List of all possible spores + self.spores = [One_Spore('q'), One_Spore('e')] + self.image = pygame.Surface((32, 84)) + self.image.set_colorkey((0,0,0)) # Makes the default color of a surface, black, into transparent + + # Draws each OneSpore onto self.image + for index, spore in enumerate(self.spores): + self.image.blit(spore.image, (0, 52*index)) + + self.rect = self.image.get_rect() + self.rect.centerx = 32 + self.rect.y = 420 + self.current_room = current_room + + def change(self): + # Updates the currently boxed OneSpore based on the current spore selected in current_room + self.spores[self.current_room.spore_list.index(self.current_room.active_spore)].change_state() + self.image = pygame.Surface((32, 84)) + self.image.set_colorkey((0,0,0)) + for index, spore in enumerate(self.spores): + self.image.blit(spore.image, (0, 52*index)) + +class One_Spore(pygame.sprite.Sprite): + """ Each spore indicator. The currently selected spore is boxed in blue. """ + def __init__(self, key): + # Key means which key each spore corresponds to + self.key = key + + self.image_unselect = pygame.Surface((32, 32)) + self.image_select = pygame.Surface((32, 32)) + + colors_dict = {'q':pygame.Color('chartreuse3'), 'e':pygame.Color('darkgoldenrod4')} + + self.image_unselect.fill(colors_dict[key], pygame.Rect(10, 10, 14, 14)) + self.image_select.fill(colors_dict[key], pygame.Rect(10, 10, 14, 14)) + pygame.draw.rect(self.image_select, pygame.Color('cyan'), pygame.Rect(0, 0, 32, 32), 2) + + # By default, q, the devour spore, is selected + if key == 'q': + self.selected = True + else: + self.selected = False + + if self.selected: + self.image = self.image_select + else: + self.image = self.image_unselect + + def change_state(self): + self.selected = not self.selected + if self.selected: + self.image = self.image_select + else: + self.image = self.image_unselect \ No newline at end of file diff --git a/Intro.py b/Intro.py new file mode 100644 index 0000000..7063e18 --- /dev/null +++ b/Intro.py @@ -0,0 +1,68 @@ +### This module provides the beginning text intro + +import math, sys, pickle +import pygame +from pygame.locals import * + +class IntroMovie(object): + """ This class contains the images for the different intro screens as a list. """ + def __init__(self, screen): + # IntroMovie must be given the screen you want it to blit onto + self.screen = screen + self.done = False + + # Initialize the list of images in order of which you want displayed. Does not currently resize anything. + self.image_list = [pygame.image.load("png/title.png").convert_alpha(), + pygame.image.load("png/frame2.png").convert_alpha(), + pygame.image.load("png/frame3.png").convert_alpha(), + pygame.image.load("png/frame4.png").convert_alpha(), + pygame.image.load("png/frame5.png").convert_alpha(), + pygame.image.load("png/frame6.png").convert_alpha(), + pygame.image.load("png/frame7.png").convert_alpha(), + pygame.image.load("png/frame8.png").convert_alpha(), + pygame.image.load("png/frame9.png").convert_alpha(), + pygame.image.load("png/frame10.png").convert_alpha(), + pygame.image.load("png/frame11.png").convert_alpha(), + pygame.image.load("png/frame12.png").convert_alpha(), + pygame.image.load("png/frame13.png").convert_alpha() + ] + + # Set the starting image + self.image_index = -1 + self.change_image() + + def change_image(self): + # Moves to the next image and centers it + self.image_index += 1 + self.image = self.image_list[self.image_index] + self.rect = self.image.get_rect() + self.rect.center = self.screen.get_rect().center + + def update(self): + # Check for any updates, such as they are trying to skip through it all. + # Controller is not currently running, so this must be done within IntroMovie + for event in pygame.event.get(): + if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): + self.done = True + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + if self.image_index < len(self.image_list)-1: + self.change_image() + else: + self.done = True + + # Display on-screen with a black background, if applicable + self.screen.fill((0,0,0)) + self.screen.blit(self.image, self.rect) + + pygame.display.flip() + +def run(screen, clock): + """ Makes things run. This is called in game_base.py before the game begins, + so that you only see it once. clock and screen are initialized outside of here + in order to make them be the same as the game will be played with.""" + video = IntroMovie(screen) + + while not video.done: + video.update() + clock.tick(60) \ No newline at end of file diff --git a/LivingThings.py b/LivingThings.py new file mode 100644 index 0000000..dd4bd60 --- /dev/null +++ b/LivingThings.py @@ -0,0 +1,447 @@ +### All of the living things + +import math, sys +import pygame +from pygame.locals import * +from numpy import sign + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Living(pygame.sprite.Sprite): + """ This class is all the things that move. """ + def __init__(self, x, y, width, height, image_file_name, initial_speed): + """ x = upper left corner x component + y = upper left corner y component + width = x dimension to resize image to + height = y dimension to resize image to + image_file_name = a string of the image file name to load + initial_speed = how quickly it moves in the x direction + """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set default image + self.image = pygame.image.load(image_file_name).convert_alpha() + self.image = pygame.transform.scale(self.image, (width, height)) + + # Set position + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + + # Set initial_speed vector + self.change_x = initial_speed + self.change_y = 0 + + # Set basic parameters/all the flags + self.room = None # makes it so you can check collisions with objects in the room/affect them + self.flipped = False # flips you over, used to draw you upside-down and let you float + self.wet = False # checks to see if you are touching water and will make you drown + self.talked = False # checks to see if you have spoken to your mushroom and triggers text + + def calc_grav(self): + """ Calculate effect of gravity. Changes based on whether you're in the water or floating or on the ground. """ + if self.wet and self.flipped and not self.is_floating(): + self.change_y -= .2 + elif self.is_floating() and self.flipped: + pass + else: + if self.change_y == 0: # gives an initial speed bump + self.change_y = 1 + else: + self.change_y += .35 # steadily increases the fall + + def update(self): + """ Makes sure all living things can update """ + pass + + def is_floating(self): + """ Check to see if you are floating on top of water """ + # Checks if there is water 1 pixel below you + self.rect.y += 1 + water_beneath = pygame.sprite.spritecollide(self, self.room.sludge, False) + + # Checks if there is water in the spot you actually occupy + self.rect.y -= 1 + in_water = pygame.sprite.spritecollide(self, self.room.sludge, False) + + # If there's water beneath you but you're not in water, you're floating! + return water_beneath and not in_water + +class MushroomGuy(Living): + """ This class represents the player character. """ + def __init__(self): + self.size = (75, 75) + # Call the parent's constructor + Living.__init__(self, 0, 0, self.size[0], self.size[1], 'png/mg_tc0.png', 0) + + # Set images + self.image_list = [pygame.image.load('png/mg_tc0.png').convert_alpha(), pygame.image.load('png/mg_tc1.png').convert_alpha(), pygame.image.load('png/mg_tc2.png').convert_alpha()] + for index, image in enumerate(self.image_list): + self.image_list[index] = pygame.transform.scale(image, self.size) + + # Make list of things your mushroom will say to you + self.text = ["SYMBIOTE: C'mon, we won't be able to find your family if we don't eat something...!", + "SYMBIOTE: Look at how strong we are! We don't need anyone else, aren't I enough for you?", + "SYMBIOTE: Wow, um... I think that's... probably enough?"] + + self.speed = 6 + + # Corruption starts at zero. Eating mushrooms increases corruption. As corruption increases, + # player avatar image changes (every corrupt_change points) + self.corruption = 0 + self.corrupt_change = 7 + self.list_index = 0 + + # Set shot direction: 1 = right, -1 = left + self.shot_dir = 1 + + # Set how much abuse the player can take before dying. wound will increase until it hits max_wound + self.wound = 0 + self.max_wound = 1000 + + #sets drowning for sludge + self.drown = 0 + self.max_drown = 120 + + #Fire! + self.on_fire = False + + self.talk_length = 240 # Sets how long text from hitting 't' will last + + # Player-controlled movement: + def go_left(self): + """ Called when the user hits the left arrow. """ + if ((self.is_floating() or self.wet) and self.flipped) or not self.flipped: + self.change_x = -self.speed + else: + self.change_x = 0 + # Make the shot direction to the left + self.shot_dir = -1 + + def go_right(self): + """ Called when the user hits the right arrow. """ + if ((self.is_floating() or self.wet) and self.flipped) or not self.flipped: + self.change_x = self.speed + else: + self.change_x = 0 + + # Make the shot direction to the right + self.shot_dir = 1 + + def stop(self): + """ Called when the user lets off the keyboard. """ + self.change_x = 0 + + def jump(self): + """ Called when user hits 'jump' button. Currently does nothing, but can be uncommented if desired. """ + pass + # # move down a bit and see if there is a platform below us. + # # Move down 2 pixels because it doesn't work well if we only move down + # # 1 when working with a platform moving down. + # self.rect.y += 2 + # wall_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + # self.rect.y -= 2 + + # # If it is ok to jump, set our speed upwards + # # That's a really cool way to do this + # if len(wall_hit_list) > 0 and not self.flipped: + # self.change_y = -5 + + def how_corrupt(self): + """ Changes the image based on the corruption level of the player. Currently, 3 levels of corruption. """ + self.list_index = self.corruption/self.corrupt_change + if self.list_index > len(self.image_list) - 1: + self.list_index = len(self.image_list) - 1 + self.image = self.image_list[self.list_index] + + def draw_flipped(self): + """Flips the player's sprite based on the value assigned to self.flipped (controlled by keypress)""" + if self.list_index > len(self.image_list) - 1: + self.list_index = len(self.image_list) - 1 + if self.flipped: + self.image = pygame.transform.flip(self.image_list[self.list_index], False, True) + + def climb(self): + """ Allows the player to climb ledge fungi. """ + if pygame.sprite.spritecollide(self, self.room.can_climb, False): + self.change_y = -5 + + def update(self): + """ Update the player position. """ + + # Gravity + self.calc_grav() + + # Move left/right + self.rect.x += self.change_x + + # You only get to talk once. + self.talked = False + + # Did this update cause us to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # Check if it is deadly + if block.mortality == True: + self.wound += 50 + else: + # If we are moving right, snap our right side to the left side of + # the item we hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if we are moving left, do the opposite. + self.rect.left = block.rect.right + + # Move up/down + self.rect.y += self.change_y + + # Check and see if we hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # Check if it's deadly ISUE: You can survive lava if you're at the bottom of a lake + if block.mortality == True: + self.wound += 50 + + else: + # Reset our position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop our vertical movement + self.change_y = 0 + + # Check if we are stuck in something viscous and slow us down + drown us if we are + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + if block_hit_list: + self.wet = True + if not self.flipped: + self.drown += 1 + else: + self.drown = 0 + self.wet = False + for block in block_hit_list: + self.rect.x -= self.change_x*block.visc + self.rect.y -= self.change_y*block.visc + + # Check if we're hitting a dangerous enemy + enemy_hit_list = pygame.sprite.spritecollide(self, self.room.enemy_list, False) + for enemy in enemy_hit_list: + if enemy.mortality == True: + self.wound += 10 + + # Kill player if he's beyond max_wound or max_drown + if self.wound > self.max_wound or self.drown > self.max_drown: + self.kill() + + # Update corruption and flipped status + self.how_corrupt() + self.draw_flipped() + + # Turn off death for easier debugging + death = True + if not death: + self.wound = 0 + + def __str__(self): + # Used in Text + return 'Player' + +class Enemy(Living): + """ This is the base class for anything that is alive and should move that isn't the player. """ + def __init__(self, x, y, width, height, end_x, speed = -2, mortality = True): + """ x = upper left corner x component + y = upper left corner y component + width = x dimension + height = y dimension + speed = how quickly it moves in the x direction + distance = how far it can walk + mortality = does it kill you? """ + + # Set the range of values it can go between + self.start_x = x - width + self.end_x = end_x + + # Call the parent's constructor + Living.__init__(self, self.start_x, y, width, height, 'png/enemy.png', speed) + + # Set speed vector + self.speed = abs(speed) + self.change_x = speed + self.change_y = 0 + + self.mortality = mortality + self.text = ['MONSTER: Rawr!', 'MONSTER: Rawr!', 'MONSTER: Rawr!'] + self.talk_length = 60 + + self.near_player = False + + def update(self): + """ Update the enemy position. """ + # Gravity + self.calc_grav() + # Move left/right + self.rect.x += self.change_x + # If you talked last time, you don't talk this time + self.talked = False + #Check if you're on the same level as the player and close to the player + if (abs(self.room.player.rect.centerx - self.rect.centerx) <= 300 and + self.room.player.rect.bottom == self.rect.bottom): + # Move towards him ISSUE: Enemy occasionally teleport far away and disappears + self.change_x = sign(self.room.player.rect.centerx - self.rect.centerx)*self.speed*1.5 + if not self.near_player: # If I wasn't near him last step + self.talked = True + self.near_player = True + else: + #Reset your speed if you choose to change it + self.change_x = sign(self.change_x)*self.speed + self.near_player = False + + # Did this update cause it to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # If the enemy is moving right, set its right side to the left side of + # the item it hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if it is moving left, do the opposite. + self.rect.left = block.rect.right + + # Change direction + self.change_x = -self.change_x + + # Check to see if it has hit the end of its range + if self.rect.x <= self.end_x: + self.change_x = self.speed + elif self.rect.x >= self.start_x: + self.change_x = -self.speed + # Move up/down + self.rect.y += self.change_y + + # Check and see if it hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + + # Reset its position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop its vertical movement + self.change_y = 0 + + def __str__(self): + return 'Enemy' + +class Friend(Enemy): + """ A class of living creatures that will not kill you. Currently, it does not move.""" + def __init__(self, x, y, width, height, not_used, image_file_name): + """ x = upper left corner x component + y = upper left corner y component + width = x dimension + height = y dimension + image_file_name = the image wanted for the friend. + The friend does not move, so speed and distance are 0 and mortality is False""" + Enemy.__init__(self, x, y, width, height, 0, 0, False) + self.image = pygame.image.load(image_file_name).convert_alpha() + self.image = pygame.transform.scale(self.image, (width, height)) + self.near_player = False + self.talk_length = 180 + + def update(self): + self.calc_grav() + self.talked = False + + # Talks to you if you are within a certain distance + if abs(self.room.player.rect.centerx - self.rect.centerx) <= 150: + if not self.near_player: + self.talked = True + self.near_player = True + else: + self.near_player = False + + # Move up/down + self.rect.y += self.change_y + + # Check and see if it hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + + # Reset its position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop its vertical movement + self.change_y = 0 + + def __str__(self): + return 'Friend' + +class AdultDuck(Friend): + """ Makes an Adult Duck. No difference in corruption, just a different image and default size.""" + def __init__(self, x, y, width = 100, height = 100, not_used = 0): + self.width = width + self.height = height + Friend.__init__(self, x, y, self.width, self.height, not_used, "png/adult_duck.png") + self.text = ["DUCK: I'm sorry, but you can't stay with us. Good luck.", + "DUCK: Ugh! Leave us alone, you don't belong with us!", + "DUCK: Get away, you monster! We don't want you here!"] + +class ChildDuck(Friend): + """ Baby Duck. Smaller than Adult. """ + def __init__(self, x, y, width = 75, height = 75, not_used = 0): + self.width = width + self.height = height + Friend.__init__(self, x, y, self.width, self.height, not_used, "png/child_duck_friend.png") + self.text = ["BABY DUCK: Hi! Wanna play?", + "BABY DUCK: Uh... what's that on your head?", + "BABY DUCK: Eek! Get away! MOMMY!"] + +class Log(Enemy): + """ Unmoving enemy class, does not block or harm. """ + def __init__(self, x, y, width = 100, height = 100, not_used = 0): + Enemy.__init__(self, x, y, width, height, not_used, speed = 0, mortality = False) + self.text = ["Shhhh, it's sleeping", "Hah, it can't see us coming!", "This just makes it easier!"] + +class Edible(pygame.sprite.Sprite): + """ This is the base class; any new foods should be modified from this one. """ + def __init__(self, x, y, width, height, corr_points = 1, health_points = 50): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set the visual + self.image = pygame.image.load('png/edible.png').convert_alpha() + self.image = pygame.transform.scale(self.image, (width, height)) + + # Set parameters + self.corr_points = corr_points + self.health_points = health_points + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + +class FriendEdible(Edible): + """ This is an edible food that only comes from when you have killed a friendly creature. """ + def __init__(self, x, y, width, height): + Edible.__init__(self, x, y, width, height, 5, 150) \ No newline at end of file diff --git a/Menu.py b/Menu.py new file mode 100644 index 0000000..8f00efd --- /dev/null +++ b/Menu.py @@ -0,0 +1,71 @@ +import pygame +from pygame.locals import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Button(object): + """ Each button in the menu is a Button object. """ + def __init__(self, text, position): + self.text = text + self.position = position + self.hovered = False + self.make_button() + + def color(self): + # Determines the color of the button depending on whether the mouse is over it + if self.hovered: + return (0, 0, 0) + else: + return (100, 100, 200) + + def make_button_params(self): + # Defines parameters for the button + font = pygame.font.Font(pygame.font.get_default_font(), 24) + self.button_surf = font.render(self.text, True, self.color(), pygame.Color('red')) + + def make_button(self): + # Makes the bounding rect for the button that allows you to check its collisions with the mouse + self.make_button_params() + self.rect = self.button_surf.get_rect() + self.rect.center = self.position + + def draw(self, screen): + self.make_button_params() + screen.blit(self.button_surf, self.rect) + + def pressed(self): + return self.text + +class Menu(object): + """ Menu object contains a number of buttons and draws them onto the screen. """ + def __init__(self, menu_on): + self.menu_on = menu_on + + button_width = 300 + self.buttons = [] + + def make_buttons(self, names): + # Evenly spaces the buttons based on how many there are. + start = 100 + spacing = (SCREEN_HEIGHT - 200)/len(names) + for number, name in enumerate(names): + self.buttons.append(Button(name, (SCREEN_WIDTH/2, start + (spacing*number)))) + + def draw(self, screen): + if self.menu_on: + screen.fill(BLACK) + for button in self.buttons: + button.draw(screen) + + diff --git a/Mushroom_Recording.mp4 b/Mushroom_Recording.mp4 new file mode 100644 index 0000000..cfe81f5 Binary files /dev/null and b/Mushroom_Recording.mp4 differ diff --git a/Mushroom_Recording2.mp4 b/Mushroom_Recording2.mp4 new file mode 100644 index 0000000..4bfcc3e Binary files /dev/null and b/Mushroom_Recording2.mp4 differ diff --git a/README.md b/README.md index 4b78d42..ddda669 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,95 @@ -# bug-free-spork -We cannot allow our great nation's cutlery to be overwhelmed by these vermin-bearing hoards. Bring out the mushroom hound! +# Symbiosis + +**Sean Foley, Kaitlyn Keil, Apurva Raman** + +**Software Design, Spring 2016** + +Symbiosis is a platform game in which you play as a blobby orphan baby trying to find a family to accept it. Using powers granted to you by a mushroom symbiote, traverse levels and make decisions to meet your goal. + +Game Site: https://sites.google.com/site/symbiosisthegame/home + +Game Drive: https://drive.google.com/open?id=0Byeh9J0R89gxbTJKakREYWRnbTA + +## Dependencies +This project uses the math, sys, collections, numpy and pygame libraries. Make sure these are installed before playing the game. + +## Modules +To play, run the file game_base2.py. This imports the modules Spores, LivingThings, Terrain, and Room. These contain the classes needed to run the game. +- Spores contains the classes for the thrown spores, such as decomposition and ledge-creation. +- Terrain contains the classes for the platforms and surfaces and obstacles. +- LivingThings contains the classes for the player and creatures that move. +- Room contains and constructs the levels, and imports the above modules. +- HUD contains classes for dialogue and stat bars +- Menu creates a menu +- Intro contains Video/cutscenes +- game_base2 displays and runs the game using a Controller and View class + +## Getting Started +To download the code to run Symbiosis, open https://github.com/SeanFoley123/bug-free-spork/archive/master.zip in a browswer. + +## Usage +Run from game_base2.py. This should open a pygame window, beginning with a cutscene. Press 'space' to advance through this cutscene. The game will then begin. + +### Keybindings +Use the left and right arrow keys to move. Spacebar throws spores; change which type using 'e' (grows ledges) and 'q' (kills and destroys objects). The down arrow key lets you eat mushrooms to regain health. 't' allows you to talk to your sybiotic mushroom friend. 'p' brings up the pause menu. Don't hit the enemy, try to survive! + +## Credit +http://programarcadegames.com/python_examples/show_file.php?file=platform_jumper.py for basic platforming code + +## License +MIT License + +Copyright (c) 2016 Sean Foley, Kaitlyn Keil, Apurva Raman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +# THINGS TO DO + +## Must be done ASAP + + Make the tutorial more intuitive/helpful + + Fix the whole level-traversing thing. Maybe make you able to go both ways? -- Done + + Shrink level 2 -- Done + + Ledges expire after a certain amount of time (10 seconds?) -- Done + + Only one key to switch spores + + Fix the spore-HUD thing + + Display key-bindings on menu + + Make multiple menus + + Terrain rectangles shouldn't affect movement or ledges spreading + +## Would be nice + + Make more cool levels + + New spore abilities + + Implement more story + + More levels of corruption + + Make lava look dangerous/make a barrier between it and water \ No newline at end of file diff --git a/Room.py b/Room.py new file mode 100644 index 0000000..49b85fe --- /dev/null +++ b/Room.py @@ -0,0 +1,325 @@ +### All the stuff for Rooms +import math, sys +import pygame +from pygame.locals import * +from Spores import * +from LivingThings import * +from Terrain import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = pygame.Color('cadetblue1') + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +GROUND_LEVEL = 550 +STARTING_LEVEL = 100 +NEXT_LEVEL = -150 + +class Room(object): + """ This is a generic super-class used to define a level. + Create a child class for each level with level-specific + info. """ + + def __init__(self, player): + """ Constructor. Pass in a handle to player. Needed for when moving platforms + collide with the player. This is not currently applicable, but may be eventually.""" + self.wall_list = pygame.sprite.Group() + self.enemy_list = pygame.sprite.Group() + self.sludge = pygame.sprite.Group() + self.consumeable = pygame.sprite.Group() + self.can_climb = pygame.sprite.Group() + self.player = player + self.spore_list = [Decompose_Spore, Ledge_Spore] + self.active_spore = self.spore_list[0] + + # Background image + self.background = None + + # Makes it so you can change to the next level if there is one, set to 0 if it is the last level + self.next_level = 1 + + # Checks if the Room is a tutorial level + self.is_tutorial = False + self.tutorial = None + + def update(self): + """ Update everything in this level.""" + self.wall_list.update() + self.enemy_list.update() + self.sludge.update() + self.consumeable.update() + self.can_climb.update() + + def draw(self): + """ Draw everything on this level. """ + + # Draw the background + self.world.fill(BLUE) + + # Draw all the sprite lists that we have + self.wall_list.draw(self.world) + self.enemy_list.draw(self.world) + self.sludge.draw(self.world) + self.consumeable.draw(self.world) + self.can_climb.draw(self.world) + +class Room_01(Room): + """ Definition for level 1. """ + + def __init__(self, player): + """ Create level 1. """ + + # Call the parent constructor + Room.__init__(self, player) + + self.world_size = (4000, 800) + self.world = pygame.Surface(self.world_size) + self.next_level = 1 + + # Solid objects. Array with width, height, x, y, and class of obstacle + room = [[200, SCREEN_HEIGHT-STARTING_LEVEL, 0, STARTING_LEVEL, Ground], + [300, 300, 200, 300, Ground], + [50, SCREEN_HEIGHT-150, 500, 150, Ground], + [200, 425, 550, 375, Ground], + [100, 500, 750, 300, Ground], + [100, 425, 850, 375, Ground], + [100, 325, 950, 475, Ground], + [650, 100, 1200, 350, Ground], + [400, 200, 1450, 150, Ground], + [350, 125, 1500, 350, Ground], + [275, 50, 1575, 425, Ground], + [150, 325, 1700, 475, Ground], + [200, 100, 2050, 300, Lava], + [200, 400, 2050, 400, Ground], + [400, 500, 2250, 300, Ground], + [200, 600, 2650, 200, Ground], + [150, 325, 3050, 100, Ground], + [400, 100, 3400, 150, Ground], + [200, 100, 3800, 200, Ground], + [self.world_size[0], 25, 0, 775, Ground]] + + # Objects that hinder movement (and drown the player if they are not flipped) + # Array with width, height, x, y, and class of obstacle + sludge = [[200, 75, 550, 300, Water], + [700, 225, 1050, 550, Water], + [200, 475, 1850, 300, Water], + [200, 500, 2850, 275, Water], + [150, 350, 3050, 425, Water], + [800, 500, 3200, 275, Water] + ] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [[50, 50, 150, 50, Edible], + [50, 50, 300, 250, Edible], + [50, 50, 875, 325, Edible], + [50, 50, 1625, 100, Edible], + [50, 50, 1625, 500, Edible], + [50, 50, 2600, 250, Edible], + [50, 50, 3950, 150, Edible]] + + # Enemies on the level- (width, height, start_x, start_y, end_x) + enemy_list = [[75, 75, 500, 0, 200, Enemy], + [75, 75, 1850, 75, 1450, Enemy], + [75, 75, 2650, 75, 2252, Enemy], + [75, 75, 3800, 75, 3400, Enemy], + [100, 100, 3700, 100, 0, AdultDuck], + [75, 75, 2550, 75, 0, ChildDuck]] + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + + for enemy in enemy_list: + block = enemy[5](enemy[2], enemy[3], enemy[0], enemy[1], enemy[4]) + self.enemy_list.add(block) + +class Room_02(Room): + """ Definition for level 2. """ + + def __init__(self, player): + """ Create level 2. """ + + # Call the parent constructor + Room.__init__(self, player) + self.next_level = 0 + + self.world_size = (7000, 1010) + self.world = pygame.Surface(self.world_size) + + # Solid objects. Array with width, height, x, y, and class of obstacle + room = [[self.world_size[0], 10, 0, self.world_size[1] - 10, Ground], + [200, 800, 200, 0, Ground], [200, 500, 600, 500, Ground], + [300, 100, 600, 400, Lava], [200, 200, 600, 200, Ground], + [200, 500, 800, 500, Lava], [400, 900, 1000, 100, Ground], + [250, 200, 1800, 600, Ground], [200, 100, 2000, 600, Ground], + [50, 100, 1800, 500, Ground], [500, 100, 1850, 500, Lava], + [50, 100, 2350, 500, Ground], [250, 200, 2150, 600, Ground], + [1000, 200, 2600, 800, Ground], [75, 225, 2800, 400, Ground], + [325, 25, 2875, 600, Ground], [325, 50, 2875, 550, Lava], + [100, 625, 3200, 0, Ground], [100, 500, 3600, 550, Ground], + [200, 50, 3500, 500, Ground], [150, 50, 3300, 300, Ground], + [300, 25, 3500, 100, Ground], [100, 800, 3700, 125, Ground], + [3200, 10, 3800, self.world_size[1]-20, Lava], + [300, 25, 4400, 400, Ground], [100, 325, 4600, 0, Ground], + [100, 565, 4600, 425, Ground], [200, 50, 4700, 275, Ground], + [400, 25, 4900, 150, Ground], [400, 200, 4900, 400, Ground], + [200, 225, 5100, 175, Ground], [200, 50, 5300, 350, Lava], + [200, 100, 5300, 400, Ground], [200, 525, 5500, 75, Ground], + [300, 150, 5700, 300, Ground], [200, 25, 5700, 575, Ground], + [200, 200, 6000, 400, Ground], [400, 590, 6400, 400, Ground], + [200, 390, 6800, 600, Ground]] + + # Objects that hinder movement (and drown the player if they are not flipped) + # Array with width, height, x, y, and class of obstacle + sludge = [[1200, 200, 1400, 800, Water], + [800, 490, 3800, 500, Water], + [1700, 390, 4700, 600, Water]] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [] + + # Enemies on the level- (width, height, start_x, start_y, end_x) + enemy_list = [[75, 75, 1400, 0, 1000, Enemy], + [75, 75, 2875, 200, 0, ChildDuck], + [75, 75, 3400, 600, 2600, Enemy], + [75, 75, 3500, 0, 3300, Enemy], + [75, 75, 3700, 300, 3500, Enemy], + [75, 75, 4900, 0, 4700, Enemy], + [75, 75, 6800, 0, 6400, Enemy], + [75, 75, 5775, 500, 0, ChildDuck], + [100, 100, 6700, 200, 0, AdultDuck]] + + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + + for enemy in enemy_list: + block = enemy[5](enemy[2], enemy[3], enemy[0], enemy[1], enemy[4]) + self.enemy_list.add(block) + +class Room_00(Room): + """ Definition for Tutorial Level. """ + + def __init__(self, player): + """ Create Tutorial. """ + + # Call the parent constructor + Room.__init__(self, player) + + self.world_size = (3000, 800) + self.world = pygame.Surface(self.world_size) + self.next_level = 1 + self.is_tutorial = True + self.tutorial = Tutorial() + + # Solid objects. Array with width, height, x, y, and class of obstacle + room = [[3000, 200, 0, 600, Ground], + [500, 400, 0, 200, Ground], + [200, 300, 500, 300, Ground], + [300, 200, 700, 400, Ground], + [200, 300, 1000, 300, Ground], + [200, 500, 1500, 100, Ground], + [100, 400, 1700, 200, Ground], + [200, 300, 2000, 300, Lava], + [200, 300, 2200, 300, Ground], + [600, 500, 2400, 100, Ground]] + + # Objects that hinder movement (and drown the player if they are not flipped) + # Array with width, height, x, y, and class of obstacle + sludge = [[300, 100, 700, 300, Water], + [300, 300, 1200, 300, Water], + [200, 300, 1800, 300, Water]] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [] + + # Enemies on the level- (width, height, start_x, start_y, end_x) + enemy_list = [[100, 100, 400, 100, 0, Log], + [100, 100, 1100, 200, 0, Log], + [75, 75, 2900, 25, 2400, Enemy], + [75, 75, 2900, 25, 0, ChildDuck]] + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + + for enemy in enemy_list: + block = enemy[5](enemy[2], enemy[3], enemy[0], enemy[1], enemy[4]) + self.enemy_list.add(block) + +class Tutorial(object): + """ A class that defines the text used in the tutorial. """ + def __init__(self): + self.text = ['Shoot a spore to decompose the enemy with space! Then eat it... if you dare.', + "You're not very buoyant unless you 'f'lip over!", + "Try getting up higher using the things you know!", + "Y'know... lava doesn't look very safe to touch.", + "Use 'e' and 'q' to switch between your spore powers!", + "Talk to me with 't'. Also... that duck looks... tasty. Er, fun. Yeah. Fun."] + self.talk_length = 60 + + def __str__(self): + return 'Enemy' diff --git a/Room.pyc b/Room.pyc new file mode 100644 index 0000000..f2a97ca Binary files /dev/null and b/Room.pyc differ diff --git a/Sean_Code_Review.py b/Sean_Code_Review.py new file mode 100644 index 0000000..c236180 --- /dev/null +++ b/Sean_Code_Review.py @@ -0,0 +1,128 @@ +### All the stuff for Rooms +import math, sys +import pygame +from pygame.locals import * +from Spores import * +from LivingThings import * +from Terrain import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Room(object): + """ This is a generic super-class used to define a level. + Create a child class for each level with level-specific + info. """ + + def __init__(self, player): + """ Constructor. Pass in a handle to player. Needed for when moving platforms + collide with the player. """ + self.wall_list = pygame.sprite.Group() + self.enemy_list = pygame.sprite.Group() + self.sludge = pygame.sprite.Group() + self.consumeable = pygame.sprite.Group() + self.can_climb = pygame.sprite.Group() + self.player = player + self.spore_list = [Decompose_Spore, Ledge_Spore] + self.active_spore = self.spore_list[0] + + # Background image + self.background = None + + # Update everythign on this level + def update(self): + """ Update everything in this level.""" + self.wall_list.update() + self.enemy_list.update() + self.sludge.update() + self.consumeable.update() + self.can_climb.update() + + def draw(self): + """ Draw everything on this level. """ + + # Draw the background + self.world.fill(BLUE) + + # Draw all the sprite lists that we have + self.wall_list.draw(self.world) + self.enemy_list.draw(self.world) + self.sludge.draw(self.world) + self.consumeable.draw(self.world) + self.can_climb.draw(self.world) + + def draw_end(self, screen): + """ Draw the game over screen. """ + screen.fill(BLACK) + game_over_pic = pygame.transform.scale(pygame.image.load('game_over_mushroom.jpg').convert(), [350, 350]) + screen.blit(game_over_pic, (SCREEN_W_MID-175, SCREEN_H_MID-175)) + +# Create platforms for the level +class Room_01(Room): + """ Definition for level 1. """ + + def __init__(self, player): + """ Create level 1. """ + + # Call the parent constructor + Room.__init__(self, player) + + self.world_size = (1000, 600) + self.world = pygame.Surface(self.world_size) + + # Solid objects. Array with width, height, x, y, and class of obstacle + room = [[500, 50, 0, 550, Ground], + [180, 30, 200, 400, Ground], + [200, 30, 500, 300, Ground], + [100, 400, 900, 200, Ground], + [300, 50, 500, 550, Lava] + ] + + # Objects that hinder movement. Array with width, height, x, y, and class of obstacle + sludge = [[300, 100, 400, 350, Water]] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [[50, 50, 450, 500, Edible], + [50, 50, 245, 350, Edible], + [50, 50, 160, 500, Edible], + [50, 50, 300, 500, Edible], + [50, 50, 400, 500, Edible]] + + # Enemies on the level + enemy_list = [[75, 75, 425, 475, Enemy]] + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + + for enemy in enemy_list: + block = enemy[4](enemy[2], enemy[3], enemy[0], enemy[1]) + self.enemy_list.add(block) \ No newline at end of file diff --git a/Shelf-Fungus.jpg b/Shelf-Fungus.jpg new file mode 100644 index 0000000..f0de8d7 Binary files /dev/null and b/Shelf-Fungus.jpg differ diff --git a/Spores.py b/Spores.py new file mode 100644 index 0000000..9472174 --- /dev/null +++ b/Spores.py @@ -0,0 +1,272 @@ + ### All the stuff for the spore classes +import math, sys +import pygame +from pygame.locals import * +from LivingThings import * + +# -- Global constants + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Spore(pygame.sprite.Sprite): + """ Base class of spores. + + player: pass the player into the shot + speed: a tuple of the x velocity and the y velocity + size: a tuple of the width and height of the shot""" + def __init__(self, player, speed = (8,0), size = (10,10)): + # Call the parent's init + pygame.sprite.Sprite.__init__(self) + + # Make visible and set direction. player.shot_dir corresponds to the most recent + # direction the player was going + self.image = pygame.Surface([size[0], size[1]]) + self.image.fill(pygame.Color('blueviolet')) + self.direction = player.shot_dir + + # Set up initial position and the speed the shot is going. Currently, no spores have y-velocity. + self.rect = self.image.get_rect() + + self.rect.y = player.rect.centery + self.change_x = speed[0] * self.direction + self.change_y = speed[1] * self.direction + + self.rect.x = player.rect.centerx + + # Set up the room and list of things it can hit. Different spores will affect different things + self.room = None + self.unaffected = pygame.sprite.Group() + self.affected = pygame.sprite.Group() + + # Set the length of time the spore will be on screen before deleting itself. Each second is 60 + self.life = 240 + + def setup_lists(self): + """ Sets up the list of what it can affect and what it cannot. Specific to spore types. """ + pass + + def update(self): + """ Updates the spore position. """ + self.rect.x += self.change_x + self.rect.y += self.change_y + + self.life -= 1 + if self.life == 0: + self.kill() + +class Decompose_Spore(Spore): + """ A spore that decomposes things it touches. """ + def __init__(self, player): + Spore.__init__(self, player) + self.image.fill(pygame.Color('chartreuse3')) + + def setup_lists(self): + """ Sets up the list of what it can affect and what it cannot. """ + + # Decompose spores do not affect terrain like ground or water + for thing in self.room.wall_list: + self.unaffected.add(thing) + + for thing in self.room.sludge: + self.unaffected.add(thing) + + # It does, however, destroy enemies and things that are alive. Later implement logs. + for thing in self.room.enemy_list: + self.affected.add(thing) + + for thing in self.room.can_climb: + self.affected.add(thing) + + def kill_it(self, other): + """ Kills the creature and leaves a food in its place """ + # Killing a 'friendly' creature will drop a larger mushroom + if isinstance(other, Friend): + new_food = FriendEdible(other.rect.x, other.rect.y, 75, 50) + height_change = other.rect.height - 50 + new_food.rect.x = other.rect.x + new_food.rect.y = other.rect.y + height_change + new_food.player = other.room.player + other.room.consumeable.add(new_food) + elif isinstance(other, Enemy): + # killing a small + new_food = Edible(other.rect.x, other.rect.y, 50, 50) + height_change = other.rect.height - 50 + new_food.rect.x = other.rect.x + new_food.rect.y = other.rect.y + height_change + new_food.player = other.room.player + other.room.consumeable.add(new_food) + other.kill() + self.kill() + + def update(self): + """ Updates the spore. """ + Spore.update(self) + + unaffected_hit_list = pygame.sprite.spritecollide(self, self.unaffected, False) + for thing in unaffected_hit_list: + self.kill() + + affected_hit_list = pygame.sprite.spritecollide(self, self.affected, False) + for thing in affected_hit_list: + self.kill_it(thing) + +class Ledge_Spore(Spore): + """ Creates ledge-like fungi that allow you to climb up a surface. Cover the entire surface. """ + def __init__(self, player): + Spore.__init__(self, player) + self.image.fill(pygame.Color('darkgoldenrod4')) + + def setup_lists(self): + """ Sets up the list of what it can affect and what it cannot. """ + + # Ledge spores affect walls, but not lava, water, or enemies. + for thing in self.room.wall_list: + if thing.mortality == False: + self.affected.add(thing) + else: + self.unaffected.add(thing) + + for thing in self.room.sludge: + self.unaffected.add(thing) + + for thing in self.room.enemy_list: + self.unaffected.add(thing) + + def grow_fungi(self, wall): + """ Creates a a surface on the wall which the player can climb up. """ + if self.direction == 1: + ledge_fungus = FirstLedge(self.rect.centery, self.room, wall, 'right') + self.room.can_climb.add(ledge_fungus) + else: + ledge_fungus = FirstLedge(self.rect.centery, self.room, wall, 'left') + self.room.can_climb.add(ledge_fungus) + + def update(self): + """ Updates the spore. """ + Spore.update(self) + + unaffected_hit_list = pygame.sprite.spritecollide(self, self.unaffected, False) + for thing in unaffected_hit_list: + if not isinstance(thing, Enemy): + self.kill() + + affected_hit_list = pygame.sprite.spritecollide(self, self.affected, False) + for thing in affected_hit_list: + self.grow_fungi(thing) + self.kill() + +class FirstLedge(pygame.sprite.Sprite): + """ A set of fungi which a player can climb up. + hit_y: the y-coordinate of the spore when it hits the wall + room: the room so that new ledges can be added to the room + wall: the wall object the fungus is growing on + wall_direction: 'left' or 'right' to tell which side the fungus is growing on + is_first: boolian to see if it is the first ledge to be grown. + """ + def __init__(self, hit_y, room, wall, wall_direction): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + self.wall = wall + self.room = room + self.direction = wall_direction + + if self.wall.rect.height <= 50: + height = self.wall.rect.height + else: + height = 50 + + # Make a blue wall, of the size specified in the parameters + if self.direction == 'right': + self.image = pygame.image.load('png/ledge_attach_right.png').convert_alpha() + else: + self.image = pygame.image.load('png/ledge_attach_left.png').convert_alpha() + self.image = pygame.transform.scale(self.image, (50, height)) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.centery = hit_y + if wall_direction == 'right': + self.rect.x = self.wall.rect.left - 50 + else: + self.rect.x = self.wall.rect.right + self.spread_per_update = 1 + self.spread_up = self.rect.top + self.spread_down = self.rect.bottom + self.climb_okay = True + # Keep track of the most recent fungi grown on the wall, looking at the top of the ones growing + # upward and the bottom of the ones growing down + self.grow_above = self.rect.top + self.grow_below = self.rect.bottom + + self.timer = 660 + + def grow_new_above(self): + new_ledge = Ledge(self.spread_up, self.grow_above, self.rect.centerx, self.direction) + blah = True + for thing in self.room.wall_list: + if new_ledge.rect.colliderect(thing): + blah = False + if blah: + self.room.can_climb.add(new_ledge) + self.grow_above = new_ledge.rect.top + + def grow_new_below(self): + new_ledge = Ledge(self.grow_below, self.spread_down, self.rect.centerx, self.direction) + blah = True + for thing in self.room.wall_list: + if new_ledge.rect.colliderect(thing): + blah = False + if blah: + self.room.can_climb.add(new_ledge) + self.grow_below = new_ledge.rect.bottom + + def update(self): + """ Makes the fungi grow """ + if self.spread_up > self.wall.rect.top: + self.spread_up -= self.spread_per_update + if (self.grow_above - self.spread_up) == 50: + self.grow_new_above() + elif self.spread_up == self.wall.rect.top and (self.grow_above-self.spread_up) > 25: + self.grow_new_above() + + if self.spread_down < self.wall.rect.bottom: + self.spread_down += self.spread_per_update + if self.spread_down - self.grow_below == 50: + self.grow_new_below() + elif self.spread_down == self.wall.rect.bottom and (self.spread_down - self.grow_below) > 25: + self.grow_new_below() + + self.timer -= 1 + if self.timer <= 0: + self.kill() + + +class Ledge(pygame.sprite.Sprite): + def __init__(self, top, bottom, centerx, direction): + pygame.sprite.Sprite.__init__(self) + + height = abs(top-bottom) + self.direction = direction + if self.direction == 'right': + self.image = pygame.image.load('png/ledge_attach_right.png').convert_alpha() + else: + self.image = pygame.image.load('png/ledge_attach_left.png').convert_alpha() + self.image = pygame.transform.scale(self.image, (50, height)) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.centerx = centerx + self.rect.y = top + self.climb_okay = True + self.timer = 420 + + def update(self): + self.timer -= 1 + if self.timer <= 0: + self.kill() \ No newline at end of file diff --git a/TechnicalReview2 b/TechnicalReview2 new file mode 100644 index 0000000..0a3c987 --- /dev/null +++ b/TechnicalReview2 @@ -0,0 +1,5 @@ +Background: We'll show a demo of what we've done so far. It's fairly similar to the last iteration with a number of additional +features. We'll also talk about how we shifted from building everything from scratch to using Pygame's built in sprite class. +Questions: We'd like help with a lava-related bug, and we need advice on how to make a system so we can build large levels +easily. Finally, we'll ask a couple questions about UI elements people would like to see. +Agenda: We'll start by giving a bit of background and doing a demo, then we'll just ask questions of the class. diff --git a/Technical_Review_2_Reflection b/Technical_Review_2_Reflection new file mode 100644 index 0000000..16956f3 --- /dev/null +++ b/Technical_Review_2_Reflection @@ -0,0 +1,13 @@ +### Technical Review Reflection 2 + +## Feedback and Decisions +We asked our audience about some specific bugs which were disrupting our game. From this, we were given a lot of suggestions for both work-arounds (give yourself more health and have it regenerate slowly rather than reset) and solutions which may or may not have worked. Most of the ideas built off of each other, and the idea of health that slowly decreased was the one that stuck out the most. Another suggested only updating the health once, after everything had been checked. Part of this time was spent with the audience trying to figure out our problem, not realizing that the bug was a side effect of a work-around that we were aware of, rather than a complete mystery. However, their idea was sound and we are hoping to incorporate it. +They also suggested that we build a GUI-based level builder. When we indicated that we may not necessarily have time for this, they recommended clear variable names and all terrain stored in easily editable lists, which was our current solution. +Our final question revolved around our immediate next steps, mostly along the lines of user-interface. This was valuable in hearing what our audience, the potential users, wanted most, which was mainly a quit/restart option on the death screen so that we don’t have to reopen it each time and a display of stat bars, particularly if we do implement health as a bigger player than it currently is. +We implemented the lava fix, but decided that our remaining time didn’t afford us the luxury of making a special level builder. We’re going to continue making levels by hand and try to implement robust, fun gameplay. + +## Review Process Reflection +Suggestions we receive may or may not be appropriate to implement given the time constraints and our priorities. Our questions were fairly open, such as “how would you fix x bug, and consequently the discussion was varied in topic and helpfulness, +Drawing out (on the whiteboard) what the issues were in the code was useful when there was some confusion. Putting up actual code didn’t seem to garner much useful feedback when the audience couldn’t scroll through it on their own computer and see how it interacted with other parts of the code. +Asking specific, targeted questions (like asking people to prioritize features they would like) was useful in getting helpful feedback in a short time. Having a sheet that they ranked things on physically would have been beneficial. +It would have been good for us to have let them download the game and play it themselves, so we heard the opinions of people who haven’t been involved in all of the creation process. diff --git a/Terrain.py b/Terrain.py new file mode 100644 index 0000000..b8eb739 --- /dev/null +++ b/Terrain.py @@ -0,0 +1,59 @@ +### All the stuff for terrain + +import math, sys +import pygame +from pygame.locals import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Obstacle(pygame.sprite.Sprite): + """ Immobile things that the player might run into. """ + def __init__(self, x, y, width, height, visc = 1, mortality = False): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Make a blue wall, of the size specified in the parameters + self.image = pygame.Surface([width, height]) + self.image.fill(BLUE) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + + # Add the extra attributes we want. + self.visc = visc # causes it to be harder to move through + self.mortality = mortality # makes it deadly + +class Ground(Obstacle): + """ Solid surfaces or walls. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, 0, False) + self.image = pygame.Surface((w, h)) + self.image.fill((85, 140, 90)) + +class Lava(Obstacle): + """ Deadly red terrain. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, True) + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('chocolate1')) + +class Water(Obstacle): + """ Slows you down. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, False) + self.image = pygame.Surface((w, h)) + self.image.fill((85, 200, 255)) \ No newline at end of file diff --git a/Terrain.pyc b/Terrain.pyc new file mode 100644 index 0000000..5e89267 Binary files /dev/null and b/Terrain.pyc differ diff --git a/UML_Diagram.png b/UML_Diagram.png new file mode 100644 index 0000000..b751d64 Binary files /dev/null and b/UML_Diagram.png differ diff --git a/Untitled.ipynb b/Untitled.ipynb new file mode 100644 index 0000000..f4857e2 --- /dev/null +++ b/Untitled.ipynb @@ -0,0 +1,60 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Symbiosis\n", + "\n", + "**Sean Foley, Kaitlyn Keil, Apurva Raman**\n", + "\n", + "**Software Design, Spring 2016**\n", + "\n", + "Symbiosis is a game in which you play as a blobby orphan baby trying to find a family to accept it. Using powers granted to you by a mushroom symbiote, traverse levels and make decisions to meet your goal.\n", + "\n", + "## Dependencies\n", + "This project uses the math, sys, and pygame libraries. Make sure these are installed before playing the game.\n", + "\n", + "## Modules\n", + "To play, run the file game_base2.py. This imports the modules Spores, LivingThings, Terrain, and Room. These contain the classes needed to run the game.\n", + "- Spores contains the classes for the thrown spores, such as decomposition and ledge-creation.\n", + "- Terrain contains the classes for the platforms and surfaces and obstacles.\n", + "- LivingThings contains the classes for the player and creatures that move.\n", + "- Room contains and constructs the levels, and imports the above modules.\n", + "\n", + "## Keybindings\n", + "Use the arrow keys to move. Spacebar throws spores. Up arrow key allows you to jump. Don't hit the enemy, try to survive!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/backups/game_base_backup1 b/backups/game_base_backup1 new file mode 100644 index 0000000..864675e --- /dev/null +++ b/backups/game_base_backup1 @@ -0,0 +1,449 @@ +import math, sys +import pygame +from pygame.locals import * + +# -- Global constants + +# Colors +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. + +class MushroomGuy(pygame.sprite.Sprite): + """ This class represents the bar at the bottom that the player + controls. """ + + # Constructor function + def __init__(self): + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set height, width + self.image_list = [pygame.image.load('dog.jpg'), pygame.image.load('evil_dog1.jpg')] + self.image = pygame.transform.scale(self.image_list[0], (100, 75)) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = 0 + self.rect.x = 0 + + # Set speed vector + self.change_x = 0 + self.change_y = 0 + + # List of sprites we can bump against + self.room = None + + # Set corruption points + self.corruption = 0 + + # Set shot direction + self.shot_dir = 1 + + # Player-controlled movement: + def go_left(self): + """ Called when the user hits the left arrow. """ + self.change_x = -6 + + # Make the shot direction to the left + self.shot_dir = -1 + + def go_right(self): + """ Called when the user hits the right arrow. """ + self.change_x = 6 + + # Make the shot direction to the right + self.shot_dir = 1 + + def stop(self): + """ Called when the user lets off the keyboard. """ + self.change_x = 0 + + def jump(self): + """ Called when user hits 'jump' button. """ + + # move down a bit and see if there is a platform below us. + # Move down 2 pixels because it doesn't work well if we only move down + # 1 when working with a platform moving down. + self.rect.y += 2 + wall_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + self.rect.y -= 2 + + # If it is ok to jump, set our speed upwards + if len(wall_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT: + self.change_y = -10 + + def calc_grav(self): + """ Calculate effect of gravity. """ + if self.change_y == 0: + self.change_y = 1 + else: + self.change_y += .35 + + # See if we are on the ground. + if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0: + self.change_y = 0 + self.rect.y = SCREEN_HEIGHT - self.rect.height + + def how_corrupt(self): + """ Changes the image based on the corruption level of the player. """ + self.image = pygame.transform.scale(self.image_list[self.corruption/5], (100, 75)) + + def update(self): + """ Update the player position. """ + # Gravity + self.calc_grav() + # Move left/right + self.rect.x += self.change_x + + # Did this update cause us to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # If we are moving right, set our right side to the left side of + # the item we hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if we are moving left, do the opposite. + self.rect.left = block.rect.right + + # Did this update cause us to hit a deadly object? + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.x -= self.change_x*block.visc + + # Move up/down + self.rect.y += self.change_y + + # Check and see if we hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + + # Reset our position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop our vertical movement + self.change_y = 0 + + # Check if we are stuck in something viscous and slow us down if we are + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.y -= self.change_y*block.visc + + # Check to see if we hit something deadly + block_hit_list = pygame.sprite.spritecollide(self, self.room.deadlies, False) + for block in block_hit_list: + self.kill() + + # Check to see if we ate anything + food_hit_list = pygame.sprite.spritecollide(self, self.room.consumeable, True) + for food in food_hit_list: + self.corruption += food.corr_points + + # Update the picture if necessary + self.how_corrupt() + +class Spore(pygame.sprite.Sprite): + """ Base class of spores. + + player: pass the player into the shot + speed: a tuple of the x velocity and the y velocity + size: a tuple of the width and height of the shot""" + def __init__(self, player, speed = (8,0), size = (5,5)): + # Call the parent's init + pygame.sprite.Sprite.__init__(self) + + # Make visible and set direction + self.image = pygame.Surface([size[0], size[1]]) + self.image.fill(pygame.Color('blueviolet')) + self.direction = player.shot_dir + + # Set up initial position and direction of shot + self.rect = self.image.get_rect() + + self.rect.y = player.rect.y + player.rect.height/2 + self.change_x = speed[0] + self.change_y = speed[1] + + if self.direction == 1: + self.rect.x = player.rect.x + player.rect.width + else: + self.rect.x = player.rect.x + + def update(self): + """ Updates the spore. """ + self.rect.x += self.change_x + self.rect.y += self.change_y + +class Obstacle(pygame.sprite.Sprite): + """ Immobile things that the player might run into. """ + def __init__(self, x, y, width, height, visc = 1, mortality = False): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Make a blue wall, of the size specified in the parameters + self.image = pygame.Surface([width, height]) + self.image.fill(BLUE) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + + # Add the extra attributes we want + self.visc = visc + self.mortality = mortality + +class Ground(Obstacle): + """ Solid surfaces or walls. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, 0, False) + + # Make the color and all different + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('aquamarine4')) + +class Lava(Obstacle): + """ Deadly red terrain. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, False) + + # Make the color correct + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('chocolate1')) + +class Water(Obstacle): + """ Slows you down. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, False) + + # Make the color correct + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('cadetblue1')) + +class Edible(pygame.sprite.Sprite): + """ This is the base class; any new foods should be modified from this one. + Maybe make this an inherited class from Obstacle? """ + def __init__(self, x, y, width, height, corr_points = 1): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set the visual + self.image = pygame.Surface([width, height]) + self.image.fill(pygame.Color('deeppink2')) + self.corr_points = corr_points + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + +class Room(object): + """ This is a generic super-class used to define a level. + Create a child class for each level with level-specific + info. """ + + def __init__(self, player): + """ Constructor. Pass in a handle to player. Needed for when moving platforms + collide with the player. """ + self.wall_list = pygame.sprite.Group() + self.enemy_list = pygame.sprite.Group() + self.deadlies = pygame.sprite.Group() + self.sludge = pygame.sprite.Group() + self.consumeable = pygame.sprite.Group() + self.player = player + + # Background image + self.background = None + + # Update everythign on this level + def update(self): + """ Update everything in this level.""" + self.wall_list.update() + self.enemy_list.update() + self.deadlies.update() + self.sludge.update() + self.consumeable.update() + + def draw(self, screen): + """ Draw everything on this level. """ + + # Draw the background + screen.fill(BLUE) + + # Draw all the sprite lists that we have + self.wall_list.draw(screen) + self.enemy_list.draw(screen) + self.deadlies.draw(screen) + self.sludge.draw(screen) + self.consumeable.draw(screen) + + def draw_end(self, screen): + """ Draw the game over screen. """ + screen.fill(BLACK) + game_over_pic = pygame.transform.scale(pygame.image.load('game_over_mushroom.jpg'), [350, 350]) + screen.blit(game_over_pic, (SCREEN_W_MID-175, SCREEN_H_MID-175)) + +# Create platforms for the level +class Room_01(Room): + """ Definition for level 1. """ + + def __init__(self, player): + """ Create level 1. """ + + # Call the parent constructor + Room.__init__(self, player) + + # Solid, non-deadly objects. Array with width, height, x, y, and class of obstacle + room = [[500, 50, 0, 550, Ground], + [200, 30, 200, 400, Ground], + [200, 30, 500, 300, Ground], + ] + + # Kills you when you touch it. Array with width, height, x, y, and class of obstacle + deadly = [[300, 50, 500, 550, Lava]] + + # Objects that hinder movement. Array with width, height, x, y, and class of obstacle + sludge = [[300, 100, 400, 350, Water]] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [[10, 10, 490, 540, Edible], + [10, 10, 295, 390, Edible], + [10, 10, 200, 540, Edible], + [10, 10, 300, 540, Edible], + [10, 10, 400, 540, Edible]] + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in deadly: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.deadlies.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + +def View(): + """ Main Program """ + pygame.init() + + # Set the height and width of the screen + size = [SCREEN_WIDTH, SCREEN_HEIGHT] + screen = pygame.display.set_mode(size) + + pygame.display.set_caption("Jump Jump Jump") + + # Create the player + player = MushroomGuy() + + # Create all the levels + room_list = [] + room_list.append( Room_01(player) ) + + # Set the current level + current_room_no = 0 + current_room = room_list[current_room_no] + + active_sprite_list = pygame.sprite.Group() + player.room = current_room + + player.rect.x = 0 + player.rect.y = 0 + active_sprite_list.add(player) + + # Loop until the user clicks the close button. + done = False + + # Used to manage how fast the screen updates + clock = pygame.time.Clock() + + # -------- Main Program Loop ----------- + while not done: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + done = True + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + player.go_left() + if event.key == pygame.K_RIGHT: + player.go_right() + if event.key == pygame.K_UP: + player.jump() + + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT and player.change_x < 0: + player.stop() + if event.key == pygame.K_RIGHT and player.change_x > 0: + player.stop() + + # Update the player. + active_sprite_list.update() + + # Update items in the level + current_room.update() + + # If the player gets near the right side, shift the world left (-x) + if player.rect.right > SCREEN_WIDTH: + player.rect.right = SCREEN_WIDTH + + # If the player gets near the left side, shift the world right (+x) + if player.rect.left < 0: + player.rect.left = 0 + + # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT + if player not in active_sprite_list: + current_room.draw_end(screen) + else: + current_room.draw(screen) + active_sprite_list.draw(screen) + + # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT + + # Limit to 60 frames per second + clock.tick(60) + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # Be IDLE friendly. If you forget this line, the program will 'hang' + # on exit. + pygame.quit() + +if __name__ == "__main__": + View() diff --git a/backups/game_base_backup2 b/backups/game_base_backup2 new file mode 100644 index 0000000..2b4b298 --- /dev/null +++ b/backups/game_base_backup2 @@ -0,0 +1,122 @@ +import math, sys +import pygame +from pygame.locals import * +from Spores import * +from LivingThings import * +from Terrain import * +from Room import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. + +def View(): + """ Main Program """ + pygame.init() + + # Set the height and width of the screen + size = [SCREEN_WIDTH, SCREEN_HEIGHT] + screen = pygame.display.set_mode(size) + + pygame.display.set_caption("Jump Jump Jump") + + # Create the player + player = MushroomGuy() + + # Create all the levels + room_list = [] + room_list.append( Room_01(player) ) + + # Set the current level + current_room_no = 0 + current_room = room_list[current_room_no] + + for enemy in current_room.enemy_list: + enemy.room = current_room + + active_sprite_list = pygame.sprite.Group() + player.room = current_room + + player.rect.x = 0 + player.rect.y = 0 + active_sprite_list.add(player) + + # Loop until the user clicks the close button. + done = False + + # Used to manage how fast the screen updates + clock = pygame.time.Clock() + + # -------- Main Program Loop ----------- + while not done: + for event in pygame.event.get(): + if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): + done = True + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + player.go_left() + if event.key == pygame.K_RIGHT: + player.go_right() + if event.key == pygame.K_UP: + player.jump() + if event.key == pygame.K_SPACE: + spore = Decompose_Spore(player) + spore.setup_lists(current_room) + active_sprite_list.add(spore) + + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT and player.change_x < 0: + player.stop() + if event.key == pygame.K_RIGHT and player.change_x > 0: + player.stop() + + # Update the player. + active_sprite_list.update() + + # Update items in the level + current_room.update() + + # If the player gets near the right side, shift the world left (-x) + if player.rect.right > SCREEN_WIDTH: + player.rect.right = SCREEN_WIDTH + + # If the player gets near the left side, shift the world right (+x) + if player.rect.left < 0: + player.rect.left = 0 + + # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT + if player not in active_sprite_list: + current_room.draw_end(screen) + else: + current_room.draw(screen) + active_sprite_list.draw(screen) + + # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT + + # Limit to 60 frames per second + clock.tick(60) + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # Be IDLE friendly. If you forget this line, the program will 'hang' + # on exit. + pygame.quit() + +if __name__ == "__main__": + View() diff --git a/code_review_kaitlyn.py b/code_review_kaitlyn.py new file mode 100644 index 0000000..f3efcc2 --- /dev/null +++ b/code_review_kaitlyn.py @@ -0,0 +1,84 @@ + def update(self): + """ Update the player position. """ + # Check changes in position. If not on the ground, calculate gravity. Move left or right. + self.calc_grav() + self.rect.x += self.change_x + + # Did this update cause us to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # Check if it is deadly. If so, hurt the player + if block.mortality == True: + self.wound += 1 + if self.wound > self.max_wound: + self.kill() + else: + # If we are moving right, set our right side to the left side of the item we hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if we are moving left, do the opposite. + self.rect.left = block.rect.right + self.wound = 0 # reset health if not only touching the deadly object. Currently lets you survive if touching the ground and the lava. + + # Did this update cause us to enter water or other speed-altering substance? If so, change speed by the viscosity of the substance. + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.x -= self.change_x*block.visc + + ### Move up/down and repeat previous steps for the vertical movement + self.rect.y += self.change_y + + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + if block.mortality == True: + self.wound += 1 + if self.wound > self.max_wound: + self.kill() + else: + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop our vertical movement if landing on something. + self.change_y = 0 + self.wound = 0 + + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.y -= self.change_y*block.visc + + ### Check for collisions where x/y doesn't matter: enemies, food, and objects to climb. + enemy_hit_list = pygame.sprite.spritecollide(self, self.room.enemy_list, False) + for enemy in enemy_hit_list: + if enemy.mortality == True: + self.kill() + + food_hit_list = pygame.sprite.spritecollide(self, self.room.consumeable, True) + for food in food_hit_list: + self.corruption += food.corr_points # If the food is immorally eaten, increase corruption + + if pygame.sprite.spritecollide(self, self.room.can_climb, False) != []: + self.climb_okay = True + else: + self.climb_okay = False + + # Update the player picture if necessary + self.how_corrupt() + + def calc_grav(self): + """ Calculate effect of gravity. """ + if self.change_y == 0: + self.change_y = 1 + else: + self.change_y += .35 + + # See if we are on the ground, don't fall if we are. + if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0: + self.change_y = 0 + self.rect.y = SCREEN_HEIGHT - self.rect.height + + def climb(self): + """ If player hits 'c,' they climb upwards in a burst of 5 pixels. """ + self.change_y = -5 \ No newline at end of file diff --git a/different-organization_discontinued/controller.py b/different-organization_discontinued/controller.py new file mode 100644 index 0000000..7834c29 --- /dev/null +++ b/different-organization_discontinued/controller.py @@ -0,0 +1,13 @@ +import math, sys +import pygame +from pygame.locals import * + +class Controller(object): + def __init__(self, model): + self.model = model + + def update(self): + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() \ No newline at end of file diff --git a/different-organization_discontinued/controller.pyc b/different-organization_discontinued/controller.pyc new file mode 100644 index 0000000..d7eba70 Binary files /dev/null and b/different-organization_discontinued/controller.pyc differ diff --git a/different-organization_discontinued/main.py b/different-organization_discontinued/main.py new file mode 100644 index 0000000..7ea177a --- /dev/null +++ b/different-organization_discontinued/main.py @@ -0,0 +1,15 @@ +import math, sys +import pygame +from pygame.locals import * +from model import * + +def main(): + pygame.init() + clock = pygame.time.Clock() + model = Model() + running = True + while running: + clock.tick(60) + model.update() + +main() \ No newline at end of file diff --git a/different-organization_discontinued/model.py b/different-organization_discontinued/model.py new file mode 100644 index 0000000..b94a45e --- /dev/null +++ b/different-organization_discontinued/model.py @@ -0,0 +1,38 @@ +import math, sys +import pygame +from pygame.locals import * +from view import * +from controller import * +from rooms import * +from objects import * + +class Model(object): + ### Contains the controller, the view, the current room, and the mushroom guy. Keeps track of the current room. + ### Changes self.currentroom when told to, and puts the mushroom guy in the current room. I think it might make sense + ### to do all the collision checking junk in the room instances. + def __init__(self): + # Need some kind of spatially-organized list of rooms/levels + # Need a mushroom guy + # Need a current room + # Need a viewer of the proper size and a controller + self.hero = Mushroom_Guy() + + self.room_list = [Room1(self.hero), Room2(self.hero)] + self.current_room = self.room_list[0] + + self.controller = Controller(self) + + screen_size = (800, 600) + self.view = View(self, screen_size) + + def update(self): + self.controller.update() + self.view.update() + + def change_room(self, direction): + try: + self.current_room = self.room_list.index(self.current_room) + direction + except: + print "You can't go there! What have you done you foolish programmer? You've doomed us all!" + pygame.quit() + sys.exit() \ No newline at end of file diff --git a/different-organization_discontinued/model.pyc b/different-organization_discontinued/model.pyc new file mode 100644 index 0000000..d9cb3ea Binary files /dev/null and b/different-organization_discontinued/model.pyc differ diff --git a/different-organization_discontinued/objects.py b/different-organization_discontinued/objects.py new file mode 100644 index 0000000..32af5ac --- /dev/null +++ b/different-organization_discontinued/objects.py @@ -0,0 +1,14 @@ +import math, sys +import pygame +from pygame.locals import * + +class Walking_things(object): + ###Defines basic movement for things that can move/jump + pass + +class Mushroom_Guy(Walking_things): + ### He moves, he shoots spores. I guess he needs to decide if he's just a funky little furry guy or a guy with a + ### mushroom. + def __init__(self): + # Possible variables: corruption, position, weight, power, flipped/not flipped, health + pass \ No newline at end of file diff --git a/different-organization_discontinued/objects.pyc b/different-organization_discontinued/objects.pyc new file mode 100644 index 0000000..3aa9f79 Binary files /dev/null and b/different-organization_discontinued/objects.pyc differ diff --git a/different-organization_discontinued/rooms.py b/different-organization_discontinued/rooms.py new file mode 100644 index 0000000..cf97755 --- /dev/null +++ b/different-organization_discontinued/rooms.py @@ -0,0 +1,22 @@ +import math, sys +import pygame +from pygame.locals import * + +class Room(object): + ### Assumes you make a self.objects_list in your __init__. + def update(self): + pass + + +class Room1(Room): + ### Needs to be specialized for the particular arrangement of things in it; should have a list of objects, which will + ### keep track of their own position, a room size, and a background picture. + def __init__(self, hero): + self.room_size = (3000, 1000) + self.background = pygame.Surface(self.room_size) + self.background.fill(pygame.Color('blue')) + + +class Room2(Room): + def __init__(self, hero): + pass \ No newline at end of file diff --git a/different-organization_discontinued/rooms.pyc b/different-organization_discontinued/rooms.pyc new file mode 100644 index 0000000..f546f48 Binary files /dev/null and b/different-organization_discontinued/rooms.pyc differ diff --git a/different-organization_discontinued/view.py b/different-organization_discontinued/view.py new file mode 100644 index 0000000..ac1882b --- /dev/null +++ b/different-organization_discontinued/view.py @@ -0,0 +1,17 @@ +import math, sys +import pygame +from pygame.locals import * + +class View(object): + ### The room object in the model keeps track of the positions of all the things, and the view needs to draw them in + ### the right places. It should keep track of its own position (top left corner) relative to the top left of the current room too. + def __init__(self, model, screen_size): + # Model is the big container, and screen_size is a tuple (width, height) + self.model = model + self.screen_size = screen_size + self.screen = pygame.display.set_mode(screen_size) + self.position = (0, self.model.current_room.room_size[1] - self.screen_size[1]) + + def update(self): + self.screen.blit(self.model.current_room.background, (-self.position[0], -self.position[0])) + pygame.display.update() \ No newline at end of file diff --git a/different-organization_discontinued/view.pyc b/different-organization_discontinued/view.pyc new file mode 100644 index 0000000..6c49cf2 Binary files /dev/null and b/different-organization_discontinued/view.pyc differ diff --git a/dog.jpg b/dog.jpg new file mode 100644 index 0000000..d5ec7ee Binary files /dev/null and b/dog.jpg differ diff --git a/evil_dog1.jpg b/evil_dog1.jpg new file mode 100644 index 0000000..93ff030 Binary files /dev/null and b/evil_dog1.jpg differ diff --git a/evilmushroom.png b/evilmushroom.png new file mode 100644 index 0000000..c4a7060 Binary files /dev/null and b/evilmushroom.png differ diff --git a/game_base2.py b/game_base2.py new file mode 100644 index 0000000..d2929a5 --- /dev/null +++ b/game_base2.py @@ -0,0 +1,276 @@ +import math, sys, pickle +import pygame +from pygame.locals import * +from Spores import * +from LivingThings import * +from Terrain import * +from Room import * +from HUD import * +from Menu import * +from Intro import * +from collections import OrderedDict + +# -- Global constants + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +class Controller(object): + """ Controller is responsible for updating the object in the room and handling all user input. """ + def __init__(self, menu, room_number): + # Dictionary of all potential spores + self.spores_dict = {pygame.K_q: 0, pygame.K_e: 1} + # Create the player + self.player = MushroomGuy() + + # Create all the levels + self.room_list = [] + + self.room_list.append( Room_00(self.player) ) + self.room_list.append( Room_01(self.player) ) + self.room_list.append( Room_02(self.player) ) + + # Set the first level + self.current_room_no = 1#room_number + self.change_room(0) + + self.active_sprite_list = pygame.sprite.Group() + self.active_sprite_list.add(self.player) + + # Loop until the user clicks the close button. + self.done = False + + # Initialize pause menu + self.menu = menu + self.menu_dict = OrderedDict([('Resume', self.resume), ('New Game', main), ('Quit Game', self.quit_game)]) + self.menu.make_buttons(self.menu_dict.keys()) + + # Put in all the HUD components + self.hud_components = pygame.sprite.Group() + self.hud_components.add(HealthBar(self.player)) + self.spore_box = Spore_Boxes(self.current_room) + self.hud_components.add(self.spore_box) + + + def update(self, other): + # Main update loop, occurs 60 times a second + # Check through every user input event that pygame recognized this clock cycle + for event in pygame.event.get(): + # Handle closing the program + if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): + pygame.quit() + sys.exit() + + # Handle user input while the game is playing, aka the pause menu is not active + if not self.menu.menu_on: + if event.type == pygame.KEYDOWN: + + # Changing active spore + if event.key in self.spores_dict: + self.spore_box.change() + self.current_room.active_spore = self.current_room.spore_list[self.spores_dict[event.key]] + self.spore_box.change() + + # Shooting a spore + if event.key == pygame.K_SPACE: + spore = self.current_room.active_spore(self.player) + spore.room = self.current_room + spore.setup_lists() + self.active_sprite_list.add(spore) + + # Toggling the flip state + if event.key == pygame.K_f: + self.player.flipped = not self.player.flipped + + # Talk to your mushroom hat + if event.key == pygame.K_t: + self.player.talked = True + + # Eat mushrooms + if event.key == pygame.K_DOWN: + food_hit_list = pygame.sprite.spritecollide(self.player, self.current_room.consumeable, False) + if food_hit_list: + food = food_hit_list[0] + self.player.corruption += food.corr_points + self.player.wound = max(0, self.player.wound - food.health_points) + food.kill() + + # Stop the player from moving when you release the movement keys + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT and self.player.change_x < 0: + self.player.stop() + if event.key == pygame.K_RIGHT and self.player.change_x > 0: + self.player.stop() + + # If the pause menu is active, user input doesn't change the current room at all, but causes different effects + else: + # Check through every option in the menu to see if it's hovered over and if it's being pressed + for button in self.menu.buttons: + if button.rect.collidepoint(pygame.mouse.get_pos()): + button.hovered = True + if pygame.mouse.get_pressed()[0]: + x = button.pressed() + self.menu_dict[x]() # Execute the action specified by the button + else: + button.hovered = False + + # Toggle the pause menu + if event.type == pygame.KEYDOWN and event.key == pygame.K_p: + self.menu.menu_on = not self.menu.menu_on + + # Additional update code to be run if the pause menu is not active + if not self.menu.menu_on: + # Player movement + if pygame.key.get_pressed()[pygame.K_UP]: + self.player.climb() + if pygame.key.get_pressed()[pygame.K_LEFT]: + self.player.go_left() + if pygame.key.get_pressed()[pygame.K_RIGHT]: + self.player.go_right() + + # Check who in the room has talked this step and display the most important message + talkers = ([creature for creature in self.current_room.enemy_list if creature.talked] + [player for player in [self.player] if player.talked] + + [tut for tut in [self.current_room.tutorial] if self.current_room.is_tutorial]) + for talker in talkers: + # In the tutorial, the text to display is determined by the players current position + if isinstance(talker, Tutorial): + self.hud_components.add(Text(other, self.player, talker.text[self.player.rect.x/500], talker.talk_length, talker.__str__())) + # Otherwise, it's determined by the player's corruption level + else: + self.hud_components.add(Text(other, self.player, talker.text[self.player.list_index], talker.talk_length, talker.__str__())) + if talkers: + # This bit removes all but the most important message. In the event of a tie, it removes the earlier message. + messages = [message for message in self.hud_components if isinstance(message, Text)] + most_important = max(messages) + self.hud_components.remove([message for message in messages if message.words != most_important.words]) + + # Update the player. + self.active_sprite_list.update() + + # Update items in the level + self.current_room.update() + + # Stop the player from going off the sides + self.player.rect.centerx = min(max(self.player.rect.centerx, self.player.rect.w/2), self.current_room.world_size[0]-self.player.rect.w/2) + + # Update the HUD + for piece in self.hud_components: + piece.update() + + # Move to the next room if you reach the far right side of this room + if self.player.rect.right >= (self.current_room.world_size[0]-10) and self.current_room_no < len(self.room_list) - 1: + self.change_room(self.current_room.next_level) + print 'checking' + + def change_room(self, direction): + # Adds direction to current_room_no and initializes our new room + self.current_room_no += direction + self.current_room = self.room_list[self.current_room_no] + + # Initialize the objects in the room + for enemy in self.current_room.enemy_list: + enemy.room = self.current_room + + # Put the player in the new room + self.player.room = self.current_room + self.player.rect.x = 0 + self.player.rect.y = 0 + + def save(self): + # Save the current state of the game. Not yet tested. + save_values = {'current_room':self.current_room, 'player':self.player} + f = open('save_file', 'w') + pickle.dump(save_values, f) + f.close() + + def open(self): + # Load a previous game. Not yet tested. + f = open('save_file') + save_values = pickle.load(f) + f.close() + self.current_room = self.save_values['current_room'] + self.player = self.save_values['player'] + + def resume(self): + # Restart the game if the player is dead, otherwise just close the pause menu + if self.player not in self.active_sprite_list: + main(self.current_room_no) + self.menu.menu_on = False + + def quit_game(self): + self.done = True + +class View(object): + """ View is responsible for drawing everything in the current gameworld. It blits (pastes) the pygame surface representing the game world, world, onto + the surface representing the viewing window, screen, every step. """ + def __init__(self, screen, menu): + self.screen = screen + + # Where relative to the screen the world should be blit + self.position = (0, 0) + + self.menu = menu + self.end_timer = 0 + self.end_timer_max = 120 + + def update(self, other): + # If the player is dead, draw the game over screen + if other.player not in other.active_sprite_list: + self.draw_end() + self.end_timer += 1 + # After end_time_max clock ticks, put in the pause menu (eventually a game over menu) + if self.end_timer >= self.end_timer_max: + other.menu.menu_on = True + else: + other.current_room.draw() + other.active_sprite_list.draw(other.current_room.world) + # Position tracks the top left corner of the screen relative to the world. It should always be positive and no greater + # than the w/h of the world minus the w/h of the screen. + self.position = (min(max(0, other.player.rect.centerx - SCREEN_W_MID), other.current_room.world_size[0]-SCREEN_WIDTH), + min(max(0, other.player.rect.centery - SCREEN_H_MID), other.current_room.world_size[1]-SCREEN_HEIGHT)) + # Blit the background, whose coordinate in the world coordinate system is (0, 0), at the negative of your position. + self.screen.blit(other.current_room.world, (-self.position[0], -self.position[1])) + other.hud_components.draw(self.screen) + self.menu.draw(self.screen) + # Useful debugging tool below: prints current mouse position + #print (self.position[0] + pygame.mouse.get_pos()[0], self.position[1] + pygame.mouse.get_pos()[1]) + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + def draw_end(self): + # Draw the game over screen. + self.screen.fill(BLACK) + game_over_pic = pygame.transform.scale(pygame.image.load('game_over_mushroom.jpg').convert(), [350, 350]) + self.screen.blit(game_over_pic, (SCREEN_W_MID-175, SCREEN_H_MID-175)) + +def main(room_number): + # Initialize all the main components of the game + pygame.init() + # Used to manage how fast the screen updates + clock = pygame.time.Clock() + menu = Menu(False) + view = View(screen, menu) + controller = Controller(menu, room_number) + + while not controller.done: + controller.update(view) + view.update(controller) + clock.tick(60) + + pygame.quit() + + +# This block of code runs the introductory sequence +pygame.init() +clock = pygame.time.Clock() +size = [SCREEN_WIDTH, SCREEN_HEIGHT] +screen = pygame.display.set_mode(size) + +pygame.display.set_caption("Symbiosis") +run(screen, clock) +# Once run() is done playing the intro sequence, start the actual game +main(0) \ No newline at end of file diff --git a/game_over_mushroom.jpg b/game_over_mushroom.jpg new file mode 100644 index 0000000..e1cd14f Binary files /dev/null and b/game_over_mushroom.jpg differ diff --git a/old_junk/Reflect_Synthesis_Tech_1 b/old_junk/Reflect_Synthesis_Tech_1 new file mode 100644 index 0000000..acc629b --- /dev/null +++ b/old_junk/Reflect_Synthesis_Tech_1 @@ -0,0 +1,21 @@ +Reflection and Synthesis: Tech Review 1 + +Feedback Synthesis: +Main feedback: +-Avoid trying to implement too many features +-Water could be handled by either instant death or just a slow movement to start +-Have mechanics evolve over time and a final stage where the mechanics all come together +-Focus either on implementing several features or puzzle design, doing both might be too much +-Shooting spores should be simple (or at least have the option to be simple) + +Going forward, we will identify the key features and figure out what order makes the most sense for implementation so that if we have time, we can expand, but will be fine otherwise. We will try out some of the suggestions for how the mechanics should behave, possibly in a series of short trial levels. + +New questions: +-Which features/abilities are the most important to create good puzzles? +-What controller interaction makes the most intuitive sense for each ability? + +Process Reflection: + +We entered this technical review with a fairly vague plan, evidenced in part by our lack of an agenda-setting slide, something most of the other groups had. However, we had discussed our plan ahead of time, and we knew the general sense of what we wanted from the review. We didn't have any pressing technical questions, so quite a bit of our time was spent introducing the audience to our idea and explaining some of the nuances of story and gameplay we wanted. This led to brainstorming as a class, which was fun and helpful. Because of how well this played out, I am inclined to believe that we provided enough context to intrigue them and make their suggestions useful. + +Talking to the group helped us refine our idea of an MVP based on what the audience latched onto (puzzles, corruption points, and abilities with or without the mushroom) and what they weren't as excited about (the story element was not discussed heavily). We could probably get even more out of this in the future if we stuck more closely to our questions and presented in a manner that flowed more gracefully from piece to piece, with questions scattered intermittently rather than gathered into one slide at the end. However, as an introduction, a little more guidance here was necessary. \ No newline at end of file diff --git a/old_junk/Review1 b/old_junk/Review1 new file mode 100644 index 0000000..c8f2370 --- /dev/null +++ b/old_junk/Review1 @@ -0,0 +1,28 @@ +Background and Context: +Game Background +You are a blobby baby (orphan) who is trying to find your family with the help (?) of a symbiotic mushroom. +Genre: Puzzle platformer +Use a variety of fungi to traverse levels +Hang-gliding +Decomposing +Climbing +Floating like a boat +Choices you make throughout the levels determine your final fate: will you be happy or will you rule the world? + +Context +We want to create a story-driven platformer with intriguing core mechanics +We want an emphasis on object-oriented programming and model-view-controller + +Key Questions: +What can we add to the story to make it more interesting? +What sounds most fun? +How should we handle drowning and water interactions in general? +What can we add to the game to convey the story effectively? +What can we add to the story to make it more interesting? +Is there anything you think we should specifically avoid (from past experience, etc)? +How do you envision this? + +Agenda: + +We hope to get feedback on story and some technical aspects as well as get more input and possible direction for the project. +We will talk about background/concept first to frame the discussion, and demonstrating what we have so far will hopefully help the audience understand some of the basics of our game. We will then ask our key questions, starting with ones to understand how our idea comes across and what might be some larger design elements to incorporate/modify/edit out, and narrowing down to specific technical questions. This order may change depending on the questions our audience has for us and the overall direction of the discussion. diff --git a/old_junk/dirty_rects.py b/old_junk/dirty_rects.py new file mode 100644 index 0000000..987ab2f --- /dev/null +++ b/old_junk/dirty_rects.py @@ -0,0 +1,252 @@ +import math, sys +import pygame +from pygame.locals import * +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. +class Room(object): + ### Assumes you make a self.objects_list, a self.start_positions, and a self.hero in your __init__. + def update(self): + for thing in self.objects_list[0] + self.objects_list[1]: + thing.update() + + def enter_room(self, direction): + # Direction is +1 if you're coming in from the left and -1 if you're coming in from the right. So start_positions should + # have the rightmost start position first and the leftmost second. + self.hero.position = self.start_positions[int(direction/2.0+.5)] + + +class Room1(Room): + ### Needs to be specialized for the particular arrangement of things in it; should have a list of objects, which will + ### keep track of their own position, a room size, and a background picture. Which should have clouds. And trees. + def __init__(self, hero): + self.hero = hero + self.room_size = (1000, 600) + self.background = pygame.transform.scale(pygame.image.load('dog.jpg'), self.room_size) + self.gravity = 1 + # Color chart at https://sites.google.com/site/meticulosslacker/pygame-thecolors + # This sets start positions based on how big the room is, where the ground is (200 from bottom), and how big the hero is. + self.start_positions = [(self.room_size[0]-100, self.room_size[1]-200-self.hero.rect.h/2), (100, self.room_size[1]-200-self.hero.rect.h/2)] + # Okay new way. First is a list of things that interact with you when you're on them, like lava that kills you or mushrooms you can eat. + # Second list is viscous things. Third is hard things. + self.objects_list = [[self.hero, Lava(pygame.Rect(self.room_size[0]/3, self.room_size[1]-210, self.room_size[0]/3, 210))], + [Lava(pygame.Rect(self.room_size[0]/3, self.room_size[1]-210, self.room_size[0]/3, 210))], + [Ground(pygame.Rect(0, self.room_size[1]-199, self.room_size[0]/3, 200)), + Ground(pygame.Rect(2*self.room_size[0]/3, self.room_size[1]-280, self.room_size[0]/3, 280))]] + + +class Room2(Room): + def __init__(self, hero): + pass + + +class Obstacle(object): + def __init__(self, rect, sprite, mortality = False, visc = 1): + self.visc = visc + self.mortality = mortality + self.sprite = sprite + self.rect = rect + + def update(self): + pass + + +class Ground(Obstacle): + def __init__(self, rect): + sprite = pygame.Surface((rect.w, rect.h)) + sprite.fill(pygame.Color('aquamarine4')) + Obstacle.__init__(self, rect, sprite, False, 0) + + +class Lava(Obstacle): + def __init__(self, rect): + sprite = pygame.Surface((rect.w, rect.h)) + sprite.fill(pygame.Color('chocolate1')) + Obstacle.__init__(self, rect, sprite, True, .5) + + +class WalkingThings(object): + ### Defines basic movement for things that can move/jump + ### Permeability type thing: a multiplicative factor on gravity. + def walk(self, direction): + self.vx += direction*self.speed*self.visc + + def update(self): + print 'hi' + blockedx, blockedy = 1, 1 + self.check_viscous_collisions() + if not self.check_below(): + # Checks if you're falling + self.vy += self.model.current_room.gravity*self.visc + if self.check_hard_collisions('horz'): + self.snap('horz', self.check_hard_collisions('horz')) + blockedx = 0 + if self.check_hard_collisions('vert'): + self.snap('vert', self.check_hard_collisions('vert')) + blockedy = 0 + self.position = self.position[0]+self.vx*blockedx, self.position[1]+self.vy*blockedy + self.rect.center = self.position + self.check_soft_collisions() + + def check_soft_collisions(self): + # I think we only care about collisions with non-solid things. We shouldn't actually ever overlap with a solid object. + for thing in self.model.current_room.objects_list[0]: + if self.rect.colliderect(thing.rect): + if thing.mortality: + self.die() + + def check_viscous_collisions(self): + # Direction is 'horz' or 'vert'. Returns the viscosity of whatever is there. If nothing's there, return 1. + swimming_in = pygame.Rect(self.rect.left, self.rect.top, self.rect.w, self.rect.h).collidelistall(self.model.current_room.objects_list[1]) + if swimming_in: + self.visc = min([self.model.current_room.objects_list[1][i].visc for i in swimming_in]) + else: + self.visc = 1 + + def check_hard_collisions(self, direction): + # Takes in a direction, returns distance to what you would hit or None + directions = {'horz': (self.vx, 0), 'vert': (0, self.vy)} + things_I_hit = pygame.Rect(self.rect.left+directions[direction][0], self.rect.top+directions[direction][1], self.rect.w, self.rect.h).collidelistall(self.model.current_room.objects_list[2]) + if things_I_hit: + # This finds the closest hard object that you're colliding with, and returns that distance. Inelegant. We should make a better way. + if directions[direction] > 0 and direction == 'horz': + return min([self.model.current_room.objects_list[2][i].rect.left - self.rect.right for i in things_I_hit]) + elif directions[direction] < 0 and direction == 'horz': + return max([self.model.current_room.objects_list[2][i].rect.right - self.rect.left for i in things_I_hit]) + elif directions[direction] > 0 and direction == 'vert': + return min([self.model.current_room.objects_list[2][i].rect.top - self.rect.bottom for i in things_I_hit]) + elif directions[direction] < 0 and direction == 'vert': + return min([self.model.current_room.objects_list[2][i].rect.bottom - self.rect.top for i in things_I_hit]) + else: + return None + + def check_below(self): + # Returns True if there's something below you + return self.rect.collidelistall(self.model.current_room.objects_list[2]) + + def snap(self, direction, distance): + # Moves you distance in direction. Meant to prevent you from stopping before an obstacle. + print self.position + if direction == 'horz': + self.position = self.position[0]+distance*self.vx/(abs(self.vx)-1), self.position[1] + elif direction == 'vert': + self.position = self.position[0], self.position[1]+distance*self.vy/(abs(self.vy)-1) + + def die(self): + self.model.current_room.objects_list[0].remove(self) + + +class MushroomGuy(WalkingThings): + ### He moves, he shoots spores. I guess he needs to decide if he's just a funky little furry guy or a guy with a + ### mushroom. + def __init__(self, model): + # Possible variables: corruption, position, weight, power, flipped/not flipped, health + self.model = model + self.rect = pygame.Rect(0, 0, 100, 75) + self.position = (self.rect.centerx, self.rect.centery) + self.moved = False + self.speed = 10 #how fast you walk + self.sprite = pygame.image.load('dog.jpg') + self.sprite = pygame.transform.scale(self.sprite, (100, 75)) + self.mortality = False + self.visc = 1 + self.vx, self.vy = 0, 0 + + def die(self): + self.sprite.fill(pygame.Color('red'), pygame.Rect(0, self.rect.h/2, self.rect.w, self.rect.h/2)) + + +class View(object): + ### The room object in the model keeps track of the positions of all the things, and the view needs to draw them in + ### the right places. It should keep track of its own position (top left corner) relative to the top left of the current room too. + def __init__(self, model, screen_size): + # Model is the big container, and screen_size is a tuple (width, height) + self.model = model + self.screen_size = screen_size + self.screen = pygame.display.set_mode(screen_size) + self.position = (0, self.model.current_room.room_size[1] - self.screen_size[1]) + + def update(self): + self.position = min(max(self.model.hero.position[0] - self.screen_size[0]/2, 0), self.model.current_room.room_size[0]-self.screen_size[0]), self.position[1] + self.screen.blit(self.model.current_room.background, (-self.position[0], -self.position[1])) + for thing in self.model.current_room.objects_list[0] + self.model.current_room.objects_list[1] + self.model.current_room.objects_list[2]: + self.screen.blit(thing.sprite, (thing.rect.left-self.position[0], thing.rect.top-self.position[1])) + pygame.display.update() + + +class Controller(object): + def __init__(self, model): + self.model = model + self.left_down = False + self.right_down = False + + def update(self): + if self.right_down and self.left_down: + self.model.current_room.hero.vx = 0 + elif self.right_down: + self.model.current_room.hero.vx = self.model.current_room.hero.speed*self.model.current_room.hero.visc + elif self.left_down: + self.model.current_room.hero.vx = -self.model.current_room.hero.speed*self.model.current_room.hero.visc + else: + self.model.current_room.hero.vx = 0 + for event in pygame.event.get(): + if event.type == QUIT or event.type == KEYDOWN and event.key == pygame.K_ESCAPE: + pygame.quit() + sys.exit() + elif event.type == KEYDOWN and event.key == pygame.K_RIGHT: + self.right_down = True + elif event.type == KEYUP and event.key == pygame.K_RIGHT: + self.right_down = False + if event.type == KEYDOWN and event.key == pygame.K_LEFT: + self.left_down = True + elif event.type == KEYUP and event.key == pygame.K_LEFT: + self.left_down = False + + +class Model(object): + ### Contains the controller, the view, the current room, and the mushroom guy. Keeps track of the current room. + ### Changes self.currentroom when told to, and puts the mushroom guy in the current room. I think it might make sense + ### to do all the collision checking junk in the room instances. + def __init__(self): + # Need some kind of spatially-organized list of rooms/levels + # Need a mushroom guy + # Need a current room + # Need a viewer of the proper size and a controller + self.hero = MushroomGuy(self) + + self.room_list = [Room1(self.hero), Room2(self.hero)] + self.current_room = self.room_list[0] + self.current_room.enter_room(1) + + self.controller = Controller(self) + + screen_size = (800, 600) + self.view = View(self, screen_size) + + def update(self): + self.controller.update() + self.current_room.update() + self.view.update() + + def change_room(self, direction): + ### You try to move into the room that's in the direction you want to go: -1 means going left (so entering from the right), + ### and 1 means going right. + try: + self.current_room = self.room_list.index(self.current_room) + direction + except: + print "You can't go there! What have you done you foolish programmer? You've doomed us all!" + pygame.quit() + sys.exit() + + +def main(): + pygame.init() + clock = pygame.time.Clock() + model = Model() + running = True + while running: + clock.tick(60) + model.update() + +main() \ No newline at end of file diff --git a/old_junk/frank_test.py b/old_junk/frank_test.py new file mode 100644 index 0000000..3ff5e10 --- /dev/null +++ b/old_junk/frank_test.py @@ -0,0 +1,10 @@ +class Frank(object): + def __init__(self, bob): + self.bob = bob + def __cmp__(self, other): + return self.bob - other.bob + +franky = Frank(10) +franklin = Frank(2) +franks_list = [franky, franklin] +print min(franks_list).bob \ No newline at end of file diff --git a/old_junk/game_base.py b/old_junk/game_base.py new file mode 100644 index 0000000..95bcce3 --- /dev/null +++ b/old_junk/game_base.py @@ -0,0 +1,607 @@ +import math, sys +import pygame +from pygame.locals import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. + +""" Code for the Player """ + +class MushroomGuy(pygame.sprite.Sprite): + """ This class represents the bar at the bottom that the player + controls. """ + + # Constructor function + def __init__(self): + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set height, width + self.image_list = [pygame.image.load('dog.jpg').convert(), pygame.image.load('evil_dog1.jpg')] + for index, image in enumerate(self.image_list): + self.image_list[index] = pygame.transform.scale(image, (100, 75)) + self.image = self.image_list[0] + print self.image + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + print self.rect + self.rect.y = 0 + self.rect.x = 0 + + # Set speed vector + self.speed = 6 + self.change_x = 0 + self.change_y = 0 + + # List of sprites we can bump against + self.room = None + + # Set corruption points + self.corruption = 0 + + # Set shot direction + self.shot_dir = 1 + + # Player-controlled movement: + def go_left(self): + """ Called when the user hits the left arrow. """ + self.change_x = -self.speed + + # Make the shot direction to the left + self.shot_dir = -1 + + def go_right(self): + """ Called when the user hits the right arrow. """ + self.change_x = self.speed + + # Make the shot direction to the right + self.shot_dir = 1 + + def stop(self): + """ Called when the user lets off the keyboard. """ + self.change_x = 0 + + def jump(self): + """ Called when user hits 'jump' button. """ + + # move down a bit and see if there is a platform below us. + # Move down 2 pixels because it doesn't work well if we only move down + # 1 when working with a platform moving down. + self.rect.y += 2 + wall_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + self.rect.y -= 2 + + # If it is ok to jump, set our speed upwards + if len(wall_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT: + self.change_y = -10 + + def calc_grav(self): + """ Calculate effect of gravity. """ + if self.change_y == 0: + self.change_y = 1 + else: + self.change_y += .35 + + # See if we are on the ground. + if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0: + self.change_y = 0 + self.rect.y = SCREEN_HEIGHT - self.rect.height + + def how_corrupt(self): + """ Changes the image based on the corruption level of the player. """ + self.image = pygame.transform.scale(self.image_list[self.corruption/5], (100, 75)) + + def update(self): + """ Update the player position. """ + # Gravity + self.calc_grav() + # Move left/right + self.rect.x += self.change_x + + # Did this update cause us to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # If we are moving right, set our right side to the left side of + # the item we hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if we are moving left, do the opposite. + self.rect.left = block.rect.right + + # Did this update cause us to hit a deadly object? + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.x -= self.change_x*block.visc + + # Move up/down + self.rect.y += self.change_y + + # Check and see if we hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + + # Reset our position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop our vertical movement + self.change_y = 0 + + # Check if we are stuck in something viscous and slow us down if we are + block_hit_list = pygame.sprite.spritecollide(self, self.room.sludge, False) + for block in block_hit_list: + self.rect.y -= self.change_y*block.visc + + # Check to see if we hit something deadly + block_hit_list = pygame.sprite.spritecollide(self, self.room.deadlies, False) + for block in block_hit_list: + self.kill() + + # Check to see if we ate anything + food_hit_list = pygame.sprite.spritecollide(self, self.room.consumeable, True) + for food in food_hit_list: + self.corruption += food.corr_points + + # Update the picture if necessary + self.how_corrupt() + +""" Code for the Spores """ + +class Spore(pygame.sprite.Sprite): + """ Base class of spores. + + player: pass the player into the shot + speed: a tuple of the x velocity and the y velocity + size: a tuple of the width and height of the shot""" + def __init__(self, player, speed = (8,0), size = (10,10)): + # Call the parent's init + pygame.sprite.Sprite.__init__(self) + + # Make visible and set direction + self.image = pygame.Surface([size[0], size[1]]) + self.image.fill(pygame.Color('blueviolet')) + self.direction = player.shot_dir + + # Set up initial position and direction of shot + self.rect = self.image.get_rect() + + self.rect.y = player.rect.y + player.rect.height/2 + self.change_x = speed[0] * self.direction + self.change_y = speed[1] * self.direction + + if self.direction == 1: + self.rect.x = player.rect.x + player.rect.width + else: + self.rect.x = player.rect.x + + # Set up the room and list of things it can hit + self.room = None + self.unaffected = pygame.sprite.Group() + self.affected = pygame.sprite.Group() + + def setup_lists(self, room): + """ Sets up the list of what it can affect and what it cannot. """ + pass + + def update(self): + """ Updates the spore. """ + self.rect.x += self.change_x + self.rect.y += self.change_y + +class Decompose_Spore(Spore): + """ A spore that decomposes things it touches. """ + def __init__(self, player): + Spore.__init__(self, player) + self.image.fill(pygame.Color('chartreuse3')) + + def setup_lists(self, room): + """ Sets up the list of what it can affect and what it cannot. """ + + # First, the unaffected things + for thing in room.wall_list: + self.unaffected.add(thing) + + for thing in room.deadlies: + self.unaffected.add(thing) + + for thing in room.sludge: + self.unaffected.add(thing) + + # Then the things it can affect + for thing in room.enemy_list: + self.affected.add(thing) + + def update(self): + """ Updates the spore. """ + self.rect.x += self.change_x + self.rect.y += self.change_y + + unaffected_hit_list = pygame.sprite.spritecollide(self, self.unaffected, False) + for thing in unaffected_hit_list: + self.kill() + + affected_hit_list = pygame.sprite.spritecollide(self, self.affected, True) + for thing in affected_hit_list: + self.kill() + +""" Code for Enemies and Enemy-related objects """ + +class Edible(pygame.sprite.Sprite): + """ This is the base class; any new foods should be modified from this one. + Maybe make this an inherited class from Obstacle? """ + def __init__(self, x, y, width, height, corr_points = 1): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set the visual + self.image = pygame.Surface([width, height]) + self.image.fill(pygame.Color('deeppink2')) + self.corr_points = corr_points + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + +class Enemy(pygame.sprite.Sprite): + """ This is the base class for anything that is alive and should move that isn't the player. """ + def __init__(self, x, y, width, height, speed = -2, distance = -200, mortality = True): + """ x = upper left corner x component + y = upper left corner y component + width = x dimension + height = y dimension + speed = how quickly it moves in the x direction + distance = how far it can walk + mortality = does it kill you? """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Set default image + self.image = pygame.image.load('evil_dog1.jpg') + self.image = pygame.transform.scale(self.image, (width, height)) + + # Set position + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + + # Set the range of values it can go between + self.start_x = x + self.end_x = x + distance - self.rect.width + + # Set speed vector + self.change_x = speed + self.change_y = 0 + + self.room = None + + def calc_grav(self): + """ Calculate effect of gravity. """ + if self.change_y == 0: + self.change_y = 1 + else: + self.change_y += .35 + + # See if we are on the ground. + if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.change_y >= 0: + self.change_y = 0 + self.rect.y = SCREEN_HEIGHT - self.rect.height + + def update(self): + """ Update the enemy position. """ + # Gravity + self.calc_grav() + # Move left/right + self.rect.x += self.change_x + + # Did this update cause it to hit a wall? + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + # If the enemy is moving right, set its right side to the left side of + # the item it hit + if self.change_x > 0: + self.rect.right = block.rect.left + else: + # Otherwise if it is moving left, do the opposite. + self.rect.left = block.rect.right + + # Change direction + self.change_x = -self.change_x + + # Check to see if it has hit the end of its range + if self.rect.x <= self.end_x or self.rect.x >= self.start_x: + self.change_x = -self.change_x + + # Move up/down + self.rect.y += self.change_y + + # Check and see if it hit anything + block_hit_list = pygame.sprite.spritecollide(self, self.room.wall_list, False) + for block in block_hit_list: + + # Reset its position based on the top/bottom of the object. + if self.change_y > 0: + self.rect.bottom = block.rect.top + else: + self.rect.top = block.rect.bottom + + # Stop its vertical movement + self.change_y = 0 + +""" Code for the Obstacles and Stage """ + +class Obstacle(pygame.sprite.Sprite): + """ Immobile things that the player might run into. """ + def __init__(self, x, y, width, height, visc = 1, mortality = False): + """ Constructor for the wall that the player can run into. """ + # Call the parent's constructor + pygame.sprite.Sprite.__init__(self) + + # Make a blue wall, of the size specified in the parameters + self.image = pygame.Surface([width, height]) + self.image.fill(BLUE) + + # Make our top-left corner the passed-in location. + self.rect = self.image.get_rect() + self.rect.y = y + self.rect.x = x + + # Add the extra attributes we want + self.visc = visc + self.mortality = mortality + +class Ground(Obstacle): + """ Solid surfaces or walls. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, 0, False) + + # Make the color and all different + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('aquamarine4')) + +class Lava(Obstacle): + """ Deadly red terrain. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, False) + + # Make the color correct + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('chocolate1')) + +class Water(Obstacle): + """ Slows you down. """ + def __init__(self, x, y, w, h): + Obstacle.__init__(self, x, y, w, h, .5, False) + + # Make the color correct + self.image = pygame.Surface((w, h)) + self.image.fill(pygame.Color('cadetblue1')) + +class Room(object): + """ This is a generic super-class used to define a level. + Create a child class for each level with level-specific + info. """ + + def __init__(self, player): + """ Constructor. Pass in a handle to player. Needed for when moving platforms + collide with the player. """ + self.wall_list = pygame.sprite.Group() + self.enemy_list = pygame.sprite.Group() + self.deadlies = pygame.sprite.Group() + self.sludge = pygame.sprite.Group() + self.consumeable = pygame.sprite.Group() + self.player = player + + # Background image + self.background = None + + # Update everythign on this level + def update(self): + """ Update everything in this level.""" + self.wall_list.update() + self.enemy_list.update() + self.deadlies.update() + self.sludge.update() + self.consumeable.update() + + def draw(self, screen): + """ Draw everything on this level. """ + + # Draw the background + screen.fill(BLUE) + + # Draw all the sprite lists that we have + self.wall_list.draw(screen) + self.enemy_list.draw(screen) + self.deadlies.draw(screen) + self.sludge.draw(screen) + self.consumeable.draw(screen) + + def draw_end(self, screen): + """ Draw the game over screen. """ + screen.fill(BLACK) + game_over_pic = pygame.transform.scale(pygame.image.load('game_over_mushroom.jpg'), [350, 350]) + screen.blit(game_over_pic, (SCREEN_W_MID-175, SCREEN_H_MID-175)) + +# Create platforms for the level +class Room_01(Room): + """ Definition for level 1. """ + + def __init__(self, player): + """ Create level 1. """ + + # Call the parent constructor + Room.__init__(self, player) + + # Solid, non-deadly objects. Array with width, height, x, y, and class of obstacle + room = [[500, 50, 0, 550, Ground], + [200, 30, 200, 400, Ground], + [200, 30, 500, 300, Ground], + ] + deadlies = [[300, 50, 500, 550]] + + # Kills you when you touch it. Array with width, height, x, y, and class of obstacle + deadly = [[300, 50, 500, 550, Lava]] + + # Objects that hinder movement. Array with width, height, x, y, and class of obstacle + sludge = [[300, 100, 400, 350, Water]] + + # Objects you can eat. Array with width, height, x, y, and class of obstacle + consumeable = [[10, 10, 490, 540, Edible], + [10, 10, 295, 390, Edible], + [10, 10, 200, 540, Edible], + [10, 10, 300, 540, Edible], + [10, 10, 400, 540, Edible]] + + # Enemies on the level + enemy_list = [[75, 75, 425, 475, Enemy]] + + # Go through the array above and add obstacles + for obstacle in room: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.wall_list.add(block) + + for obstacle in deadly: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.deadlies.add(block) + + for obstacle in sludge: + block = obstacle[4](obstacle[2], obstacle[3], obstacle[0], obstacle[1]) + block.rect.x = obstacle[2] + block.rect.y = obstacle[3] + block.player = self.player + self.sludge.add(block) + + for food in consumeable: + block = food[4](food[2], food[3], food[0], food[1]) + block.rect.x = food[2] + block.rect.y = food[3] + block.player = self.player + self.consumeable.add(block) + + for enemy in enemy_list: + block = enemy[4](enemy[2], enemy[3], enemy[0], enemy[1]) + self.enemy_list.add(block) + +def View(): + """ Main Program """ + pygame.init() + + # Set the height and width of the screen + size = [SCREEN_WIDTH, SCREEN_HEIGHT] + screen = pygame.display.set_mode(size) + + pygame.display.set_caption("Jump Jump Jump") + + # Create the player + player = MushroomGuy() + + # Create all the levels + room_list = [] + room_list.append( Room_01(player) ) + + # Set the current level + current_room_no = 0 + current_room = room_list[current_room_no] + + for enemy in current_room.enemy_list: + enemy.room = current_room + + active_sprite_list = pygame.sprite.Group() + player.room = current_room + + player.rect.x = 0 + player.rect.y = 0 + active_sprite_list.add(player) + + # Loop until the user clicks the close button. + done = False + + # Used to manage how fast the screen updates + clock = pygame.time.Clock() + + # -------- Main Program Loop ----------- + while not done: + for event in pygame.event.get(): + if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): + done = True + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + player.go_left() + if event.key == pygame.K_RIGHT: + player.go_right() + if event.key == pygame.K_UP: + player.jump() + if event.key == pygame.K_SPACE: + spore = Decompose_Spore(player) + spore.setup_lists(current_room) + active_sprite_list.add(spore) + + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT and player.change_x < 0: + player.stop() + if event.key == pygame.K_RIGHT and player.change_x > 0: + player.stop() + + # Update the player. + active_sprite_list.update() + + # Update items in the level + current_room.update() + + # If the player gets near the right side, shift the world left (-x) + if player.rect.right > SCREEN_WIDTH: + player.rect.right = SCREEN_WIDTH + + # If the player gets near the left side, shift the world right (+x) + if player.rect.left < 0: + player.rect.left = 0 + + # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT + if player not in active_sprite_list: + current_room.draw_end(screen) + else: + current_room.draw(screen) + active_sprite_list.draw(screen) + + # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT + + # Limit to 60 frames per second + clock.tick(60) + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # Be IDLE friendly. If you forget this line, the program will 'hang' + # on exit. + pygame.quit() + +if __name__ == "__main__": + View() diff --git a/old_junk/game_base2.py b/old_junk/game_base2.py new file mode 100644 index 0000000..2b4b298 --- /dev/null +++ b/old_junk/game_base2.py @@ -0,0 +1,122 @@ +import math, sys +import pygame +from pygame.locals import * +from Spores import * +from LivingThings import * +from Terrain import * +from Room import * + +# -- Global constants + +# Colors - check out pygame.Colors. Probably does exactly what you want +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +BLUE = (50, 50, 255) + +# Screen dimensions +SCREEN_WIDTH = 800 +SCREEN_HEIGHT = 600 +SCREEN_W_MID = SCREEN_WIDTH/2 +SCREEN_H_MID = SCREEN_HEIGHT/2 + +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. + +def View(): + """ Main Program """ + pygame.init() + + # Set the height and width of the screen + size = [SCREEN_WIDTH, SCREEN_HEIGHT] + screen = pygame.display.set_mode(size) + + pygame.display.set_caption("Jump Jump Jump") + + # Create the player + player = MushroomGuy() + + # Create all the levels + room_list = [] + room_list.append( Room_01(player) ) + + # Set the current level + current_room_no = 0 + current_room = room_list[current_room_no] + + for enemy in current_room.enemy_list: + enemy.room = current_room + + active_sprite_list = pygame.sprite.Group() + player.room = current_room + + player.rect.x = 0 + player.rect.y = 0 + active_sprite_list.add(player) + + # Loop until the user clicks the close button. + done = False + + # Used to manage how fast the screen updates + clock = pygame.time.Clock() + + # -------- Main Program Loop ----------- + while not done: + for event in pygame.event.get(): + if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): + done = True + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_LEFT: + player.go_left() + if event.key == pygame.K_RIGHT: + player.go_right() + if event.key == pygame.K_UP: + player.jump() + if event.key == pygame.K_SPACE: + spore = Decompose_Spore(player) + spore.setup_lists(current_room) + active_sprite_list.add(spore) + + if event.type == pygame.KEYUP: + if event.key == pygame.K_LEFT and player.change_x < 0: + player.stop() + if event.key == pygame.K_RIGHT and player.change_x > 0: + player.stop() + + # Update the player. + active_sprite_list.update() + + # Update items in the level + current_room.update() + + # If the player gets near the right side, shift the world left (-x) + if player.rect.right > SCREEN_WIDTH: + player.rect.right = SCREEN_WIDTH + + # If the player gets near the left side, shift the world right (+x) + if player.rect.left < 0: + player.rect.left = 0 + + # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT + if player not in active_sprite_list: + current_room.draw_end(screen) + else: + current_room.draw(screen) + active_sprite_list.draw(screen) + + # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT + + # Limit to 60 frames per second + clock.tick(60) + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # Be IDLE friendly. If you forget this line, the program will 'hang' + # on exit. + pygame.quit() + +if __name__ == "__main__": + View() diff --git a/old_junk/game_initial.py b/old_junk/game_initial.py new file mode 100644 index 0000000..ad64f9e --- /dev/null +++ b/old_junk/game_initial.py @@ -0,0 +1,127 @@ +import math, sys +import pygame +from pygame.locals import * +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. +class Room(object): + ### Assumes you make a self.objects_list, a self.start_positions, and a self.hero in your __init__. + def update(self): + pass + + def enter_room(self, direction): + # Direction is +1 if you're coming in from the left and -1 if you're coming in from the right. So start_positions should + # have the rightmost start position first and the leftmost second. + self.hero.position = self.start_positions[int(direction/2.0+.5)] + + +class Room1(Room): + ### Needs to be specialized for the particular arrangement of things in it; should have a list of objects, which will + ### keep track of their own position, a room size, and a background picture. Which should have clouds. And trees. + def __init__(self, hero): + self.hero = hero + self.room_size = (3000, 1000) + self.background = pygame.Surface(self.room_size) + # Color chart at https://sites.google.com/site/meticulosslacker/pygame-thecolors + self.background.fill(pygame.Color('deepskyblue')) + self.background.fill(pygame.Color('lightsalmon3'), pygame.Rect(0, self.room_size[1]-200, self.room_size[0], 200)) + # This sets start positions based on how big the room is, where the ground is (200 from bottom), and how big the hero is. + self.start_positions = [(self.room_size[0]-100, self.room_size[1]-200-self.hero.rect.h/2), (100, self.room_size[1]-200-self.hero.rect.h/2)] + self.objects_list = [self.hero] + + +class Room2(Room): + def __init__(self, hero): + pass + + +class Walking_things(object): + ###Defines basic movement for things that can move/jump + pass + +class Mushroom_Guy(Walking_things): + ### He moves, he shoots spores. I guess he needs to decide if he's just a funky little furry guy or a guy with a + ### mushroom. + def __init__(self): + # Possible variables: corruption, position, weight, power, flipped/not flipped, health + self.rect = pygame.Rect(0, 0, 100, 75) + self.position = (self.rect.centerx, self.rect.centery) + + def update(self): + self.rect.center = self.position + +class View(object): + ### The room object in the model keeps track of the positions of all the things, and the view needs to draw them in + ### the right places. It should keep track of its own position (top left corner) relative to the top left of the current room too. + def __init__(self, model, screen_size): + # Model is the big container, and screen_size is a tuple (width, height) + self.model = model + self.screen_size = screen_size + self.screen = pygame.display.set_mode(screen_size) + self.position = (0, self.model.current_room.room_size[1] - self.screen_size[1]) + + def update(self): + self.screen.blit(self.model.current_room.background, (-self.position[0], -self.position[1])) + for thing in self.model.current_room.objects_list: + pygame.draw.rect(self.screen, pygame.Color('orange'), thing.rect) + pygame.display.update() + + +class Controller(object): + def __init__(self, model): + self.model = model + + def update(self): + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + +class Model(object): + ### Contains the controller, the view, the current room, and the mushroom guy. Keeps track of the current room. + ### Changes self.currentroom when told to, and puts the mushroom guy in the current room. I think it might make sense + ### to do all the collision checking junk in the room instances. + def __init__(self): + # Need some kind of spatially-organized list of rooms/levels + # Need a mushroom guy + # Need a current room + # Need a viewer of the proper size and a controller + self.hero = Mushroom_Guy() + + self.room_list = [Room1(self.hero), Room2(self.hero)] + self.current_room = self.room_list[0] + self.current_room.enter_room(1) + + self.controller = Controller(self) + + screen_size = (800, 600) + self.view = View(self, screen_size) + + def update(self): + self.controller.update() + self.view.update() + + def change_room(self, direction): + ### You try to move into the room that's in the direction you want to go: -1 means going left (so entering from the right), + ### and 1 means going right. + try: + self.current_room = self.room_list.index(self.current_room) + direction + self.current_room.enter_room(direction) + except: + print "You can't go there! What have you done you foolish programmer? You've doomed us all!" + pygame.quit() + sys.exit() + + +def main(): + pygame.init() + clock = pygame.time.Clock() + model = Model() + running = True + while running: + clock.tick(60) + model.update() + +main() \ No newline at end of file diff --git a/old_junk/greg_test.py b/old_junk/greg_test.py new file mode 100644 index 0000000..5e3fd22 --- /dev/null +++ b/old_junk/greg_test.py @@ -0,0 +1,3 @@ +from names import * +greg = [Greg, Greg] +print greg[0]('tall') \ No newline at end of file diff --git a/old_junk/greg_test.pyc b/old_junk/greg_test.pyc new file mode 100644 index 0000000..f306dcc Binary files /dev/null and b/old_junk/greg_test.pyc differ diff --git a/old_junk/ideation.jpg b/old_junk/ideation.jpg new file mode 100644 index 0000000..977f091 Binary files /dev/null and b/old_junk/ideation.jpg differ diff --git a/old_junk/names.py b/old_junk/names.py new file mode 100644 index 0000000..a3c9e43 --- /dev/null +++ b/old_junk/names.py @@ -0,0 +1,6 @@ +from greg_test import * +class Greg(object): + def __init__(self, char): + self.char = char + def __str__(self): + return self.char \ No newline at end of file diff --git a/old_junk/names.pyc b/old_junk/names.pyc new file mode 100644 index 0000000..cb7d04d Binary files /dev/null and b/old_junk/names.pyc differ diff --git a/old_junk/pygame_tester.py b/old_junk/pygame_tester.py new file mode 100644 index 0000000..fede062 --- /dev/null +++ b/old_junk/pygame_tester.py @@ -0,0 +1,18 @@ +import pygame +from pygame.locals import * +import random, math, sys +screen = pygame.display.set_mode((400, 400)) +background = pygame.image.load('dog.jpg').convert() +screen.blit(background, (0, 0)) +rect1 = pygame.Rect(100, 100, 80, 80) +rect2 = pygame.Rect(rect1) +rect2.center = (300, 300) +pygame.draw.rect(screen, (0, 0 , 0), rect1) +pygame.draw.rect(screen, (0, 0 , 0), rect2) +running = True +while running: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + pygame.display.update() \ No newline at end of file diff --git a/old_junk/slightly_changed.py b/old_junk/slightly_changed.py new file mode 100644 index 0000000..40b407f --- /dev/null +++ b/old_junk/slightly_changed.py @@ -0,0 +1,269 @@ +import math, sys +import pygame +import numpy as np +from pygame.locals import * +# Save files would not be hard, especially with pickling +# Really important: we need to be consistent on how we define positions. Right now I'm using relative to the upper left hand +# corner of the current room. All sprites are defined at the center of their bounding rectangles, which might make rolling +# over easier. +class Room(object): + ### Assumes you make a self.objects_list, a self.start_positions, and a self.hero in your __init__. + def update(self): + for thing in self.objects_list[0] + self.objects_list[1]: + thing.update() + + def enter_room(self, direction): + # Direction is +1 if you're coming in from the left and -1 if you're coming in from the right. So start_positions should + # have the rightmost start position first and the leftmost second. + self.hero.position = self.start_positions[int(direction/2.0+.5)] + + +class Room1(Room): + ### Needs to be specialized for the particular arrangement of things in it; should have a list of objects, which will + ### keep track of their own position, a room size, and a background picture. Which should have clouds. And trees. + def __init__(self, hero): + self.hero = hero + self.room_size = (1000, 600) + self.background = pygame.transform.scale(pygame.image.load('dog.jpg'), self.room_size) + self.gravity = 1 + # Color chart at https://sites.google.com/site/meticulosslacker/pygame-thecolors + # This sets start positions based on how big the room is, where the ground is (200 from bottom), and how big the hero is. + self.start_positions = [(self.room_size[0]-100, self.room_size[1]-200-self.hero.rect.h/2), (100, self.room_size[1]-400-self.hero.rect.h/2)] + # Okay new way. First is a list of things that interact with you when you're on them, like lava that kills you or mushrooms you can eat. + # Second list is viscous things. Third is hard things. + self.objects_list = [[self.hero, Lava(pygame.Rect(self.room_size[0]/3, self.room_size[1]-210, self.room_size[0]/3, 210))], + [Lava(pygame.Rect(self.room_size[0]/3, self.room_size[1]-210, self.room_size[0]/3, 210))], + [Ground(pygame.Rect(self.room_size[0]/3, self.room_size[1]-200, self.room_size[0]/3, 200)), + Ground(pygame.Rect(0, self.room_size[1]-200, self.room_size[0]/3, 200)), + Ground(pygame.Rect(2*self.room_size[0]/3, self.room_size[1]-280, self.room_size[0]/3, 280)), + Ground(pygame.Rect(0,0,20,self.room_size[1]))]] + + +class Room2(Room): + def __init__(self, hero): + pass + + +class Obstacle(object): + def __init__(self, rect, sprite, mortality = False, visc = 1): + self.visc = visc + self.mortality = mortality + self.sprite = sprite + self.rect = rect + + def update(self): + pass + + +class Ground(Obstacle): + def __init__(self, rect): + sprite = pygame.Surface((rect.w, rect.h)) + sprite.fill(pygame.Color('aquamarine4')) + Obstacle.__init__(self, rect, sprite, False, 0) + + +class Lava(Obstacle): + def __init__(self, rect): + sprite = pygame.Surface((rect.w, rect.h)) + sprite.fill(pygame.Color('chocolate1')) + Obstacle.__init__(self, rect, sprite, True, .5) + + +class WalkingThings(object): + ### Defines basic movement for things that can move/jump + ### Permeability type thing: a multiplicative factor on gravity. + def walk(self, direction): + if not self.is_blocked('horz', direction): + self.vx = self.speed*self.visc*direction + + def jump(self): + if not self.is_blocked('vert', -1) and self.is_blocked('vert', 1): + self.vy -= 10 + + def update(self): + self.check_viscous_collisions() + if self.check_hard_collisions('horz'): + if not self.blockedx and self.vx != 0: + self.snap('horz', self.check_hard_collisions('horz')) + self.vx = 0 + self.blockedx = 1 + else: + self.blockedx = 0 + if self.check_hard_collisions('vert') and self.vy != 0: + self.snap('vert', self.check_hard_collisions('vert')) + self.vy = 0 + if not self.is_blocked('vert', 1): + self.vy += self.model.current_room.gravity*self.visc + self.position = self.position[0]+self.vx, self.position[1]+self.vy + self.rect.center = self.position + self.check_soft_collisions() + + def check_soft_collisions(self): + # I think we only care about collisions with non-solid things. We shouldn't actually ever overlap with a solid object. + for thing in self.model.current_room.objects_list[0]: + if self.rect.colliderect(thing.rect): + if thing.mortality: + self.die() + + def check_viscous_collisions(self): + # Direction is 'horz' or 'vert'. Returns the viscosity of whatever is there. If nothing's there, return 1. + swimming_in = pygame.Rect(self.rect.left, self.rect.top, self.rect.w, self.rect.h).collidelistall(self.model.current_room.objects_list[1]) + if swimming_in: + self.visc = min([self.model.current_room.objects_list[1][i].visc for i in swimming_in]) + else: + self.visc = 1 + + def check_hard_collisions(self, direction): + # Takes in a direction, returns distance to what you would hit or None + directions = {'horz': (self.vx, 0), 'vert': (0, self.vy)} + things_I_hit = pygame.Rect(self.rect.left+directions[direction][0]+np.sign(self.vx), self.rect.top+directions[direction][1]+np.sign(self.vy), self.rect.w, self.rect.h).collidelistall(self.model.current_room.objects_list[2]) + if things_I_hit: + # This finds the closest hard object that you're colliding with, and returns that distance. Inelegant. We should make a better way. + if directions[direction][0] > 0 and direction == 'horz': + return min([self.model.current_room.objects_list[2][i].rect.left - self.rect.right - 1 for i in things_I_hit]) + elif directions[direction][0] < 0 and direction == 'horz': + return max([self.model.current_room.objects_list[2][i].rect.right - self.rect.left + 1 for i in things_I_hit]) + elif directions[direction][1] > 0 and direction == 'vert': + return min([self.model.current_room.objects_list[2][i].rect.top - self.rect.bottom - 1 for i in things_I_hit]) + elif directions[direction][1] < 0 and direction == 'vert': + return max([self.model.current_room.objects_list[2][i].rect.bottom - self.rect.top + 1 for i in things_I_hit]) + else: + return None + + def is_blocked(self, direction, other_direction): + if direction == 'horz' and np.sign(other_direction) == 1: + return pygame.Rect(self.rect.right, self.rect.top, 2, self.rect.h).collidelistall(self.model.current_room.objects_list[2]) + elif direction == 'horz' and np.sign(other_direction) == -1: + return pygame.Rect(self.rect.left-2, self.rect.top, 2, self.rect.h).collidelistall(self.model.current_room.objects_list[2]) + if direction == 'vert' and np.sign(other_direction) == 1: + return pygame.Rect(self.rect.left, self.rect.bottom, self.rect.w, 2).collidelistall(self.model.current_room.objects_list[2]) + if direction == 'vert' and np.sign(other_direction) == -1: + return pygame.Rect(self.rect.left, self.rect.top - 2, self.rect.w, 2).collidelistall(self.model.current_room.objects_list[2]) + + def snap(self, direction, distance): + # Moves you distance in direction. Meant to prevent you from stopping before an obstacle. + if direction == 'horz': + self.position = self.position[0]+distance, self.position[1] + elif direction == 'vert': + self.position = self.position[0], self.position[1]+distance + + def die(self): + self.model.current_room.objects_list[0].remove(self) + + +class MushroomGuy(WalkingThings): + ### He moves, he shoots spores. I guess he needs to decide if he's just a funky little furry guy or a guy with a + ### mushroom. + def __init__(self, model): + # Possible variables: corruption, position, weight, power, flipped/not flipped, health + self.model = model + self.rect = pygame.Rect(0, 0, 100, 75) + self.position = (self.rect.centerx, self.rect.centery) + self.moved = False + self.speed = 10 #how fast you walk + self.sprite = pygame.image.load('dog.jpg') + self.sprite = pygame.transform.scale(self.sprite, (100, 75)) + self.mortality = False + self.visc = 1 + self.vx, self.vy = 0, 0 + self.blockedx = 0 + + def die(self): + self.sprite.fill(pygame.Color('red'), pygame.Rect(0, self.rect.h/2, self.rect.w, self.rect.h/2)) + + +class View(object): + ### The room object in the model keeps track of the positions of all the things, and the view needs to draw them in + ### the right places. It should keep track of its own position (top left corner) relative to the top left of the current room too. + def __init__(self, model, screen_size): + # Model is the big container, and screen_size is a tuple (width, height) + self.model = model + self.screen_size = screen_size + self.screen = pygame.display.set_mode(screen_size) + self.position = (0, self.model.current_room.room_size[1] - self.screen_size[1]) + + def update(self): + self.position = min(max(self.model.hero.position[0] - self.screen_size[0]/2, 0), self.model.current_room.room_size[0]-self.screen_size[0]), self.position[1] + self.screen.blit(self.model.current_room.background, (-self.position[0], -self.position[1])) + for thing in self.model.current_room.objects_list[0] + self.model.current_room.objects_list[1] + self.model.current_room.objects_list[2]: + self.screen.blit(thing.sprite, (thing.rect.left-self.position[0], thing.rect.top-self.position[1])) + pygame.display.update() + + +class Controller(object): + def __init__(self, model): + self.model = model + self.left_down = False + self.right_down = False + + def update(self): + if self.right_down and self.left_down: + self.model.current_room.hero.vx = 0 + elif self.right_down: + self.model.current_room.hero.walk(1) + elif self.left_down: + self.model.current_room.hero.walk(-1) + else: + self.model.current_room.hero.vx = 0 + for event in pygame.event.get(): + if event.type == QUIT or event.type == KEYDOWN and event.key == pygame.K_ESCAPE: + pygame.quit() + sys.exit() + elif event.type == KEYDOWN and event.key == pygame.K_RIGHT: + self.right_down = True + elif event.type == KEYUP and event.key == pygame.K_RIGHT: + self.right_down = False + if event.type == KEYDOWN and event.key == pygame.K_LEFT: + self.left_down = True + elif event.type == KEYUP and event.key == pygame.K_LEFT: + self.left_down = False + if event.type == KEYDOWN and event.key == pygame.K_UP: + self.model.current_room.hero.jump() + + +class Model(object): + ### Contains the controller, the view, the current room, and the mushroom guy. Keeps track of the current room. + ### Changes self.currentroom when told to, and puts the mushroom guy in the current room. I think it might make sense + ### to do all the collision checking junk in the room instances. + def __init__(self): + # Need some kind of spatially-organized list of rooms/levels + # Need a mushroom guy + # Need a current room + # Need a viewer of the proper size and a controller + self.hero = MushroomGuy(self) + + self.room_list = [Room1(self.hero), Room2(self.hero)] + self.current_room = self.room_list[0] + self.current_room.enter_room(1) + + self.controller = Controller(self) + + screen_size = (800, 600) + self.view = View(self, screen_size) + + def update(self): + self.controller.update() + self.current_room.update() + self.view.update() + + def change_room(self, direction): + ### You try to move into the room that's in the direction you want to go: -1 means going left (so entering from the right), + ### and 1 means going right. + try: + self.current_room = self.room_list.index(self.current_room) + direction + except: + print "You can't go there! What have you done you foolish programmer? You've doomed us all!" + pygame.quit() + sys.exit() + + +def main(): + pygame.init() + clock = pygame.time.Clock() + model = Model() + running = True + while running: + clock.tick(60) + model.update() + +main() \ No newline at end of file diff --git a/old_junk/useful_things.txt b/old_junk/useful_things.txt new file mode 100644 index 0000000..449bc1a --- /dev/null +++ b/old_junk/useful_things.txt @@ -0,0 +1,2 @@ +http://www.pygame.org/docs/tut/tom/MakeGames.html +https://sites.google.com/site/meticulosslacker/pygame-thecolors diff --git a/png/adult_duck.png b/png/adult_duck.png new file mode 100644 index 0000000..820dfcd Binary files /dev/null and b/png/adult_duck.png differ diff --git a/png/child_duck_friend.png b/png/child_duck_friend.png new file mode 100644 index 0000000..814dda2 Binary files /dev/null and b/png/child_duck_friend.png differ diff --git a/png/edible.png b/png/edible.png new file mode 100644 index 0000000..f25a358 Binary files /dev/null and b/png/edible.png differ diff --git a/png/enemy.png b/png/enemy.png new file mode 100644 index 0000000..d157367 Binary files /dev/null and b/png/enemy.png differ diff --git a/png/frame10.png b/png/frame10.png new file mode 100644 index 0000000..009841a Binary files /dev/null and b/png/frame10.png differ diff --git a/png/frame11.png b/png/frame11.png new file mode 100644 index 0000000..d52b856 Binary files /dev/null and b/png/frame11.png differ diff --git a/png/frame12.png b/png/frame12.png new file mode 100644 index 0000000..3a405a2 Binary files /dev/null and b/png/frame12.png differ diff --git a/png/frame13.png b/png/frame13.png new file mode 100644 index 0000000..679cca3 Binary files /dev/null and b/png/frame13.png differ diff --git a/png/frame2.jpg b/png/frame2.jpg new file mode 100644 index 0000000..65cdd74 Binary files /dev/null and b/png/frame2.jpg differ diff --git a/png/frame2.png b/png/frame2.png new file mode 100644 index 0000000..b91fb3f Binary files /dev/null and b/png/frame2.png differ diff --git a/png/frame3.png b/png/frame3.png new file mode 100644 index 0000000..04cd726 Binary files /dev/null and b/png/frame3.png differ diff --git a/png/frame4.png b/png/frame4.png new file mode 100644 index 0000000..fea4af1 Binary files /dev/null and b/png/frame4.png differ diff --git a/png/frame5.png b/png/frame5.png new file mode 100644 index 0000000..32ae6cd Binary files /dev/null and b/png/frame5.png differ diff --git a/png/frame6.png b/png/frame6.png new file mode 100644 index 0000000..ffafd15 Binary files /dev/null and b/png/frame6.png differ diff --git a/png/frame7.png b/png/frame7.png new file mode 100644 index 0000000..5824568 Binary files /dev/null and b/png/frame7.png differ diff --git a/png/frame8.png b/png/frame8.png new file mode 100644 index 0000000..de9a6ad Binary files /dev/null and b/png/frame8.png differ diff --git a/png/frame9.png b/png/frame9.png new file mode 100644 index 0000000..b3b4a2a Binary files /dev/null and b/png/frame9.png differ diff --git a/png/ledge_attach_left.png b/png/ledge_attach_left.png new file mode 100644 index 0000000..a8d3f95 Binary files /dev/null and b/png/ledge_attach_left.png differ diff --git a/png/ledge_attach_right.png b/png/ledge_attach_right.png new file mode 100644 index 0000000..ecea74f Binary files /dev/null and b/png/ledge_attach_right.png differ diff --git a/png/mg_c0.png b/png/mg_c0.png new file mode 100644 index 0000000..5c7b757 Binary files /dev/null and b/png/mg_c0.png differ diff --git a/png/mg_c1.png b/png/mg_c1.png new file mode 100644 index 0000000..4f1ad6d Binary files /dev/null and b/png/mg_c1.png differ diff --git a/png/mg_c2.png b/png/mg_c2.png new file mode 100644 index 0000000..07f9357 Binary files /dev/null and b/png/mg_c2.png differ diff --git a/png/mg_tc0.png b/png/mg_tc0.png new file mode 100644 index 0000000..5c7b757 Binary files /dev/null and b/png/mg_tc0.png differ diff --git a/png/mg_tc1.png b/png/mg_tc1.png new file mode 100644 index 0000000..4f1ad6d Binary files /dev/null and b/png/mg_tc1.png differ diff --git a/png/mg_tc2.png b/png/mg_tc2.png new file mode 100644 index 0000000..552d3fb Binary files /dev/null and b/png/mg_tc2.png differ diff --git a/png/title.png b/png/title.png new file mode 100644 index 0000000..fd4561f Binary files /dev/null and b/png/title.png differ diff --git a/symbiosis poster.pdf b/symbiosis poster.pdf new file mode 100644 index 0000000..9ef7227 Binary files /dev/null and b/symbiosis poster.pdf differ diff --git a/useful_things.txt~ b/useful_things.txt~ new file mode 100644 index 0000000..693161a --- /dev/null +++ b/useful_things.txt~ @@ -0,0 +1,2 @@ +http://www.pygame.org/docs/tut/tom/MakeGames.html +