wadaltmon Posted June 8, 2019 Share Posted June 8, 2019 Hello. I'm currently wanting to make a game that uses physics similar to Half Life 2, and am doing so with Leadwerks C++ (don't really want to use Lua). Thus, I want to be able to pick up objects. I read a topic from about 9 years ago that covered this topic, but it didn't do so very in-depth. What I gathered from it is that in order to be able to pick something up, I'd use the pick functionality and then within the PickInfo, there is an Entity pointer that points to the specific entity that I'd want to pick up. However, I can't seem to get my code working. I created a ground and small platform in the level editor, each with collision type rigid body - scene. I also created a small box, with mass 0.5 and collision type rigid body - prop. The idea was that I could walk up to this box and pick it up and move it around, then simply drop it, each with a click of the mouse. The way I approached this was by creating a pivot that was parented to the camera, to keep the camera's rotation. I used carryPivot->SetPosition(Vec3(0,0,2)) to move the pivot to in front of the camera. I used the cameraPick function in my main while(true) loop when the mouse is clicked to try and choose an object, carry it, and then set it to the position of the pivot. Here's the code for that part: if (gameWindow->MouseHit(1)) { Vec3 p = Vec3(gameWindow->GetWidth() / 2, gameWindow->GetHeight() / 2, 0); if (cam->Pick(p.x, p.y, pickinfo, 0, true)) { if ( (pickinfo.entity->mass <= 0.6) && (heldObject == NULL) && (pickinfo.entity->GetDistance(carryPivot->GetPosition(true)) < 0.75) ) { heldObject = pickinfo.entity; heldObjectMass = heldObject->mass; heldObject->mass = 0; } } if (heldObject != NULL) { heldObject->mass = heldObjectMass; heldObject = NULL; } } if (heldObject != NULL) { heldObject->SetPosition(carryPivot->GetPosition(true)); } Remember all that is in my while(true) loop in main.cpp. There's more inside the while(true) loop than that, but that's the relevant stuff. What am I doing wrong here? How should I go about picking up an object in game this way (only such that they are objects I desire the player to be able to pick up)? Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 8, 2019 Share Posted June 8, 2019 I don't know C++ really well but if it's similar to Lua it looks like you have your pick radius set to 0? (cam->Pick(p.x, p.y, pickinfo, 0, true)) Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 It is set to 0. When I was doing testing with the pick function, this basically made it to the position in the PickInfo filled by the pick operation was directly in contact with the entity, rather than being, say, 0.5 units off the surface of it. No matter the value I put in there, the code still doesn't work. EDIT: I should elaborate on this. Basically by using a pick radius above 0, I believe you allow for a pick operation to collide with a sphere around a potential pick point. By setting it to 0, I should only be able to pick relative to the actual geometry of the model. Quote Link to comment Share on other sites More sharing options...
gamecreator Posted June 8, 2019 Share Posted June 8, 2019 0 should work fine. Anything larger slows the function down because it needs to check an area instead of a point. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 8, 2019 Share Posted June 8, 2019 I don't know C++ really well but if it's similar to Lua it looks like you have your pick radius set to 0? (cam->Pick(p.x, p.y, pickinfo, 0, true)) Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 13 minutes ago, gamecreator said: 0 should work fine. Anything larger slows the function down because it needs to check an area instead of a point. Exactly. But the object still isn't lifting, it still just sits there. I'm not sure how I can check if the entity is actually being selected or at what stage the problem arises, as I can't really draw text to the screen. 4 minutes ago, havenphillip said: I don't know C++ really well but if it's similar to Lua it looks like you have your pick radius set to 0? (cam->Pick(p.x, p.y, pickinfo, 0, true)) Double post? Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 8, 2019 Share Posted June 8, 2019 lol Yeah double post. I typed out a whole other bit of "helpful" nonsense but for some reason... Quote Link to comment Share on other sites More sharing options...
Yue Posted June 8, 2019 Share Posted June 8, 2019 colRay = World: Pick ... System: Print (colRay) It also checks whether the material is for collection. Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 4 minutes ago, Iris3D Games said: colRay = World: Pick ... System: Print (colRay) It also checks whether the material is for collection. Why would I switch to World::Pick? That operates completely differently; I'd have to constantly calculate the direction the camera was facing globally. If I could calculate that, I wouldn't need the pivot object in the first place; I could calculate the look vector and set the position of the carried object x units from the camera position in that direction. Also, won't this always return true even if I'm looking at an object I can't grab? Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 8, 2019 Share Posted June 8, 2019 What's happening, specifically? Is it not even picking prop types? Or is it not allowing you to lift them on the mouse click, or what? Maybe there's something funky about using Vec3 p or something like the p.z needs to be greater or something? The index example just uses "GetMousePosition." If it's not picking prop types I've sometimes seen it written like: if (camera:Pick(p.x,p.y,pickinfo,pickradius,true,Collision.Prop)) then... local p = window:GetMousePosition() if (camera:Pick(p.x,p.y,pickinfo,pickradius,true)) then Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 I figured out the basic problem; it was the way I was disabling the carrying of the object on a second mouse click. It works kind of like I want it now; I can pick up an object, move it around, and then drop it. Here is the code there: if (gameWindow->MouseHit(1)) { if (heldObject == NULL) { Vec3 p = Vec3(gameWindow->GetWidth() / 2, gameWindow->GetHeight() / 2, 0); if (cam->Pick(p.x, p.y, pickinfo, 0, true)) { if ((pickinfo.entity->mass <= 0.6) && (pickinfo.entity->mass > 0.0) && (heldObject == NULL) && (pickinfo.entity->GetDistance(playerDummy->GetPosition(true)) < 2)) { System::Print(true); heldObject = pickinfo.entity; heldObject->SetGravityMode(false); } else { System::Print(false); } } } else { heldObject->SetGravityMode(true); heldObject = NULL; } } if (heldObject != NULL) { heldObject->SetPosition(carryPivot->GetPosition(true)); } So this works, but as of now, the carried object doesn't interact with the environment as I'm carrying it. Also, I'd like to be able to swing objects to the side and let go, and throw them. Plus, I want the speed of the object to be based on the speed of the mouselook. This should be able to be accomplished by basically changing the SetPosition function to a function that would say "MoveToPoint" where I could tell the entity to move toward a given point in space at a speed directly proportional to the difference in its position and the carryPivot's. But, it doesn't seem like that exists in Leadwerks. Is there such a function? How would i go about accomplishing that? 1 Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 8, 2019 Share Posted June 8, 2019 I think what you might need is the kinematic joint, where you can use joint->SetTargetPositon(carryPivot->GetPosition(true)). I will still react with physics i believe. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 8, 2019 Share Posted June 8, 2019 Nice. If it's not interacting the only things I can think of is whether the model has any physics set on it, and if Nav obstacle is set to true, and I think mass affects it, too. Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 43 minutes ago, Lethal Raptor Games said: I think what you might need is the kinematic joint, where you can use joint->SetTargetPositon(carryPivot->GetPosition(true)). I will still react with physics i believe. Not sure how you mean here. Is there a kinematic joint automatically associated with each physics-enabled entity? If not, how do I associate one with the object I pick up such that I can use that feature? Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 8, 2019 Share Posted June 8, 2019 Joint* heldObjectJoint = nullptr; if (gameWindow->MouseHit(1)) { if (heldObject == NULL) { Vec3 p = Vec3(gameWindow->GetWidth() / 2, gameWindow->GetHeight() / 2, 0); if (cam->Pick(p.x, p.y, pickinfo, 0, true)) { if ((pickinfo.entity->mass <= 0.6) && (pickinfo.entity->mass > 0.0) && (heldObject == NULL) && (pickinfo.entity->GetDistance(playerDummy->GetPosition(true)) < 2)) { System::Print(true); heldObject = pickinfo.entity; heldObjectJoint = Joint::Kinematic(0.0f, 0.0f, 0.0f, heldObject); } else { System::Print(false); } } } else { heldObject->SetGravityMode(true); heldObject = NULL; } } if (heldObject != NULL) { heldObjectJoint->SetTargetPosition(carryPivot->GetPosition(true)); } You could try this, not sure how removing the joint would go but you could play around with it a bit. Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 8, 2019 Author Share Posted June 8, 2019 That does work a lot closer to what I'd like, @Lethal Raptor Games. But, when I put an object down (click the button again), it leaves it in the air, and kind of messes up any future interactions with that object (as you predicted). On the plus side, this inadvertently created prop surfing. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 9, 2019 Share Posted June 9, 2019 You would have to remove the joint. Try this when you click again; .......... else { heldObjectJoint->Release(); heldObjectJoint = nullptr; heldObject->SetGravityMode(true); heldObject = nullptr; } I did a quick test and it doesn't delete the child object (heldObject in this case). I'm not sure how it will work though. 1 Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 9, 2019 Author Share Posted June 9, 2019 That did it! And it even inherently allows me to throw stuff around (though I will have to mess with the friction, stuff is sliding around like crazy haha)! Will also mess with the motor speed to give it different speed depending on how quickly I move it around. Thanks everyone for the help! Here's the final code within the while(true): if (gameWindow->MouseHit(1)) { if (heldObject == nullptr) { Vec3 p = Vec3(gameWindow->GetWidth() / 2, gameWindow->GetHeight() / 2, 0); if (cam->Pick(p.x, p.y, pickinfo, 0, true)) { if ((pickinfo.entity->mass <= 0.6) && (pickinfo.entity->mass > 0.0) && (heldObject == NULL) && (pickinfo.entity->GetDistance(playerDummy->GetPosition(true)) < 2)) { heldObject = pickinfo.entity; heldObject->SetGravityMode(false); heldObjectJoint = Joint::Kinematic(0.0, 0.0, 0.0, heldObject); } else { //do something } } } else { heldObjectJoint->Release(); heldObject->SetGravityMode(true); heldObject = nullptr; heldObjectJoint = nullptr; } } if (heldObject != nullptr) { heldObjectJoint->SetTargetPosition(carryPivot->GetPosition(true)); if (heldObject->GetDistance(playerDummy) > 3) { heldObjectJoint->Release(); heldObject->SetGravityMode(true); heldObject = nullptr; heldObjectJoint = nullptr; } } 3 Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 9, 2019 Author Share Posted June 9, 2019 Would anyone have any input on how to make it so prop surfing doesn't happen? I had tried to do a raycast downward (with a pickradius) to try and check if the object was directly beneath the player Model, but it wasn't remotely consistent. Is there a way to detect in real time if I am standing on top of a given Entity that has a pointer? BTW, attached is prop surfing vid 2019-06-08 17-01-58.flv Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 9, 2019 Share Posted June 9, 2019 That looks to be the character controller colliding with the box, your setting the target position of the cube which is forcing its way under the controller. Try disabling collision between the prop you grab and the character controller. Collsion::SetResponse(int type1, int type2, int response) Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 9, 2019 Share Posted June 9, 2019 If you want to still collide the heldobject with other entities in your scene you may have to set something up like this; Collision::SetResponse(PROP, CHARACTER, Collision::Collide); Collision::SetResponse(PROP, PROP, Collision::Collide); Collision::SetResponse(PROP, HELDITEM, Collision::Collide); Collision::SetResponse(HELDITEM, CHARACTER, Collision::None); Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 9, 2019 Author Share Posted June 9, 2019 3 minutes ago, Lethal Raptor Games said: That looks to be the character controller colliding with the box, your setting the target position of the cube which is forcing its way under the controller. Try disabling collision between the prop you grab and the character controller. Collsion::SetResponse(int type1, int type2, int response) 1 minute ago, Lethal Raptor Games said: If you want to still collide the heldobject with other entities in your scene you may have to set something up like this; Collision::SetResponse(PROP, CHARACTER, Collision::Collide); Collision::SetResponse(PROP, PROP, Collision::Collide); Collision::SetResponse(PROP, HELDITEM, Collision::Collide); Collision::SetResponse(HELDITEM, CHARACTER, Collision::None); Hm, I'm not really understanding the integer constants that are in there. What are the values held by PROP, CHARACTER, HELDITEM? Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 9, 2019 Share Posted June 9, 2019 Ah they can be any constant. These are some that come with Leadwerks; const int COLLISION_NONE = 0; const int COLLISION_PROP = 1; const int COLLISION_SCENE = 2; const int COLLISION_CHARACTER = 3; const int COLLISION_TRIGGER = 4; const int COLLISION_DEBRIS = 5; I'd create my own; const int PROP = 10; const int HELDITEM = 11; const int CHARACTER = 12; I think the max number is 100. Based on this variable in PhysicsDriver.h; int collisionresponse[100][100]; Quote Link to comment Share on other sites More sharing options...
wadaltmon Posted June 9, 2019 Author Share Posted June 9, 2019 I guess I'm not understanding more how essentially writing Collision::SetResponse(11, 12, 0) is going to relate that desired response to the actual instance of a given heldObject (which is just an Entity pointer). It's also worth noting that there's no documentation page for this command. Quote Link to comment Share on other sites More sharing options...
SpiderPig Posted June 9, 2019 Share Posted June 9, 2019 Yeah there's not. After setting up those collisions, you then have to assign them to which ever entity you want. E.g. All the boxes you create; SetCollisionType(PROP) On the player; SetCollisionType(CHARACTER) When you right click and pick the object up; HeldItem->SetCollisionType(HELDITEM) When you right click and release the object; HeldItem->SetCollisionType(PROP) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.