Position of player on the world, to a map drawn with surface.SetMaterial etc
13 replies, posted
Hey, so I'm trying to figure out the position of the player on the world and convert it to the map, but I cannot figure it our for the life of me. I've tried a ton of things and I'm sure there has to be an easier way.
This is my code:
include( "sh_init.lua" )
local pi = math.pi
local function drawCircle( x, y, rad, quality, col )
surface.SetDrawColor( col )
local step = (2 * pi) / quality
local verts = {}
local ang
for i=1,quality do
ang = i * step
table.insert( verts, {
x = x + math.cos( ang ) * rad,
y = y + math.sin( ang ) * rad
} )
end
surface.DrawPoly( verts )
end
function GM:HUDPaint()
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawRect( 50, 50, 256, 256 )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial(Material("redacted/redacted/dustii.png"))
surface.DrawTexturedRect( 50, 50, 255, 255 )
local pos = LocalPlayer():GetPos()
drawCircle(pos.x / 2, pos.y / 2, 10, 100, Color(0,0,255))
end
The circle is the player position.
Currently looks like this:
https://i.imgur.com/nz1tfJ4.png
Any ideas?
Player position is not 2D. It's 3D vector and it can be negative. You need to convert player size according to world size and then remap to 2d render
What would be an easy way to do that?
You need to work out the scale between the size of the game map and the size of the mini-map.
To do this you need to know the size of the game map, you could use the mins and maxs from Entity/GetModelBounds with game.GetWorld as the entity you run it on (for an exact size of the map). Using the values you get, add the absolute values of x from min and max and also y from min and max for your X and Y sizes of the map.
Eg. I ran "print(game.GetWorld():GetModelBounds())" for my map and got the Vectors below as a result:
"-14337.000000 -16289.000000 -14913.000000 14337.000000 14337.000000 3489.000000"
For my maps X size: I take the absolute values for both x values. so its 14337 + 14337 which is 28674. This means my maps X length is 28674 units exactly.
The same can be done for the Y lengths. My case the maps Y length is 30626 units
Say your map is 500x500 in the UI.
This means that the scale between the two is minimapX/worldmapX (this will give us a multiplying factor to convert world position onto our map) For mine it is 500/28674 which is 0.0174373997 (you dont need to be this accurate if you dont want to)
The same can be done for Y values, although if your world map is square than it will be the same but mine is: 500 / 30626 = 0.0163259975.
Now we have the multiplying factors to convert world position onto the map we need to implement this.
World positions can be negative but our map only goes from 0 to 500px so we need a way to translate this across.
If our world position is negative we can leave it as is and take the absolute value of the result
eg. Vector(-8000, -2000, 0) onto our map.
x value = -8000 * multiplierX = -8000 * 0.0174373997 = -139.499198. Taking the absolute value would be 139px into the UI Map. Same can be done for the Y.
y value = -2000 * multiplierY = -2000 * 0.0163259975 = -32.651995 - absolute = 32.651995
However if the value is not negative we need to add half of our map size onto the result. This puts it in the right half of the map.
eg. Vector(8000, 2000, 0)
same math as before. x value = 8000 * multiplierX = -8000 * 0.0174373997 = 139.499198. but that would put it at the same position as our negative world position and we know its on the other side of the map, so we add half of our map size which is 250 for me and the result would be 389px in.
again the Y is done the same way: y value = 2000 * multiplierY = 2000 * 0.0163259975 = 32.651995 but then, again we add our 250px because the original value was not in the negative portion of the map.
Sorry if I over-complicated this or confused you more, but I tried :/
Okay, so I have this
function GM:HUDPaint()
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawRect( 50, 50, 500, 500 )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial(Material("arnydahamsta/bombdefusal/dustiinew.png"))
surface.DrawTexturedRect( 50, 50, 500, 500 )
local pos = LocalPlayer():GetPos()
local posx = pos.x * (500 / 15586) + (500 / 2) + 50
local posy = pos.y * (500 / 7682) + (500 / 2) + 50
surface.SetDrawColor( 0, 0, 0, 255 )
draw.RoundedBox( 0, math.abs(posx), math.abs(posy), 10, 10, Color(0,0,255) )
--drawCircle(posx, posy, 5, 100, Color(255,0,0,255))
--LocalPlayer():ChatPrint(tostring(pos).." "..tostring(posx).." "..tostring(posy))
end
And it draws it here
https://i.imgur.com/4IPmdjr.png
Even though I am actually here
https://i.imgur.com/6xKWVYa.jpg
First off we will need to do something about your actual UI Map being flipped the opposite way to the actual world orientation. . This could also be achieved by flipping the map in a photo editor such as Photoshop.
|You are also always adding 250 which is only needed when the player is in the left hand side of the map so we need to do some logic for that.
Try this:
function GM:HUDPaint()
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawRect( 50, 50, 500, 500 )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial(Material("arnydahamsta/bombdefusal/dustiinew.png"))
surface.DrawTexturedRect( 50, 50, 500, 500 )
local pos = LocalPlayer():GetPos()
local posx = 500 - (pos.x < 0 and (pos.x * (500 / 7682) + (500 / 2) + 50) or (pos.x * (500 / 7682) + 50))
local posy = 500 - (pos.y < 0 and (pos.y * (500 / 7682) + (500 / 2) + 50) or (pos.y * (500 / 7682) + 50))
surface.SetDrawColor( 0, 0, 0, 255 )
draw.RoundedBox( 0, math.abs(posx), math.abs(posy), 10, 10, Color(0,0,255) )
--drawCircle(posx, posy, 5, 100, Color(255,0,0,255))
--LocalPlayer():ChatPrint(tostring(pos).." "..tostring(posx).." "..tostring(posy))
end
This should account for the fact that your map is the wrong way and also fix the positioning.
Yeah, sorry the map was flipped, was testing something, but now, however, it should be the right way round.
function GM:HUDPaint()
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawRect( 50, 50, 500, 500 )
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial(Material("arnydahamsta/bombdefusal/de_dust2_radar.png"))
surface.DrawTexturedRect( 50, 50, 500, 500 )
local pos = LocalPlayer():GetPos()
local posx = 500 - (pos.x < 0 and (pos.x * (500 / 15586) + (500 / 2) + 50) or (pos.x * (500 / 7682) + 50))
local posy = 500 - (pos.y < 0 and (pos.y * (500 / 7682) + (500 / 2) + 50) or (pos.y * (500 / 7682) + 50))
surface.SetDrawColor( 0, 0, 0, 255 )
draw.RoundedBox( 0, math.abs(posx), math.abs(posy), 10, 10, Color(0,0,255) )
--drawCircle(posx, posy, 5, 100, Color(255,0,0,255))
--LocalPlayer():ChatPrint(tostring(pos).." "..tostring(posx).." "..tostring(posy))
end
But, the square keeps teleporting away when I enter a negative x or y value, and the player is not at the correct position on the map
https://i.imgur.com/EaBAFVv.jpg
As you have fixed the orientation of the map you no longer need to take away from 500 (that was added to fix the orientation issue but no longer needed). Try the same code without the 500 - at the position calculations
This is what it's currently like, with '500 -' removed
https://www.youtube.com/watch?v=Njer2D7tvoQ
Can you try the latest code above/=
From here, the map is aligned perfectly
https://i.imgur.com/L0HEyLR.jpg
However, over here, it is not aligned correctly, or any other part of the map
https://i.imgur.com/MbmNbQB.jpg
Can you run "lua_run print(game.GetWorld():GetModelBounds())" in the server console and paste the result.
I am not really sure what the problem is. It may be that the map picture you are using doesnt actually match the world map but not too sure.
You could try generating your own map image? If you wish to do that follow the "Make the raw overview" section of this tutorial Creating a working mini
Sorry, you need to Log In to post a reply to this thread.