1
$\begingroup$

8 years using blender and still, never tried the Python API. Never too late to begin! Then I was stuck on something very frustrating, tried 2 days, created variant, searched for bugtracks and looking for others stack thread.

The context

I'm working on a "civ-like" game with tiles. To generate my map I want to run a small "buildmap.py" script allowing to place tiles and control them.

So, I put the tiles and tiles variant on my second layer and call them from the first layer with a "spawner" Empty object at the launch of the scene:

Always (tap) -> python : buildmap.py

Here is the code :

import bge

world = bge.logic.getCurrentScene()

world.addObject("Tile", "spawner",0)

The problem

When I launch the game everything looks good, the tiles are placed at the right places. Then I clicked on the first one... And realized that my script putted 2 "Tile" objects on each position. I removed the loop to study the addObject and branch it to a keyboard with same result. By calling once addObject it places 2 objects.

Maybe I’m missing something ? so I came here :)

$\endgroup$
  • $\begingroup$ What happened to your project? $\endgroup$ – user58715 Jul 10 at 20:08
2
$\begingroup$

Do not enable the [Tap] option. It makes no sense.

Background

The Always sensor "always evaluates positive".

Any sensor will trigger all connected controllers when the evaluation result changes (from not positive to positive and from positive to not positive).

As the always sensor never evaluate not positive, it will only trigger when the object was just created. So it is more a "is created" trigger.

There are configuration options that modify the behavior of the sensor. You set the Tap option. This option changes the behavior of the sensor to evaluate not positive the next frame after evaluating positive, regardless of the real situation. This was introduced to make the use of the keyboard sensor a bit more comfortable.

As you enabled that option, you get this processing from the always sensor

  • frame 1: evaluate positive -> (result changed): trigger the controller
  • frame 2: evaluate negative (because of Tap) -> (result changed): trigger the controller
  • frame 3+: evaluate negative -> no trigger

Solutions

Assumption: single trigger

With the default settings (no Tap, no Triggering Levels, no Inv ...) the always sensor (and the delay sensor) will trigger the controller exactly once.

With that Assumption (one trigger) you can run your Python code as is.

Common use case

When you have different settings or other sensors (like a keyboard sensor) you need to implement the supposed behavior of a controller.

You ALWAYS check the status of ALL connected sensors and consider that in your custom code.

if all(sensor.positive for sensor in bge.logic.getCurrentController().sensors):
    ...
else:
    ...

Remark: even the basic controllers (AND, OR ...) do that. That is the minimum code you should write (unless the above assumption applies).

$\endgroup$
  • $\begingroup$ Omg i'm sooo idiot x) , never realized that the process behind an "always" was separated. thank you so much for the clear answer <3 $\endgroup$ – QuentinVB Apr 27 '18 at 8:39
  • $\begingroup$ @Monster Could I use tap on this as a counter for positions? For example, put a house and with each tap make it turn 90 degrees + / - before giving the last click to place it? Do you think this is valid to start a question? $\endgroup$ – user58715 Jul 10 at 20:06

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.