def grab(cont): own = cont.owner
grabcol = cont.sensors["grabcol"]
if own["active"] == 1 and grabcol.positive:
target = grabcol.hitObject
target.applyForce((own.worldPosition - target.worldPosition) * 100000)
target.setLinearVelocity([0, 0, 0])
if not grabcol.positive:
own["active"] = 0
It identifies if boolean active is true then applies a force between the collision box and hitObject. It then sets the linear velocity of the hitObject to 0, 0, 0.
I would like to make this more like the valve source engine method of grabbing objects (prop physics). This method “loses” the object when moving too fast and when the grabbed object collides with another object it goes flying at enormous speeds… Any fixes I can make?
You “lose” the object because your active grab depends on a collision sensor for the entire period (which can loose contact). To avoid this, you should use multiple functions that represent different states for grab (where you can set conditions that must be satisfied to pick something up), and for hold, which will depend on depressing the relevant mouse button.
I don’t know of a way to make it “Valve perfect”, because the BGE doesn’t really offer certain bullet features that would make that possible … Although, I would recommend looking at physics constraints, because that might provide some options (but I think they would have to be really ugly hacks).
Okay so I tried out a few things, and I REALLY don’t like using states for scripts (just a personal preference). Is there a way to do the following?:
In
import bgeimport GameLogic as g
cont = g.getCurrentController()
own = cont.owner
grabcol = cont.sensors["grabcol"]
hitobject = grabcol.hitObject
print(hitobject)
if own["active"] == 1:
hitobject = grabcol.hitObject
hitobject.applyForce((own.worldPosition - hitobject.worldPosition) * 10000)
hitobject.setLinearVelocity([0, 0, 0])
Assign assign the collision object to a property/variable, but prevent it from setting its value back to “None” unless another object is collided with while active is false? (The collision hitObject variable needs to not be None while active == 1.
I don’t like those either, but if you watch my video, you can see the mental model of a state machine encoded into functions.
There is only one function that runs at any given time, and which depends on what self.main was last set to - that determines what “state” you’re in, but it has nothing to do with states in the logic brick system.
def grab(self):
if grab_condition:
pick_up()
self.main = self.carry
def carry(self):
if drop_condition: # typically, a mouse btn release
drop_object()
self.main = self.grab
I understand how your “states” work by setting functions as other functions, thereby eliminating the other function until it is activated again.
I’m new to python and don’t really understand classes yet. They’re like a function collation containing functions or something (still learning how to use them).
So I tried to copy your method from your tutorial (practically word for word):
import bge
import GameLogic as g
cont = g.getCurrentController
coltarget = cont.sensors["grabcol"]
rclick = cont.sensors["rightclick"]
hitobj = None #self.pickup
main = pickup
def pickup():
if coltarget.positive and rclick.positive:
hitobj = coltarget.hitObject
main = carry
def carry():
delta = cont.owner.worldPosition - grabbed.worldPosition
grabbed.applyForce(delta * 1000)
if rclick.positive:
main = pickup
def main(): #no clue what this should do...
How do I execute this properly? Do I need to use classes for this?
Also, how do I make it detect if the object is still alive? (If it dies, reset the states.)