A script for camera-actor moving (for a ball)

Is there any script, (or built-in method) that can make my actor follow the camera axis instead of the globar axes? I mean, if i set uparrow as “goin forward” the actor will continue going forward depending on the view of the camera? Like all the “Normal” games.

The difficulty is that my actor is a ball that rotates, so none of the pre-buit options in blender can help me, i think.

If your problem is making an object track the ball without rotating then you can place a single, unconnected vertex on the ball’s mesh at the centre of the ball. Vertex parent an empty or other object to this unconnected vertex and the empty/object will track the position of this vertex (the position of the ball’s center) without rotating.

You might then be able to use the orientation of the empty/object to direct any forces you apply.

Hope this clue leads you closer to your aim. I’ve never tried this yet.

There are a couple of rolling ball games in the game competition so you could see how it was done there.

yes that’s a solution for that.ì, but it’s relatively my minor problem. Once the camera is behind the ball, let assume, after turning right, the player have to continue pressing “right” notwithstanding from the view for the camera it’s going straight, because uparrow is still pointing to +Y and never change.

Which games are you refering to? There so many

alignAxisToVect localOrientation

I saw things like this, can these be the solution? How do i use this?

Off the top of my head…

Maybe an empty isn’t necessary. Vertex parent your camera directly to the ball, as above. Use camera.getVectTo(ball) to get the global vector from camera to ball. Then normalise this vector to get it of unit length. You could then multiply that unit vector by the linear force you want to apply in order to get the component forces along global axes.

These global component forces could be applied to the ball in global space to accelerate it by the correct amount.

I have a knack for finding the most contrived and inappropriate solutions for problems :wink: so there may well be a simpler way of doing this, but it seems that this method might work.

Good luck. :slight_smile:

Edit: Slideball is a good game in the competition. It’s well worth checking out in it’s own right. Not sure if the .blend is available, but the control mechanism sounds very much like what you’re after.

Edit 2: If you’re new to Python then there are quite a few decent links scattered about the forums. Most game Python help can be found on the “Game engine support and discussion forum”. Check out the thread “Python for new people”. Some of the game Python tutorials are a good start too. I make extensive use of the API reference that can be found here:
This is the wrong API to use in games. Sorry. :o
http://www.zoo-logique.org/3D.Blender/scripts_python/API/

This is the correct one:
http://www.tutorialsforblender3d.com/GameDoc/index_GameDoc.html

There are some pretty good code examples interspersed with a well organised representation of the API.

I think you can help me. That’s the kind of solutions i was looking for. I started studying python (for GE) this afeternoon, so you can immagine where I am. Examples helps much more. IF you have time, can you write me the text to enter in blender text editor to have camera.getVectTo(ball) set correctly, shall I text it changing to my names directly after “import game logic?”

import GameLogic
controller = GameLogic.getCurrentController()
from Blender import Camera, Object, Scene
vect = Camera.getVectTo(palla)

This report an error: Attribute error: ‘module’ object has no attribute ‘getVectTo’

Where am i wrong?

Just messed about a little, and the getVectTo() function return distance and unit vector.


import GameLogic as G
import Mathutils as M
 
scene = G.getCurrentScene()
 
for obj in scene.objects:
     if obj.name == "OBBall":
          ball = obj
     if obj.name == "OBCamera":
          camera = obj
 
vecTo = camera.getVectTo(ball)
 
distance = vecTo[0]
vector = M.Vector(vecTo[1])
 
print distance
print vector
 
#an example of how vectors can be used to do things that lists can't
print vector * distance
print M.Vector(ball.position) - M.Vector(camera.position)

I imported Mathutils in order to define an actual vector object from the list that is returned by getVectTo() since they have useful properties such as being able to multiply the vector by the force you want to apply.

Check out the functions in the API reference that I linked above to learn more.

Edit: You got an error because the getVectTo() function is a method of a game object. You must first get the game object and then call the function from that game object as I did above.

Edit 2: Oops!!! I linked the wrong API!! The game engine API is here:
http://www.tutorialsforblender3d.com/GameDoc/index_GameDoc.html

(gonna edit the post above, too)

The script works finally, but didn’t solve my problem. The arrows-movement are stil fixed to the global axes.

Can this fuction?
getAxisVect(vect)

For the edits: AAAAAAAAA


import GameLogic as G
import Mathutils as M
 
scene = G.getCurrentScene()
cont = G.getCurrentController()
act = cont.actuators['act']
 
for obj in scene.objects:
 if obj.name == "OBCube":
  cube = obj
 if obj.name == "OBCamera":
  camera = obj
 
vecTo = camera.getVectTo(cube)
distance = vecTo[0]
vec = M.Vector(vecTo[1])
 
force = [vec[0],vec[1],vec[2]]
act.force = (force)
cont.activate(act)
 
print distance
print vec
#an example of how to use vectors
print vec * distance
print M.Vector(cube.position) - M.Vector(camera.position)
print act.force

I’ve got stuff to do now, but I’ve added a couple of lines to the script above to make it do some stuff.

In blender’s default scene add a plane below the default cube and scale it up so there is a surface for it to fall on.

In the logic settings for the cube, set it to “rigid body” and attach an always actuator to the python controller to run the script and to a “simple motion” actuator.

