2
$\begingroup$

From this piece of code:

# import game engine modules
from bge import render
from bge import logic
# import stand alone modules
import bgl
import blf


def init():
    """init function - runs once"""
    # create a new font object, use external ttf file
    font_path = logic.expandPath('C://Documents and Settings//Guillermo//Mis documentos//Google Drive//Gproyectos//Proyectos con Blender/Zeyada.ttf')
    # store the font indice - to use later
    logic.font_id = blf.load(font_path)

    # set the font drawing routine to run every frame
    scene = logic.getCurrentScene()
    scene.post_draw = [write]


def write():
    """write on screen"""
    width = render.getWindowWidth()
    height = render.getWindowHeight()

    # OpenGL setup
    bgl.glMatrixMode(bgl.GL_PROJECTION)
    bgl.glLoadIdentity()
    bgl.gluOrtho2D(0, width, 0, height)
    bgl.glMatrixMode(bgl.GL_MODELVIEW)
    bgl.glLoadIdentity()

    # BLF drawing routine
    font_id = logic.font_id
    blf.position(font_id, (width * 0.2), (height * 0.3), 0)
    blf.size(font_id, 50, 72)
    blf.draw(font_id,"Hello World!")

init()
write()

that it works fine, I want to make some changes so that I can enter the text to the write function through a variable. So my code would be as follows:

# import game engine modules
from bge import render
from bge import logic
# import stand alone modules
import bgl
import blf


def init():
    """init function - runs once"""
    # create a new font object, use external ttf file
    font_path = logic.expandPath('C://Documents and Settings//Guillermo//Mis documentos//Google Drive//Gproyectos//Proyectos con Blender/Zeyada.ttf')
    # store the font indice - to use later
    logic.font_id = blf.load(font_path)

    # set the font drawing routine to run every frame
    scene = logic.getCurrentScene()
    scene.post_draw = [write]


def write(chain):
    """write on screen"""
    width = render.getWindowWidth()
    height = render.getWindowHeight()

    # OpenGL setup
    bgl.glMatrixMode(bgl.GL_PROJECTION)
    bgl.glLoadIdentity()
    bgl.gluOrtho2D(0, width, 0, height)
    bgl.glMatrixMode(bgl.GL_MODELVIEW)
    bgl.glLoadIdentity()

    # BLF drawing routine
    font_id = logic.font_id
    blf.position(font_id, (width * 0.2), (height * 0.3), 0)
    blf.size(font_id, 50, 72)
    blf.draw(font_id,chain)

init()
chain = "Hello citizen!"
write(chain)

however this piece of code doesn´t work. I can read a message from the console that say:

Type error: write() missing 1 required positional argument: ´chain´

I don´t understand why it doesn´t work.

$\endgroup$
  • 1
    $\begingroup$ It will be from when write() is called from scene.post_draw handler. AFAIK There is no implied argument(s) when method from list is called after render draw event.. $\endgroup$ – batFINGER Jan 9 '18 at 11:02
2
$\begingroup$

As commented, adding write() as a callback in post_draw means it cannot have a parameter.

One solution would be to use your script as a python module. Code at the top of the script will be run once at game start, allowing you to initialise your module variables, then functions in the module can be used as needed. To be a module, the name of the text block must end in .py. For your first code example, you don't need to call write() at the bottom of your script, just naming it with .py should be all you have to do for it to work.

You can then use it in a python controller, set as a module, and call one of the functions based on the attached sensor. In this example I read a game property when the sensor runs the update(cont) function to update the modules chain property, the controller calling the function is passed in this case.

sample logic bricks

Text block "drawtext.py" -

# import game engine modules
from bge import render, logic
# import stand alone modules
import bgl, blf

# create a new font object, use external ttf file
font_path = logic.expandPath('//bmonofont-i18n.ttf')
# store the font indice - to use later
font_id = blf.load(font_path)
chain = 'this is the message'

def write():
    """write on screen"""
    width = render.getWindowWidth()
    height = render.getWindowHeight()
    # OpenGL setup
    bgl.glMatrixMode(bgl.GL_PROJECTION)
    bgl.glLoadIdentity()
    bgl.gluOrtho2D(0, width, 0, height)
    bgl.glMatrixMode(bgl.GL_MODELVIEW)
    bgl.glLoadIdentity()

    # BLF drawing routine
    blf.position(font_id, (width * 0.2), (height * 0.3), 0)
    blf.size(font_id, 50, 72)
    bgl.glColor4f(1.0, 0.0, 0.0, 1.0)
    blf.draw(font_id,chain)

def update(cont):
    own = cont.owner
    chain = own['msg']

# set the font drawing routine to run every frame
scene = logic.getCurrentScene()
scene.post_draw = [write]

You might use a property actuator to change the objects msg property, or a property sensor to run the update when the property changes. You can also import the module in another script and adjust the module property and call other functions.

import drawtext
drawtext.chain = 'New message'
drawtext.anotherfunc()
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.