2
$\begingroup$

I need to run some basic physics simulations on a headless machine and I'd like to program agent movements based on function outputs (e.g. "move left")-I have some code that programs WASD to move a cube that I'd like to modify such that it doesn't actually require me to press any keys but rather, if the program receives "Wkey" as an input (from another function) it's able to move the agent in the desired direction. Is this possible? (I also want to try to avoid using the logic editor to run the script if possible, any help on that would also be appreciated)

Current code below:

import bge


def main():

    cont = bge.logic.getCurrentController()
    own = cont.owner

    keyboard = bge.logic.keyboard

    wKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.WKEY]
    sKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.SKEY]
    aKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.AKEY]
    dKey = bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.DKEY]

    if wKey: 
        own.applyMovement([0,0.2,0],True)

    if sKey: 
        own.applyMovement([0,-0.2,0],True)

    if aKey: 
        own.applyMovement([-0.2,0,0],True)

    if dKey: 
        own.applyMovement([0.2,0,0],True)

main()
$\endgroup$
  • $\begingroup$ I don't know about sending keystrokes but here's a suggestion : make dummy object ( the keyboard ) with bool properties ( keys ) and the functions set the props and others read them , how is that ? $\endgroup$ – Chebhou Jul 29 '15 at 20:02
  • $\begingroup$ Generating keyboard events is outside the scope of the BGE. I suggest to look for external tools (e.g. tools for GUI testing). Your "main()" problem is that you rely on the keyboard events. I suggest to remove that dependency and control the objects behavior via other events (e.g. messages, property values). $\endgroup$ – Monster Jul 30 '15 at 7:16
1
$\begingroup$

Here is a simple script that will create a keyboard object ( an empty )that have properties act as keys, this objects read the keys states from a file (inside blender or on the system ) and set them according to it.
the script will also create a player object (a cube) which will read the keys properties of the keyboard object and use it as real keyboard input. ( I added the keyboard object to keep the players scripts simple and they will be easy to convert to use a real keyboard )


this script will automate the whole process : create objects, set the logic bricks, load the scripts' files and start the game engine.

To test the script start blender and paste the script and hit Run Script you'll see the game engine start and the cube start moving. or you can start blender from the command line with this script to avoid using the GUI

#key strokes for each logic tic

keys_str="""w,w,w,w d,w d,w,w,w,w,w,w,a,a,
a,a w,a w,a w,w,w,w,w d,w d,w,w,w,w,w,
w,a,a,a,a w,a w,a w,w,w,w,w d,w d,w,w,
w,w,w,w,a,a,a,a w,a w,a w,w,w,w,w d,w 
d,w,w,w,w,w,w,a,a,a,a w,a w,a w,w,w,w,
w d,w d,w,w,w,w,w,w,a,a,a,a w,a w,a w,
w,w,w,w d,w d,w,w,w,w,w,w,a,a,a,a w,a 
w,a w,w,w,w,w d,w d,w,w,w,w,w,w,a,a,a,
a w,a w,a w,w,w,w,w d,w d,w,w,w,w,w,w,
a,a,a,a w,a w,a w,w,w,w,w d,w d,w,w,w,
w,w,w,a,a,a,a w,a w,a w,""".replace('\n','')


#### script for the player object
ob_txt="""
import bge, bge.logic

scene = bge.logic.getCurrentScene() 

kb = scene.objects["keyboard"]
keys = ["shift", "ctrl", "space", "w", "s", "a", "d"]

cont = bge.logic.getCurrentController()
own = cont.owner

if kb["w"] :
        own.applyMovement([0,0.2,0],True)
if kb["s"] :
        own.applyMovement([0,-0.2,0],True)
if kb["d"] :
        own.applyRotation([0,0,10],True)
if kb["a"] :
        own.applyRotation([0,0,-10],True)
"""        


### script for the keyboard object
kb_txt="""

import bge, bge.logic
import bpy

keys = ["shift", "ctrl", "space", "w", "s", "a", "d"]
scene = bge.logic.getCurrentScene() 
cont = bge.logic.getCurrentController()
own = cont.owner

def reset_keys():
        for key in keys:
            if own[key]:
                own[key] = False


def read_keys():
      i = own['line']
      # with open(r'C:\path\to\myfile', 'r') as file:
      #       line = file.read().split(',')[i]
      line = bpy.data.texts['keys'].as_string().split(',')[i]
      cmds = line.split(' ')
      for key in cmds :
            if key in keys:
                  own[key] =True
      own['line'] += 1

reset_keys()
read_keys()
"""


### setup script

import bpy

context = bpy.context
data = bpy.data
scene = context.scene

##### scripts' texts ####
kb_script_txt = bpy.data.texts.new('kb_script')
kb_script_txt.write(kb_txt)

ob_script_txt = bpy.data.texts.new('ob_script')
ob_script_txt.write(ob_txt)

keys_txt = bpy.data.texts.new('keys')
keys_txt.write(keys_str)

##### keyboard object #######
bpy.ops.object.empty_add()
bpy.context.object.name="keyboard"

####### properties  ########
keys = ["shift", "ctrl", "space", "w", "s", "a", "d"]
for key in keys:
    bpy.ops.object.game_property_new(type='BOOL', name=key)
bpy.ops.object.game_property_new(type='INT', name='line')

######## logicBricks ######
actuators = bpy.context.object.game.actuators
controllers = bpy.context.object.game.controllers
sensors = bpy.context.object.game.sensors
#always sensor
bpy.ops.logic.sensor_add(type='ALWAYS')
always = sensors['Always']
always.use_pulse_true_level = True
always.frequency = 24
#script controller
bpy.ops.logic.controller_add(type='PYTHON', name="script_cont")
script_cont = controllers["script_cont"]
script_cont.text = kb_script_txt
#link them
always.link(script_cont)




##### player object #######
bpy.ops.mesh.primitive_cube_add()
bpy.context.object.name="player"

######## logicBricks ######
actuators = bpy.context.object.game.actuators
controllers = bpy.context.object.game.controllers
sensors = bpy.context.object.game.sensors
#always sensor
bpy.ops.logic.sensor_add(type='ALWAYS')
always = sensors['Always']
always.use_pulse_true_level = True
always.frequency = 24
#script controller
bpy.ops.logic.controller_add(type='PYTHON', name="script_cont")
script_cont = controllers["script_cont"]
script_cont.text = ob_script_txt
#link them
always.link(script_cont)


##### start game engine ######

bpy.context.scene.render.engine = 'BLENDER_GAME'
for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        override = bpy.context.copy()
        override['area'] = area
        bpy.ops.view3d.game_start()
        break
$\endgroup$
  • $\begingroup$ oh wow, thank you so much-quick question, once i've loaded up blender from the command line, how do i run this script within it? $\endgroup$ – Archana Ram Aug 1 '15 at 19:09
  • $\begingroup$ @ArchanaRam blender --python myscript.py this how you run it from the start $\endgroup$ – Chebhou Aug 1 '15 at 19:18
  • $\begingroup$ you have to save it in .py file, and put the cmd can find it ( where you started the cmd ) $\endgroup$ – Chebhou Aug 1 '15 at 19:27
  • $\begingroup$ Sorry-quick question: how do I end the game engine? Would it be bpy.ops.view3d.game_end() ? $\endgroup$ – Archana Ram Aug 1 '15 at 23:56
  • $\begingroup$ Working on getting this to run-do I save the file in the same directory as the one from which I'd open blender? $\endgroup$ – Archana Ram Aug 2 '15 at 1:14

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.