Logo Search packages:      
Sourcecode: whichwayisup version File versions  Download package

game.py

import pygame
from pygame.locals import *
import os
import random

from locals import *

from player import Player
from spider import Spider
from particle import Particle
from level import Level
from sound import play_sound
from util import *
from variables import Variables, error_message

import data

keys_released = {}

#This function parses inputs from the keyboard and returns them as an array
def parse_inputs(joystick = None):
  keys = pygame.key.get_pressed()
  inputs = [False, False, False, False, False, False, False, 0.0]

  if keys[K_LEFT]:
    inputs[LEFT] = True

  if keys[K_RIGHT]:
    inputs[RIGHT] = True

  if keys[K_DOWN]:
    if keys_released["K_DOWN"]:
      inputs[DOWN] = True
    keys_released["K_DOWN"] = False
  else:
    keys_released["K_DOWN"] = True

  if keys[K_z]:
    inputs[UP] = True
    if keys_released["K_z"]:
      inputs[JUMP] = True
    keys_released["K_z"] = False
  else:
    keys_released["K_z"] = True

  if keys[K_p]:
    if keys_released["K_p"]:
      inputs[PAUSE] = True
    keys_released["K_p"] = False
  else:
    keys_released["K_p"] = True

  if keys[K_UP]:
    inputs[UP] = True
    if keys_released["K_UP"]:
      inputs[JUMP] = True
    keys_released["K_UP"] = False
  else:
    keys_released["K_UP"] = True

  if keys[K_F10]:
    inputs[SPECIAL] = True

  if joystick != None and joystick.get_numbuttons() > 1:   # Parse joystick input

    axis0 = joystick.get_axis(0)

    if axis0 < -0.1:
      inputs[LEFT] = True
      inputs[ANALOG] = -axis0

    if axis0 > 0.1:
      inputs[RIGHT] = True
      inputs[ANALOG] = axis0

    if joystick.get_button(0):
      inputs[UP] = True
      if keys_released["J_B0"]:
        inputs[JUMP] = True
      keys_released["J_B0"] = False
    else:
      keys_released["J_B0"] = True

    if joystick.get_button(1):
      if keys_released["J_B1"]:
        inputs[DOWN] = True
      keys_released["J_B1"] = False
    else:
      keys_released["J_B1"] = True

  return inputs


def run(screen, level_name = "w0-l0", score_mod = 0, score = None, joystick = None):
  done = False
  objects = []
  particles = []

  if score == None:
    score = Score(0)

  try:
    level = Level(screen, level_name)
  except:
    error_message("Couldn't open level '" + level_name + "'")
    return END_QUIT

  objects = level.get_objects()
  player = level.get_player()
  objects.append(player)

  player.life = score.life

  clock = pygame.time.Clock()

  end_trigger = END_NONE
  scripted_event_on = False

  #There's no music at the moment:
  #pygame.mixer.music.load( data.filepath(os.path.join("music", "music.ogg")) )
  #pygame.mixer.music.play(-1)

  scripted_events = level.get_scripted_events()
  current_scripted_event = None

  scripted_event_trigger = TRIGGER_LEVEL_BEGIN

  flip_wait = -1

  keys_released["K_z"] = True
  keys_released["K_p"] = True
  keys_released["K_DOWN"] = True
  keys_released["K_UP"] = True
  keys_released["J_B0"] = True
  keys_released["J_B1"] = True

  fading = True
  fade_target = FADE_STATE_NONE
  Util.fade_state = FADE_STATE_BLACK

  paused = False

  while (end_trigger == END_NONE or fading):

    add_time = True #The ingame time counter toggle - this is False when there's a scripted event

    # Pygame event and keyboard input processing
    for event in pygame.event.get():
      if event.type == QUIT:
        end_trigger = END_HARD_QUIT
      if (event.type == KEYDOWN and event.key == K_ESCAPE):
        end_trigger = END_QUIT
        if fading == False:
          fading = True
        fade_target = FADE_STATE_HALF

    inputs = parse_inputs(joystick)

    trigger = TRIGGER_NONE

    if scripted_event_on:
      if inputs[JUMP] or inputs[DOWN]:
        cleared = True

    moved = False

    #Translates input to commands to the player object if there isn't something special going on
    if not scripted_event_on and not level.flipping and not fading and not paused and player.current_animation != "dying":
      if inputs[LEFT]:
        player.move((-PLAYER_MAX_ACC, 0))
        moved = True

      if inputs[RIGHT]:
        player.move((PLAYER_MAX_ACC, 0))
        moved = True

      if inputs[JUMP]:
        if (player.on_ground):
          count = 0
          while (count < 5):
            count += 1
            particles.append(Particle(screen, 10, player.rect.centerx - player.dx / 4 + random.uniform(-3, 3), player.rect.bottom, -player.dx * 0.1, -0.5, 0.3, level.dust_color, 4))
          player.jump()

          #The blobs always try to jump when the player jumps

          for o in objects:
            if o.itemclass == "blob":
              o.jump()

      if inputs[UP] and not player.on_ground:
        player.jump()

      if inputs[DOWN]:
        pick_up_item = level.pick_up(player.x, player.y)
        if pick_up_item != None:
          play_sound("coins")
          player.inventory.append(pick_up_item)
          scripted_event_trigger = pick_up_item.itemclass

        if flip_wait == -1:
          trigger = level.trigger(player.x, player.y)

      #Debug command for flipping:
      if inputs[SPECIAL]:
        trigger = TRIGGER_FLIP

    if inputs[PAUSE] and player.current_animation != "dying":
      paused = not paused
      #fading = True
      #if paused:
      #  fade_target = FADE_STATE_HALF
      #if not paused:
      #  fade_target = FADE_STATE_NONE

    #Decelerates the player, if he doesn't press any movement keys or when he is dead and on the ground
    if ((player.current_animation != "dying" and not moved) or (player.current_animation == "dying" and player.on_ground)) and not paused:
      player.dec((PLAYER_MAX_ACC, 0))

    if trigger == TRIGGER_FLIP:
      if flip_wait == -1:
        flip_wait = 0
        play_sound("woosh")

    if flip_wait != -1 and not paused:
      flip_wait += 1
      if flip_wait > FLIP_DELAY:
        flip_direction = CLOCKWISE
        if player.y > player.x and player.y > 240:
          flip_direction = COUNTER_CLOCKWISE
        flip_wait = -1
        level.flip(flip_direction)
        for o in objects:
          o.flip(flip_direction)
        for p in particles:
          p.flip()

    #Dust effect rising from the character's feet:

    if (player.current_animation == "walking"):
      particles.append(Particle(screen, 10, player.rect.centerx - player.dx / 2 + random.uniform(-2, 2), player.rect.bottom, -player.dx * 0.1, 0.1, 0.3, level.dust_color))

    #Updating level and objects:

    if scripted_event_trigger == TRIGGER_NONE:
      scripted_event_trigger = level.update()
    else:
      level.update()

    #Objects are only updated when there's not a scripted event going on

    if not scripted_event_on and not fading and not paused:
      for o in objects:
        if o.dead and o.itemclass != "player":
          objects.remove(o)
          continue
        new_particles = o.update(level)
        if o.itemclass == "projectile":
          if player.rect.collidepoint(o.x, o.y) and o.current_animation == "default":
            new_particles = player.take_damage(o.damage)
            o.die()
        if type(new_particles) == list: #Sometimes the type of the return value is int (hackity hack)
          if new_particles != None:
            for p in new_particles:
              particles.append(p)

      for p in particles:
        p.update()
        if p.dead:
          particles.remove(p)

    #Rendering level - background and tiles
    level.render()

    #Rendering objects and particles
    for o in objects:
      if o.itemclass == "player":
        o.render(None, None, (fading or paused) )
      else:
        o.render(None, None, (scripted_event_on or fading or paused) )
      #On special conditions the animations aren't updated. The player is updated on a scripted event, others are not.

    for p in particles:
      p.render()

    #Rendering GUI on top of everything else:

    render_gui(screen, player.life, score.score, (5, 5))

    # Scripted event triggering:

    if scripted_event_trigger != TRIGGER_NONE:
      if player.on_ground:
        for ev in scripted_events:
          if ev.trigger_type == scripted_event_trigger:
            scripted_event_on = True
            current_scripted_event = ev
            current_scripted_event_element = None
            text = None
            phase = 0
            cleared = False        # Clearing dialog boxes
            player.dy = 0
            player.dx = 0
            player.update()
            scripted_event_trigger = TRIGGER_NONE

    # Scripted event processing:

    if scripted_event_on and not fading and not paused:
      add_time = False
      if (current_scripted_event_element == None) or (current_scripted_event_element.finished):

        current_scripted_event_element = current_scripted_event.next_element()

        if current_scripted_event_element.event_type == "end":
          scripted_event_on = False
          current_scripted_event_element = None

      else:

        if not Variables.vdict["dialogue"]:  #Dialogue skipping
          while (current_scripted_event_element.event_type == "dialogue" or current_scripted_event_element.event_type == "player"):
            current_scripted_event_element.finished = True
            current_scripted_event_element = current_scripted_event.next_element()
            if current_scripted_event_element.event_type == "end":
              current_scripted_event_element.finished = True

        if current_scripted_event_element.event_type == "wait":
          current_scripted_event_element.finished = True
        elif current_scripted_event_element.event_type == "dialogue":
          if text == None:
            text = current_scripted_event_element.text
            phase = 0
          phase = render_text_dialogue(screen, text, phase)
          if (phase == -1) and cleared:
            current_scripted_event_element.finished = True
            phase = 0
            cleared = False
            text = None
          if cleared:
            phase = -1
            cleared = False
        elif current_scripted_event_element.event_type == "player":
          if current_scripted_event_element.text == "orientation":
            player.orientation = current_scripted_event_element.orientation
          current_scripted_event_element.finished = True
        elif current_scripted_event_element.event_type == "change_level":
          end_trigger = END_NEXT_LEVEL
          score.score += (5 + score_mod) * ((player.life + 4) / 5 + 12)
          score.levels += 1
          current_scripted_event_element.finished = True
          fading = True
          fade_target = FADE_STATE_BLACK

    if player.dead:
      end_trigger = END_LOSE
      fading = True
      fade_target = FADE_STATE_HALF

    if (fading or Util.fade_state != FADE_STATE_NONE):
      add_time = False
      if fade_to_black(screen, fade_target):
        #Fading finished
        fading = False

    #And finally, rendering the pause button even on top of the fading:

    if paused:
      add_time = False
      render_text_dialogue(screen, "Game paused. Press P to continue.", -1, "p")

    if(add_time):
      score.time += 1

    #Display, clock

    pygame.display.flip()

    clock.tick(FPS)

  #Main game loop finished

  score.life = player.life #To make the player's health stay the same to the next level

  return end_trigger

Generated by  Doxygen 1.6.0   Back to index