On the motion actuator make sure the little “L” next to the force parameters is unchecked. This makes the force act globally.

The script will apply a constant force along the line from the camera to the cube.

With a bit of messing about and learning you should be able to make changes that will do what you want.

Good luck. :slight_smile:

Edit: Uploaded a .blend to Pasteall:
http://www.pasteall.org/blend/225

OK, I’m really beggining to understand now.

How can I add rot and loc to the script? Or it will not function? Or how can i give details, like aumenting or reducing the force?

Can I
applyMovement

and
applyRotation

inside yuor script? (Folowing th camera axes)

how can i give details, like aumenting or reducing the force?


#This will halve the force applied
multiplier = 0.5
 
vec *= multiplier

Before you set “force = […]”

This is the joy of vectors as opposed to lists since you can use scalar multipliers on the whole vector instead of multiplying each component.

How can I add rot and loc to the script?

The script applies force to the object so the loc and rot are managed by the physics library. Moving an object by physics is more reliable for collision detection than incrementing loc anyway.

Or did I misunderstand the question?

To rotate the camera around the ball, I’d vertex parent an empty to the centre of the ball and then parent the camera to the empty. The camera could then be rotated around the ball by rotating the empty. It would also stay in the same position relative to the ball as the ball moves.

You got it. Thank you again. I tried to change the parameters of force, damping, mass but none of this has since permetted me to eliminate the time between a movement and the opposite movement when using force. Is there a metthod to “accelerate” this changing of direction?

If you want to drive the object directly instead of using forces then try the setLinearVelocity() method on game objects.


import GameLogic as G
cont = G.getCurrentController()
 
obj = cont.owner
 
linV = [0,1,0]
obj.setLinearVelocity(linV,0)

To use this with the script above, substitute “act.force = (force)” for “cube.setLinearVelocity(force,0)”. Then you could change “multiplier” to whatever seems good.

You could then delete the lines that set up the motion actuator and get rid of the motion actuator from the logic blocks.

Alternatively, you could research servo motion and use a servo motion actuator then tune it to behave how you want.

Edit: Not had much experience with servos myself so had a bit of a mess about. Here’s a .blend:
http://www.pasteall.org/blend/228

Change the Max and Min values on the servo actuator to change the maximum and minimum forces applied. Higher values will change velocity faster. The linV values are the target speeds as set in the script. The P,I,D values also change how the servo acts.

In the .blend, I set the Q and E keys to increment/decrement the multiplier so the direction and magnitude of the target velocity can be altered. You should see that the cube returns to rest/goes the opposite way pretty quickly with the current settings.

I find experiments are the best way to learn, but it’s good to have a starting point to work from. :wink:

Just noticed… In the script, I use the original variable name “force”. In this implementation this is confusing. A better name would be “targetVelocity”.

Edit 2: Shrunk down the script a bit to see how small I could get it. :wink:


import GameLogic as G, Mathutils as M
scene = G.getCurrentScene()
cont = G.getCurrentController()
act = cont.actuators['act']
for obj in scene.objects:
 if obj.name == "OBCube": cube = obj
 if obj.name == "OBCamera": camera = obj
vec = M.Vector(camera.getVectTo(cube)[1])
vec *= cube['multiplier']
act.linV = [vec[0],vec[1],vec[2]]
act.useLocalLinV = False
cont.activate(act)

12 lines isn’t bad, I don’t think. :smiley:

OK, i think this last one is the best for now, i could even add some force to produce more “inertia”

Does servo control behave well with collisions?

How can i set this

OBCube.moltipleier= x,000000000

that appears everytime i start the game to appear to the player too, mayble like a velocity measurement

Is there a way to change the velocity by duration of the pressing instead of the number as it’s now

Change the values on the servo controller. You have to get a feel for this yourself. The multiplier and vector only sets the maximum velocity. The servo itself handles how fast and smooth acceleration is due to the maximum/minimum force available and the PID settings. Reduce the numbers for the maximum force to get it to accelerate more slowly or change the PID settings to change how stongly/weakly the servo applies the available force.

Servo control uses forces so is good for physics and collision detection. The servo decides how much force to apply based on the settings you give it. It will not exceed max or drop below min, but the exact force at any given time is not easy to determine. This gives smooth acceleration/deceleration.

You could have 2 servo actuators with one controlling acceleration when a button is pressed and another controlling deceleration when no button is pressed.

How can i set this

OBCube.moltipleier= x,000000000

that appears everytime i start the game

Not sure what you mean… Print the speed to the screen? This can be tricky in BGE due to the poor support for text, but there are ways. Try searching for “blender game text tutorial” or something for one of the methods available.

How do I do that?

How do I do that?

I’d use a keyboard sensor set to All Keys and False level triggering, an AND controller connected to the deceleration servo actuator with target velocity set to 0. Not sure if this is the best way.

A very strange thing. The file i was developing my self didn’t show it. I copied everthing exatly as you did in push_cube2, but nothing. The “print debug info” is pressed down. Where did you set that property to appear?

“Show debug properties” in the Game menu then press the little D button next to the property in the logic panel. You might have forgot to press that button. Only properties that are set to debug like that will be displayed.

Hope it’s coming along well. :slight_smile: