Sign in to follow this  

In-game Console and Scripting

This topic is 3560 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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 Frosty
import GameState
import EditControl
import code
import sys

class 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()

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 3560 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this