[BGMC17]{Hard-Topic}Rod and hook physics!

yes, seem that lack some sort of elasticity , this is probably due to a “premature” manipulation of position ,
plus also “reflect” is not very right.

this seem that work well (tested):



import bge

def custom_constraint(ob1, ob2, dist_min=1.0, dist_max=2.0, multiplier=1.0):
	dist, vec, _ = ob1.getVectTo(ob2)
	
	if dist > dist_min:
		ob1.worldLinearVelocity += vec * multiplier
		
		if dist > dist_max:
			ob1.worldPosition = ob2.worldPosition - vec * dist_max






def hook(cont):
    own = cont.owner
    target = own.scene.objects["RodTip"]
    
    custom_constraint(own, target, dist_min=8.0, dist_max=15.0, multiplier=10.3)

basically the constraint has 3 “states” based on the distance.
A)nothing … B)add velocity … C)limit position

i forget a piece


def custom_constraint(ob1, ob2, dist_min=1.0, dist_max=2.0, multiplier=1.0):
	dist, vec, _ = ob1.getVectTo(ob2)
	
	if dist > dist_min:
		ob1.worldLinearVelocity += vec * (dist-dist_min) * multiplier ###### this
		
		if dist > dist_max:
			ob1.worldPosition = ob2.worldPosition - vec * dist_max

Thanks! After returning from work I will obiouvsly check this:)


import bge
from bge import logic
import random


def custom_constraint(ob1, ob2, dist_min=1.0, dist_max=2.0, multiplier=1.0):
	dist, vec, _ = ob1.getVectTo(ob2)
	
	if dist > dist_min:
		ob1.worldLinearVelocity += vec * multiplier
		
		if dist > dist_max:
			ob1.worldPosition = ob2.worldPosition - vec * dist_max


def hook(cont):
    own = cont.owner
    scene = logic.getCurrentScene()
    
    rod = scene.objects["Rod"]
    target = scene.objects["throwTarget"]
    rodTip = scene.objects["RodTip"]
    
    own["distance"] = own.getDistanceTo(rodTip)
    lineLength = rod["lineLength"]
    
    custom_constraint(own, rodTip, 0.1, lineLength, 1.0)
    
    vel = own.localLinearVelocity
    
    if rod["fishing"] == False:
        if cont.sensors["space"].positive:
            rod["fishing"] = True
            throwVec = own.getVectTo(target)
            modifier = 5000.0
            rod["lineLength"] += 3.0
            own.applyForce(throwVec[1] * modifier, False)
    else:
        if own["distance"] < 0.5:
            rod["fishing"] = False
            if own["fishOn"] == True:
                player = scene.objects["player"]
                player["cash"] += own["weight"] * 10 + 1
                player["XP"] += own["weight"] + 1
                own["fishOn"] = False
                own["fish"] = 0
                own["weight"] = 0
                own["fishStrength"] = 0
                own["fishStamina"] = 0
                rod["lineTension"] = 0
                rod["tensionLevel"] = 0
            
    if cont.sensors["water"].status == 1:
        scene.addObject("WaterSplash", own, 10)
        cont.activate(cont.actuators["splash"])
            
    if cont.sensors["water"].positive:
        rod["lineLength"] -= 0.05
        own["inWater"] = True
    else:
        own["inWater"] = False
        
    fishlists = {"windy_medium_lake": [1, 2, 2, 3], "windy_shallow_lake": [1, 1, 2, 3, 3], "grassy_shallow_lake": [1, 1, 2, 3, 3]}
    area = cont.sensors["area"]
    if area.positive:
        fish_list_type = area.hitObject["fish_list"]
        own["fish_list"] = fishlists[fish_list_type]
        
    if own["inWater"] == True:
        if own["fishOn"] == False:
            fishTimer = random.randint(0, 1000 / (rod["bait"] / 3))
            if fishTimer == 5:
                cont.activate(cont.actuators["splash"])
                own["fish"] = random.choice(own["fish_list"])
                own["fishOn"] = True
                # Fish
                # 1 = perch
                # 2 = trout
                # 3 = tench
                if own["fish"] == 1:
                    own["weight"] = random.uniform(0.05, 2.0)
                elif own["fish"] == 2:
                    own["weight"] = random.uniform(0.2, 4.0)
                elif own["fish"] == 3:
                    own["weight"] = random.uniform(0.25, 4.5)
                own["fishStrength"] = own["weight"] * 0.01
                own["fishStamina"] = 100.0
                
    if own["fishOn"] == True:
        if rod["tensionLevel"] == 0:
            rod["lineLength"] += 0.1
            rodVect = own.getVectTo(rod)
            own.applyForce(-rodVect[1] * own["weight"] * own["fishStamina"] / 100.0, False)
            if rod["lineTension"] > 0.0:
                rod["lineTension"] -= own["fishStrength"]
            else:
                rod["lineTension"] = 0.0
        elif rod["tensionLevel"] == 1:
            rod["lineTension"] += own["fishStrength"] * own["fishStamina"] / 100.0
            own["fishStamina"] -= 0.02
        else:
            rod["lineTension"] += own["fishStrength"] * own["fishStamina"] / 50.0
            own["fishStamina"] -= 0.04
    
    if own["fishStamina"] < 0:
        own["fishStamina"] = 0.0
    
    fishVis = scene.objects["FishRig"]
    scaling = own["weight"]**(1/3)
    fishVis.scaling = [scaling, scaling, scaling]

I tried to setup my current script as this, but something werid appears to be happening if I throw the hook with SPACE.

we say that the difference between dist_min and dist_max , should be costant
since is the elasticity given by the rod.

while what can change is “dist_min”.
so, dist_max is ever dist_min + constant

note that the line 5 of custom_constraint() is a bit different






def custom_constraint(ob1, ob2, dist_min=1.0, dist_max=2.0, multiplier=1.0):
	dist, vec, _ = ob1.getVectTo(ob2)
	
	if dist > dist_min:
		ob1.worldLinearVelocity += vec * (dist-dist_min) * multiplier ######## <- changed
		
		if dist > dist_max:
			ob1.worldPosition = ob2.worldPosition - vec * dist_max






def hook(cont):
    own = cont.owner
    scene = logic.getCurrentScene()
    
    rod = scene.objects["Rod"]
    target = scene.objects["throwTarget"]
    rodTip = scene.objects["RodTip"]
    
    own["distance"] = own.getDistanceTo(rodTip)
    lineLength = rod["lineLength"]
    
    CONST = 2.0 # the oscillation max in meters of the rodTip 
    custom_constraint(own, rodTip, lineLength, lineLength+CONST, 1.0)
    

in the other code you should just change -> rod[“lineLength”]

…to me semm that work , at least in my tests

Well, I will still check it when I return from work, but if I won’t succeed with it, I will just continue using my method. However, lineLength + CONST will change every frame as lineLength does…

lineLength can change in any moment

see this blend at least you see what i mean for “for me work” .
adding too many things can become quikly complex.

Attachments

fisher2.blend (90.6 KB)

MarcoIT, your example works good. It is very cool, but I managed to make my approach work almost the same. If I will have time at the end of the contest, I will try to merge your method in, though;)

no problem if you have already a thing working , better keep it and finish it :wink: