Advertisement
Guest User

main.py

a guest
Mar 4th, 2013
65,035
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 71.76 KB | None | 0 0
  1.  #s!/usr/bin/python
  2. # import pygame and everything else
  3. try:
  4.     import sys
  5.     import random
  6.     import math
  7.     import os
  8.     import getopt
  9.     import pygame
  10.     import pickle
  11.     import copy
  12.     from collections import *
  13.     from socket import *
  14.     from pygame.locals import *
  15.     from vector import *
  16.     import yaml
  17.     import pygame.mixer
  18. #    import ConfigParser
  19.  
  20. except ImportError, err:
  21.     print "couldn't load module. %s" % (err)
  22.     sys.exit(2)
  23.  
  24. # level handling
  25. # Load image function
  26. def load_png(name):
  27.     """ Load image and return image object"""
  28.     fullname = os.path.join('data/images', name)
  29.     try:
  30.         image = pygame.image.load(fullname)
  31.         if image.get_alpha() is None:
  32.             image = image.convert()
  33.         else:
  34.             image = image.convert_alpha()
  35.     except pygame.error, message:
  36.         print 'Cannot load image:', fullname
  37.         raise SystemExit, message
  38.     return image
  39.  
  40. #load sound function
  41. def load_sound(name):
  42.     class NoneSound:
  43.         def play(self): pass
  44.     if not pygame.mixer or not pygame.mixer.get_init():
  45.         return NoneSound()
  46.     fullname = os.path.join('data/sounds', name)
  47.     try:
  48.         sound = pygame.mixer.Sound(fullname)
  49.     except pygame.error:
  50.         print ('Cannot load sound: %s' % fullname)
  51.         raise SystemExit(str(geterror()))
  52.     return sound
  53.  
  54. #load tile set function
  55. def load_tile_table(filename, width, height):
  56.     image = pygame.image.load(os.path.join('data/images', filename))
  57.     image_width, image_height = image.get_size()
  58.     tile_table = []
  59.     for tile_x in range(0, image_width/width):
  60.         line = []
  61.         tile_table.append(line)
  62.         for tile_y in range(0, image_height/height):
  63.             rect = (tile_x*width, tile_y*height, width, height)
  64.             line.append(image.subsurface(rect))
  65.     return tile_table
  66.  
  67. #count files in directiory
  68. def count_files(in_directory):
  69.     joiner= (in_directory + os.path.sep).__add__
  70.     return sum(
  71.         os.path.isfile(filename)
  72.         for filename
  73.         in map(joiner, os.listdir(in_directory))
  74.     )
  75.  
  76.  
  77. #calculate depth of collision
  78. def GetIntersectionDepth(rect_A, rect_B):
  79.     # Calculate half sizes.
  80.     halfWidthA = rect_A.width / 2
  81.     halfHeightA = rect_A.height / 2
  82.     halfWidthB = rect_B.width / 2
  83.     halfHeightB = rect_B.height / 2
  84.    
  85.     #calculate centers
  86.     center_A = Vector(rect_A.left + halfWidthA, rect_A.top + halfHeightA)
  87.     center_B = Vector(rect_A.left + halfWidthA, rect_A.top + halfHeightA)
  88.  
  89.     #Calculate current and minimum-non-intersecting distances between centers.
  90.     distance_x = center_A.x - center_B.x
  91.     distance_y = center_A.y - center_B.y
  92.     minDistance_x = halfWidthA + halfWidthB
  93.     minDistance_y = halfHeightA + halfHeightB
  94.  
  95.     #If we are not intersecting at all, return (0, 0).
  96.     if distance_x >= minDistance_x and distance_y >= minDistance_y:
  97.         return Vector.Zero
  98.  
  99.     #Calculate and return intersection depths
  100.     if distance_x > 0:
  101.         depth_x = minDistance_x - distance_x
  102.     else:
  103.         depth_x = -minDistance_x - distance_x
  104.  
  105.     if distance_x > 0:
  106.         depth_y = minDistance_y - distance_y
  107.     else:
  108.         depth_y = -minDistance_y - distance_y
  109.    
  110.     return Vector(depth_x, depth_y)
  111.  
  112. def fill_gradient(surface, color, gradient, rect=None, vertical=True, forward=True):
  113.     """fill a surface with a gradient pattern
  114.    Parameters:
  115.    color -> starting color
  116.    gradient -> final color
  117.    rect -> area to fill; default is surface's rect
  118.    vertical -> True=vertical; False=horizontal
  119.    forward -> True=forward; False=reverse
  120.    
  121.    Pygame recipe: http://www.pygame.org/wiki/GradientCode
  122.    """
  123.     if rect is None: rect = surface.get_rect()
  124.     x1,x2 = rect.left, rect.right
  125.     y1,y2 = rect.top, rect.bottom
  126.     if vertical: h = y2-y1
  127.     else:        h = x2-x1
  128.     if forward: a, b = color, gradient
  129.     else:       b, a = color, gradient
  130.     rate = (
  131.         float(b[0]-a[0])/h,
  132.         float(b[1]-a[1])/h,
  133.         float(b[2]-a[2])/h
  134.     )
  135.     fn_line = pygame.draw.line
  136.     if vertical:
  137.         for line in range(y1,y2):
  138.             color = (
  139.                 min(max(a[0]+(rate[0]*(line-y1)),0),255),
  140.                 min(max(a[1]+(rate[1]*(line-y1)),0),255),
  141.                 min(max(a[2]+(rate[2]*(line-y1)),0),255)
  142.             )
  143.             fn_line(surface, color, (x1,line), (x2,line))
  144.     else:
  145.         for col in range(x1,x2):
  146.             color = (
  147.                 min(max(a[0]+(rate[0]*(col-x1)),0),255),
  148.                 min(max(a[1]+(rate[1]*(col-x1)),0),255),
  149.                 min(max(a[2]+(rate[2]*(col-x1)),0),255)
  150.             )
  151.             fn_line(surface, color, (col,y1), (col,y2))
  152.  
  153. #game class
  154. class Game(object):
  155.     def __init__(self):
  156.         pygame.mixer.init()
  157.        
  158.         self.clock = pygame.time.Clock()
  159.  
  160.         self.game_state = "menu_main"
  161.  
  162.         #initialize Keyboard() class
  163.         self.keyboard = Keyboard()
  164.  
  165.         self.list_update_always = [self.keyboard]
  166.         self.list_update = []
  167.         self.list_draw = []
  168.  
  169.         #The number of times our engine should update per second.
  170.         self.preferred_fps = 60
  171.  
  172.         #Used to print the fps of the game onto the console window.
  173.         self.fpsTimer = 0.0
  174.  
  175.         #Should Ragnarok print the number of frames the game is running at?
  176.         self.print_frames = False
  177.        
  178.         #The number of milliseconds between printing out the frame rate
  179.         self.print_fps_frequency = 1000
  180.  
  181.         #self.level_1 = Level("data/maps/level_1.map")
  182.         self.level_menu_main = Level_menu_main()
  183.        
  184.     def get_keyboard(self):
  185.         return self.keyboard
  186.  
  187.     def go(self):
  188.         running = True
  189.         while running:
  190.             #print frame
  191.             #This is the main game loop
  192.             #Update our clock
  193.             self.clock.tick(self.preferred_fps)
  194.             elapsed_milliseconds = self.clock.get_time()
  195.  
  196.             #Print the fps that the game is running at.
  197.             if self.print_frames:
  198.                 self.fpsTimer += elapsed_milliseconds
  199.                 if self.fpsTimer > self.print_fps_frequency:
  200.                     print "FPS: ", self.clock.get_fps()
  201.                     self.fpsTimer = 0.0
  202.  
  203.             for event in pygame.event.get():
  204.                 if event.type == pygame.QUIT:
  205.                     running = False
  206.  
  207.             function = getattr(self, self.game_state)
  208.             function()
  209.            
  210.             #drawing and updating
  211.             for obj in self.list_update_always:
  212.                 obj.update(17) # put elapsed_milliseconds instead of 17 if you want it to be affected by time
  213.             for obj in self.list_update:
  214.                 obj.update(17) # put elapsed_milliseconds instead of 17 if you want it to be affected by time
  215.  
  216.             #screen.fill((230, 255, 255))
  217.            
  218.             for obj in self.list_draw:
  219.                 obj.draw(17, screen) # put elapsed_milliseconds instead of 17 if you want it to be affected by time
  220.            
  221.             ### debug ###
  222.             #
  223.             #pygame.draw.line(screen, (0,0,0), (0,windowHeight/2), (windowWidth,windowHeight/2), 1)
  224.             #pygame.draw.line(screen, (0,0,0), (windowWidth/2,0), (windowWidth/2,windowHeight), 1)
  225.             #
  226.             #############
  227.            
  228.             pygame.display.flip()
  229.         pygame.quit()
  230.        
  231.     def menu_main(self):
  232.         self.list_update = [self.level_menu_main]
  233.         self.list_draw = [self.level_menu_main]
  234.  
  235.     def menu_info(self):
  236.         self.list_update = []
  237.         self.list_draw = []
  238.  
  239.     def game(self):
  240.         #self.list_update = [self.debug_info, self.camera]
  241.         #self.list_draw = [self.debug_info, self.camera]
  242.         pass
  243.  
  244.     def menu_loadlevel(self):
  245.         self.list_update = [self.menu_level_loader]
  246.         self.list_draw = [self.menu_level_loader]
  247.  
  248. #######################################################################################################################
  249. # out of main game classes
  250.  
  251. class UpdatableObj(object):
  252.     """
  253.    The base class of our game engine.
  254.    Represents an object that can be updated.
  255.    """
  256.     #The number of objects that have existed so far. Used to create a unique object id.
  257.     __total_id = 0
  258.  
  259.     def __init__(self, level, update_order = 0):
  260.         self.level = level
  261.         #The order in which this object should update relative to the other objects.
  262.         self.update_order = update_order
  263.  
  264.         #Represents the unique identifer for this object.
  265.         self.obj_id = self.__total_id
  266.  
  267.         #Keeps track of the total number of object created since game start.
  268.         UpdatableObj.__total_id += 1
  269.  
  270.         #Is the object allowed to update druing the update loop?
  271.         self.is_enabled = True
  272.  
  273.         #Does the object stay in one place even if the camera is moving?
  274.         self.is_static = True
  275.  
  276.         #Represents the location of the object in world space.
  277.         self.position = Vector(0, 0)
  278.  
  279.         #Allows the user to define the object as they want.
  280.         self.tag = ""
  281.  
  282.         #allows to add commands
  283.         self.commands = None
  284.  
  285.         #variables to be used by self.commands
  286.         self.variable_1 = 0
  287.         self.variable_2 = 0
  288.         self.variable_3 = 0
  289.  
  290.     def __str__(self):
  291.         return "{ \nUpdateableObj: \t Update Order: " + str(self.update_order) + "\t Object ID: " \
  292.                + str(self.obj_id) + "\t Is Enabled: " + str(self.is_enabled)+ "\n}"
  293.  
  294.     def update(self, milliseconds):
  295.         #Update the object.
  296.         if not self.commands == None:
  297.             exec self.commands
  298.  
  299. class DrawableObj(UpdatableObj):
  300.     """An object that represents something that can be drawn."""
  301.     def __init__(self, level, update_order = 0, draw_order = 0):
  302.         super(DrawableObj, self).__init__(level, update_order)
  303.         self.draw_order = draw_order
  304.  
  305.         #Should the object draw during the update loop?
  306.         self.is_visible = True
  307.  
  308.         #The surface rendered onto the screen when draw is called.
  309.         self.image = pygame.surface.Surface((0, 0))
  310.  
  311.         self.offset = Vector(0,0)
  312.  
  313.         try:
  314.             self.scale_factor
  315.         except AttributeError:
  316.             self.scale_factor = 1
  317.  
  318.     def show(self):
  319.         """Enable and show the object."""
  320.         self.is_enabled = true
  321.         self.is_visible = true
  322.  
  323.     def hide(self):
  324.         """Disable and hide the object."""
  325.         self.is_enabled = false
  326.         self.is_visible = false
  327.  
  328.     def is_visible_to_camera(self, camera):
  329.         """Is the object visible to the camera?"""
  330.         #if self.image.get_rect().colliderect(camera.rect):
  331.         #   return True
  332.         # ^ doesn't work, don't know why
  333.         return True
  334.  
  335.     def draw(self, milliseconds, surface):
  336.         #Draw the object
  337.         if self.is_static:
  338.             surface.blit(self.image, self.position + self.offset)
  339.         else:
  340.             relative_position = (self.position + self.offset) - self.level.camera.position
  341.             # glich fix, the render makes weird jumps (only for some objects) between two pixels if you dont do this
  342.             relative_position = Vector(relative_position.x, relative_position.y - 0.2)
  343.             surface.blit(self.image, relative_position)
  344.  
  345.  
  346. #keyboard and keystate class from ragnarok engine
  347. class KeyState(object):
  348.     def __init__(self):
  349.         #Contains a reference to all pressed status of all the keys
  350.         self.key_states = []
  351.  
  352.     def copy(self):
  353.         new_keys = []
  354.         for key in self.key_states:
  355.             new_keys.append(key)
  356.         state_cpy = KeyState()
  357.         state_cpy.key_states = new_keys
  358.         return state_cpy
  359.  
  360.     def query_state(self, key):
  361.         """
  362.        Query the state of a key. True if the key is down, false if it is up.
  363.        key is a pygame key.
  364.        """
  365.         return self.key_states[key]
  366.  
  367. class Keyboard(UpdatableObj):
  368.     def __init__(self):
  369.         super(Keyboard, self).__init__(None)
  370.         self.current_state = KeyState()
  371.         self.previous_state = KeyState()
  372.         self.current_state.key_states = pygame.key.get_pressed()
  373.  
  374.     def is_down(self, key):
  375.         return self.current_state.query_state(key)
  376.  
  377.     def is_up(self, key):
  378.         return not self.current_state.query_state(key)
  379.  
  380.     def is_clicked(self, key):
  381.         return self.current_state.query_state(key) and (not self.previous_state.query_state(key))
  382.  
  383.     def is_released(self, key):
  384.         return self.previous_state.query_state(key) and (not self.current_state.query_state(key))
  385.  
  386.     def is_any_down(self):
  387.         """Is any button depressed?"""
  388.         for key in range(len(self.current_state.key_states)):
  389.             if self.is_down(key):
  390.                 return True
  391.         return False
  392.  
  393.     def is_any_clicked(self):
  394.         """Is any button clicked?"""
  395.         for key in range(len(self.current_state.key_states)):
  396.             if self.is_clicked(key):
  397.                 return True
  398.         return False
  399.  
  400.     def update(self, milliseconds):
  401.         keys = pygame.key.get_pressed()
  402.         self.previous_state = self.current_state.copy()
  403.         self.current_state.key_states = keys
  404.         super(Keyboard, self).update(milliseconds)
  405.  
  406.  
  407. class Camera(UpdatableObj):
  408.     def __init__(self, level, position):
  409.         super(Camera, self).__init__(level)
  410.  
  411.         self.offset = Vector(windowWidth/2, windowHeight/2)
  412.         self.scale = Vector(windowWidth, windowHeight)
  413.         self.position = position - self.offset + self.level.player.scale/2
  414.         self.rect = pygame.Rect(self.position, self.scale)
  415.         self.velocity = Vector(0,0)
  416.  
  417.         self.image = pygame.Surface((10,10)).convert()
  418.         self.image.fill((0,0,255))
  419.        
  420.     def update(self, milliseconds):
  421.         #time = (milliseconds / 1000.0)
  422.         #self.velocity.y = 0
  423.         #self.velocity.x = 0
  424.         #if main_game.keyboard.is_down(K_w):
  425.         #    self.velocity.y = -200
  426.         #if main_game.keyboard.is_down(K_s):
  427.         #    self.velocity.y = 200
  428.         #if main_game.keyboard.is_down(K_d):
  429.         #    self.velocity.x = 200
  430.         #if main_game.keyboard.is_down(K_a):
  431.         #    self.velocity.x = -200
  432.         #self.position += self.velocity * time
  433.         camera_position = self.position + self.offset
  434.         player_position = self.level.player.position + self.level.player.scale/2
  435.         distance = player_position - camera_position
  436.         cam_x = 0 #150 # allowed_distance_x_from_camera
  437.        
  438.         camera_position.y = player_position.y
  439.         if distance.x > cam_x:
  440.             camera_position.x = player_position.x - cam_x
  441.         if distance.x < -cam_x:
  442.             camera_position.x = player_position.x + cam_x
  443.  
  444.         self.position = camera_position - self.offset
  445.        
  446.         self.rect.topleft = self.position #- self.offset
  447.  
  448. # blueprint
  449. class Level(UpdatableObj):
  450.     def __init__(self, level_file = None, player_position = None):
  451.         super(Level, self).__init__(self)
  452.        
  453.         self.list_update = []
  454.         self.list_draw = []
  455.  
  456.         #Do we need to sort our list of updatable objects?
  457.         self.__do_need_sort_up = False
  458.  
  459.         #Do we need to sort our list of drawable objects?
  460.         self.__do_need_sort_draw = False
  461.  
  462.         self.player_position = player_position
  463.  
  464.         if not level_file == None:
  465.             self.load_level(level_file)
  466.  
  467.     def load_level(self, level_file):
  468.         self.load_level_file(level_file)
  469.         self.parse_level_file()
  470.  
  471.     def find_obj_in_list(self, search_list, value, tag_or_id):
  472.         if tag_or_id == "tag":
  473.             for obj in search_list:
  474.                 if obj.tag == value:
  475.                     return obj
  476.         elif tag_or_id == "id":
  477.             for obj in search_list:
  478.                 if obj.obj_id == value:
  479.                     return obj
  480.         else:
  481.             print "error tag_or_id"
  482.    
  483.     def load_level_file(self, level_file):
  484.         filename = "data/maps/" + level_file #filename
  485.         stream = open(filename, 'r')            #opening stream
  486.         yaml_file = yaml.load(stream)           #loading stream
  487.         #print yaml_file
  488.  
  489.         ########################################################
  490.         # this is becaus YAML doesn't load dicts in the order it
  491.         # was written and python only does it with OrderedDict()
  492.         begin_dict = OrderedDict(yaml_file[0])
  493.         for index, dictionary in enumerate(yaml_file):
  494.             if not index == 0:
  495.                 begin_dict.update(dictionary)
  496.        
  497.         ########################################################
  498.         self.level = begin_dict
  499.    
  500.     def parse_level_file(self):
  501.         self.list_collision = []
  502.  
  503.         camera_position = Vector(0,0)
  504.  
  505.         ###### temporary ############
  506.  
  507.         self.background = DrawableObj(self)
  508.         surface = copy.copy(screen)
  509.         fill_gradient(surface, (170, 255, 255), (255, 255, 255))
  510.         self.background.image = surface
  511.         self.list_draw.append(self.background)
  512.  
  513.         #############################
  514.         self.scale_factor = 3.0 # best to use integer or 1/2 because of rounding faults of the program
  515.         scale_factor = self.scale_factor
  516.        
  517.         for obj in self.level:
  518.  
  519.             obj_postion = Vector(0,0)
  520.             if "position" in self.level[obj]:
  521.                 obj_position = Vector(self.level[obj]["position"][0]*scale_factor, self.level[obj]["position"][1]*scale_factor)
  522.             obj_offset = Vector(0,0)
  523.             if "offset" in self.level[obj]:
  524.                 obj_offset = Vector(self.level[obj]["offset"][0]*scale_factor, self.level[obj]["offset"][1]*scale_factor)
  525.             obj_scale = Vector(0,0)
  526.             if "scale" in self.level[obj]:
  527.                 obj_scale = Vector(self.level[obj]["scale"][0]*scale_factor, self.level[obj]["scale"][1]*scale_factor)
  528.                 obj_scale_int = Vector(int(self.level[obj]["scale"][0]*scale_factor), int(self.level[obj]["scale"][1]*scale_factor)) # scale values in integers
  529.             if "image" in self.level[obj]:
  530.                 if isinstance(self.level[obj]["image"], basestring):
  531.                     obj_image = load_png(self.level[obj]["image"])
  532.                 elif isinstance(self.level[obj]["image"][1], list):
  533.                     tile_scale_x = self.level[obj]["image"][1][0]
  534.                     tile_scale_y = self.level[obj]["image"][1][1]
  535.                     tileset = load_tile_table(self.level[obj]["image"][0], tile_scale_x, tile_scale_y)
  536.                     tile_pos_x = self.level[obj]["image"][2][0]
  537.                     tile_pos_y = self.level[obj]["image"][2][1]
  538.                     obj_image = tileset[tile_pos_x][tile_pos_y]
  539.             obj_commands = None
  540.             if "commands" in self.level[obj]:
  541.                 obj_commands = self.level[obj]["commands"]
  542.  
  543.             if "randomclouds" in self.level[obj]:
  544.                 tileset_file = self.level[obj]["randomclouds"]
  545.                 self.create_clouds(tileset_file)
  546.  
  547.             if obj == "player":
  548.                 if self.player_position == None:
  549.                     self.player_position = obj_position
  550.                     camera_position = copy.copy(obj_position)
  551.                     self.player = Player(self, obj_position)
  552.                     self.list_update.append(self.player)
  553.                     self.list_draw.append(self.player)
  554.                 else:
  555.                     camera_position = copy.copy(self.player_position)
  556.                     self.player = Player(self, copy.copy(self.player_position))
  557.                     self.list_update.append(self.player)
  558.                     self.list_draw.append(self.player)
  559.  
  560.             elif "cloud" in self.level[obj]:
  561.                 layer = self.level[obj]["cloud"]
  562.                 cloud_image = pygame.transform.scale(obj_image, obj_scale_int)
  563.                 cloud = Cloud(self, obj_position, obj_scale, cloud_image, layer)
  564.                 self.list_draw.append(cloud)
  565.                
  566.             elif "interactive" in self.level[obj]:
  567.                 if self.level[obj]["interactive"] == "npc":
  568.                     npc_image_transformed = pygame.transform.scale(obj_image, obj_scale_int)
  569.                     npc_dialog_file = self.level[obj]["dialog"]
  570.                     npc = NPC(self, obj_position, obj_scale, npc_image_transformed, npc_dialog_file)
  571.  
  572.                     self.list_collision.append(npc)
  573.                     self.list_draw.append(npc)
  574.                    
  575.             elif "animation" in self.level[obj]:
  576.                 if self.level[obj]["animation"] == "loop":
  577.                     image_sequence = self.level[obj]["image"]
  578.                     tpf = self.level[obj]["tpf"]
  579.                     ani_obj = AnimationLoopObj(self, obj_position, obj_scale, image_sequence, tpf)
  580.                     ani_obj.commands = obj_commands
  581.                     self.list_update.append(ani_obj)
  582.                     self.list_draw.append(ani_obj)
  583.                    
  584.                 elif self.level[obj]["animation"] == "oncollision":
  585.                     image_sequence = self.level[obj]["image"]
  586.                     tpf = self.level[obj]["tpf"]
  587.                     condition = self.level[obj]["condition"]
  588.                     ani_obj = AnimationOnCollisionObj(self, obj_position, obj_scale, image_sequence, tpf, condition)
  589.                     ani_obj.commands = obj_commands
  590.                     self.list_collision.append(ani_obj)
  591.                     self.list_update.append(ani_obj)
  592.                     self.list_draw.append(ani_obj)
  593.            
  594.             elif "tile_solids" in self.level[obj]:
  595.                 thing = DrawableObj(self)
  596.                 thing.position = obj_position
  597.                 thing.image = pygame.transform.scale(obj_image, obj_scale_int)
  598.                 thing.is_static = False
  599.                 self.list_draw.append(thing)
  600.                 if "tile_solids" in self.level[obj]:
  601.                     #tile_scale_without_scale_factor = Vector(self.level[obj]["tile_scale"][0], self.level[obj]["tile_scale"][1])
  602.                     tile_scale = Vector(self.level[obj]["tile_scale"][0]*scale_factor, self.level[obj]["tile_scale"][1]*scale_factor)
  603.                     solid_tiles = self.level[obj]["tile_solids"].split()
  604.                     #print solid_tiles
  605.                     for map_y, line in enumerate(solid_tiles):
  606.                         for map_x, character in enumerate(line):
  607.                             if character == "#":
  608.                                 tile_pos = Vector(map_x*tile_scale.x, map_y*tile_scale.y)
  609.                                 collision_obj = SolidObj(self, tile_pos, tile_scale)
  610.                                 self.list_collision.append(collision_obj)
  611.                                 #self.list_draw.append(collision_obj) # for debugging
  612.                                 #self.list_update.append(collision_obj) # for debugging
  613.                             if character == "^":
  614.                                 tile_pos = Vector(map_x*tile_scale.x, map_y*tile_scale.y)
  615.                                 collision_obj = PlatformObj(self, tile_pos, tile_scale)
  616.                                 self.list_collision.append(collision_obj)
  617.                                 #self.list_draw.append(collision_obj) # for debugging
  618.                                 #self.list_update.append(collision_obj) # for debugging
  619.                                
  620.             elif "solid" in self.level[obj]:
  621.                 try:
  622.                     thing = SolidObj(self, obj_position, Vector(int(self.level[obj]["solid"][0]*scale_factor), int(self.level[obj]["solid"][1]*scale_factor)))
  623.                     thing.image = pygame.transform.scale(obj_image, obj_scale_int)
  624.                     thing.commands = obj_commands
  625.                     thing.offset = obj_offset
  626.                     self.list_collision.append(thing)
  627.                     if not obj_commands == None:
  628.                         self.list_update.append(thing)
  629.                     self.list_draw.append(thing)
  630.                 except TypeError:
  631.                     thing = PlatformObj(self, obj_position, Vector(int(self.level[obj]["solid"]*scale_factor),0))
  632.                     thing.image = pygame.transform.scale(obj_image, obj_scale_int)
  633.                     thing.commands = obj_commands
  634.                     thing.offset = obj_offset
  635.                     self.list_collision.append(thing)
  636.                     if not obj_commands == None:
  637.                         self.list_update.append(thing)
  638.                     self.list_draw.append(thing)
  639.             else:
  640.                 thing = DrawableObj(self)
  641.                 thing.position = obj_position
  642.                 thing.image = pygame.transform.scale(obj_image, obj_scale_int)
  643.                 thing.is_static = False
  644.                 thing.commands = obj_commands
  645.                 if not obj_commands == None:
  646.                     self.list_update.append(thing)
  647.                 self.list_draw.append(thing)
  648.  
  649.         self.camera = Camera(self, camera_position)
  650.         self.list_update.append(self.camera)
  651.        
  652.     def get_tile(self, x, y):
  653.         try:
  654.             char = self.map[y][x]
  655.         except IndexError:
  656.             return {}
  657.         try:
  658.             return self.key[char]
  659.         except KeyError:
  660.             return {}
  661.  
  662.     def get_bool(self, x, y, name):
  663.         """Tell if the specified flag is set for position on the map."""
  664.        
  665.         value = self.get_tile(x, y).get(name) # return value
  666.         return value in (True, 1, 'true', 'yes', 'True', 'Yes', '1', 'on', 'On')
  667.  
  668.     def get_attribute(self, x, y, name):
  669.         """Tell if the specified flag is set for position on the map."""
  670.        
  671.         value = self.get_tile(x, y).get(name) # return value of that name
  672.         return value
  673.  
  674.     def create_clouds(self, tileset_image):
  675.         # simple extra function too randomly create clouds on the background of the level
  676.         for cloud in range(7):
  677.             tileset = load_tile_table(tileset_image, 48, 48)
  678.             tile_pos_x = random.randint(0, 2)
  679.             tile_pos_y = 0
  680.             obj_image = tileset[tile_pos_x][tile_pos_y]
  681.             obj_position = Vector(random.randint(0, 3200), random.randint(0, 1600))
  682.             scale = random.randint(250, 360)
  683.             obj_scale = Vector(scale,scale)
  684.             layer = random.randint(4, 9)/10.0
  685.             cloud_image = pygame.transform.scale(obj_image, obj_scale)
  686.             cloud = Cloud(self, obj_position, obj_scale, cloud_image, layer)
  687.             self.list_draw.append(cloud)
  688.  
  689.     def create_gradient_background(self, color_1, color_2):
  690.         self.background = DrawableObj(self)
  691.         surface = copy.copy(screen)
  692.         fill_gradient(surface, color_1, color_2)
  693.         self.background.image = surface
  694.         self.list_draw.append(self.background)
  695.    
  696.     def __draw_cmp(self, obj1, obj2):
  697.         """Defines how our drawable objects should be sorted"""
  698.         if obj1.draw_order > obj2.draw_order:
  699.             return 1
  700.         elif obj1.draw_order < obj2.draw_order:
  701.             return -1
  702.         else:
  703.             return 0
  704.  
  705.     def __up_cmp(self, obj1, obj2):
  706.         """Defines how our updatable objects should be sorted"""
  707.         if obj1.update_order > obj2.update_order:
  708.             return 1
  709.         elif obj1.update_order < obj2.update_order:
  710.             return -1
  711.         else:
  712.             return 0
  713.  
  714.     def __sort_up(self):
  715.         """Sort the updatable objects according to ascending order"""
  716.         if self.__do_need_sort_up:
  717.             self.list_update.sort(self.__up_cmp)
  718.             self.__do_need_sort_up = False
  719.  
  720.     def __sort_draw(self):
  721.         """Sort the drawable objects according to ascending order"""
  722.         if self.__do_need_sort_draw:
  723.             self.list_draw.sort(self.__draw_cmp)
  724.             self.__do_need_sort_draw = False
  725.  
  726.     def update(self, milliseconds):
  727.         """Updates all of the objects in our world."""
  728.         self.__sort_up()
  729.         for obj in self.list_update:
  730.             obj.update(milliseconds)
  731.  
  732.     def draw(self, milliseconds, surface):
  733.         """Draws all of the objects in our world."""
  734.         self.__sort_draw()
  735.         for obj in self.list_draw:
  736.             #Check to see if the object is visible to the camera before doing anything to it.
  737.             if obj.is_static or obj.is_visible_to_camera(self.camera):
  738.                 obj.draw(milliseconds, surface)
  739.  
  740.  
  741. class Level_2(Level):
  742.     def __init__(self):
  743.         super(Level_2, self).__init__("level_1_YAML.map")
  744.        
  745. #        self.load_level("level_1_YAML.map")
  746.  
  747.         # put debug in only for debugging (obviously)
  748.         debug = Debug(self)
  749.         self.list_update.append(debug)
  750.         self.list_draw.append(debug)
  751.  
  752. class Level_menu_main(Level):
  753.     def __init__(self):
  754.         super(Level_menu_main, self).__init__()
  755.        
  756.         self.create_gradient_background((170, 255, 255), (255, 255, 255))
  757.        
  758.         self.menu = Menu_main(self)
  759.         self.list_draw.append(self.menu)
  760.         self.list_update.append(self.menu)
  761.        
  762.  
  763. class Level_1(Level):
  764.     def __init__(self):
  765.         super(Level_1, self).__init__()
  766.  
  767.         self.background = DrawableObj(self)
  768.         surface = copy.copy(screen)
  769.         fill_gradient(surface, (170, 255, 255), (255, 255, 255))
  770.         self.background.image = surface
  771.         self.list_draw.append(self.background)
  772.         self.load_level("data/maps/level_1.map")
  773.  
  774.         cloud_1 = Cloud(self, Vector(-200, 0), Vector(0, 0))
  775.         cloud_2 = Cloud(self, Vector(1600, 400), Vector(1, 0))
  776.         cloud_3 = Cloud(self, Vector(1200, -200), Vector(2, 0))
  777.         self.list_clouds = [cloud_1, cloud_2, cloud_3]
  778.  
  779.         self.list_update.append(self.player)
  780.         self.list_update.append(self.camera)
  781.  
  782.         self.list_draw.extend(self.list_clouds)
  783.         self.list_draw.append(self.image_background)
  784.         self.list_draw.extend(self.list_npc)
  785.         #self.list_draw.extend(self.list_interactive_tiles)
  786.         self.list_draw.append(self.player)
  787.         self.list_draw.append(self.image_overlay)
  788.         #self.list_draw.extend(self.list_collidables) # used for debug to know where solid tiles are
  789.  
  790.         # debug is above everything
  791.         # can't seem to get it to work properly
  792.         #name = "main.game." + str(main_game.list_update[0]) + ".player.collision_y"
  793.         debug = Debug(self)
  794.         self.list_update.append(debug)
  795.         self.list_draw.append(debug)
  796.  
  797.  
  798. # menu and button classes
  799. # blueprint
  800. class Button(DrawableObj):
  801.     def __init__(self, level, scale, position, image_deselect, image_select, image_selected = None):
  802.         super(Button, self).__init__(level)
  803.        
  804.         self.scale = scale
  805.         self.position = position
  806.         if image_selected == None:
  807.             image_selected = image_select
  808.         self.image_deselect = pygame.transform.scale(image_deselect, scale)
  809.         self.image_select = pygame.transform.scale(image_select, scale)
  810.         self.image_selected = pygame.transform.scale(image_selected, scale)
  811.         self.image = self.image_deselect
  812.         self.selected = False
  813.        
  814.     def select(self):
  815.         self.selected = True
  816.         self.image = self.image_select
  817.        
  818.     def deselect(self):
  819.         self.selected = False
  820.         self.image = self.image_deselect
  821.        
  822.     def clicked_action(self):
  823.         self.image = self.image_selected
  824.         ''' needs to be overwritten'''
  825.         pass
  826.  
  827. class Button_main_menu(Button):
  828.     def __init__(self, level, scale, position, image_deselect, image_select):
  829.         super(Button_main_menu, self).__init__(level, scale, position, image_deselect, image_select)
  830.  
  831.         self.sound_select = load_sound("menu/menu_select.wav")
  832.         self.sound_select.set_volume(0.04)
  833.         self.sound_selected = load_sound("menu/menu_selected.wav")
  834.         self.sound_selected.set_volume(0.04)
  835.  
  836.     def select(self):
  837.         super(Button_main_menu, self).select()
  838.         self.sound_select.play()
  839.    
  840.     def clicked_action(self):
  841.         super(Button_main_menu, self).clicked_action()
  842.         self.sound_selected.play()
  843.  
  844. class Button_new_game(Button_main_menu):
  845.     def __init__(self, level):
  846.         scale = Vector(38*10, 7*10)
  847.         position = Vector(50, 5*10)
  848.         image_deselect = load_png("menu/button_new_game_deselected.png")
  849.         image_select = load_png("menu/button_new_game_selected.png")
  850.        
  851.         super(Button_new_game, self).__init__(level, scale, position, image_deselect, image_select)
  852.  
  853.     def clicked_action(self):
  854.         super(Button_new_game, self).clicked_action()
  855.         main_game.game_state = "game"
  856.  
  857.         level_2 = Level_2()
  858.         main_game.list_update = [level_2]
  859.         main_game.list_draw = [level_2] # main_game.player is drawn in level_1 so you can use layers
  860.         # for debug put main_game.debug_info, main_game.camera in the list
  861.         #game.list_draw.extend(level_1.list_solid_tiles)
  862.  
  863. class Button_load_level(Button_main_menu):
  864.     def __init__(self, level):
  865.         scale = Vector(41*10, 7*10)
  866.         position = Vector(50, 13*10)
  867.         image_deselect = load_png("menu/button_load_level_deselected.png")
  868.         image_select = load_png("menu/button_load_level_selected.png")
  869.        
  870.         super(Button_load_level, self).__init__(level, scale, position, image_deselect, image_select)
  871.  
  872.     def clicked_action(self):
  873.         super(Button_load_level, self).clicked_action()
  874.         print "level loading begins"
  875.         main_game.game_state = "menu_loadlevel"
  876.  
  877. class Button_info(Button_main_menu):
  878.     def __init__(self, level):
  879.         scale = Vector(17*10, 7*10)
  880.         position = Vector(50, 21*10)
  881.         image_deselect = load_png("menu/button_info_deselected.png")
  882.         image_select = load_png("menu/button_info_selected.png")
  883.        
  884.         super(Button_info, self).__init__(level, scale, position, image_deselect, image_select)
  885.  
  886.     def clicked_action(self):
  887.         super(Button_info, self).clicked_action()
  888.         print "main main_game begins"
  889.         main_game.game_state = "menu_info"
  890.  
  891. # blueprint
  892. class Menu(DrawableObj):
  893.     def __init__(self, level):
  894.         super(Menu, self).__init__(level)
  895.  
  896.         #The keyboard button that selects the button above the currently selected button.
  897.         self.move_up_button = K_UP
  898.  
  899.         #The keyboard button that selects the button below the currently selected button.
  900.         self.move_down_button = K_DOWN
  901.  
  902.         #The keyboard button we will querty for clicked events.
  903.         self.select_button = K_SPACE
  904.  
  905.         #The index of the currently selected button.
  906.         self.current_index = -1
  907.  
  908.         #List of buttons
  909.         self.buttons = []
  910.        
  911.     def update(self, milliseconds):
  912.         #Set the default selected button. This is necessary to to get correct behavior when the menu first starts running.
  913.         if self.current_index == -1:
  914.             self.current_index = 0
  915.             self.buttons[self.current_index].select()
  916.        
  917.         if main_game.keyboard.is_clicked(self.move_up_button):
  918.             self.move_up()
  919.         if main_game.keyboard.is_clicked(self.move_down_button):
  920.             self.move_down()
  921.         if main_game.keyboard.is_released(self.select_button):
  922.             self.buttons[self.current_index].clicked_action()
  923.  
  924.         super(Menu, self).update(milliseconds)
  925.            
  926.     def move_up(self):
  927.         """
  928.        Try to select the button above the currently selected one.
  929.        If a button is not there, wrap down to the bottom of the menu and select the last button.
  930.        """
  931.         old_index = self.current_index
  932.         self.current_index -= 1
  933.         self.__wrap_index()
  934.         self.__handle_selections(old_index, self.current_index)
  935.  
  936.     def move_down(self):
  937.         """
  938.        Try to select the button under the currently selected one.
  939.        If a button is not there, wrap down to the top of the menu and select the first button.
  940.        """
  941.         old_index = self.current_index
  942.         self.current_index += 1
  943.         self.__wrap_index()
  944.         self.__handle_selections(old_index, self.current_index)
  945.        
  946.     def __wrap_index(self):
  947.         """Wraps the current_index to the other side of the menu."""
  948.         if self.current_index < 0:
  949.             self.current_index = len(self.buttons) - 1
  950.         elif self.current_index >= len(self.buttons):
  951.             self.current_index = 0
  952.  
  953.     def __handle_selections(self, old_index, new_index):
  954.         #Don't perform any deselections or selections if the currently selected button hasn't changed.
  955.         if old_index is not new_index:
  956.             #Deselect the old button
  957.             self.buttons[old_index].deselect()
  958. ##            print "Button " + str(old_index) + " deselected."
  959.  
  960.             #Select the new button.
  961.             self.buttons[new_index].select()
  962. ##            print "Button " + str(new_index) + " selected."
  963.            
  964.     def draw(self, milliseconds, surface):
  965.         for button in self.buttons:
  966.             button.draw(milliseconds, surface)
  967.         super(Menu, self).draw(milliseconds, surface)
  968.        
  969.  
  970. class Menu_main(Menu):
  971.     def __init__(self, level):
  972.         super(Menu_main, self).__init__(level)
  973.        
  974.         self.button_new_game = Button_new_game(level)
  975.         self.button_load_level = Button_load_level(level)
  976.         self.button_info = Button_info(level)
  977.         self.buttons = [self.button_new_game, self.button_load_level, self.button_info]
  978.  
  979. class Button_level_1(Button):
  980.     def __init__(self, level):
  981.         scale = Vector(48*10, 7*10)
  982.         position = Vector(100, 10*10)
  983.         image_deselect = load_png("menu/button_level_1_deselected.png")
  984.         image_select = load_png("menu/button_level_1_selected.png")
  985.        
  986.         super(Button_level_1, self).__init__(level, scale, position, image_deselect, image_select)
  987.  
  988.     def clicked_action(self):
  989.         print "main game begins"
  990.         main_game.game_state = "game"
  991.  
  992.         level_1 = Level("data/maps/level_1.map")
  993.         main_game.list_update = [main_game.debug_info, main_game.camera, main_game.player]
  994.         main_game.list_draw = [level_1, game.debug_info] # game.player is drawn in level_1 so you can use layers
  995.         # for debug put game.debug_info, game.camera in the list
  996.         #game.list_draw.extend(level_1.list_solid_tiles)
  997.  
  998. class Menu_level_loader(Menu):
  999.     def __init__(self, level):
  1000.         super(Menu_level_loader, self).__init__()
  1001.  
  1002.         self.button_level_1 = Button_level_1(level)
  1003.         self.buttons = [self.button_level_1]
  1004.  
  1005.        
  1006. #######################################################################################################################
  1007. # in game classes
  1008. class PhysicsObj(DrawableObj):
  1009.     """A class with basic physics implemented."""
  1010.     def __init__(self, level, position = Vector(0,0), scale = Vector(0,0), velocity = Vector(0,0), acceleration = Vector(0,0)):
  1011.         super(PhysicsObj, self).__init__(level)
  1012.  
  1013.         self.is_static = False
  1014.         self.position = copy.copy(position)
  1015.         self.velocity = copy.copy(velocity)
  1016.         self.acceleration = copy.copy(acceleration)
  1017.  
  1018.         self.scale = Vector(int(scale.x), int(scale.y))
  1019.         self.rect = pygame.Rect(self.position, self.scale)
  1020.  
  1021.         self.scale_factor = copy.copy(self.level.scale_factor)
  1022.  
  1023.     def update(self, milliseconds):
  1024.         super(PhysicsObj, self).update(milliseconds)
  1025.         #vf = vi + a * t
  1026.         time = (milliseconds / 1000.0)
  1027.         self.velocity += self.acceleration * time
  1028.         self.position += self.velocity * time
  1029.         self.rect.topleft = self.position
  1030.  
  1031. class SolidObj(PhysicsObj):
  1032.     """A class for solid tiles etc..."""
  1033.     def __init__(self, level, position, scale):
  1034.         super(SolidObj, self).__init__(level, position, scale)
  1035.  
  1036.         self.image = pygame.Surface((int(self.scale.x), int(self.scale.y)))
  1037.         self.image.fill((0, 255, 0))
  1038.  
  1039.     def collision_response(self, player, xvel, yvel):
  1040.         if not self.velocity.x == 0:
  1041.             relative_velocity = player.velocity - self.velocity
  1042.             if self.velocity.x < 0:
  1043.                 if relative_velocity.x > 0:
  1044.                     player.velocity.x -= relative_velocity.x
  1045.                     player.velocity.x -= 18
  1046.                 if relative_velocity.x < 0:
  1047.                     player.velocity.x += relative_velocity.x
  1048.             if self.velocity.x > 0:
  1049.                 if relative_velocity.x > 0:
  1050.                     player.velocity.x += relative_velocity.x + 10
  1051.                 if relative_velocity.x < 0:
  1052.                     player.velocity.x -= relative_velocity.x
  1053.                     player.velocity.x += 80
  1054.        
  1055.         if xvel > 0:
  1056.             player.position.x = self.rect.left - player.scale.x
  1057.             player.rect.left = player.position.x
  1058.             player.velocity.x = 0
  1059.             player.collision_x = 2
  1060.         if xvel < 0:
  1061.             player.position.x = self.rect.right
  1062.             player.rect.left = player.position.x
  1063.             player.velocity.x = 0
  1064.             player.collision_x = 1
  1065.         if yvel > 0:
  1066.             player.position.y = self.rect.top - player.scale.y
  1067.             player.rect.top = player.position.y
  1068.             player.velocity.y = 0
  1069.             player.collision_y = 1
  1070.         if yvel < 0:
  1071.             player.position.y = self.rect.bottom
  1072.             player.rect.top = player.position.y
  1073.             player.velocity.y = 0
  1074.             player.collision_y = 2
  1075.  
  1076. class PlatformObj(PhysicsObj):
  1077.     """A class for platform tiles etc..."""
  1078.     def __init__(self, level, position, scale):
  1079.         super(PlatformObj, self).__init__(level, position, scale)
  1080.  
  1081.         self.image = pygame.Surface((self.scale.x, self.scale.y))
  1082.         self.image.fill((0, 0, 255))
  1083.  
  1084.         self.scale_factor = copy.copy(self.level.scale_factor)
  1085.        
  1086.     def collision_response(self, player, xvel, yvel):
  1087.         if yvel > 0:
  1088.             if 0.1 * yvel > 15:
  1089.                 variable = 15
  1090.             else:
  1091.                 variable = 0.1 * yvel
  1092.             if (player.position.y + player.scale.y) < self.rect.top + variable * self.scale_factor:
  1093.                 player.position.y = self.rect.top - player.scale.y
  1094.                 player.rect.top = player.position.y
  1095.                 player.velocity.y = 0
  1096.                 player.collision_y = 1
  1097.  
  1098.                 # this part is for moving platforms
  1099.                 if not self.velocity.x == 0:
  1100. ##                    relative_velocity = player.velocity - self.velocity
  1101. ##                    if self.velocity.x < 0:
  1102. ##                        if relative_velocity.x > 0:
  1103. ##                            player.velocity.x -= relative_velocity.x
  1104. ##                            #player.velocity.x /= 0.7
  1105. ##                            #player.velocity.x -= 18
  1106. ##                        if relative_velocity.x < 0:
  1107. ##                            player.velocity.x += relative_velocity.x
  1108. ##                            #player.velocity.x /= 0.7
  1109. ##                    if self.velocity.x > 0:
  1110. ##                        if relative_velocity.x > 0:
  1111. ##                            player.velocity.x += relative_velocity.x # + 10
  1112. ##                            #player.velocity.x /= 0.7
  1113. ##                        if relative_velocity.x < 0:
  1114. ##                            player.velocity.x -= relative_velocity.x
  1115. ##                            #player.velocity.x /= 0.7
  1116. ##                            #player.velocity.x += 80
  1117.                     if self.scale_factor == 1.0:
  1118.                         player.position.x += self.velocity.x/10
  1119.                     elif self.scale_factor == 2.0:
  1120.                         player.position.x += self.velocity.x/15
  1121.                     elif self.scale_factor == 3.0:
  1122.                         player.position.x += self.velocity.x/20
  1123.                     elif self.scale_factor == 4.0:
  1124.                         player.position.x += self.velocity.x/20
  1125.                     else:
  1126.                         print "no number specified for this specific scale_factor in the PlatformObj.collision_response()"
  1127.  
  1128.  
  1129. class AnimationLoopObj(DrawableObj):
  1130.     """A class for animations that loop"""
  1131.     def __init__(self, level, position, scale, image_sequence, tpf):
  1132.         super(AnimationLoopObj, self).__init__(level)
  1133.  
  1134.         self.scale_factor = copy.copy(self.level.scale_factor)
  1135.         self.is_static = False
  1136.         self.position = copy.copy(position)
  1137.         self.scale = copy.copy(scale)
  1138.         self.rect = pygame.Rect(self.position, self.scale)
  1139.  
  1140.         scale = Vector(int(scale.x), int(scale.y))
  1141.  
  1142.         self.image_sequence = []
  1143.         images_folder = os.path.join('data/images', image_sequence[0])
  1144.         for i in range(count_files(images_folder)):
  1145.             path_1 = os.path.join(image_sequence[0], image_sequence[1])
  1146.             path_2 = path_1 + str(i+1) + ".png"
  1147.             image = pygame.transform.scale(load_png(path_2), scale)
  1148.             self.image_sequence.append(image)
  1149.  
  1150.         self.image = self.image_sequence[0]
  1151.  
  1152.         #variables for animation
  1153.         self.pause = 0
  1154.         self.frame = 0
  1155.         self.delay = tpf # ticks per frame
  1156.  
  1157.     def update(self, milliseconds):
  1158.         super(AnimationLoopObj, self).update(milliseconds)
  1159.        
  1160.         self.pause += 1
  1161.         if self.pause > self.delay:
  1162.             self.pause = 0
  1163.             self.frame += 1
  1164.             if self.frame >= len(self.image_sequence):
  1165.                 self.frame = 0
  1166.        
  1167.         self.image = self.image_sequence[self.frame]
  1168.  
  1169.  
  1170. class AnimationOnCollisionObj(SolidObj):
  1171.     """A class for animations that animate on collision"""
  1172.     def __init__(self, level, position, scale, image_sequence, tpf, condition):
  1173.         super(AnimationOnCollisionObj, self).__init__(level, position, scale)
  1174.  
  1175.         self.position.x += 1 # glitch fix these objects are 1 pixel off
  1176.         self.position.y += 1 # glitch fix these objects are 1 pixel off
  1177.  
  1178.         self.scale_factor = copy.copy(self.level.scale_factor)
  1179.  
  1180.         scale = Vector(int(scale.x), int(scale.y))
  1181.  
  1182.         self.image_sequence = []
  1183.         images_folder = os.path.join('data/images', image_sequence[0])
  1184.         for i in range(count_files(images_folder)):
  1185.             path_1 = os.path.join(image_sequence[0], image_sequence[1])
  1186.             path_2 = path_1 + str(i+1) + ".png"
  1187.             image = pygame.transform.scale(load_png(path_2), scale)
  1188.             self.image_sequence.append(image)
  1189.  
  1190.         self.image = self.image_sequence[0]
  1191.  
  1192.         #variables for animation
  1193.         self.pause = 0
  1194.         self.frame = 0
  1195.         self.delay = tpf # ticks per frame
  1196.         self.timer = 0
  1197.  
  1198.         self.condition = condition
  1199.  
  1200.         self.animation_done = False
  1201.         self.animation_loop = True
  1202.  
  1203.     def collision_response(self, player, xvel, yvel):
  1204.         exec self.condition
  1205.  
  1206.     def update(self, milliseconds):
  1207.         super(AnimationOnCollisionObj, self).update(milliseconds)
  1208.        
  1209.         if self.timer == 1:
  1210.             self.pause += 1
  1211.             if self.pause > self.delay:
  1212.                 self.pause = 0
  1213.                 self.frame += 1
  1214.                 if self.frame >= len(self.image_sequence):
  1215.                     if self.animation_loop:
  1216.                         self.frame = 0
  1217.                         self.timer = 0
  1218.                     else:
  1219.                         self.frame = len(self.image_sequence) - 1
  1220.                         self.animation_done = True
  1221.            
  1222.             self.image = self.image_sequence[self.frame]
  1223.  
  1224. class NPC(SolidObj):
  1225.     """A class for NPC's"""
  1226.     def __init__(self, level, position, scale, image, dialog_file):
  1227.         super(NPC, self).__init__(level, position, scale)
  1228.  
  1229.         self.image = image
  1230.         self.dialog_file = dialog_file
  1231.         self.dialog_tree = Dialog_tree(level, self, dialog_file)
  1232.  
  1233.         self.likes_player = 0
  1234.  
  1235.     def collision_response(self, player, xvel, yvel):
  1236.         #dialog test
  1237.         if not self.level.find_obj_in_list(self.level.list_draw, "dialog", "tag"):
  1238.             if main_game.keyboard.is_clicked(K_DOWN):
  1239.                 self.dialog_tree.load_node(0)
  1240.  
  1241.                 self.level.list_draw.append(self.dialog_tree)
  1242.                 self.level.list_update.append(self.dialog_tree)
  1243.  
  1244.        
  1245.  
  1246. class AABoundingBox(PhysicsObj):
  1247.     """Represents an axis aligned bounding box."""
  1248.     def __init__(self, level, position, scale, velocity = Vector(0, 0), acceleration = Vector(0, 0)):
  1249.         super(AABoundingBox, self).__init__(level, position, scale, velocity, acceleration)
  1250.  
  1251.         self.collision_x = 0
  1252.         self.collision_y = 0
  1253.  
  1254.     def collision_detection(self, objects, xvel = None, yvel = None):
  1255.         if xvel == None:
  1256.             xvel = self.velocity.x
  1257.         if yvel == None:
  1258.             yvel = self.velocity.y
  1259.        
  1260.         for obj in objects:  
  1261.             if self.rect.colliderect(obj.rect):
  1262.                 function = getattr(obj, "collision_response")
  1263.                 function(self, xvel, yvel)
  1264.  
  1265.     def update(self, milliseconds):
  1266.         #print int(self.velocity.x)
  1267.         #print self.position.x
  1268.        
  1269.         self.collision_x = 0
  1270.         self.collision_y = 0
  1271.         time = (milliseconds / 1000.0)
  1272.  
  1273.         self.velocity.y += self.acceleration.y
  1274.         self.position.y += self.velocity.y * time * self.scale_factor
  1275.         #self.position.y = int(self.position.y) # so he doesn't sometimes bounce 1 pixel on y or x axis
  1276.         self.rect.top = self.position.y
  1277.         self.collision_detection(self.level.list_collision, 0, self.velocity.y)
  1278.  
  1279.         self.velocity.x += self.acceleration.x
  1280.         self.position.x += self.velocity.x * time * self.scale_factor
  1281.         #self.position.x = int(self.position.x) # so he doesn't sometimes bounce 1 pixel on y or x axis
  1282.         self.rect.left = self.position.x
  1283.         self.collision_detection(self.level.list_collision, self.velocity.x, 0)
  1284.  
  1285.  
  1286. # PLAYER class
  1287. class Player(AABoundingBox):
  1288.     def __init__(self, level, position, velocity = Vector(0, 0), acceleration = Vector(0, 0)):
  1289.         self.scale_factor = copy.copy(level.scale_factor)
  1290.         scale = Vector(int(9*self.scale_factor), int(18*self.scale_factor))#Vector(80,180)
  1291.         super(Player, self).__init__(level, position, scale, velocity, acceleration)
  1292.         #AABoundingBox.__init__(self, level, position, scale, velocity, acceleration)
  1293.  
  1294.         self.image_offset = Vector(int(2*self.scale_factor), int(3*self.scale_factor))#Vector(20,30)
  1295.         self.image_scale = Vector(int(13*self.scale_factor), int(24*self.scale_factor))#Vector(120,240)
  1296.         self.image = pygame.transform.scale(load_png("characters/player/player.png"), self.image_scale)
  1297.  
  1298.         #self.scale_factor *= 2
  1299.  
  1300.         self.acceleration = Vector(0, 3.75)
  1301.         self.terminal_velocity = 175
  1302.         self.terminal_velocity_wall = 25
  1303.         self.sliding_down_wall_speed = 75
  1304.         self.jump_power = 125
  1305.         self.jump_power_side = 125
  1306.         self.horizontal_terminal_velocity = 200
  1307.         self.horizontal_acceleration = 30
  1308.         self.jumped = False
  1309.         self.move_wait_time = 10 # used to configure
  1310.         self.move_wait_variable_left = 0 # actually used by the class
  1311.         self.move_wait_variable_right = 0 # actually used by the class
  1312.  
  1313.         self.sound_init()
  1314.         self.animation_init()
  1315.  
  1316.     def sound_init(self):
  1317.         self.sound_channel_walking = pygame.mixer.Channel(0)
  1318.         self.sound_walking = load_sound("walking_test_1.ogg")
  1319.        
  1320.         self.sound_channel_jump = pygame.mixer.Channel(1)
  1321.         self.sound_jump_list = [load_sound("jump/jump_sound_0.ogg"), load_sound("jump/jump_sound_1.ogg"), load_sound("jump/jump_sound_2.ogg"), load_sound("jump/jump_sound_3.ogg"), load_sound("jump/jump_sound_4.ogg")]
  1322.         self.sound_jump_variable = 0
  1323.  
  1324.         self.sound_channel_landing = pygame.mixer.Channel(2)
  1325.         self.sound_landing = load_sound("landing/landing_1.ogg")
  1326.         self.sound_landing.set_volume(0.6)
  1327.         self.sound_landing_list = [0,0]
  1328.        
  1329.         self.sound_channel_glide = pygame.mixer.Channel(3)
  1330.         self.sound_glide = load_sound("glide.ogg")
  1331.        
  1332.     def animation_init(self):
  1333.        
  1334.         #pygame.transform.scale(load_png("characters/player.png"),self.image_scale)
  1335.        
  1336.         self.standing_frame1 = pygame.transform.scale(load_png('characters/player/standing_frame1.png'),self.image_scale)
  1337.         self.falling_frame1 = pygame.transform.scale(load_png('characters/player/falling_frame1.png'),self.image_scale)
  1338.         self.jumping_frame1 = pygame.transform.scale(load_png('characters/player/jumping_frame1.png'),self.image_scale)
  1339.         self.jumping_frame2 = pygame.transform.scale(load_png('characters/player/jumping_frame2.png'),self.image_scale)
  1340.         self.hanging_frame1 = pygame.transform.scale(load_png('characters/player/hanging_frame1.png'),self.image_scale)
  1341.  
  1342.         running_frame1 = pygame.transform.scale(load_png('characters/player/running_frame1.png'),self.image_scale)
  1343.         running_frame2 = pygame.transform.scale(load_png('characters/player/running_frame2.png'),self.image_scale)
  1344.         running_frame3 = pygame.transform.scale(load_png('characters/player/running_frame3.png'),self.image_scale)
  1345.         running_frame4 = pygame.transform.scale(load_png('characters/player/running_frame4.png'),self.image_scale)
  1346.         running_frame5 = pygame.transform.scale(load_png('characters/player/running_frame5.png'),self.image_scale)
  1347.         running_frame6 = pygame.transform.scale(load_png('characters/player/running_frame6.png'),self.image_scale)
  1348.         running_frame7 = pygame.transform.scale(load_png('characters/player/running_frame7.png'),self.image_scale)
  1349.         running_frame8 = pygame.transform.scale(load_png('characters/player/running_frame8.png'),self.image_scale)
  1350.        
  1351.         self._images = [running_frame1, running_frame2, running_frame3, running_frame4, running_frame5, running_frame6, running_frame7, running_frame8]
  1352.  
  1353.         fps = 20 # 15
  1354.        
  1355.         # Track the time we started, and the time between updates.
  1356.         # Then we can figure out when we have to switch the image.
  1357.         self._start = pygame.time.get_ticks()
  1358.         self._delay = 1000 / fps
  1359.         self._last_update = 0
  1360.         self._frame = 0
  1361.  
  1362.         self.state_animation = 0 #0 = standing still, 1 = jumping, 2 = falling, 3 = running, 4 = hanging
  1363.         self.leftorright = 0 #0 = right, 1 = left
  1364.         self.variable = 0 #needed for collision check in animation()
  1365.  
  1366.         #for jump animation
  1367.         self.jump_variable = False
  1368.         self.jump_counter = 0
  1369.  
  1370.         # Call update to set our first image.
  1371.         self.update_animation(pygame.time.get_ticks())
  1372.  
  1373.     def update(self, milliseconds):
  1374.         self.handle_event(main_game.keyboard)
  1375.         self.velocity.x *= 0.7
  1376.  
  1377.         self.move_wait_variable_left -= 1
  1378.         self.move_wait_variable_right -= 1
  1379.  
  1380.         if self.collision_y == 0:
  1381.             if self.collision_x == 0:
  1382.                 if self.velocity.y > self.terminal_velocity:
  1383.                     self.velocity.y = self.terminal_velocity
  1384.             else:
  1385.                 if main_game.keyboard.is_down(K_DOWN):
  1386.                     self.velocity.y = self.sliding_down_wall_speed
  1387.                 elif self.velocity.y > self.terminal_velocity_wall:
  1388.                     #self.sound_channel_glide.play(self.sound_glide)
  1389.                     self.velocity.y = self.terminal_velocity_wall
  1390.         #else:
  1391.         #    self.sound_channel_glide.stop()
  1392.        
  1393.         super(Player, self).update(milliseconds)
  1394.  
  1395.         self.update_animation(pygame.time.get_ticks())
  1396.         self.update_sound()
  1397.  
  1398.     def update_sound(self):
  1399.         if self.sound_jump_variable > 4:
  1400.             self.sound_jump_variable = 0
  1401.  
  1402.         self.sound_landing_list.pop()
  1403.         self.sound_landing_list.insert(0,self.state_animation)
  1404.        
  1405.         if (self.sound_landing_list[0] == 0 or self.sound_landing_list[0] == 3 or self.sound_landing_list[0] == 4) and self.sound_landing_list[1] == 2:
  1406.             self.sound_channel_landing.play(self.sound_landing)
  1407.    
  1408.     def update_animation(self,t):
  1409.         if self.collision_y == 1:
  1410.             self.variable = 0
  1411.             if main_game.keyboard.is_down(K_LEFT) or main_game.keyboard.is_down(K_RIGHT):
  1412.                 self.state_animation = 3
  1413.             if not (main_game.keyboard.is_down(K_LEFT) or main_game.keyboard.is_down(K_RIGHT)) or (main_game.keyboard.is_down(K_LEFT) and main_game.keyboard.is_down(K_RIGHT)):
  1414.                 self.state_animation = 0
  1415.  
  1416.         if self.collision_y != 1:
  1417.             self.variable += 1
  1418.             if self.variable > 3:
  1419.                 if self.velocity.y < 0:
  1420.                     #jumping
  1421.                     self.state_animation = 1
  1422.                 if self.velocity.y > 0:
  1423.                     #falling
  1424.                     self.state_animation = 2
  1425.                
  1426.         if self.collision_x == 1 or self.collision_x == 2:
  1427.             self.state_animation = 4
  1428.  
  1429.         if self.collision_x == 2:
  1430.             self.leftorright == 0
  1431.             if self.collision_x == 1:
  1432.                 self.leftorright == 1
  1433.  
  1434.         if self.state_animation == 0:
  1435.             #standing still
  1436.             self.image = self.standing_frame1
  1437.             if self.leftorright == 1:
  1438.                 self.image = pygame.transform.flip(self.image, True, False)
  1439.         if self.state_animation == 1:
  1440.             #jumping
  1441.             if self.jump_variable == False:
  1442.                 self.jump_variable = True
  1443.                 self.jump_counter = 0
  1444.             self.image = self.jumping_frame1
  1445.             if 10 < self.jump_counter < 20:
  1446.                 self.image = self.jumping_frame2
  1447.             if self.jump_counter >= 20:
  1448.                 self.image = self.falling_frame1
  1449.             self.jump_counter += 1
  1450.            
  1451.             if self.leftorright == 1:
  1452.                 self.image = pygame.transform.flip(self.image, True, False)
  1453.         else:
  1454.             self.jump_variable = False
  1455.         if self.state_animation == 2:
  1456.             #falling
  1457.             self.image = self.falling_frame1
  1458.             if self.leftorright == 1:
  1459.                 self.image = pygame.transform.flip(self.image, True, False)
  1460.         if self.state_animation == 4:
  1461.             #falling
  1462.             self.image = self.hanging_frame1
  1463.             if self.leftorright == 1:
  1464.                 self.image = pygame.transform.flip(self.image, True, False)
  1465.         if self.state_animation == 3:
  1466.             if not self.sound_channel_walking.get_busy():
  1467.                 self.sound_channel_walking.play(self.sound_walking)
  1468.             if t - self._last_update > self._delay:
  1469.                 self._frame += 1
  1470.                 if self._frame >= len(self._images): self._frame = 0
  1471.                 self.image = self._images[self._frame]
  1472.                 self._last_update = t
  1473.                 if self.leftorright == 1:
  1474.                     self.image = pygame.transform.flip(self.image, True, False)
  1475.         else:
  1476.             if self.sound_channel_walking.get_busy():
  1477.                 self.sound_channel_walking.stop()
  1478.    
  1479.     def draw(self, milliseconds, surface):
  1480.         #Draw the object
  1481.         if self.is_static:
  1482.             surface.blit(self.image, self.position)
  1483.         else:
  1484.             relative_position = self.position - self.level.camera.position - self.image_offset
  1485.             surface.blit(self.image, relative_position)
  1486.        
  1487.     def handle_event(self, keyboard):
  1488.         if keyboard.is_down(K_LEFT):
  1489.             self.leftorright = 1
  1490.             if self.move_wait_variable_left < 0:
  1491.                 if self.velocity.x > -self.horizontal_terminal_velocity:
  1492.                     self.velocity.x -= self.horizontal_acceleration
  1493.         if keyboard.is_down(K_RIGHT):
  1494.             self.leftorright = 0
  1495.             if self.move_wait_variable_right < 0:
  1496.                 if self.velocity.x < self.horizontal_terminal_velocity:
  1497.                     self.velocity.x += self.horizontal_acceleration
  1498.         if keyboard.is_down(K_UP):
  1499.             self.velocity.y = -62.5
  1500.         if keyboard.is_down(K_SPACE):
  1501.             if self.jumped == False:
  1502.                 if self.collision_y == 1:
  1503.                     self.velocity.y = -self.jump_power
  1504.                     self.jumped = True
  1505.                     self.sound_channel_jump.play(self.sound_jump_list[self.sound_jump_variable])
  1506.                     self.sound_jump_variable += 1
  1507.                 elif self.collision_x == 1:
  1508.                     self.velocity.y = -self.jump_power
  1509.                     self.velocity.x = self.jump_power_side
  1510.                     self.jumped = True
  1511.                     self.move_wait_variable_left = self.move_wait_time
  1512.                     self.sound_channel_jump.play(self.sound_jump_list[self.sound_jump_variable])
  1513.                     self.sound_jump_variable += 1
  1514.                 elif self.collision_x == 2:
  1515.                     self.velocity.y = -self.jump_power
  1516.                     self.velocity.x = -self.jump_power_side
  1517.                     self.jumped = True
  1518.                     self.move_wait_variable_right = self.move_wait_time
  1519.                     self.sound_channel_jump.play(self.sound_jump_list[self.sound_jump_variable])
  1520.                     self.sound_jump_variable += 1
  1521.            
  1522.         if keyboard.is_up(K_SPACE) and (self.collision_y == 1 or self.collision_x == 1 or self.collision_x == 2):
  1523.             self.jumped = False
  1524.         if keyboard.is_down(K_LSHIFT):
  1525.             self.velocity.y = 1
  1526.         if keyboard.is_down(K_LEFT) and keyboard.is_down(K_RIGHT):
  1527.             pass
  1528.    
  1529.     def collision_response(self, obj, xvel, yvel):
  1530.         obj.collision_response()
  1531.  
  1532. class Debug(DrawableObj):
  1533.     """simple debug class that shows variables realtime on screen"""
  1534.     def __init__(self, level):
  1535.         super(Debug, self).__init__(level)
  1536.  
  1537.         pixel_art_font = "/Library/Fonts/pixel-art_1.ttf" # other option: "/Library/Fonts/pixel-art_2.ttf"
  1538.         self.font = pygame.font.Font(pixel_art_font, 15)
  1539.        
  1540.         self.text = "variable = "
  1541.         self.image = self.font.render(self.text, True, (255,255,255), (0,0,0))
  1542.  
  1543.     def update(self, milliseconds):
  1544.         self.text = "variable = " + str(main_game.clock.get_fps()) # put main_game.clock.get_fps() in the str() if you want the fps
  1545.         self.image = self.font.render(self.text, True, (255,255,255), (0,0,0))
  1546.  
  1547.  
  1548. class TextBox(DrawableObj):
  1549.     def __init__(self, level, position, width, text, scroll = False, font_size = 5 , font_path = "/Library/Fonts/pixel-art_1.ttf"):  # other option: "/Library/Fonts/pixel-art_2.ttf"
  1550.         super(TextBox, self).__init__(level)
  1551.  
  1552.         self.scale_factor = copy.copy(self.level.scale_factor)
  1553.  
  1554.         self.tag = "TextBox"
  1555.         self.position = position
  1556.         self.font = pygame.font.Font(font_path, int(font_size * self.scale_factor))
  1557.         self.is_static = False
  1558.         self.dialog = []
  1559.         self.width = int(width * self.scale_factor)
  1560.  
  1561.         self.timer = 0
  1562.  
  1563.         self.text_color = (0,0,0)
  1564.         self.background_color = (255,255,255)
  1565.         self.border_color = (0,0,0)
  1566.  
  1567.         self.border_width = int(1.25 * self.scale_factor)
  1568.         self.margin = int(2 * self.scale_factor)
  1569.         self.space_between_lines = int(0.75 * self.scale_factor)
  1570.  
  1571.         self.character_number = 0
  1572.         self.scroll = scroll
  1573.         self.done_with_scroll = False
  1574.  
  1575.         self.set_text(text)
  1576.  
  1577.     def set_text(self, text):
  1578.         if self.scroll == True:
  1579.             self.final_text = text
  1580.             self.text = ""
  1581.         else:
  1582.             self.final_text = text
  1583.             self.text = self.final_text
  1584.  
  1585.         self.make_box(self.width)
  1586.         self.make_text(self.width)
  1587.  
  1588.     def make_box(self, width = None):
  1589.         if width == None:
  1590.             width = self.width
  1591.        
  1592.         # calculate the height of the message box width the given width
  1593.         xpos = copy.copy(self.margin)
  1594.         ypos = copy.copy(self.margin)
  1595.         for word in self.final_text.split(" "):
  1596.             ren = self.font.render(word + " ", True, self.text_color)
  1597.             w = ren.get_width()
  1598.             if xpos > width - w:
  1599.                 ypos += ren.get_height() + self.space_between_lines
  1600.                 xpos = copy.copy(self.margin)
  1601.             xpos += w
  1602.  
  1603.         if ypos == self.margin:
  1604.             width = xpos
  1605.  
  1606.         height = ypos + ren.get_height() + self.margin
  1607.         self.image = pygame.Surface((width, height))
  1608.         self.scale = Vector(width, height)
  1609.         self.image.fill(self.background_color)
  1610.         if self.border_width != 0:
  1611.             pygame.draw.rect(self.image, self.border_color, (0, 0, width, height), self.border_width)
  1612.            
  1613.     def make_text(self, width = None):
  1614.         if width == None:
  1615.             width = self.width
  1616.            
  1617.         # actually draw the text on the created surface (above)
  1618.         xpos = copy.copy(self.margin)
  1619.         ypos = copy.copy(self.margin)
  1620.         for word in self.text.split(" "):
  1621.             ren = self.font.render(word + " ", True, self.text_color)
  1622.             w = ren.get_width()
  1623.             if xpos > width - w:
  1624.                 ypos += ren.get_height() + self.space_between_lines
  1625.                 xpos = copy.copy(self.margin)
  1626.             self.image.blit(ren, (xpos, ypos))
  1627.             xpos += w
  1628.  
  1629.     def update(self, milliseconds):
  1630.         if self.scroll == True:
  1631.             if self.character_number < len(self.final_text):
  1632.                 self.character_number += 0.5
  1633.                 if main_game.keyboard.is_down(K_SPACE):
  1634.                     self.character_number += 1.0
  1635.                 self.text = self.final_text[:int(self.character_number)]
  1636.                 self.make_box()
  1637.                 self.make_text()
  1638.             else:
  1639.                 self.done_with_scroll = True
  1640.            
  1641.  
  1642. class Button_dialog(Button):
  1643.     def __init__(self, level, scale, position, image_deselect, image_select, dialog_tree, node_to_go, commands, npc_owner):
  1644.         super(Button_dialog, self).__init__(level, scale, position, image_deselect, image_select)
  1645.  
  1646.         self.node_to_go = node_to_go
  1647.         self.dialog_tree = dialog_tree
  1648.         self.commands = commands
  1649.         self.npc_owner = npc_owner
  1650.        
  1651.     def clicked_action(self):
  1652.         if not self.commands == None:
  1653.             exec self.commands
  1654.            
  1655.         self.dialog_tree.load_node(self.node_to_go)
  1656.  
  1657. class Node_dialog(Menu):
  1658.     def __init__(self, level, dialog_tree, data_list, position, npc_owner):
  1659.         super(Node_dialog, self).__init__(level)
  1660.  
  1661.         self.scale_factor = copy.copy(self.level.scale_factor)
  1662.        
  1663.         self.npc_owner = npc_owner
  1664.         data_list = copy.copy(data_list)
  1665.         position = copy.copy(position)
  1666.  
  1667.         self.move_up_button = K_UP
  1668.         self.move_down_button = K_DOWN
  1669.         self.select_button = K_RETURN
  1670.  
  1671.         #print data_list
  1672.        
  1673.         self.parse_data_list(data_list)
  1674.  
  1675.         distance_between_choices = 10
  1676.        
  1677.         self.message_TextBox = TextBox(level, position, 50, self.message_text, True)
  1678.         choice_position = position + Vector(0, self.message_TextBox.scale.y)
  1679.        
  1680.         for choice in self.choice_list:
  1681.             choice_position += Vector(0, distance_between_choices) # + Vector(0,self.choice_list.index(choice))
  1682.             choice_TextBox = TextBox(level, copy.copy(choice_position), 50, choice[0])
  1683.             choice_position += Vector(0, choice_TextBox.scale.y)
  1684.  
  1685.             scale = choice_TextBox.scale
  1686.             commands = choice[2]
  1687.             image_deselect = choice_TextBox.image
  1688.  
  1689.             # make image select by changing background color
  1690.             choice_TextBox.background_color = (200,200,200)
  1691.             choice_TextBox.make_box()
  1692.             choice_TextBox.make_text()
  1693.             image_select = choice_TextBox.image
  1694.  
  1695.             node_to_go = choice[1]
  1696.        
  1697.             button_position = copy.copy(choice_TextBox.position)
  1698.            
  1699.             choice_button = Button_dialog(level, scale, button_position, image_deselect, image_select, dialog_tree, node_to_go, commands, self.npc_owner)
  1700.             choice_button.is_static = False
  1701.             self.buttons.append(choice_button)
  1702.        
  1703.         self.height = -(position.y - (button_position.y + choice_TextBox.scale.y))
  1704.         message_offset = Vector(0, 0)
  1705.         message_offset.x = -self.message_TextBox.scale.x/2 + self.npc_owner.scale.x/2
  1706.         message_offset.y = -self.message_TextBox.scale.y - (3.75 * self.scale_factor) + 0.2 # + 0.5 is against wobbling
  1707.         choices_offset = Vector(0, 0)
  1708.         choices_offset.x = -self.message_TextBox.scale.x/2 + self.npc_owner.scale.x/2 + (self.message_TextBox.scale.x - (9.5 * self.scale_factor))
  1709.         choices_offset.y = -self.message_TextBox.scale.y - (3.75 * self.scale_factor) + 0.2 # + 0.5 is against wobbling
  1710.        
  1711.         self.message_TextBox.position += message_offset
  1712.         for buttons in self.buttons:
  1713.             buttons.position += choices_offset
  1714.  
  1715.     def parse_data_list(self, data_list):
  1716.         self.message_text = data_list[0]
  1717.         self.choice_list = data_list
  1718.         self.choice_list.remove(self.message_text)
  1719.  
  1720.     def draw(self, milliseconds, surface):
  1721.         self.message_TextBox.draw(milliseconds, surface)
  1722.         if self.message_TextBox.done_with_scroll:
  1723.             super(Node_dialog, self).draw(milliseconds, surface)
  1724.  
  1725.     def update(self, milliseconds):
  1726.         self.message_TextBox.update(milliseconds)
  1727.         if self.message_TextBox.done_with_scroll:
  1728.             super(Node_dialog, self).update(milliseconds)
  1729.        
  1730.        
  1731. class Dialog_tree(DrawableObj):
  1732.     def __init__(self, level, npc_owner, dialog_file):
  1733.         super(Dialog_tree, self).__init__(level)
  1734.  
  1735.         self.tag = "dialog"
  1736.         self.npc_owner = npc_owner
  1737.         self.position = npc_owner.position
  1738.         self.parse_dialog_file(dialog_file)
  1739.         self.load_node(0)
  1740.  
  1741.     def load_node(self, node):
  1742.         if node == "end":
  1743.             self.level.list_update.remove(self)
  1744.             self.level.list_draw.remove(self)
  1745.         else:
  1746.             data_list = self.dialog[node]
  1747.             self.node = Node_dialog(self.level, self, data_list, self.position, self.npc_owner)
  1748.  
  1749.     def parse_dialog_file(self, dialog_file):
  1750.         #Using the PyYAML parser
  1751.         #It makes a dialog in this structure:
  1752.         # {'node_start':
  1753.         #               ["message_start", ['choice_1', node_to_be_sent_to_if_choice_1_is_chosen], ['choice_2', node_to_be_sent_to_if_choice_2_is_chosen]],
  1754.         #  'node_01':
  1755.         #               ["message", ['choice_1', node_to_be_sent_to_if_choice_1_is_chosen]]
  1756.         # }
  1757.         filename = "data/dialog/" + dialog_file #filename
  1758.         stream = open(filename, 'r')            #opening stream
  1759.         yaml_file = yaml.load(stream)           #loading stream
  1760.         #print yaml_file
  1761.  
  1762.         self.dialog = yaml_file
  1763.  
  1764.     def update(self, milliseconds):
  1765.         self.node.update(milliseconds)
  1766.  
  1767.         super(Dialog_tree, self).update(milliseconds)
  1768.  
  1769.     def draw(self, milliseconds, surface):
  1770.         self.node.draw(milliseconds, surface)
  1771.        
  1772.         super(Dialog_tree, self).draw(milliseconds, surface)
  1773.  
  1774. class Cloud(DrawableObj):
  1775.     def __init__(self, level, position, scale, image, layer = 0.7):
  1776.         super(Cloud, self).__init__(level)
  1777.         self.position = position
  1778.         self.scale = scale
  1779.         self.layer = layer
  1780.         self.is_static = False
  1781.        
  1782.         self.image = image
  1783.    
  1784.     def draw(self, milliseconds, surface):
  1785.         #Draw the object
  1786.         relative_position = self.position - self.level.camera.position
  1787.         relative_position *= self.layer
  1788.         surface.blit(self.image, relative_position)
  1789.  
  1790.  
  1791. #######################################################################################################################
  1792.  
  1793. pygame.init()
  1794. pygame.display.set_icon(pygame.image.load("data/images/icon_low.png"))
  1795. windowWidth, windowHeight = 854, 480 #854, 480 #640, 360 #750, 500 #1280, 720
  1796. window = pygame.display.set_mode((windowWidth,windowHeight)) # put ",pygame.FULLSCREEN" after "windowHeight)" for fulscreen
  1797. pygame.display.set_caption('First Game')
  1798. screen = pygame.display.get_surface()
  1799. pygame.mouse.set_visible(True)
  1800.  
  1801. #initialize Game()
  1802. main_game = Game()
  1803.  
  1804. #main function
  1805. def main():    
  1806.     main_game.go()
  1807.  
  1808. #import cProfile as profile
  1809. #profile.run('main()')
  1810. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement