In-game Console and Scripting
I haven't implemented a scripting language or a Quake-style console in my games yet. I was thinking about it and wondering if it's worth implementing a console if you already have a script hooked in.
The way I thought about it is that you could run the game windowed and have the main scripts open in a text editor. Then you could (F5) refresh the scripts and get most of the benefit of inputs to the console.
The console is also used for debug printing info. You could have an overlay that lists all the important variables and their values.
I was wondering if people knew of good examples of a console in a game that is tied to a scripting language like lua or python. Hopefully freely downloadable. I would like to see it, because most consoles seem to stop short of being a full language.
I wonder if all the error-checking, logging, and flexibility with scripting/xml/consoles is worth it for a moderately sized game. Then I think of some counterexamples and know it's worth it to some extent.
Here's an example of writing a Python console in Python. It uses Python's code.InteractiveInterpreter to handle parsing the Python code and sets itself as stderr and stdout to get messages. It isn't usable by itself but should give you an idea of what can be done.
import Frostyimport GameStateimport EditControlimport codeimport sysclass ConsoleState(GameState.GameState, code.InteractiveInterpreter): def __init__(self, game): GameState.GameState.__init__(self, game) code.InteractiveInterpreter.__init__(self, locals()) self.held_state = None self.font = Frosty.Font("Console Font") self.edit = EditControl.EditControl() self.edit.set_font(self.font) self.history = [] # image list for display self.ps1 = self.font.render_font(">>>", 128, 128, 255) self.ps2 = self.font.render_font("...", 128, 128, 255) self.prompt = self.ps1 self.input_buffer = [] # source text not processed by interpreter self.command_buffer = [] # command history self.command_index = 0 self.last_line = "" self.last_line_image = None sys.stdout = self sys.stderr = self def _on_key_down(self, scan_code, unicode): if scan_code == Frosty.SDLK_ESCAPE: self.transition(self.held_state) else: self.on_key_down(scan_code, chr(unicode)) def on_key_down(self, key, unicode): if key == Frosty.SDLK_RETURN: self.command_index = 0 text = self.edit.get_text(); self.edit.set_text("") if self.last_line: self.history.append( (self.last_line_image,) ) self.last_line = "" if text: self.command_buffer.append(text) self.history.append( (self.prompt, self.font.render_font(text, 255, 255, 255) ) ) else: self.history.append( (self.prompt,) ) more = self.push(text) if more: self.prompt = self.ps2 else: self.prompt = self.ps1 elif key == Frosty.SDLK_UP: if self.command_index < len(self.command_buffer): self.command_index += 1 self.edit.set_text(self.command_buffer[-self.command_index]) elif key == Frosty.SDLK_DOWN: if self.command_index > 1: self.command_index -= 1 self.edit.set_text(self.command_buffer[-self.command_index]) elif self.command_index == 1: self.command_index = 0 self.edit.set_text("") else: self.edit.on_key_down(key, unicode) def render(self, surface): self.held_state.render(surface) filter = surface.create_compatible_filter() filter.clear(0, 0, 0) filter.set_alpha(192) filter.blit(surface, 0, 0) x = self.ps1.width y = self.holder.height - self.edit.height() line = 1 self.prompt.blit(surface, 0, y) self.edit.render(surface, x, y) size = len(self.history) if self.last_line: y -= 12 self.last_line_image.blit(surface, 0, y) while (y > 0) and (line <= size): y -= 12 if (self.history[-line]): if len(self.history[-line]) == 2: self.history[-line][0].blit(surface, 0, y) self.history[-line][1].blit(surface, x + 3, y) else: self.history[-line][0].blit(surface, 0, y) line += 1 def update(self, time): self.edit.update(time) def reset_buffer(self): self.input_buffer = [] def push(self, line): self.input_buffer.append(line) source = "\n".join(self.input_buffer) more = self.runsource(source, "<ConsoleState>") if not more: self.reset_buffer() return more def write(self, text): if text: lines = text.split("\n") lines[0] = self.last_line + lines[0] self.last_line = lines[-1] self.last_line_image = self.font.render_font(self.last_line, 255, 255, 255) for line in lines[:-1]: if line: self.history.append( (self.font.render_font(line, 255, 255, 255), ) ) Frosty.echo(line) else: self.history.append(None) Frosty.echo()
Having a scripting system, as well as a console really does push up productivity.
If you're testing things out it's nice to bring up a console and type "addmodel dropship.x" instead of closing the game, editing the code, recompiling and running again.
I didn't realise its advantages until I implemented it. Now I can't live without it.
If you're testing things out it's nice to bring up a console and type "addmodel dropship.x" instead of closing the game, editing the code, recompiling and running again.
I didn't realise its advantages until I implemented it. Now I can't live without it.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement