(Probably Basic) Python Questions.

Hello there, not too long ago I posted about help for too much logic, and was told that python would be the best route for fixing my problem. So I’ve decided to learn python! I tried typing a simple movement script from what I remember from like a year and a half ago, and its not quite working.

heres the code.

import bgeg = bge.logic
o=g.getCurrentController().owner
cont = bge.logic.getCurrentController()
own = cont.owner
move = cont.actuators["move"]
up = cont.sensors["up"]
down = cont.sensors["down"]
left = cont.sensors["left"]
right = cont.sensors["right"]


if up.positive:
    move.dLoc [0.0, 0.0, 0.02]
    cont.activate(move)
    
if down.positive:
    move.dLoc [0.0, 0.0, -0.02]
    cont.activate(move)


if left.positive:
    move.dLoc [-0.02, 0.0, 0.0]
    cont.activate(move)
  
if right.positive:
    move.dLoc [0.02, 0.0, 0.0]
    cont.activate(move)
  

So here are my questions.

  1. Why isnt my character moving?
  2. Is it possible to move other objects through the script?
  3. How would I use a property? like “if property [name] = 0, then do this” and “set property [name] = 1”

Thanks in advanced for any help!

Hey there. First, is your character set to dynamic physics type? if so i’d recommend using applyMovement. As far as i know or investigated i think dLoc is outdated (Still learning python, so sorry if i’m worng :)), here’s a small movement code i made for my game using applyMovement:


from bge import logic
cont = logic.getCurrentController()
own = cont.owner
wKey = cont.sensors['W']
aKey = cont.sensors['A']
sKey = cont.sensors['S']
dKey = cont.sensors['D']
qKey = cont.sensors['Q']
eKey = cont.sensors['E']


if dKey.positive:
    own.applyMovement([1.0, 0.0, 0.0], 1)
if wKey.positive:
    own.applyMovement([0.0, 1.0, 0.0], 1)
if sKey.positive:
    own.applyMovement([0.0, -1.0, 0.0], 1)
if aKey.positive:
    own.applyMovement([-1.0, 0.0, 0.0], 1)
if eKey.positive:
    own.applyRotation([0, 0, -0.05], 1)
if qKey.positive:
    own.applyRotation([0, 0, 0.05], 1)    

Maybe it’s not the prettiest thing, but it’ll probably help you understand.

As for your other questions. Yes you can move objects with the same script you’re using for you player. First you have to get the other object’s name by using something like:


otherObject = [obj for obj in bge.logic.getCurrentScene().objects if obj.name == "otherObject"][0]
#Do whatever you wanna do.
#For example rotation for both the player and the other object:

own.applyRotation([0, 0, 0.05], 0) #This is for the player
otherObject.applyRotation([1.0, 0, 0], 0) #This is for the other object

#For movement, you would need to use the same method i used in the first code up there, say:
if wKey.positive:
own.applyMovement([1.0, 0.0, 0.0], 1)
otherObject.applyMovement([0.0, 1.0, 0.0], 1)

And for the properties, it’s pretty simple. First you have to set the name of the property. If it’s in your player object, then use


own = cont.owner

testProperty = own["property1"] #Get the property name

#Now change the property if the value is "0". This will change the value of the property in the object that has the script.

if testProperty == 0: # "==" is used to compared the value of the property
   own["property1"] = 1

#You can do whatever you want with the property or objects in the scene from here

Hope this helped! If you’ve got any questions, feel free to ask. The community here is awesome :slight_smile:


import bgeg = bge.logic
o=g.getCurrentController().owner
cont = bge.logic.getCurrentController()
own = cont.owner

you also got something qwerky going on here

if this is what youve got in your script then its probably wrong…and your defining owner twice…once as o and once as own…

if this is how this line is in the script
import bgeg = bge.logic

then thats not going to work…maybe your trying to import logic as bgeg or your trying to define logic as g. i cant really tell. looks like where 2 scripts were pasted together and people had different styles. just clean that up a bit


import bge
from bge import logic
cont = logic.getCurrentController()
own = cont.owner


also keep your console open…more than likely this error would have showed up in the console window and told you where to look for problems. I would agree with socker to do away with the movement actuator and just applyMovent directly in progress. The only thing that i would do different is since it is dynamic i would use localLinearVelocity, just because I dont like applymovement.

Thanks a bunch, I tried remaking my script and it looks like this

import bgefrom bge import logic
cont = logic.getCurrentController()
own = cont.owner
up = cont.sensors['up']
down = cont.sensors['down']
left = cont.sensors['left']
right = cont.sensors['right']


if up.positive:
    own.applyMovement([0.0, 0.0, 0.02], 1)
if down.positive:
    own.applyMovement([0.0, 0.0, -0.02], 1)
if left.positive:
    own.applyMovement([-0.02, 0.0, 0.0], 1)
if right.positive:
    own.applyMovement([0.02, 0.0, 0.0], 1)

My character moves, but only in increments, where as I’d like it to be continuous motion. Any advice? Thank you in advance for any help. and yeah this community is great, i dont know what i would do without it.

Yeah, the bgeg thing was a type, ive been reading other peoples scripts to try and get a better understanding for python, which is why it looks like different peoples styles. Thanks for the help!

The reason for increments is because you are using applyMovement, try using obj.linearVelocity, or better yet, a servo-motion actuator (or PID python class)

To set up obj.linearVelocity would i just do something like this

if up.positive:
    own.obj.linearVelocity([0.0, 0.0, 0.02], 1)

I tried that and it didnt work :confused: so I tried a couple of other things and still cant seem to get it working, sorry if im being annoying, just new at this whole python thing. Thanks in advanced!

use can use it this way

own.localLinearVelocity = [ 0.0, 5.0, 0.0]

or like this

own.localLinearVelocity.y = 5.0

Hint: Please ALWAYS open a console when using Python.

I wondered why you wrote your code of the first post does not work. At the first sight it seems to be fine. So the first thought is … there is an error that prevents it from full execution. And it is …
the first line is syntactical not correct:


import bgeg = bge.logic

I let you find out by yourself ;).

Next:
you forgot the assignment operator “=” on the actuator’s attribute:


move.dLoc [0.0, 0.0, 0.02] ---> move.dLoc = [0.0, 0.0, 0.02]

The console should have printed some errors.

Clarification:
dLoc
is not “outdated”. How could it be?
dLoc is a position/location change. It is NOT a motion. Think about it as a teleport.
Use this for placing objects at specific location.

The “d” part of “dLoc” means “delta” and should let you assume that the given change is relative to the current position(“delta” is the common greek character to express a differences in math).

Be aware the Label of the Motion Actuator is “Loc” (rather than dLoc) - a little inconsistency.

dRot
The same belongs to dRot. It is a change in the orientation (not a motion too).

applyMovement
This is nothing else then


gameObject.localPosition += [x,y,z]

[I never understood why this was introduced a a separate function.]
It is a position/location change too. The change will be performed by the controller rather than an actuator. It runs exactly one time. Which means the Python controller needs to be triggered every time the change should be performed.

