When I create an object when the spawning object is travelling at speed, the added object lags behind, for what looks like 1 frame.
What I don’t understand is that I thought added objects inherited the speed of the spawning object. So if a gunbarrel travels at 300 b/u’s then added objects (in this case a muzzleflash) travel at the same rate.
Here is the code I am using, as far as I can see nothing is too out of the ordinary:
import bge
def Cannon(cont):
scene = bge.logic.getCurrentScene()
Cannon_barrel = cont.owner
Turret = Cannon_barrel.parent
cannonHelper = [i for i in Cannon_barrel.children if "Cannon" in i]
cannonRay = cannonHelper[0].sensors["Ray"]
cannonRadar = cannonHelper[0].sensors["cannonRadar"]
currentSpeed = Cannon_barrel.getLinearVelocity(True)
if Turret["lapNumber"] and Turret["lapNumber"] > 0 and Turret["const"].valid():
print(currentSpeed)
if cannonRadar.positive and Cannon_barrel["ammunition"] > 0:
muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
Cannon_barrel["ammunition"] -=1
if cannonRay.positive and cannonRadar.positive and Cannon_barrel["ammunition"] > 0:
pos = cannonRay.hitPosition
Cannon_barrel["ammunition"] -= 1
added = scene.addObject('generic_hit', cannonHelper[0], 1)
added.worldPosition = pos
muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
shipHit = cannonRay.hitObject
if shipHit["health"] and shipHit["health"] > 0:
shipHit["health"] -= 1
shipHit["weapon_hit_toggle"] = True
if Cannon_barrel["ammunition"] <= 0:
Cannon_barrel["ammunition"] = 0
It just seems that the object is added too late… attached is a screenshot of what I mean:
The next thing is if cannonHelper[0] is not dynamic it has no velocity either. But I guess it has as you print the “speed”.
Some Remarks:
Try to avoid writing the exactly same code multiple times. I think you already recognized this produced a lot of additional work.
Alternatives:
–> Add a function and call the function
–> re-desing the conditions (they are replicated as well)
using the sensors of another object is pretty dangerous better run the script at the “cannonHelper” (better call it cannonControl or something like that)
the conditions are to complex and therefore hard to read
do not read the list all the time for the exact same element (this is heavier than reading it once and cache it in a variable).
redesigned (and renamed identifier according to PEP008):
import bge
def cannon(cont):
scene = bge.logic.getCurrentScene()
cannon_barrel = cont.owner
muzzleEmitters = [i for i in cannon_barrel.children if "Cannon" in i]
muzzleEmitter = muzzleEmitters[0]
cannonRay = muzzleEmitter .sensors["Ray"]
cannonRadar = muzzleEmitter .sensors["cannonRadar"]
if not Turret["lapNumber"]:
return
if Turret["lapNumber"] < 0:
return
if not Turret["const"].valid():
return
if (not cannonRadar.positive or
not cannon_barrel["ammunition"] > 0):
return
muzzleflash = scene.addObject('generic_gunShot', muzzleEmitter, 2)
muzzleflash.setLinearVelocity(muzzleEmitter.getLinearVelocity(True),1)
cannon_barrel["ammunition"] -=1
if cannonRadar.positive:
hitPosition = cannonRay.hitPosition
cannon_barrel["ammunition"] -= 1 # dangerous you have decreased this value already
hitVisualization = scene.addObject('generic_hit', cannonHelper[0], 1)
hitVisualization.worldPosition = hitPosition
hitShip= cannonRay.hitObject
health = hitShip["health"]
if (health > 0):
hitShip["health"] = health - 1
hitShip["weapon_hit_toggle"] = True
if cannon_barrel["ammunition"] < 0: # shouldn't be necessary
cannon_barrel["ammunition"] = 0
This code is untested, but should give you an idea
First it test for all conditions when the code should not proceed. The conditions are the opposite to your conditions. Indeed you can merge them to larger “if” statements.
Only perform processing when it is needed (e.g. reading linear velocity ;))
Hi guys- you are both right that the muzzle flash is not dynamic- it is just a shape set to no collision as anything else blocks the raycast used to ‘shoot’ through it and hit the target (ghosted objects still receive raycasts). I imagine I will have to re-arrange things or find a new effect.
Monster, why is it dangerous to access sensors from another object? I have to communicate via the parent/child method as my vehicles use several parts (for example the cannon uses six pieces), messages would be more complex, and I wish to avoid globalDict if I can. Since the object that has the sensor is accessed via a list (since the cannon could be duplicated on another racing ship) does this negate any problems? If I kept this as it was, what could /would happen?
It is in that way dangerous as you run logic by one object but you look for events at another one. As you see this is possible. But it is very confusing as there is no obvious relationship between them.
As you do not even touch the sensors of the other object it wiuld
make sense to run the controller from the object with the sensor.
You have to search for the other object anyway.
This enables you to use the sensors to trigger the Python controller when the sensors detect changes. this increases performance.
Additional you can easily see the relationship between the Sensors and controllers at the GUI. This increases reada ility and prevents hard to discover side effects.
Try to make your code as less dependent to other objects (game objects, sensors, etc.) as possible. If you have dependencies try to make it as obvious as possible.
This will help you when your game is growing. Keep in mind you cant hold every detail in your head. Therefore it is good to makeit as readable aspossible.
I see- so is it better to have one sensor (radar or near) that feeds several functions (detecting other objects, collision avoidance etc) or have a radar/ near sensor for each, or is there no net benefit as long as the sensor is not triggered unnecessarily?
Sensors are always evaluated. (…but you can deactivate them with a state switch.) The evaluation eats processing time. Therefore as less sensors you have at the same time as better it is performance-wise.
If you have multiple sensors checking for exactly the same results it is better to use only one of them. Otherwise they do exactly the same work … multiple time. (This is not only true on sensors, it is also true on code).
There might be good reasons to ignore the performance and continue with multiple sensors. This needs to be decided for each situation.
From your code I can see you have a radar and a ray. They both do differentiated things. From first sight this looks ok. Without more details it is hard to guess if one of them is obsolete or not.
What I meant with my above code is:
A sensor of one object should be checked from a connected controller (as this is what a reader would expect when looking at the GUI … and the code).
Please keep in mind, sensors without a connected controller will not be evaluated or in worst case not even exist in the BGE. The above design can easily produce these situations. Therefore it is dangerous.
How would you code a system that exchanges information between objects inside a group?
Since this group of objects can be duplicated in any number I avoided globalDict, and I would have to make any sent message unique (which is possible since I have something similar working already). Creating lists is handy as it (the duplicated parent) searches for any connected children, ensuring each group does not trigger each other.
Was I wrong to take the approach I did, or am I underestimating the capabilities of messages and globalDict?
No you approach was fine. You searched through the parent/child tree. This is one of the options to do that.
A) parenting -> parent the objects of the group together (not always applicable) then parse through the tree
B) interobject connection -> connect logic bricks of different objects together (can easily produce ugly and complicated structures)
C) combination of both
D) other
You can have a look at LinkLib (see my signature) it uses the uses the parenting method as well.