Script problem - this shouldn't be happening

Hello,

I have a strange maths problem. if you follow the script and calculate the rotationAngle, it should be 0 when the Power is 0. But I always get the result 0,08333 as a result?!
can someone please take a look at this script and tell me what’s wrong?!
The Property Power is a timer that is set to 0.00. I want it to have a maximum of 2 seconds, that’s why I divide the PowerPercentage with 0.2…

(I never know which modules to import, so I import them all)

from bge import logic
import math
import bpy
import GameLogic as logic
from math import sqrt
from math import *
from mathutils import *
import mathutils as mt

cont = logic.getCurrentController()
Twintip = cont.owner

Power = Twintip[“Power”]

PowerPercent = Power / 0.02
RotationAngle = PowerPercent * 0.1
Twintip[“RotationAngle”] = RotationAngle

Twintip.setAngularVelocity([0, 0, RotationAngle], 1)

Thanks in advance for your help!

Being a “timer” variable, Power increments at each iteration by 1/60 [secs] = 0.01666… [secs].
Thus when the script is called the first time its value is 0.01666, and RotationAngle = 0.1*(0.01666/0.02) = 0.083333.
Therefore a possible diagnosis could be that you call the module only once: have you activated at least one level triggering pushbutton?

mb

hmm… yes I have the timer just activated when y-key is pressed (True pulse On and Invert)… and in the debug properties I can check that the Timer is set to 0.0000 but the object keeps rotating with 0.08333

Sorry, it is not clear to me what you want to obtain.
Do you want Twintip to rotate (or may be accelerate?) every time the y-key is pressed, but for for no more than 2 seconds? Why do you expect that this can be achieved by dividing PowerPercentage by 0.02?:

The Property Power is a timer that is set to 0.00. I want it to have a maximum of 2 seconds, that’s why I divide the PowerPercentage with 0.2…

To clarify a bit: twintip should rotate faster when the power is more (or the longer you hold the key). In other words; The longer you hold the Y-key, the faster it rotates. But you should not be able to hold longer than 2 seconds.
E.g.: if you hold the key for just 0.5 seconds, the rotation should be 2,5 angularV
0,5/0,02 = 25
25 * 0,1 = 2,5

if you hold it for 2 seconds which is 100% the rotation schould be 10 angularV

The 0,02 is just 1% of the 2 seconds (2/100=0,02)

I hope it is more clear now

Best supply a blend, for this may be implementation error.

Ok, here’s a prepared blend (my game would be 80mb).
In this example I have two objects, Cube1 and Cube2.
Cube1 is rotating with torque-force. This is the result I want to achieve.
Cube2 is rotating with angularVelocity. There the problem is visible.

Cube1 has the result I want to achieve. Unfortunately, I cannot use torque because it brings other problems that I cannot solve… Now I need to achieve the same result as the torque rotation with DRot. I also need the rotation not to stop abrupt but like with torque with a smooth and slow damping.
I tried to use DRot but blender doesn’t recognize the command anymore (object.setDRot()) What is the new command for blender 2.6?

Furthermore I wanted to constrain the timer to 2 seconds. Therefore I implemented an if-statement: if Power <= 2: But it seems that timers are not held as integers or floats. Is there a way to convert it, or how can I access the timer? (Also tried to constrain it with an interval property, but the timer doesn’t seem to respond to integer numbers…)

I hope someone can help me out. Thanks for all help!!!

http://www.pasteall.org/blend/9959

Greetings André

Furthermore I wanted to constrain the timer to 2 seconds. Therefore I implemented an if-statement: if Power <= 2:
if power is less than 2???
don’t you mean if power is greater than 2?

…DRot…
Please, [sob] don’t use DRot [sob]… Even if it does work (or it’s replacement, setRotation (I think)) it is a nuicance. If you rotate to close to a wall, you start rotating through. Remember what happens if you use the “loc” setting on logic bricks? It’s lie that.

here’s some new code, with a few important changes:

import bge


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

power = obj["Power"]

print (power)


#Instead of using a timer I used the script
key = cont.sensors["Keyboard"]
#Seeing if the key is pressed, if it is then adding 0.1
if key.triggered:
    power = power + 0.1
else:
    power = 0

#Maxing it out at 2
if power &gt; 2:
    power = 2

#Assigning the property power to it's new value
obj["Power"] = power
    
#Stuff from your sctipt
powerPercent =  power / 0.02
rotationAngle = powerPercent * 0.1

obj["RotationAngle"] = rotationAngle

obj.setAngularVelocity([0, 0, rotationAngle], 1)  

Myself I don’t like timers, I find them un-predictable. So instead I use a property that always adds, or in this case, the script decides whether to add or not.
So copy/paste the script and re-wire your keyboard sensor to connect to the python script, and get rid of the “invert.”
Get rid of the toggle logic brick, and make the former timer property into a plain old “float” as well.
If you don’t understand any of the script, then just ask.

There are a few script-writing conventions that you should take note of:

  1. “obj”. The cont.owner is ALWAYS either “obj” or “own”. This is just so that you don’t get confused if you run the same script from more than one object, as is the case when games get more complex.

  2. camelCode. In all languages, for some stupid reason we have camel-code. What this is is that any property name, object name etc has lower case first letter, and any subsequent words in the name have capitals, so it is “power” or “powerPercent” or “thePowerPercent” or “theAwesomePowerPercent” or maybe “iThinkYouGetTheIdeaNow”. Don’t ask me why this is convention, it just is.

  3. only import what you need.

from bge import logic
import math
import bpy
import GameLogic as logic
from math import sqrt
from math import *

from mathutils import *
import mathutils as mt

Keh!!!
This chunk of code imports the same thing quite a few times. It imports math twice, sqrt three times (in the math, and by itself), game logic twice, and mathutils twice.
In general you only need (and in this case) the module “bge”

You use math for complex maths (sqrt, sin, cos, tan, etc)
You use mathutils for vectors

To use part of a module, use:
moduleName.functionName

While there is no harm in importing to many, it just isn’t good practice.
If you want to use “GameLogic” you can replace it with “bge.gameLogic”, saving you importing that module.
I would replace that whole chunk with just:

import bge
import bpy (which can't be used in game I think, just check up on that)
import math
import mathutils

then in a script you can use:

math.sqrt
bge.logic
mathutils.vector

etc

I hope I haven’t put you off here (I can be a bit pedantic), python is a valuable tool, and one that is essential to creating good games in blender.
If you want the modified blend then just ask.

May be previous posts have solved your problem.
If not you can try this, that behaves like cube 1 in your sample file for me:

import bge, GameKeys
  
# define limiting function
def limit(x, min, max):
    # Limits x between min and max
    if x &gt; max: out = max
    elif x &lt; min: out = min
    else: out = x
    return out

deltaSpeed = 0.001  # speed increment per iteration [radians per iteration]
speedMax = 1  # radians per iteration

obj = bge.logic.getCurrentScene().objects['TwinTip']
speed = obj['speed']  # get current speed

# get Y key status:
YkeyStatus = obj.sensors['InputKey'].getKeyStatus(GameKeys.YKEY)

# if Y-key is pressed increment speed, otherwise decrement:
if YkeyStatus == bge.logic.KX_SENSOR_ACTIVE:
    speed = speed + deltaSpeed
else:
    speed = speed - deltaSpeed

# limit speed between 0 and speedMax
speed = limit(speed, 0, speedMax)
obj.applyRotation([0, 0, speed], True) # apply incremental rotation
obj['speed'] = speed # save speed for next call

Set variables deltaSpeed and speedMax according to your needs.
The script is associated to a keyboard sensor named inputKey with both level triggering buttons pressed.

sdfgeoff is correct - it’s always a good idea to only import what you need. It’s also not a bad idea to just import modules instead of importing * from modules, because if the modules are custom-written, you can have some naming conflicts.

Also, GameKeys is not used in Blender 2.6. It’s bge.events now.

I’ve tested the script with GameKeys and it works.
I don’t know whether in the future it will be totally replaced by bge.events, but for now it is not even deprecated, as far as I know.
Something similar occurs with bge.logic and GameLogic: they are equivalent and both valid in blender 2.60.

mb

wow, thanks a lot guys!! this is really helpful, also for my further python scripting. I am just starting now to involve more and more python scripts, but game logic is so easy and for lazy people like me :slight_smile:

For the modules… I just imported them all, because I never know which module when to import. But now I can see things more clearly.

Very helpful, thanks again!

ok, now my scriptproblem got to the next level :slight_smile:
I’ve been trying to program this all day, but I cannot find out how to do this.
What I want to do:
Take a look at the youtube Link: http://www.youtube.com/watch?v=kaxltQTaSK0

I want to do the same like the jumping and trick-system of supreme snowboarding.
That means - when board is touching the ground and left or right is pressed the rotation has a fixed value and the board is either turning left or right.
When pressing space, but still on the ground (space for jumping), the normal left/right-rotation stops -> you are not able to steer anymore. Instead the rotation for the jump begins to load.
As soon as you release the jump-key, the board starts rotating with the last value of the rotation-loading.

What I could do so far:
-The board is rotating right when jump-key is not pressed and it has contact with the ground. I don’t know why, but to the left it doesn’t work??? I’ve got exactly the same script there…

-When I press space, the normal left/right rotation stops and the jump-loading-rotation starts. when I release the space-key, the board turns with the last value assigned to the jump-loading-rotation. (with jump-loading-rotation I mean the lower left arrows in the clip)

Unfortunately, the board keeps on turning forever until space is pressed again. I need the rotation to stop slowly like with damping.

Furthermore the right rotation when not pressing space is abrupt… there is either on or off, not smooth (i’ve tried to do it with:
groundContact.positive and rightKey.triggered and jumpLoading == 0:
rotationAngle2 = rotationAngle2 + 0.3

but it doens’t count up step by step, instead it is directly 0.3)

And another question: To check if a key is released is this command right " if spaceKey.status == 2:" ?

Here’s the file, kind of hard to explain, it’s easier to understand in the file. I also made some comments…

http://www.pasteall.org/blend/9985

I hope you guys could help me out, my head is exploding and this seems to be out of my programming skills.

I used sdfgeoff script as a base!

Thanks in advance for your help!

You mean something like this?

May be you can find the source blender file on the web.

nevermind, found the solution today, hehe… sometimes it helps to get some distance and do something completely different :smiley: