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

menu_2d.py

# -*- coding: utf-8 -*-
# Balazar in the Rancid Skull Dungeon
# Copyright (C) 2008 Jean-Baptiste LAMY
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys, os, os.path, time, atexit
import pygame, pygame.image, pygame.color, pygame.mixer
from pygame.locals import *

import balazar3.globdef as globdef
import balazar3.game    as game
from balazar3.driver_2d import BACKBUFFER, SCREEN_RECT, FONT_MODEL

BACKGROUND  = None
FOCUS       = None
MENU        = None
DIRTY_RECTS = []

X0 = (SCREEN_RECT.width - 640) / 2

class Menu(object):
  def __init__(self, menu_items):
    self.menu_items = menu_items
    self.focus      = 0
    x = 160 + X0
    y = 240
    for menu_item in menu_items:
      menu_item.set_xy(x, y)
      y += 40
    self.draw()
    
  def draw(self):
    DIRTY_RECTS.append(BACKBUFFER.blit(BACKGROUND, (130 + X0, 240), (130, 240, 640 - 130, 480 - 240)))
    for menu_item in self.menu_items:
      menu_item.draw()
    BACKBUFFER.blit(FOCUS, (130 + X0, 240 + self.focus * 40))
    
  def draw_focus(self):
    DIRTY_RECTS.append(BACKBUFFER.blit(BACKGROUND, (130 + X0, 240), (130, 240, 30, 480 - 240)))
    BACKBUFFER.blit(FOCUS, (130 + X0, 240 + self.focus * 40))
    
  def begin_round(self):
    events = pygame.event.get()
    for event in events:
      if   event.type == KEYDOWN        : self.key_down(event.key, event.unicode)
      elif event.type == MOUSEBUTTONDOWN: self.click   (*event.pos)
      
  def key_down(self, key, unicode):
    if   key == K_DOWN  : self.focus = (self.focus + 1) % len(self.menu_items); self.draw_focus()
    elif key == K_UP    : self.focus = (self.focus - 1) % len(self.menu_items); self.draw_focus()
    elif key == K_ESCAPE: self.menu_items[-1].action()
    else:
      self.menu_items[self.focus].key_down(key, unicode)
      
  def click(self, x, y):
    if (x > 130 + X0) and (y > 200):
      self.focus = max(0, min(len(self.menu_items) - 1, int(round((y - 240 - 15) / 40.0))))
      self.draw_focus()
      self.menu_items[self.focus].click(x, y)
      
    
class MenuItem(object):
  def __init__(self, text):
    self.text   = text
    self.label  = FONT_MODEL.render_to_image(self.text)
    
  def set_xy(self, x, y):
    self.x = x
    self.y = y
    
  def draw(self):
    BACKBUFFER.blit(self.label, (self.x, self.y))

class MenuAction(MenuItem):
  def __init__(self, text, action = None):
    MenuItem.__init__(self, text)
    self.action = action
    
  def key_down(self, key, unicode):
    if key in (K_SPACE, K_RETURN, K_LSHIFT, K_RSHIFT): self.action()
  
  def click(self, x, y): self.action()

class MenuInput(MenuItem):
  def __init__(self, text, var):
    self.base_text = text
    self.var       = var
    MenuItem.__init__(self, "%s %s" % (self.base_text, getattr(globdef, var)))
    
  def set_value(self, s):
    if isinstance(s, unicode): s = s.encode("latin")
    setattr(globdef, self.var, s)
    MenuItem.__init__(self, "%s %s" % (self.base_text, s))
    MENU.draw()
    
  def key_down(self, key, char):
    if (key == K_BACKSPACE) or (key == K_DELETE): self.set_value(unicode(getattr(globdef, self.var))[:-1])
    elif char                                   : self.set_value(unicode(getattr(globdef, self.var)) + char)
    
  def click(self, x, y): pass
  
class MenuIntInput(MenuInput):
  def set_value(self, s):
    try:
      s = int(s)
    except: return
    
    setattr(globdef, self.var, s)
    MenuItem.__init__(self, "%s %s" % (self.base_text, s))
    MENU.draw()
    
class MenuToggle(MenuItem):
  def __init__(self, text, var):
    self.base_text = text
    self.var       = var
    if getattr(globdef, var): text = u"%s : %s" % (text, _(u"yes"))
    else:                     text = u"%s : %s" % (text, _(u"no" ))
    MenuItem.__init__(self, text)

  def toggle(self):
    value = not getattr(globdef, self.var)
    setattr(globdef, self.var, value)
    if value: text = u"%s : %s" % (self.base_text, _(u"yes"))
    else:     text = u"%s : %s" % (self.base_text, _(u"no" ))
    MenuItem.__init__(self, text)
    MENU.draw()
    
  def key_down(self, key, unicode):
    if key in (K_SPACE, K_RETURN, K_LSHIFT, K_RSHIFT): self.toggle()
  
  def click(self, x, y): self.toggle()

class MenuStartServer(MenuItem):
  def __init__(self):
    if game.SERVER_PID: MenuItem.__init__(self, _(u"Stop server (server is running)"))
    else:               MenuItem.__init__(self, _(u"Start server"))
    
  def toggle(self):
    if game.SERVER_PID: game.kill_server()
    else:               game.start_server_spawn()
    self.__init__()
    MENU.draw()
    
  def key_down(self, key, unicode):
    if key in (K_SPACE, K_RETURN, K_LSHIFT, K_RSHIFT): self.toggle()
  
  def click(self, x, y): self.toggle()


def message(text):
  global MENU
  MENU = Menu([
    MenuAction(text, lambda : None),
    MenuAction(_(u"Back"), main_menu),
    ])
  
def main_menu():
  if game.SERVER_PID: server_menu_text = _(u"Local server... (server is running)")
  else:               server_menu_text = _(u"Local server...")
  global MENU
  MENU = Menu([
    MenuAction(_(u"Start single-player game..."), single_menu),
    MenuAction(_(u"Join multi-player game..."), multi_menu),
    MenuAction(server_menu_text, server_menu),
    MenuAction(_(u"Preferences..."), preference_menu),
    MenuAction(_(u"Exit"), sys.exit),
    ])

  
def single_menu():
  if os.path.exists(os.path.join(globdef.SAVED_GAME_DIR, globdef.SINGLE_LOGIN)): has_reload = 1
  else:                                                                          has_reload = 0
  
  global MENU
  MENU = Menu([
    MenuAction(_(u"Reload %s") % globdef.SINGLE_LOGIN, lambda: _start_single(globdef.SINGLE_LOGIN))] * has_reload +
    [
    MenuAction(_(u"New game..."), new_single_menu),
    MenuAction(_(u"Load..."), load_menu),
    MenuAction(_(u"Back"), main_menu),
    ])

  
def load_menu(start_at = 0):
  if os.path.exists(globdef.SAVED_GAME_DIR): player_names = [dirname for dirname in os.listdir(globdef.SAVED_GAME_DIR) if dirname != "_server"]
  else:                                      player_names = []
  player_names.sort()
  nb = 4
  if start_at + nb + 1 >= len(player_names): has_next = 0; nb += 1
  else:                                      has_next = 1
  
  global MENU
  MENU = Menu([MenuAction(_(u"Load %s" % player_name), lambda player_name = player_name: _start_single(player_name)) for player_name in player_names[start_at : start_at + nb]] +
              [MenuAction(_(u"Next..."), lambda: load_menu(start_at + nb))] * has_next +
              [MenuAction(_(u"Back"), main_menu)])
 
 
def new_single_menu():
  if os.path.exists(globdef.SAVED_GAME_DIR): player_names = [dirname for dirname in os.listdir(globdef.SAVED_GAME_DIR) if dirname != "_server"]
  else:                                      player_names = []
  try:
    import getpass
    globdef.SINGLE_LOGIN = base_login = getpass.getuser()
  except:
    globdef.SINGLE_LOGIN = base_login = "Player"
    
  i = 1
  while globdef.SINGLE_LOGIN in player_names:
    i += 1
    globdef.SINGLE_LOGIN = "%s%s" % (base_login, i)
    
  global MENU
  MENU = Menu([
    MenuAction(_(u"Create"), lambda: _start_single(globdef.SINGLE_LOGIN)),
    MenuInput (_(u"Player name:"), "SINGLE_LOGIN"),
    MenuAction(_(u"Back"), main_menu),
    ])
  
def multi_menu():
  if game.SERVER_PID: not_has_server = 0
  else:               not_has_server = 1
  
  global MENU
  MENU = Menu([
    MenuAction  (_(u"Join"), _start_multi),
    MenuInput   (_(u"Player name:"), "CLIENT_LOGIN"),
    MenuInput   (_(u"Password:"), "CLIENT_PASSWORD")] +
   [MenuInput   (_(u"Host:"), "CLIENT_HOST"),
    MenuIntInput(_(u"Port:"  ), "CLIENT_PORT") ] * not_has_server +
   [MenuAction(_(u"Back"), main_menu),
    ])
  
def server_menu():
  global MENU
  MENU = Menu([
    MenuStartServer(),
    MenuInput   (_(u"Host:"), "SERVER_HOST"),
    MenuIntInput(_(u"Port:"  ), "SERVER_PORT"),
    MenuAction(_(u"Erase server data"), game.erase_server_data),
    MenuAction(_(u"Back"), main_menu),
    ])
  
def preference_menu():
  global MENU
  MENU = Menu([
    MenuInput (_(u"Save dir:") + u"\n  ", "SAVED_GAME_DIR"),
    MenuToggle(_(u"Zaurus-optimized mode"), "ZAURUS"),
    MenuAction(_(u"Exit (you need to restart the game)"), sys.exit),
    ])

import balazar3.tofu as tofu
import balazar3.game 

class StartSingleException(Exception): pass
class StartMultiException (Exception): pass

def _start_single(player_name):
  globdef.SINGLE_LOGIN = player_name
  raise StartSingleException

def _start_multi(): raise StartMultiException

atexit.register(globdef.save_config)

def start():
  menu = None
  while 1:
    try:
      start_menu(menu)
    except StartSingleException:
      menu = None
      game.start_single()
    except StartMultiException :
      import socket
      menu = None
      try: game.start_multi()
      except socket.error:
        message(repr(sys.exc_info()[1]))
        menu = MENU
    
      
def start_menu(menu):
  global BACKGROUND, FOCUS, MENU, DIRTY_RECTS
  BACKGROUND = pygame.image.load(os.path.join(globdef.APPDIR, "sprites", "titre.png")).convert()
  FOCUS      = FONT_MODEL.render_to_image(u"->")
  DIRTY_RECTS.append(BACKBUFFER.blit(BACKGROUND, (X0, 0)))
  if menu: menu.draw()
  else:    main_menu()
  
  while 1:
    MENU.begin_round()
    
    time.sleep(0.03)
    if DIRTY_RECTS:
      pygame.display.update(DIRTY_RECTS)
      DIRTY_RECTS = []


Generated by  Doxygen 1.6.0   Back to index