import sys
import os
-import kivy
-kivy.require('1.6.0')
+from erdslangetjie.constants import TILE_SIZE
from kivy.app import App
-from kivy.logger import Logger, LoggerHistory
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Color, Rectangle
+from kivy.uix.label import Label
+from kivy.uix.popup import Popup
+from kivy.utils import platform
+from kivy.config import Config
from erdslangetjie.data import filepath, load
-from erdslangetjie.level import Level
-from erdslangetjie.constants import TILE_SIZE, QUIET
+from erdslangetjie.level import (Level, WALL, GATE, BUTTON,
+ FLOOR, ENTRY, EXIT)
+
+
+if platform() != 'android':
+ Config.set('graphics', 'width', '1326')
+ Config.set('graphics', 'height', '760')
+
+
+tool_map = {
+ 'button': BUTTON,
+ 'gate': GATE,
+ 'wall': WALL,
+ 'floor': FLOOR,
+ 'add entry': ENTRY,
+ 'add exit': EXIT
+ }
class EditorWindow(FloatLayout):
def __init__(self, level):
- super(EditorWindow, self).__init__(size=(800, 600))
+ super(EditorWindow, self).__init__(size=(1326, 760))
if os.path.exists(filepath(level)):
level_data = load(level)
self.level = level
self.level = level
else:
self.level = 'levels/' + level
- self.level_obj = Level(level_data)
+ self.level_obj = Level(level_data, self.level)
level_data.close()
self.level_obj.load_tiles()
+ self.tool = None
+ self.tool_widgets = []
+
def build(self):
self.clear_widgets()
tiles = self.level_obj.get_tiles()
bx, by = 0, 0
+ self.nodes = {}
for tile_line in tiles:
bx = 0
for tile in tile_line:
- node = Widget(size=(TILE_SIZE, TILE_SIZE), pos=(bx, by))
- with node.canvas:
- Color(1, 1, 1)
- Rectangle(pos=node.pos, size=node.size,
- texture=tile.texture)
- self.add_widget(node)
+ self._draw_tile((bx, by), tile)
bx += TILE_SIZE
by += TILE_SIZE
+ name = Label(text="Level: [color=00ffcc]%s[/color]" % self.level,
+ markup=True, font_size=24, pos=(500, 360))
+ self.add_widget(name)
+
+ self.draw_toolbar()
+ self.draw_save_button()
+
+ def _draw_tile(self, tile_pos, tile):
+ if tile_pos in self.nodes:
+ self.remove_widget(self.nodes[tile_pos])
+ node = Widget(size=(TILE_SIZE, TILE_SIZE), pos=tile_pos)
+ node.bind(on_touch_down=self.change_node)
+ node.bind(on_touch_move=self.change_node)
+ with node.canvas:
+ Color(1, 1, 1)
+ Rectangle(pos=node.pos, size=node.size, texture=tile.texture)
+ self.add_widget(node)
+ self.nodes[tile_pos] = node
+
+ def draw_toolbar(self):
+ for widget in self.tool_widgets:
+ widget.unbind(on_ref_press=self.change_tool)
+ self.remove_widget(widget)
+ self.tool_widgets = []
+ y = 300
+ for tool in sorted(tool_map):
+ if self.tool == tool:
+ color = '00cccc'
+ else:
+ color = 'cccccc'
+ tool_label = Label(text='[color=%s][ref=%s]%s[/ref][/color]' %
+ (color, tool, tool), markup=True, font_size=24,
+ pos=(500, y))
+ y -= 50
+ tool_label.bind(on_ref_press=self.change_tool)
+ self.add_widget(tool_label)
+ self.tool_widgets.append(tool_label)
+
+ def draw_save_button(self):
+ save_label = Label(text='[color=ffffff][ref=save]Save[/ref][/color]',
+ markup=True, font_size=24, pos=(500, -100))
+ save_label.bind(on_ref_press=self.do_save)
+ self.add_widget(save_label)
+
+ def do_save(self, label, ref):
+ try:
+ self.level_obj.validate()
+ except RuntimeError as err:
+ popup = Popup(title='Error',
+ content=Label(text='Level not valid: %s' % err),
+ size_hint=(.5, .5))
+ popup.open()
+ return
+ save_data = self.level_obj.get_level_data()
+ savefile = file(filepath(self.level), 'w')
+ savefile.write(save_data)
+ savefile.write('\n')
+ savefile.close()
+ popup = Popup(title='Success',
+ content=Label(text='Level saved to %s' % self.level),
+ size_hint=(.5, .5))
+ popup.open()
+
+ def change_tool(self, label, ref):
+ self.tool = ref
+ self.draw_toolbar()
+
+ def contained(self, node, pos):
+ if pos[0] < node.pos[0] or pos[0] > node.pos[0] + TILE_SIZE:
+ return False
+ if pos[1] < node.pos[1] or pos[1] > node.pos[1] + TILE_SIZE:
+ return False
+ return True
+
+ def change_node(self, node, touch):
+ if self.tool and self.contained(node, touch.pos):
+ tile_pos = (node.pos[0] / TILE_SIZE, node.pos[1] / TILE_SIZE)
+ action = tool_map[self.tool]
+ if self.level_obj.get_tile_type(tile_pos) != action:
+ self.level_obj.set_tile_type(tile_pos, action)
+ for map_pos, new_tile in self.level_obj.get_changed_tiles():
+ node_pos = (map_pos[0] * TILE_SIZE, map_pos[1] * TILE_SIZE)
+ self._draw_tile(node_pos, new_tile)
+
class EditorApp(App):
+ title = "Bane's Befuddlement Level Editor"
+
def __init__(self, level):
self.level = level
super(EditorApp, self).__init__()
level = sys.argv[1]
else:
level = 'level1.txt'
- if QUIET:
- for hdlr in Logger.handlers[:]:
- if not isinstance(hdlr, LoggerHistory):
- Logger.removeHandler(hdlr)
EditorApp(level).run()