Hello fellow blender artists!
Ive been using blender for about 2 years now and finally decided to learn python. Ive started teaching myself by trying to fix bge games that were made back in 2.4, 2.5 etc.
I’m having trouble fixing a bug with the main menu that prevents me from moving the selection cursor across the 3 options. The following is output when i press the up or down keys to scroll down the main menu:
Blender Game Engine Started
Python script error - object 'Plane.003', controller 'menu':
Traceback (most recent call last):
File "menu", line 19, in <module>
AttributeError: Vector subtraction: (Vector -= int) invalid type for this operat
ion
Python script error - object 'Plane.003', controller 'menu':
Traceback (most recent call last):
File "menu", line 20, in <module>
AttributeError: Vector addition: (Vector += int) invalid type for this operation
Blender Game Engine Finished
Here are the lines of code that are causing the problem:
if up: pos -= 1
if down: pos += 1
I know it has to do with the fact that you can’t add an integer to a vector, but i’ve been searching online all day and I haven’t found a solution yet.
If you want to add an integer to a Vector (pos is a Vector in this case), you need to specify which axis you want to add it to (x, y, or z). In your case you probably want the z axis.
A keyframe is a number. Usually from type float. You would not get a problem adding 1 to a float.
Why do you call a keyframe “pos”? Is it because it is supposed to be “positive” ;)?
Anyway, it would be better to provide more details. You already know the source of the error. But we can’t guess what you want to do.
Sadly, im not the original creator of this game so I wouldn’t know why he/she used certain commands.
However, the game was originally made in 2.4, so a lot of the original code was deprecated.
Here is the code for the main menu with my modifications.
import GameLogic
import math
import mathutils
from mathutils import Vector
g = GameLogic
cont = g.getCurrentController()
own = cont.owner
pos = own.position
keys = cont.sensors["keys"].events
if not keys: keys = []
up = [146,1] in keys or [119,1] in keys
down = [144,1] in keys or [115,1] in keys
next = [13,1] in keys or [32,1] in keys
if up: pos -= 1
if down: pos += 1
if pos == 0: pos = 3
if pos == 4: pos = 1
cont.activate(cont.actuators["ipoPos"])
# Enter or space
if next:
if pos == 1: # 3d Mode
g.cont.activate(cont.actuators("arenaScene"),1)
g.gameMode = 0
elif pos == 2: # 2d Mode
g.cont.activate(cont.actuators("arenaScene"),1)
g.gameMode = 1
elif pos == 3: # Exit
g.cont.activate(cont.actuators("quitGame"),1)
The code here is functionally incorrect -> GameLogic (bge.logic) does not have a “cont” attribute.
This is closer to what you’re looking for, but without any context, I can’t write much more.
import math
from mathutils import Vector
from bge import logic, events
def close_to(x, y, epsilon=0.001):
return abs(x - y) <= epsilon
def main(cont):
own = cont.owner
pos = own.worldPosition
keyboard_events = dict(cont.sensors["keys"].events)
ipo_actuator = cont.actuators["ipoPos"]
just_pressed = logic.KX_INPUT_JUST_ACTIVATED
up = just_pressed in (keyboard_events.get(events.WKEY), keyboard_events.get("UPARROWKEY"))
down = just_pressed in (keyboard_events.get(events.SKEY), keyboard_events.get("DOWNARROWKEY"))
next = just_pressed in (keyboard_events.get(events.RETKEY), keyboard_events.get(events.SPACEKEY))
if up:
pos.z -= 1
if down:
pos.z += 1
if pos.z <= 0:
pos.z = 3
if pos.z >= 4:
pos.z = 1
cont.activate(ipo_actuator)
# Enter or space
if next:
if close_to(pos.z, 1): # 3d Mode
cont.activate(cont.actuators("arenaScene"))
g.gameMode = 0
elif close_to(pos, 2): # 2d Mode
cont.activate(cont.actuators("arenaScene"))
g.gameMode = 1
elif close_to(pos, 3): # Exit
cont.activate(cont.actuators("quitGame"))
I don’t think it’s a good idea to try and update other people’s games from old versions of Blender unless you are some kind of Blender/python wizard. I wouldn’t even try to update my own games, because even though I knew what I was doing at the time, I sure don’t know now what I was thinking then.
Changing from old versions of Blender can introduce all sorts of unintended changes or completely break old scripts in unpredictable ways.
If you want to learn Python by teaching yourself I’d recommend starting some of your own simple projects to try and do some of the things you commonly do with logic bricks.
. So it is fine, otherwise it would result in another error.
Remarks
Nevertheless this code contains some things that are not nice:
importing the module GameLogic as “g” rather than using the the well known name “GameLogic” which is more understandable.
using KX_GameObject.position which was deprecated and incorrect even in version “2.4*”
using codes as numbers in the sources (e.g. 3, 146). This makes the code hard to understand. There are constants that are much better to read. See BGE API.
mapping of the objects position to the function of the menu. This is a real design flaw.
checking a float value with == and an integer constant is usually not a good idea as the number precision makes them unequal values in most of the cases. It might have worked in the original application, but mostly because of other side-effects.
the code requires comments to explain what the situation is. This usually a sign that the code is unnecessary hard to understand. [There are situations when this is indeed necessary, but not here]
Analysis:
in pre-2.5 the position (better localPosition) returned a list with the coordinates of the position:
[x,y,z]
(since 2.5 it is a mathutils.Vector)
To be honest I never tried to perform a “+=” operation on a list. So I need to check what will happen … it results in a TypeError.
So this code as it is should not even work in 2.4*.
I can only guess that “pos” has a completely different source. It is not a list (2.4-) nor a vector (2.5+). Best bet t is supposed to be
pos = own.localPosition[2]
Solution:
As you wrote this is not your code - I suggest you look for a different menu logic with a better design and a working implementation.