1
$\begingroup$

I'd like to make one spawnpoint that, adds a different/random object every time on pressing of the same key (space bar for example). This tutorial explains nicely, How you can make random objects appear with an Always-sensor from a 'list' in the python script. But when I change it to a Keyboard-sensor, it doesn't work.

Any ideas on how I can fix the script so it spawns random object with every keystroke? Or is there a way I can link multiple 'EditObject-actuators that each add different objects' to one Keyboard-sensor... and somehow give random priorities to those?

This is the final result I'm trying to achieve, only pressing 1 key.

An example, made using add-object-actuators, each linked to different keys

Thanks in advance!

$\endgroup$
1
  • $\begingroup$ I do not see a reason why a keyboard sensor does not work with the method described in the tutorial. The mentioned code does not relay on the sensor type. But it should at least the status of the connected sensors. $\endgroup$
    – Monster
    Aug 8, 2017 at 5:39

2 Answers 2

2
$\begingroup$

When you add a sensor, you need to eval if its active in the script so you can do stuff.

enter image description here

To evalute the keyboard sensor named "Keyboard"

from bge import logic
import random

keysensor = logic.getCurrentController().sensors['Keyboard']
scene = logic.getCurrentScene()
own = logic.getCurrentController().owner
list = ['Cube','etc']
'''Eval if sensor activated'''
if keysensor.positive:
    choice = random.choice(list)
    scene.addObject(choise, own, 100)

EDIT

To properly use scene.addObject the object has to be in an inactive layer see objectsInactive

enter image description here

And the script to work properly.

from bge import logic
import random

keysensor = logic.getCurrentController().sensors['Keyboard']
scene = logic.getCurrentScene()
own = logic.getCurrentController().owner
list = scene.objectsInactive
'''Eval if sensor activated'''
if keysensor.positive:
    choice = random.choice(list)
    scene.addObject(choice, own, 100)

ObjectsInactive is a list of all objects who are in an inactive layer, so if you need just some of the objects yo can add a property to the objects so you can gather them easy.

enter image description here

enter image description here

Then change

list = scene.objectsInactive

for

list = [obj for obj in scene.objectsInactive if 'spawnObj' in obj.getPropertyNames()]

That way the list would be fill with objects that have a property named "spawnObj".

Finally use descriptive names for the sensors, instead keyboard, keyboard.001, keyboard.002, ect... SpaceKey, aKey, BKEY, ckey, etc..

Demo file:

$\endgroup$
2
  • $\begingroup$ Chek de edited answer. $\endgroup$ Aug 7, 2017 at 21:06
  • $\begingroup$ Hi, do you think there's any way to add linear velocity to the python script? (The way you can tweak linear of angular velocity on an 'AddObject' actuator. Thanks in advance! $\endgroup$
    – JPeters
    Jan 6, 2018 at 14:03
1
$\begingroup$

Adding via Keyboard sensor (or any other sensor)

I suggest to replace the always sensor with a keyboard sensor.

Disable [True Level Triggering] otherwise you will get new objects as long as you hold the key.

To avoid creating objects when releasing the key you need to check the sensor status. As I do not have the code from tutorial here is a different version of it.

import bge
import random

controller = bge.logic.getCurrentController()
if all(sensor.positive for sensor in controller.sensors):
    positionProvider = controller.owner
    templateNames = ["Sphere", "Cube"]
    templateName = random.choice(templateNames)

    addedObject = positionProvider.scene.addObject(templateName, positionProvider, 100)
    addedObject.setLinearVelocity(1.0, 0.0, 0.0)

Please notice I removed unnecessary code (such as main()) and use more descriptive names by avoiding cryptic abbreviations.

Automatically find template objects

For easier configuration you can read the available template objects directly from the scene:

import bge
import random

controller = bge.logic.getCurrentController()
if all(sensor.positive for sensor in controller.sensors):
    positionProvider = controller.owner
    scene = positionProvider.scene

    templates = scene.objectsInactive
    template = random.choice(templates)

    addedObject = scene.addObject(template, positionProvider, 100)
    addedObject.setLinearVelocity(1.0, 0.0, 0.0)

Template objects by property

When you have several emitters you can filter templates by property. Keep in mind one object can have several properties. This means you can configure an object that it gets added by different emitters.

The emitter needs a property called "filter" as String with the name of the property to look for. The objects at the hidden layer need a property with that name (the type and value are irrelevant).

import bge
import random

controller = bge.logic.getCurrentController()
if all(sensor.positive for sensor in controller.sensors):
    positionProvider = controller.owner
    scene = positionProvider.scene

    filterProperty = controller.owner.get("filter")

    templates = [template for template in scene.objectsInactive
                    if filterProperty is None or 
                       filterProperty in template]
    template = random.choice(templates)

    scene.addObject(template, positionProvider, 100)

Examples:

Your hidden layers contain this objects:

  • flame.001 property "flame"
  • flame.002 property "flame"
  • spark.001 property "flame", "spark"
  • smoke.001 property "smoke"

Your emitter has a property "filter" with value "flame". When you trigger the emitter it will emit one object out of flame.001, flame.002 or spark.001. It will never emit smoke.001.

When you have another emitter with property "filter" set to "smoke" it will emit smoke.001 only.

When you have an emitter without property "filter" it will emit from all template objects.

When you have an emitter with property "filter" set to "fog" it will result in error as there is no matching template object at the hidden layers.

$\endgroup$
6
  • $\begingroup$ Hi, is there any way to add Linear velocity to the objects that are spawned? Thanks in advance! $\endgroup$
    – JPeters
    Jan 7, 2018 at 21:54
  • $\begingroup$ Sure, when the objects are created you can do with them whatever you like. e.g. adding velocity. I update the above snippet with a sample. $\endgroup$
    – Monster
    Jan 8, 2018 at 7:23
  • $\begingroup$ Thanks! I copied the entire snippet, works perfectly...except for the linear velocity... weird. Maybe I missed something? $\endgroup$
    – JPeters
    Jan 8, 2018 at 10:48
  • $\begingroup$ Velocities and forces are considered on physics controlled objects (dynamic, rigid body, soft body) only. You can do other things e.g. start an animation or set a property. $\endgroup$
    – Monster
    Jan 8, 2018 at 21:41
  • $\begingroup$ The thing I'm trying to achieve is: a flowerpot, shooting out random objects with every push of one button. Those random objects are dynamic/rigid bodies. So, could that mean that it IS possible to give them linear velocity? Here's the rough blend-file if that helps, thanks! we.tl/VaPFzhLnKX $\endgroup$
    – JPeters
    Jan 10, 2018 at 13:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .