Jump to content

[HELP] Moving object in direction of camera lookat


Bartje

Recommended Posts

Hi,

So I think I have kind of a difficult one here. 

Is it possible to move an object towards the players camera look at? I am creating the object in front of the player and I then want to move it in the camera direction with a certain speed (not a destination). Actually just like projectiles work, but then for objects.
I have a feeling that the 'moveObject' function is not going to work here.

Any ideas or examples on how to do this?

Thanks!

Edited by Bartje
Link to comment

Hello Bartje,

I understand that you want to simulate shooting a rocket launcher in the direction of the player's view/camera/where-he-is-looking-at. I assume that you want to have the definition of the line starting from the camera position going in the direction of the camera's front vector. This is actually not as difficult as you might think. Here is some code as an idea.

client.Lua

-- Calculate the direction vector.
local csx, csy, csz, ctx, cty, ctz = getCameraMatrix();
local cdir = Vector3(ctx - csx, cty - csy, ctz - csz);
cdir:normalize();

-- The line starts of (csx, csy, csz) and the direction vector is cdir.
-- You can now interpolate on this line using setElementPosition and the following function.
local function interpolate_position(px, py, pz, dir, timeSpeed)
  return
    px + dir.x * timeSpeed,
    py + dir.y * timeSpeed,
    pz + dir.z * timeSpeed;
end

-- An example?
local obj = createObject(1454, csx, csy, csz);
local moveStart = getTickCount();

addEventHandler("onClientRender", root, function()
    local curTime = getTickCount();
    local elapsedTime = ( curTime - moveStart );
    
    local timeSeconds = elapsedTime / 1000;
    
    setElementPosition(obj, interpolate_position(csx, csy, csz, cdir, timeSeconds));
  end
);

(code not tested)

Explanation: the direction is defined as the normal vector of the difference between two 3D points. You can subtract the start 3D vector from the target 3D vector to get the difference between two 3D points.

Of course, if you want to keep multiple objects flying in certain directions you must remember their starting positions and their direction vectors along with the MTA object handle. Should be a good exercise with the boiler-plate code above. ;)

You have mentioned the moveObject function. Your feeling may be correct because that function does specify fixed timelimit for object flight whereas above code does allow for indefinite length of object flight.

- Martin

Edited by The_GTA
  • Like 2
Link to comment

Hi again!

Thank you so much. I used some of this to make my part work. So that's awesome.

Another quick question that you may have the answer to: So I am making this 'projectile' kind of thing. When it hits the player, I reduce the target's health and eventually kill it.
I am firing the setElementHealth on the serverside as I thought this would be more 'secure'. I do believe that client side would be more efficient.

With my background of webdeveloping, I would still handle this on the server-side to prevent hackers or bug-abusers. What are your thoughts on this? 

Link to comment
3 minutes ago, Bartje said:

Another quick question that you may have the answer to: So I am making this 'projectile' kind of thing. When it hits the player, I reduce the target's health and eventually kill it.

I am firing the setElementHealth on the serverside as I thought this would be more 'secure'. I do believe that client side would be more efficient.

With my background of webdeveloping, I would still handle this on the server-side to prevent hackers or bug-abusers. What are your thoughts on this? 

Since there is no serverside physics simulation you really should do the hit detection on the clientside. You have to take physics depending on player framerate into account which is impossible to do on the server. Thus the client has to trigger a server event to tell the server about a projectile hit.

I hope you see that anything involving game physics is doomed from a security point of view. But that is why we have anti-cheat detection systems built into the MTA system so do not worry. ?

  • Thanks 1
Link to comment
11 hours ago, The_GTA said:

Since there is no serverside physics simulation you really should do the hit detection on the clientside. You have to take physics depending on player framerate into account which is impossible to do on the server. Thus the client has to trigger a server event to tell the server about a projectile hit.

I hope you see that anything involving game physics is doomed from a security point of view. But that is why we have anti-cheat detection systems built into the MTA system so do not worry. ?

Exactly what I wanted to hear! Thanks!

Link to comment
On 25/03/2020 at 23:56, The_GTA said:

Explanation: the direction is defined as the normal vector of the difference between two 3D points. You can subtract the start 3D vector from the target 3D vector to get the difference between two 3D points.

Hi again. So I wanted to tweak the part a little. The moving part is working great. The object is moving into the direction where my camera is looking at. However, I want to create the object first just in front of the player (where the camera is looking at). I came as far as getting the object right on top of the player. but it should have some distance. Mathematics is not my strongest skill.

What I've got right now, is the following:

local x, y, z = getElementPosition(player)
local csx, csy, csz, ctx, cty, ctz = getCameraMatrix();
local object = createObject ( 1600, ctx + (x - ctx), cty + (y - cty) , ctz + (z - ctz) )

So the above code makes the object spawn directly at the players' position. How can I give a little offset, let's say 1 meter towards the direction of where I am looking at?

Link to comment
17 minutes ago, Bartje said:

However, I want to create the object first just in front of the player (where the camera is looking at). I came as far as getting the object right on top of the player. but it should have some distance.

By using the above "interpolate_position" function you can spawn the object one metre or farther in front of the camera.

local start_distance = 1 -- the amount of metres to be starting away from
local start_x, start_y, start_z = interpolate_position( csx, csy, csz, cdir, start_distance );
local object = createObject ( 1600, start_x, start_y, start_z )

You can then use start_x, start_y, start_z vector instead of csx, csy, csz vector in the above onClientRender event handler to perform the flight from the new position. ;) 

Maybe you want to spawn an object in front of the player instead? Then you need to use different mathematics: the element matrix. I recommend you a read of the wiki article about MTA's matrix implementation. But here is some sample code.

local rotVec = Vector3(getElementRotation(localPlayer));
local posVec = Vector3(getElementPosition(localPlayer));

local playerMat = Matrix(posVec, rotVec);

local one_metre_in_front = playerMat.transformPosition(Vector3(0, 1, 0));

This code could be simplified if you enable OOP for your MTA resource. Then you can access the "localPlayer.matrix" field to get the matrix instead of calculating it.

Edited by The_GTA
Link to comment
17 minutes ago, The_GTA said:

Maybe you want to spawn an object in front of the player instead? Then you need to use different mathematics: the element matrix. I recommend you a read of the wiki article about MTA's matrix implementation. But here is some sample code.

I think it's a bit more complicated. The part with the start distance actually does half the trick in my situation. Based on the zoom level which you can toggle with 'V', the position has to be set. So using a static number will give different offsets from the player when you use different zoom levels.

As you can see in the picture below. Both fish are at a different offset from the player because they were spawned with different camera views. That is the problem I am running into at the moment.

 

 rR1ksrb.jpg

Link to comment
2 minutes ago, Bartje said:

I think it's a bit more complicated. The part with the start distance actually does half the trick in my situation. Based on the zoom level which you can toggle with 'V', the position has to be set. So using a static number will give different offsets from the player when you use different zoom levels.

As you can see in the picture below. Both fish are at a different offset from the player because they were spawned with different camera views. That is the problem I am running into at the moment.

Could you please show your code? I cannot help you based purely on explanation because your implementation does matter for error detection.

Link to comment
1 hour ago, The_GTA said:

Could you please show your code? I cannot help you based purely on explanation because your implementation does matter for error detection.

Sure. The current code looks like this now:

local x, y, z = getElementPosition(player)
local direction = Vector3(ctx - csx, cty - csy, ctz - csz);
direction:normalize();
local start_x, start_y, start_z = interpolate_position( csx, csy, csz, direction, 10 );
local object = createObject ( 1600, start_x, start_y, start_z)

So the problem that I have now is that '10' should be relative instead of a static number. I played around with some calculations to get it, but I can't seem to figure it out.

Link to comment
14 minutes ago, Bartje said:

So the problem that I have now is that '10' should be relative instead of a static number. I played around with some calculations to get it, but I can't seem to figure it out.

Thank you for posting the code. So let me summarize what I understand:

  • no matter what state of the V zoom, you want things to spawn at the same position
  • the problem is that if your camera zooms out the object is closed to the player than what you want
  • you probably want an offset starting from the player and not from the camera position

So what about this code? I have changed line 3 from csx, csy, csz to x, y, z + 0.5 ...

local x, y, z = getElementPosition(player)
local direction = Vector3(ctx - csx, cty - csy, ctz - csz);
direction:normalize();
local start_x, start_y, start_z = interpolate_position( x, y, z + 0.5, direction, 10 );
local object = createObject ( 1600, start_x, start_y, start_z)

 

Link to comment
10 minutes ago, The_GTA said:

Thank you for posting the code. So let me summarize what I understand:

  • no matter what state of the V zoom, you want things to spawn at the same position
  • the problem is that if your camera zooms out the object is closed to the player than what you want
  • you probably want an offset starting from the player and not from the camera position

So what about this code? I have changed line 3 from csx, csy, csz to x, y, z + 0.5 ...


local x, y, z = getElementPosition(player)
local direction = Vector3(ctx - csx, cty - csy, ctz - csz);
direction:normalize();
local start_x, start_y, start_z = interpolate_position( x, y, z + 0.5, direction, 10 );
local object = createObject ( 1600, start_x, start_y, start_z)

 

 

Lol, this is it! Thank you once again.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...