Text Console Tutorial


We can display text information to a user with a text console. This is usefull for things such as detailed attack roll information.


Text Input
Split Lines
Text Wrap
Countdown Timer

Set Up

Create a plane for the background. Call it TextConsole. Give it a material. Enable Shadeless, Object Color, and Transparency. Set its Object Color, giving it partial alpha. Give the background the shown nodes and properties. Create a Text object. Name it TextConsole Text. Parent it to the background object. Give it the same material. Set its Object Color but give it full alpha. Add a TextInput object according to its directions.



import bge
# http://upbge.wikidot.com/timer-tutorial
from timer import CountdownTimer as Timer
# https://docs.python.org/3/library/textwrap.html#textwrap.wrap
from textwrap import wrap
# https://docs.python.org/3/library/json.html#json.load
import json
class TextConsole(bge.types.KX_GameObject):
  def __init__(self, DNU):
    self.text = self.child('Text')
    # Fixes buggy text.
    self.text.localScale *= self['scaleFix']
    # Clear the text.
    self.text.text = ''
    self.row = self['row']
    self.collum = self['collum']
    # Converts the string to a list of floats.
    self.fade = json.loads(self['fade'])
    # Record the objects starting transparency.
    self.baseAlpha = self.color.w
    # Make the object invisable.
    self.color.w = 0
    # Tell the console that its currently off.
    self.stage = None
  def input(self):
    # If the mouse is hovering over the object, keep restarting the timer.
    if self.sensors['MouseOver'].positive:  self.startTimer()
  def message(self, subject, body):
    # Separate the current text into a list of lines.
    lines = self.text.text.splitlines()
    # Split the received message into multiple lines if its too long for just one line.
    body = wrap(body, self.collum)
    # Add the body to the end of the list.
    lines += body
    # Get the last lines that will fit.
    lines = lines[-self.row:]
    # Convert the list back into a string.
    text = ''
    for line in lines:
      # '\n' tells the text object where the new lines should be.
      text += line+'\n'
    # Set the text object to the new text.
    self.text.text = text
    # Start the objects fading.
  def run(self):
    # Stage zero.
    if self.stage == 0:
      # Get how much time has elapsed for this stage.
      elapse = self.timer.elapsePercent
      # Max elapse at one hundred percent.
      if elapse > 1:  elapse = 1
      # This fades the object up to its base transparency.
      self.color.w = elapse * self.baseAlpha
      # Were assuming the text always maxes at one hundred percent transparency.
      self.text.color.w = elapse
      # If the object has fully faded in.
      if elapse == 1:
        # Goto the next stage.
        self.stage = 1
        # Start a new timer based off the next stages fade duration.
        self.timer = Timer(self.fade[1])
    # Stage one.
    if self.stage == 1:
      # Stage one sits at max alpha.
      self.color.w = self.baseAlpha
      self.text.color.w = 1
      if self.timer.elapsePercent >= 1:
        self.stage = 2
        self.timer = Timer(self.fade[2])
    # Stage two.
    if self.stage == 2:
      # We do the same as stage zero but in reverse.
      elapse = self.timer.remainPercent
      if elapse < 0:  elapse = 0
      self.color.w = elapse * self.baseAlpha
      self.text.color.w = elapse
      # Turn it all off.
      if elapse == 0:
        self.stage = None
        self.timer = None
        self['_run'] = False
  def startTimer(self):
    # If the fade is currently not running, start it.
    if self.stage == None:
      self.stage = 0
      # Start a new timer based off the next stages fade duration.
      self.timer = Timer(self.fade[0])
      # When this property is True, the run script will run.
      self['_run'] = True
    elif self.stage == 1:
      # If your aready in stage one, just reset the timer.
      # This keeps it suck in stage one.
      self.timer = Timer(self.fade[1])
    elif self.stage == 2:
      # This caouses it to jump back to stage one.
      self.stage = 1
      self.timer = Timer(self.fade[1])
# http://upbge.wikidot.com/child-by-name-tutorial
  def child(obj, child):
    name = obj.name.split('.')
    try:    suffix = '.'+name[1]
    except IndexError: suffix = ''
    return obj.childrenRecursive[name[0] +' '+child+ suffix]
# http://upbge.wikidot.com/oop-in-bge-tutorial
BASE_CLASS = TextConsole
import json as JSON_CODER
SEN_MESSAGE = 'Message'
def sub(cont):
  self = cont.owner
  if isinstance(self, BASE_CLASS):  return self
  else:  return BASE_CLASS(self)
def message(cont):
  sen = cont.sensors[SEN_MESSAGE]
  for i in range(sen.frameMessageCount):
    subject = sen.subjects[i]
    body = sen.bodies[i]
    try:  body = JSON_CODER.loads(body)
    cont.owner.message(subject, body)
def input(cont):  cont.owner.input()
def run(cont):  cont.owner.run()


Log in and edit this page to ask and answer questions.

Further Reading

String Methods

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License