# -*- coding: latin-1 -*- # Balazar # Copyright (C) 2003-2005 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 2 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, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import os, os.path, time, random import tofu import soya, soya.opengl as soyaopengl, soya.sdlconst as sdlconst, soya.tofu4soya, soya._soya, soya.widget as widget import balazar, balazar.sound, balazar.base as base, balazar.globdef as globdef, balazar.controller as controller from balazar.character import _P, _V def init(): if not soya.inited: soya.init(title = "Balazar", width = globdef.SCREEN_WIDTH, height = globdef.SCREEN_HEIGHT, fullscreen = globdef.FULLSCREEN) soya.set_quality(globdef.QUALITY) SHADER_DEFAULT_MATERIAL = soya.Material.get("shader") SHADER_DEFAULT_MATERIAL.filename = "__SHADER_DEFAULT_MATERIAL__" soya._soya._set_shader_default_material(SHADER_DEFAULT_MATERIAL) widget.big_font = widget.default_font widget.default_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 18, 15) # Display the splash screen soya.set_root_widget(widget.Image(None, soya.Material.get("splash"), resize_style = ("maximize",))) soya.render() soya.root_widget = None class Idler(soya.tofu4soya.Idler): def __init__(self, scene = None): soya.tofu4soya.Idler.__init__(self, scene) self.big_round_count = 0 self.min_frame_duration = globdef.MIN_FRAME_DURATION def begin_round(self): if globdef.WAIT_FOR_SOUND: time.sleep(0.00001) soya.tofu4soya.Idler.begin_round(self) if self.big_round_count == 0: self.big_round_count = 15 for scene in self.scenes: scene.big_round() else: self.big_round_count -= 1 class Scene(soya.World): def __init__(self): soya.World.__init__(self) self.camera = None from balazar.weather import WeatherAtmosphere self.atmosphere = WeatherAtmosphere(self) def advance_time(self, proportion): soya.World.advance_time(self, proportion) self.atmosphere.advance_time(proportion) def begin_round(self): soya.World.begin_round(self) self.atmosphere.begin_round() def big_round(self): self.atmosphere.big_round() for child in self.children: if hasattr(child, "big_round"): child.big_round() def check_path(d): if not os.path.exists(d): os.mkdir(d) def set_path_current(player_filename, enable): check_path(globdef.SAVED_GAME_DIR) d = os.path.join(globdef.SAVED_GAME_DIR, player_filename) check_path(d) check_path(os.path.join(d, "players")) check_path(os.path.join(d, "levels")) d = os.path.join(globdef.SAVED_GAME_DIR, player_filename) if enable: tofu.path.insert(0, d) else: tofu.path.remove(d) def start_single(login, password = ""): globdef.mode = "--single" scene = Scene() Idler(scene) init() try: import tofu.single set_path_current(login, 1) r = tofu.single.serve_forever(login = login, password = password) finally: set_path_current(login, 0) if r == "paused": while 1: time.sleep(0.1) for event in soya.process_event(): if (event[0] == sdlconst.KEYDOWN) or (event[0] == sdlconst.JOYBUTTONDOWN): break else: continue break return start_single(login, password) balazar.sound.end_music() return r def start_server(): globdef.mode = "--server" scene = Scene() Idler(scene) if globdef.SERVER_VIEW: init() soya.set_root_widget(ServerView(scene)) try: import tofu.server set_path_current("_server", 1) r = tofu.server.serve_forever() finally: set_path_current("_server", 0) return r def start_client(hostname, login, password = "", port = 6900): globdef.mode = "--client" scene = Scene() Idler(scene) init() import tofu.client r = tofu.client.serve_forever(hostname, login = login, password = password) if r == "paused": while 1: time.sleep(0.1) for event in soya.process_event(): if (event[0] == sdlconst.KEYDOWN) or (event[0] == sdlconst.JOYBUTTONDOWN): break else: continue break return start_client(hostname, login, password = "", port = 6900) balazar.sound.end_music() return r class GameInterface(soya.tofu4soya.GameInterface): def __init__(self, login, password = ""): soya.tofu4soya.GameInterface.__init__(self) self.login = login self.password = password self.hero = None self.traveling = None self.camera = soya.IDLER.scenes[0].camera = soya.TravelingCamera(soya.IDLER.scenes[0]) self.camera.back = 100.0 self.camera.speed = 0.4 #self.camera.add_traveling(soya.FixTraveling(soya.Point(), soya.Vector(None, 0.0, 0.0, -1.0))) self.camera.add_traveling(soya.FixTraveling(self.camera, soya.Vector(self.camera, 0.0, 0.0, -1.0))) balazar.sound.init(self.camera) self.root_widget = widget.Group() self.root_widget.add(self.camera) soya.set_root_widget(self.root_widget) soya.widget.FPSLabel(self.root_widget) self.life_bar = LifeBar (self.root_widget) #self.map_viewer = MapViewer(self.root_widget) self.active_widgets = [] self.current_discussion = None self.current_country = None def network_error(self, reason): soya.IDLER.stop(reason) def ready(self, notifier): soya.tofu4soya.GameInterface.ready(self, notifier) self.notifier.login_player(self.login, self.password) def close_all_widgets(self): for w in self.active_widgets: w.destroy() class ServerView(soya.TravelingCamera): def __init__(self, parent = None): soya.TravelingCamera.__init__(self, parent) self.back = 100.0 self.speed = 0.4 self.set_mobile(None) def begin_round(self): soya.TravelingCamera.begin_round(self) for event in soya.process_event(): if event[0] == sdlconst.KEYDOWN: if event[1] == sdlconst.K_TAB: mobiles = [i for i in self.parent.recursive() if isinstance(i, balazar.character.Character)] if mobiles: if self.mobile in mobiles: i = mobiles.index(self.mobile) else: i = -1 if i + 1 >= len(mobiles): self.set_mobile(None) else: self.set_mobile(mobiles[i + 1]) def set_mobile(self, mobile): self.mobile = mobile if mobile: self.add_traveling(soya.ThirdPersonTraveling(mobile, soya.Vector(None, 0.0, 0.0, 2.0))) else: self.add_traveling(soya.FixTraveling(soya.Point(), soya.Vector(None, 0.0, 0.0, -1.0))) class ActiveWidget: def __init__(self): tofu.GAME_INTERFACE.active_widgets.insert(0, self) def key_down(self, key): """Returns 1 if the event has been consumed""" def destroy(self): try: self.master.remove(self) except: pass try: tofu.GAME_INTERFACE.active_widgets.remove(self) except: pass class FocusableWidget(ActiveWidget): def __init__(self): self.focus = 0 ActiveWidget.__init__(self) def set_focus(self, focus, play_sound = 1): self.focus = focus if focus and play_sound: balazar.sound.play("menu2.wav") def key_down(self, key): if (key == controller.CONTROL_QUIT ) and self.focus: self.set_focus(0) elif(key == controller.CONTROL_JUMP ) and self.focus: self.set_focus(0) elif(key == controller.CONTROL_STRIKE) and self.focus: self.set_focus(0) elif(key == controller.CONTROL_ITEM ) and self.focus: self.set_focus(0) elif key == controller.CONTROL_MENU: focusable = [widget for widget in tofu.GAME_INTERFACE.active_widgets if isinstance(widget, FocusableWidget)] if self is focusable[0]: for widget in focusable: if widget.focus: break else: self.set_focus(1) return 1 else: preceding = focusable[focusable.index(self) - 1] if preceding.focus: preceding.set_focus(0) self .set_focus(1) return 1 if (self is focusable[-1]) and self.focus: self.set_focus(0) # Do NOT return 1, => open inventory class Bubble(widget.Widget, FocusableWidget): def __init__(self, master = None, character = None, inner_widget = None): for w in tofu.GAME_INTERFACE.active_widgets: if isinstance(w, Bubble): w.destroy() FocusableWidget.__init__(self) widget.Widget.__init__(self, master) self.character = character self.widget = inner_widget inner_widget.master = self inner_widget.resize(0, 0, 500, 600) self.width = int(inner_widget.width + 28) self.height = int(inner_widget.height + 20) self.top = 0 self.position = soya.Point() self.focus = 0 self.visible = 1 tofu.GAME_INTERFACE.current_discussion = self def destroy(self): if isinstance(self.widget, DiscussionWidget): if isinstance(self.widget.discussion, AutoDiscussion): self.widget.discussion.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_END_DISCUSSING, self.widget.discussion.character)) tofu.GAME_INTERFACE.current_discussion = None try: tofu.GAME_INTERFACE.active_widgets.remove(self.widget) except: pass FocusableWidget.destroy(self) def set_focus(self, focus, play_sound = 1): FocusableWidget.set_focus(self, focus, play_sound) self.widget.set_focus(focus) def check(self): return self.widget.check() def resize(self, parent_left, parent_top, parent_width, parent_height): pass def mouse_moved(self, x, y): return self.widget.mouse_moved( x, y) or ((self.left <= x <= self.left + self.width) and (self.top <= y <= self.top + self.height)) def mouse_down (self, button, x, y): return self.widget.mouse_down (button, x, y) or self.mouse_moved(x, y) def mouse_up (self, button, x, y): return self.widget.mouse_up (button, x, y) or self.mouse_moved(x, y) def key_down (self, key ): if self.focus: return self.widget.key_down(key) or FocusableWidget.key_down(self, key) return FocusableWidget.key_down(self, key) def widget_begin_round (self ): self.widget.widget_begin_round() def widget_advance_time(self, proportion): self.widget.widget_advance_time(proportion) def widget_end_round (self ): self.widget.widget_end_round() def render(self): if not self.visible: return self.position.__init__(self.character, 0.0, 2.6, 0.0) self.position.convert_to(tofu.GAME_INTERFACE.camera) if self.position.z > 0.0: return self.position.__init__(self.character, 0.0, 2.6, 0.0) x, y = tofu.GAME_INTERFACE.camera.coord3d_to_2d(self.position) #if x < tofu.GAME_INTERFACE.camera.width / 2 - 30: self.left = 0 #else: self.left = tofu.GAME_INTERFACE.camera.width - self.width self.left = tofu.GAME_INTERFACE.camera.width - self.width self.top = 0 content_left = self.left + 14 content_top = self.top + 5 soyaopengl.glPushMatrix() soyaopengl.glTranslatef(self.left, self.top, 0.0) soya.DEFAULT_MATERIAL.activate() soyaopengl.glEnable(soyaopengl.GL_BLEND) if self.focus: soyaopengl.glColor4f(1.0, 1.0, 1.0, 1.0) else: soyaopengl.glColor4f(1.0, 1.0, 1.0, 0.5) soyaopengl.glBegin(soyaopengl.GL_POLYGON) soyaopengl.glVertex2i(0, 0) if self.left == 0: soyaopengl.glVertex2i(0 , self.height) soyaopengl.glVertex2i(self.width - 15, self.height) soyaopengl.glVertex2i(self.width - 5 , self.height - 5) soyaopengl.glVertex2i(self.width , self.height - 15) else: soyaopengl.glVertex2i(0 , self.height - 15) soyaopengl.glVertex2i(5 , self.height - 5) soyaopengl.glVertex2i(15 , self.height) soyaopengl.glVertex2i(self.width, self.height) soyaopengl.glVertex2i(self.width, 0) soyaopengl.glEnd() soyaopengl.glBegin(soyaopengl.GL_TRIANGLES) soyaopengl.glVertex2i(int(self.width * 0.4), self.height) soyaopengl.glVertex2i(int(self.width * 0.3), self.height) soyaopengl.glColor4f(1.0, 1.0, 1.0, 0.1) soyaopengl.glVertex2i(int(round(x - self.left)), int(round(max(y, self.height + 20) - self.top))) soyaopengl.glEnd() soyaopengl.glDisable(soyaopengl.GL_BLEND) soyaopengl.glTranslatef(14.0, 5.0, 0.0) self.widget.render() soyaopengl.glPopMatrix() VOICE = None class Discussion(object): def __init__(self, character, reply, text = u"", condition = 1, action = None, check = None, source = None, voice = None, choices = ()): self.character = character self.reply = reply self.text = text self.condition = condition self.action = action self.check = check self.source = source or character self.voice = voice if not callable(choices): self.set_choices(choices) else: self._choices = choices def activate(self, focus = 0): if self.action: self.action() if self.text: global VOICE if VOICE: VOICE.stop() try: VOICE = sound.play(self.voice or (u"voice_%s.ogg" % " ".join(self.text.split()[:4])).encode("latin")) except: pass # No voice (for this discussion, or at all) discussion_widget = Bubble(soya.root_widget, self.character or tofu.GAME_INTERFACE.hero, DiscussionWidget(self)) if focus: discussion_widget.set_focus(1, 0) if discussion_widget.widget.choices: discussion_widget.widget.selection = discussion_widget.widget.choices[0][0] def is_valid(self): if callable(self.condition): return self.condition() return self.condition def set_choices(self, choices): self._choices = [] for choice in choices: if choice.is_valid(): if self._choices and (self._choices[-1].reply == choice.reply): # Same text => replace self._choices[-1] = choice else: self._choices.append(choice) if self.text and not self._choices: self.set_choices([Discussion(self.character, _("Ok"))]) def get_choices(self): if callable(self._choices): self.set_choices(self._choices()) return self._choices choices = property(get_choices) class AutoDiscussion(object): def __init__(self, hero, character, reply_key, text_key, check = None, source = None, voice = None): self.hero = hero self.character = character self.reply_key = reply_key self.reply = _(reply_key) self.text_key = text_key self.text = _(text_key) self.check = check self.source = source or character self.voice = voice self._choices = None def activate(self, focus = 0): if "_combat_" in self.text_key: self.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_DISCUSSION, self.character, "combat")) action = getattr(self.character, "discussion_action_%s" % self.text_key, None) if action: #action(self.hero) self.hero.doer.do_action(balazar.character.DiscussionAction(balazar.character.ACTION_DISCUSSION, self.character, self.text_key)) if self.text: global VOICE if VOICE: VOICE.stop() try: VOICE = sound.play(self.voice or (u"voice_%s.ogg" % " ".join(self.text.split()[:4])).encode("latin")) except: pass # No voice (for this discussion, or at all) discussion_widget = Bubble(soya.root_widget, self.character or tofu.GAME_INTERFACE.hero, DiscussionWidget(self)) if focus: discussion_widget.set_focus(1, 0) if discussion_widget.widget.choices: discussion_widget.widget.selection = discussion_widget.widget.choices[0][0] def is_valid(self): is_valid = getattr(self.character, "discussion_is_valid_%s" % self.text_key, None) if is_valid: return is_valid(self.hero) return 1 def get_choices(self): if not self._choices: self._choices = [] nb = len(self.text_key) choice2text = {} for key in balazar.globdef.translator._catalog.keys(): if key.startswith(self.text_key): nb_ = key[nb:].count("_") if nb_ == 1: choice_key = key if not choice2text.has_key(choice_key): choice2text[choice_key] = [] elif nb_ == 2: choice_key = key[:key.find("_", nb + 1)] if not choice2text.has_key(choice_key): choice2text[choice_key] = [] text_key = key choice2text[choice_key].append(text_key) choice_keys = choice2text.keys() choice_keys.sort() for choice_key in choice_keys: text_keys = choice2text[choice_key] if not text_keys: text_keys = [u""] else: if u"random" in text_keys[0][text_keys[0].rfind("_"):]: text_keys = [random.choice(text_keys)] # XXX multiplayer ??? else: text_keys.sort() for text_key in text_keys: choice = AutoDiscussion(self.hero, self.character, choice_key, text_key, self.check, self.source) if choice.is_valid(): if self._choices and (self._choices[-1].reply == choice.reply): # Same text => replace self._choices[-1] = choice else: self._choices.append(choice) if self.text and not self._choices: self._choices.append(Discussion(self.character, _("Ok"))) return self._choices choices = property(get_choices) def StartDiscussion(hero): return Discussion(hero, u"", _(u"__welcome__"), choices = [ Help(hero, _(u"Aide (ENTRÉE ou le BOUTON 3 du joypad)")), Discussion(hero, _(u"Je sais déjà jouer, merci !")), ]) def Help(hero, reply = u""): return Discussion(hero, reply, _(u"Utilise les touches HAUT BAS GAUCHE DROITE ou la MANETTE du \ joypad pour te déplacer"), choices = [ Discussion(hero, _(u"Suite (ENTRÉE ou le BOUTON 3 du joypad)"), _(u"Utilise la touche SHIFT ou le BOUTON 1 du joypad pour sauter. Appuie \ sur ENTRÉE ou le BOUTON 3 du joypad pour revenir à l'aide, puis en BAS pour \ sélectionner 'Suite', puis ENTRÉE ou le BOUTON 3 pour valider."), choices = [ Discussion(hero, _(u"Suite"), _(u"Appuis sur la touche CONTRÔLE ou le BOUTON 2 du joypad pour te \ mettre en garde. Relâche le bouton pour frapper."), choices = [ Discussion(hero, _(u"Suite"), _(u"Utilise les touches HAUT BAS GAUCHE DROITE ou la MANETTE du \ joypad pour te déplacer à l'intérieur des fenêtres. Utilise la touche ENTRÉE ou le \ BOUTON 3 du joypad pour valider, changer de fenêtre ou faire apparaître l'inventaire."), choices = lambda : [ Help(hero, _(u"Reprendre l'aide au début")), Discussion(hero, _(u"Fin de l'aide")), ]), ]), ]), ]) def QuitMenu(hero): return Discussion(hero, u"", _(u"__game_name__"), choices = [ Discussion(hero, _(u"Continuer"), ), Discussion(hero, _(u"Quitter et enregistrer"), action = lambda : tofu.GAME_INTERFACE.end_game()), Discussion(hero, _(u"Quitter sans enregistrer (suicide)"), action = lambda : (hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)), hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)), hero.doer.do_action(balazar.character.Action(balazar.character.ACTION_KILLED)))), ]) class DiscussionScript(soya.CoordSyst, base.Discutable): def __init__(self, parent = None, discussion = None, radius = 5.0): soya.CoordSyst.__init__(self, parent) self.discussion = discussion self.discussion_radius = radius if not self.discussion.source: self.discussion.source = self def start_discussion(self, hero): from balazar.controler import GrabItem if self.discussion.is_valid(): self.discussion.activate() class DiscussionWidget(widget.Label): def __init__(self, discussion): widget.Label.__init__(self) self.discussion = discussion self.selection = None def set_focus(self, focus): if not focus: self.selection = None def resize(self, parent_left, parent_top, parent_width, parent_height): self.left = parent_left self.top = parent_top self.width, self.text_height, self.text = self.font.wordwrap(self.discussion.text, parent_width) self.height = self.text_height self.choices = [] if self.discussion.choices: self.height += 10 for choice in self.discussion.choices: width, height, text = self.font.wordwrap(choice.reply, 500) self.font.create_glyphs(text) self.choices.append((choice, height, text)) if width > self.width: self.width = width self.height += height def check(self): if self.discussion.check and not self.discussion.check(): return 0 if tofu.GAME_INTERFACE.hero.distance_to(self.discussion.source) > self.discussion.source.discussion_radius: return 0 return 1 def key_down(self, key): if (key == controller.CONTROL_QUIT ): self.selection = None; self._changed = -2 elif(key == controller.CONTROL_JUMP ): self.selection = None; self._changed = -2 elif(key == controller.CONTROL_STRIKE): self.selection = None; self._changed = -2 elif(key == controller.CONTROL_ITEM ): self.selection = None; self._changed = -2 elif(key == controller.CONTROL_UP ) and self.choices and ((not self.selection) or (len(self.choices) > 1)): if self.selection: self.selection = self.choices[self.discussion.choices.index(self.selection) - 1][0] else: self.selection = self.choices[-1][0] self._changed = -2 return 1 elif(key == controller.CONTROL_DOWN) and self.choices and ((not self.selection) or (len(self.choices) > 1)): if self.selection: self.selection = self.choices[(self.discussion.choices.index(self.selection) + 1) % len(self.discussion.choices)][0] else: self.selection = self.choices[ 0][0] self._changed = -2 return 1 elif(key == controller.CONTROL_MENU) and self.selection: self.choose(self.selection) return 1 def choose(self, choice): balazar.sound.play("menu1.wav") self.master.destroy() choice.activate(1) def build_display_list(self): soyaopengl.glColor4f(0.0, 0.0, 0.0, 1.0) self._font.draw(self.text, self.left, self.top, 0) y = self.top + self.text_height + 10 for choice, height, text in self.choices: if choice is self.selection: soyaopengl.glColor4f(0.0, 0.0, 1.0, 1.0) else: soyaopengl.glColor4f(0.5, 0.5, 0.5, 1.0) self._font.draw(text, self.left, y, 0) y += height # class ActiveLabel(widget.Label, FocusableWidget): # def __init__(self, text): # FocusableWidget.__init__(self) # widget.Label.__init__(self, None, text, color = (0.0, 0.0, 1.0, 1.0)) # def check(self): return 1 # def set_focus(self, focus, play_sound = 1): # FocusableWidget.set_focus(self, focus, play_sound = 1) # if focus: self.color = (0.0, 0.0, 1.0, 1.0) # else: self.color = (0.5, 0.5, 0.5, 1.0) # def key_down(self, key): # if key == controller.CONTROL_QUIT: # self.destroy() # return 1 # def destroy(self): # balazar.sound.play("menu1.wav") # self.master.destroy() class CameraTraveling: pass class LifeBar(widget.Widget): def __init__(self, master = None): widget.Widget.__init__(self, master) self.left = 5.0 self.top = 5.0 self.width = 70.0 self.height = 300.0 self._id1 = soyaopengl.glGenList() self._id2 = soyaopengl.glGenList() self.material = soya.Material.get("life") def __del__(self): soyaopengl.glDeleteList(self._id1) soyaopengl.glDeleteList(self._id2) def render(self): soya.DEFAULT_MATERIAL.activate() soyaopengl.glCallList(self._id1) self.material.activate() soyaopengl.glCallList(self._id2) def set_life(self, life): soyaopengl.glNewList(self._id1, soyaopengl.GL_COMPILE) soyaopengl.glEnable(soyaopengl.GL_BLEND) soyaopengl.glBegin(soyaopengl.GL_QUADS) soyaopengl.glColor4f(0.5, 0.0, 0.8, 0.7) top = self.top + 47.0 + (1.0 - life) * (self.height - 47.0) soyaopengl.glVertex2f(self.left + 4.0, self.top + self.height - 20.0) soyaopengl.glVertex2f(self.left + self.width - 4.0, self.top + self.height - 20.0) soyaopengl.glVertex2f(self.left + self.width - 4.0, top) soyaopengl.glVertex2f(self.left + 4.0, top) soyaopengl.glEnd() soyaopengl.glEndList() soyaopengl.glNewList(self._id2, soyaopengl.GL_COMPILE) soyaopengl.glBegin(soyaopengl.GL_QUADS) soyaopengl.glColor4f(1.0, 1.0, 1.0, 1.0) soyaopengl.glTexCoord2f(0.0, 1.0); soyaopengl.glVertex2f(self.left , self.top + self.height) soyaopengl.glTexCoord2f(1.0, 1.0); soyaopengl.glVertex2f(self.left + self.width, self.top + self.height) soyaopengl.glTexCoord2f(1.0, 0.0); soyaopengl.glVertex2f(self.left + self.width, self.top) soyaopengl.glTexCoord2f(0.0, 0.0); soyaopengl.glVertex2f(self.left , self.top) soyaopengl.glEnd() soyaopengl.glDisable(soyaopengl.GL_BLEND) soyaopengl.glEndList() SIZE_2_TEX = { 1 : 1.0 , 2 : 1.0 , 3 : 0.75 , 4 : 1.0 , 5 : 0.625, 6 : 0.75 , 7 : 0.875, 8 : 1.0 , } class MapViewer(widget.Widget, FocusableWidget): def __init__(self, map = None): FocusableWidget.__init__(self) widget.Widget.__init__(self, None) self.set_map(map) def set_map(self, map): self.map = map self.country = balazar.level.COUNTRIES[map.country_name] self.width = (self.country.X2 - self.country.X1 + 1) * 50.0 self.height = (self.country.Z2 - self.country.Z1 + 1) * 50.0 self.left = 5.0 self.top = 5.0 self.tex_x = SIZE_2_TEX[self.country.X2 - self.country.X1 + 1] self.tex_z = SIZE_2_TEX[self.country.Z2 - self.country.Z1 + 1] self.material = soya.Material.get("item_map_%s" % self.country.name) def render(self): if self.map: hero = tofu.GAME_INTERFACE.hero level = hero.level if (self.country.X1 <= level.X <= self.country.X2) and (self.country.Z1 <= level.Z <= self.country.Z2): self.material.activate() soyaopengl.glEnable(soyaopengl.GL_BLEND) soyaopengl.glBegin(soyaopengl.GL_QUADS) soyaopengl.glTexCoord2f( 0.0, self.tex_z); soyaopengl.glVertex2f(self.left , self.top + self.height) soyaopengl.glTexCoord2f(self.tex_x, self.tex_z); soyaopengl.glVertex2f(self.left + self.width, self.top + self.height) soyaopengl.glTexCoord2f(self.tex_x, 0.0); soyaopengl.glVertex2f(self.left + self.width, self.top) soyaopengl.glTexCoord2f( 0.0, 0.0); soyaopengl.glVertex2f(self.left , self.top) soyaopengl.glEnd() soyaopengl.glDisable(soyaopengl.GL_BLEND) soya.DEFAULT_MATERIAL.activate() soyaopengl.glColor4f(0.5, 0.0, 0.8, 1.0) soyaopengl.glBegin(soyaopengl.GL_QUADS) x = self.left x += (hero.x + balazar.level.BRIDGE_DEMI_DIM) / balazar.level.LEVEL_DIM * 50.0 x += (level.X - self.country.X1) * 50.0 z = self.top z += (hero.z + balazar.level.BRIDGE_DEMI_DIM) / balazar.level.LEVEL_DIM * 50.0 z += (level.Z - self.country.Z1) * 50.0 soyaopengl.glVertex2f(x - 2, z + 2) soyaopengl.glVertex2f(x + 2, z + 2) soyaopengl.glVertex2f(x + 2, z - 2) soyaopengl.glVertex2f(x - 2, z - 2) soyaopengl.glEnd() def key_down(self, key): if key == controller.CONTROL_QUIT: self.destroy() return 1 def destroy(self): balazar.sound.play("menu1.wav") self.master.destroy()