When you use an actuator the actuator will run until you deactivate it. (BTW. your code in post#1did not deactivate the actuator when no key was pressed :wink: = positional change never stopps. )

When you want to use physics with motion, look for:

actuator.force
actuator.torque
actuator.linV
actuator.angV

or
gameObject.linearVelocity
gameObject.angularVelocity
gameObejct.applyForce
gameObject.applyImpulse

I hope it helps

My script now looks like this.

import bgefrom bge import logic
cont = logic.getCurrentController()
own = cont.owner
up = cont.sensors['up']
down = cont.sensors['down']
left = cont.sensors['left']
right = cont.sensors['right']
move = cont.actuators["move"]


if up.positive:
    own.localLinearVelocity = [ 0.0, 0.0, 0.02]
if down.positive:
    move.Loc = [0.0, 0.0, -0.02]
if left.positive:
    own.applyMovement([-0.02, 0.0, 0.0], 1)
if right.positive:
    own.applyMovement([0.02, 0.0, 0.0], 1)

Up and down arent working, just wondering if im doing this right. Also how would i ago about deactivating the actuator when no key is pressed?

you are using 3 different styles of movment there and the only one that would need an actuator would be the down movement…But if your not going to use an actuator for left right and up…you shouldnt use one for down…on down.positive…i think you are just assigning the direction on which to move…I dont see you actually activated the actuator. I dont use actuators for movement so im not real sure but i think below the line move.Loc = [0.0,0.0,1.0], you should have.

cont.activate(move)

deactivating also you should only have to do with the down sensor since none of the other directions use an actuator and it would be something like.


if down.status == 3:   ##Just released
      cont.deactivate(move)

Im not sure about doing it this way because it would kill any other direction movements using the same actuator…you could check other sensors to see if they are positive… or you could just set the Loc back to 0,0,0, but im not sure if it would deactivate. theres easier ways though.

im not sure why localLinearVelocity is not working but i bet you got something goobered up in your blend file. Check the true pulse triggering on the sensor. If its not set you wouldnt even noticing it moving with .02…Is the object dynamic or rigid body…You should really upload it so someone could take a look

I would use logic instead of python,

key w--------and------property walk =1
walk=0-------/

If walk min:1 max: (walk cycle length-1)----and----add 1 to walk

If walk=walk cycle length------and--------walk=0

If keypress w--------------and-------motion forward
If walk does not equal 0—<
____________________________–and----action property walk

So you can manage your action and have it run all the way through,
And you can have the forward force drop off, if you release the key

I would use logic, but the whole idea behind my games is that you can possess people. So im trying to set it up so that
if possessed -> then move host. I used logic for a while but im at the point where there is too much and i cant add anymore.

Replace the keyboard sensor with message triggers

So each enemy has “handles”

So when the player has his “soul” in a enemy, that is just storing the name of the message target,

So when you have a target

Soul.worldPosition =target.worldPosition

So the “icon” of the player or alpha map etc is dragged around when you move the enemy.

And have tbe keyboard sensors in the soul.

If Target equals None-----and----------motion forward
Keypress w-----------------/

If target does not equal none------python(own.worldPosition=target.worldPosition (setup message actuator target)
_______________________
Key W ---------------------------and-----------message to target subject forward

When you press up and down, do you want the character to move forward, up up in the air? Because right now you are moving up on the Z axis and fighting gravity.

As Monster said, when you press a key, it runs the python script once, and it runs again when released.
You can activate the pulse mode on the sensor, and it will keep running the code as long as the key is pressed

Or you could have a script like this


if key pressed:
    activate move actuator
else:
    deactivate move actuator

I’m not sure what’s the best way to move a character because there are so many ways.

One of the advantages of the system I mention for motion,
It does not need to be linear…

If walk min:15 max:30----------and-------motion force forward and up

If walk min:40 max:55----------and-------motion force forward and up
Which seems to be more like a person walks :slight_smile:

You may find it helpful to comment each line of code using #
Anything after the hash on that line won’t be executed by python.

later you won’t need to do it but at first it is vry useful for organizing you scripts an remembering what each line is actually doing.

still

this code is not correct

Comments

Do not do that!
If you really think you need to explain a piece of code, wrap it in a function with a descriptive name.

Use comments if there is something you want to tell that is not explained within the code e.g. the reasons why you do it that way or because you made some assumptions (which are not explicitly checked).

Comments are rarely updated. This often leads to plain wrong comments forcing the reader to misinterpret the processing. Development environments do not parse comments = no support e.g. no refactor on comments. Much comments make the code look dirty. Often seen: replicating code as comments (e.g. import bge # import bge).

Nevertheless comments can be good to teach others. But this should be code to teach not code to be in production. Example: see post #2. The comments teach you why – you should remove them after you read (and understand) them … or better you type the code into your python file without the comment.

Examples:
(I do not want to offend anyone - it is to show an [in my eyes] - cleaner way to write code)


if down.status == 3:   ##Just released
...

Seems the comment explains what 3 means. I strongly recommend to use the constants that are designed for exactly that purpose:


if down.status == bge.logic.KX_INPUT_JUST_RELEASED:   
...

Result: No need for an explaining comment anymore. The code stays for itself. If you want you can skip the qualification part by importing the constants in the current name space. If you need a different value to check you change the code without to worry you forget the comment.

Behavior mess
In general: when you apply too much behavior (logic, code) in one place it will quickly get out of control. This fits to both: logic bricks and Python code too. Moving behavior to code or back to logic bricks is not necessarily the right solution.

Better check if you can separate things e.g. place logic into another state, logic at another object, code into another function or module. Code is part of a logic brick (Python controller). Avoid a “god” controller which tries to do everything.

You seem to be a beginner with Python coding. I recommend: keep it simple … and while you processed … keep it even simpler. If code tends to be more complex - separate it. Otherwise you get your logic brick nightmare back … as Python code.

EDIT: I’m sure I’ve said all that before. Too tired today, just on auto pilot. ^^
Suffice to say I like using comments during development and maybe you will too, but officially it’s frowned upon.