trouble with the ipo actuator and python

I am having trouble with playing an IPO. My goal is to press the right-arrow, and have my tire turn to mimic steering. I would like it to play it as a flipper, so that when the button is released, the animation doesn’t finish, but returns to frame 1. Essentially, I would like to get the same effect as if I wired it as below, but instead write it completely in Python:

http://www.geocities.com/treacy_brian/logicBrick.png

The problem I am having is this: When I press the right arrow, senright returns positive, and my if statement executes, and the ipo doesn’t play until I release the right arrow. I have tried many different things to fix this, and searched the forums, and I suspect that I need to use something like setUsePosPulseMode() or setPosFrequency, but i can’t seem to get that to work either. Does anyone have any suggestions?

Also, the game kit documentation says that there are 6 ipo play types; does accessing the list begin with setType(0) or setType(1)? Thanks for helping with these two questions.

-Brian

###############################################################
###############STOPPED#########################################
if dirX == 0 and dirY == 0:
	forward = 1
	print "Stopped", orient
	senup.setKey(146) #up-arrow
	sendown.setKey(144) #down-arrow
	senleft.setKey(143) #left-arrow
	senright.setKey(145) #right-arrow
	if senup.isPositive():
		move.setLinearVelocity(1, 0, 0, 1)
		tfr.setDRot(velocity/10, 0, 0, 1)
		tfl.setDRot(velocity/10, 0, 0, 1)
		tbr.setDRot(velocity/10, 0, 0, 1)
		tbl.setDRot(velocity/10, 0, 0, 1)
		GameLogic.addActiveActuator(move, 1)
		GameLogic.addActiveActuator(tfr, 1)
		GameLogic.addActiveActuator(tfl, 1)
		GameLogic.addActiveActuator(tbr, 1)
		GameLogic.addActiveActuator(tbl, 1)


	elif sendown.isPositive():
		print "sensor down is pressed"
		forward = 0
		backward = 1
		move.setLinearVelocity(-1, 0, 0, 1)
		tfr.setDRot(-velocity/10, 0, 0, 1)
		tfl.setDRot(-velocity/10, 0, 0, 1)
		tbr.setDRot(-velocity/10, 0, 0, 1)
		tbl.setDRot(-velocity/10, 0, 0, 1)
		GameLogic.addActiveActuator(move, 1)
		GameLogic.addActiveActuator(tfr, 1)
		GameLogic.addActiveActuator(tfl, 1)
		GameLogic.addActiveActuator(tbr, 1)
		GameLogic.addActiveActuator(tbl, 1)

		
	elif senright.isPositive():
		print "sensor right is pressed"
		tfrsteer.setType(3)
		tfrsteer.setStart(1)
		tfrsteer.setEnd(16)
		
#		tfrsteer.setDRot(0, 0.1, 0, 1)
#		tflsteer.setDRot(0, 0.1, 0, 1)
		GameLogic.addActiveActuator(tfrsteer, 1)
		GameLogic.addActiveActuator(tflsteer, 1)

Hi, this is one way you could do it.


import GameLogic as g
c = g.getCurrentController()
o = c.getOwner()

if c.getSensor("Lt").isPositive() and o.steer > 2:
    o.steer = o.steer - 2
if c.getSensor("Rt").isPositive() and o.steer < 198:
    o.steer = o.steer + 2

if o.steer > 100: o.steer = o.steer - 1
if o.steer < 100: o.steer = o.steer + 1


This should return the o.steer value to 100 when nothing is pressed, so make your tires centred on frame 100. Tweek all the values to suit your needs. Im not too keen on this code to be honest, and feel theres a much tidier way to do it, but hay hoe. Hope it helps in any way.
Set the ipo type to property, and use the o.steer value, instead of a flipper.
nb. You`ll need to name your left and right steering key sensors, Lt and Rt, or what ever you want, just so you know man. :slight_smile:

Thank you for the help. Could you explain a little of your code to me though; I am new to Python and have never used the IPO property type actuator.
-Brian

Hi again, this is just one way to do it…:slight_smile:

Im assuming that your after a car type of steering. So youve probably got atleast 3 objects. (main car, left and right front wheels.)

If you start by rigging up the front wheels with this sca setup.

always -> and -> ipo (with property, steer.)

Name the above two always sensors LtFront and RtFront accordingly, for example.
I would try it with the always unpulsed, and remeber to add the prop steer to each of the obj, wheels.

Now, with all three obj selected, (car + left wheel + right wheel), cross link the always sensors on the two wheels to the car, which is where i would be running the main movement script.

Now add the following code to the previous stuff, just below the line which reads, o = c.getOwner()


ltfront = c.getSensor("LtFront").getOwner()
rtfront = c.getSensor("RtFront").getOwner()

Im not too sure how much python you know, so ill go from the point of view of myself first learning which is very little. :slight_smile:
The above lines now give you access to the front wheels as the o = c.getOwner() line give you access to the controller of the script. So… a line of o.setPosition([x,y,z]) will position the object running this script, ltfront.setPosition([x,y,z]) will… yep, set the position of the ltfront wheel.

Lastly, at the very bottom of the script, type.

ltfront.steer = rtfront.steer = o.steer

This is copying the prop steer values which you placed on the front wheels, to that of the o, main car running the script.

That, hopefully, should get the front wheels turning and you should be able to start tweeking and adjusting the ipo itself for the wheels and then the values within the script.

One of the handiest things i read was the dir function.
If you wanna try and find out about something, type.

print dir(somethinghere)

try putting o, or ltfront or rtfront inplace of somethinghere in the brackets. Try leaving the .getOwner() off the end of the ltfront, so you get hold of the actual sensor rather than its owner, then putting that between the brackets, look in the console window. Type one of the things inplace of the .getOwner() you just deleted, and print dir(?) it again.
I personnal found this really helpfull to start. Umm, you can do the same with the actuators just name the actuator then do a,

briant = c.getActuator("whatyounamedit")
print dir(briant)

Hope any of this helps or even just makes sense ;), i`ve kinda done it on the fly so…any problems. :slight_smile:

-Daz.

Thanks for the help, I think it is a great approach to my problem. I did have a couple of problems with it that you can probably help me with, and btw, thanks for sharing with me the print dir() function; I agree: it is a great help.

I set everything up just as you said, with a few minor changes. Here is the script as I have changed it:

import GameLogic as g 
c = g.getCurrentController() 
o = c.getOwner()
ltfront = c.getSensor("LtFront").getOwner() 
rtfront = c.getSensor("RtFront").getOwner()

if c.getSensor("LtFront").isPositive() and o.steer > 1: 
    o.steer = o.steer - 2 
if c.getSensor("RtFront").isPositive() and o.steer < 32: 
    o.steer = o.steer + 2 

if o.steer > 16: o.steer = o.steer - 1 
if o.steer < 16: o.steer = o.steer + 1

ltfront.steer = rtfront.steer = o.steer

I also added an int property named steer to the car and the two front wheels, each with a value of 0.

My car has an always sensor (pulse off) wired to the python controller.
Each tire has a keyboard sensor(pulses off). Each tire is wired to its own AND controller, and then wired to its own IPO property actuator (Prop: steer). The tires are also wired to the python controller that the Always sensor is wired to. I also turned debug on for all of the properties. Here are the problems I am having:

  1. When I start the game, the wheels don’t turn to frame 16. They just stay still; though, the debug shows that the properties are automatically counting to 16 and stop.

  2. If I press left or right, either the left or the right tires turn appropriately, but not together. When I press left, the left tire turns, but the right tire stays still. When I press the right arrow, the right tire turns but the left tire stays still. Neither return back to frame 16. Both, however, show the debug properties as adjusting correctly.

  3. I don’t understand why the car itself also needed the steer property. I know that it needs to be there because I got a bunch of attribute errors after I temporarily deleted it. Can you explain this to me?

Thank you again for the help.

  • Brian

Hi.

  1. You could try setting all the prop steer values to 16 as defualt. Hopefully this will make the wheels start in the middle of your ipo.
    Also, you want the script to be executed as often as possible, so turn pos/true pulse mode on.

  2. Think this may be to do with the script not being executed continually. See the last sentance above.

  3. Um, this is just how i personnally like to do it. :slight_smile: If you keep all the main prop values on one/the main object for instance, its easy to multiply properties together, without having to go off and get them. So, a crude one line example would be,


o.rotationofcar = o.velocityofcar * (o.steer-16)

rather than,


objA.rotationofcar = objB.velocityof car * (objC-16)

In most cases, i just find it easier to manipulate prop values within one object and then just copy the end result out. (probably not the best way to do it.) :slight_smile:
or,
Ive just read what you said a different way. :) Er, not sure how correct i am with this, blender at the moment, again, doesnt allow global variables or variables created on the fly.(or something like that.) so you need to create the propsteer` as its being used by the script which your running on the main car. Then copying it out to the two front wheels. :slight_smile:

Hope this helps.

-Daz.

I changed the default values of the properties to 16 and changed the keypresses to positive pulse, but neither changes fix the problems I’m having. Would you be willing to look at the .blend? Here is a link to it:

http://www.geocities.com/treacy_brian/test-steering.zip

  • Brian

hi,

On your carlogic, you want to have a PulseOn always sensor, a Keyboard sensor for the left steering called for example, LtArrow, and another one for steering right, RtArrow.
All three of these are linked to the script, and the always should be the only one with pulse turned on. (Not actually sure if having all the above sensors pulsing the script continually makes the script be executed more often?)

Change the names of the two newly created above keyboard sensors and make them different to that of the Always sensors your also getting hold of from the front wheels. Calling them as above LtArrow and RtArrow for example.

Then edit the names of the sensors you getting hold of within the script.


if c.getSensor("LtFront").isPositive() and o.steer > 1:

to


if c.getSensor("LtArrow").isPositive() and o.steer > 1:

Just do the same for RtArrow.

The above line, for example, is just checking to see if the left arrow is being pressed and that the property o.steer is greater the 1. If both of these are true, it will execute any indented lines directly below it.

Then just change the keyboard sensors you have on the front wheels to always sensors and unpulse them.

The always sensors on the front wheels are just there to continually fire the Ipo for the front wheels. Its just for vague neatness that they`re named and connected to the carlogic script too. You could name the Ipo actuator and get hold of them that way. Instead of,


ltfront = c.getSensor("LtFront").getOwner()

it would just be,


ltfront = c.getActuator("TheNameOfYourActuator").getOwner()

in the script. You could also do it with just the ipo actuator connected to your script and fire it from within the script. But i personnally just like to do it with the always sensors.

Great looking file, by the way. :slight_smile:

-Daz.

That works! Thanks for the help, I really appreciate it. I am intrigued, however, about doing it all in python. Working on this (on my own and with help from the forum) has really helped me with my python skills.

I will have quite a few cars to add this to, so I wanted to make it as portable as possible: doing most of the work once in python with as few logic bricks to add as possible.

I’ll go ahead and do some experimenting on my own, and write back if I have any problems.

Thanks again,
-Brian