So i want to align 2 objects together on the left side of the object that is the furthest to the left. So i'll sketch out a scenario:
There are 2 images on random positions on the board. You select both images(with a selection tool that has been made) and you than click: "Align objects to the left"
The image that is the furthest to the RIGHT should than snap to the same position of the edge on the left side of the other image. So when clicking the button, my code should calculate both left sides(the edge of the image on the left) of the images position, than check which one if the furthest to the right on the canvas, and move that one to the same X axis as the other image.
This way the end result will be the images will be on the exact same X axis. So if image 1 is on -73 & Image 2 is on -50, image 2 should than also move to -73, regardless of the rotation of either images.
Currently i can only find out how to find the middle position of the image, my code looks like this atm:
using com.company.program.core.pageObjects;
using com.company.program.ui.colorPicker;
using UnityEngine;
namespace com.company.program.core.SelectionManager
{
public static class SelectionAlignment
{
public static void AlignLeft(PageObjectBase pageObject)
{
Debug.Log("Let's check if this is a group first!");
if (pageObject is PageObjectGroup)
Debug.Log("Now we can AlignLeft!");
PageObjectGroup group = (PageObjectGroup)pageObject;
foreach (PageObjectBase objectBase in group.Children)
{
//objectBase.transform.position
Debug.Log("Position is now" + objectBase.transform.position);
Debug.Log("Left Position is" + objectBase.transform.position + -objectBase.transform.right);
}
}
}
}
}
Note: I have no moving function yet as im first trying to figure out what the position of the most left side of the image is. The first Debug.log works and displays the normal position(middle point of image). The second one doesn't work, and displays the same. Both images get instantiated during runtime.
Hopefully this is enough information, i'm a long time lurker but have never posted anything myself, so be gentle on me if i forgot to add information.
From your question left means a smaller X value.
So in general the left edge of an image (assuming PageObjectBase somehow inherits from MonoBehaviour and you are speaking about Image component from Unity UI with a RectTransform)
is the most left of all four corners of the image. You can get all four corners by using GetWorldCorners
private float GetLeftEdge(PageObjectBase obj)
{
RectTransform rectTransformComponent = obj.gameObject.GetComponent<RectTransform>();
if(!rectTransformComponent)
{
Debug.LogError("No Image component found", this);
return 0;
}
Vector3[] v = new Vector3[4];
rectTransformComponent.GetWorldCorners(v);
float mostLeftCorner = float.MaxValue;
foreach(var pos in v)
{
mostLeftCorner = Mathf.Min(mostLeftCorner, pos.x);
}
return mostLeftCorner;
}
This should also work if the images are rotated.
If you are not using RectTransform you have to get the width another way somehow but the rest stays the same.
Than in your loop you first have to get the smallest (most left) edge so I would split it in two loops:
// Start with the max float value so any other value should be smaller
float mostLeftEdge = float.MaxValue;
PageObjectBase referenceToMostLeftObject;
// Get the most left position and object reference
foreach (PageObjectBase objectBase in group.Children)
{
float leftEdge = GetLeftEdge(objectBase);
if(leftEdge < mostLeftEdge)
{
referenceToMostLeftObject = objectBase;
mostLeftEdge = leftEdge;
}
}
// Now you have the most left edge value and the object which is your reference
// Just a little safety skip to not move to strange values
if(referenceToMostLeftObject == null || Mathf.Approximately(mostLeftEdge, float.MaxValue))
{
Debug.LogError("Ups, I think something went wrong getting the mostLeftEdge", this);
return;
}
// Move the other objects to match with that edge
foreach (PageObjectBase objectBase in group.Children)
{
// Skip the reference object
if(objectBase == referenceToMostLeftObject) continue;
// First get the difference
float leftEdge = GetLeftEdge(objectBase);
// Should always be negative
float difference = mostLeftEdge - leftEdge;
// Than move it there
var current = objectBase.transform.position;
// Since difference should be negative
// Adding it to the current position should result in the wanted position
var newPosition = new Vector3(current.x + difference, current.y, current.z);
objectBase.transform.position = newPosition;
}
Related
I have stuck in this simple problem but unable to understand that why i am unable to control it.
I have these line of code which is displaying my canvas object in front of my player(camRotationToWatch object name in code) at certain rotation of the player.
if (camRotationToWatch.transform.localEulerAngles.x >= navigationCanvasXMinmumLimit && camRotationToWatch.transform.localEulerAngles.x <= navigationCanvasXMaximumLimit)
{
if (!navCanvasHasDisplay)
{
navigationCanvas.SetActive(true);
//Debug.Log(camRotationToWatch.transform.forward);
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
navigationCanvas.transform.position = new Vector3(navCanvas.x, navCanvas.y, navCanvas.z);
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
navCanvasHasDisplay = true;
}
}
else
{
//navigationCanvas.SetActive(false);
if (locationPanel.activeSelf == false && infoPanel.activeSelf == false) {
navigationCanvas.SetActive(false);
navCanvasHasDisplay = false;
}
}
This code is actually work fine when camRotationToWatch object rotate from down to up and Canvas show at correct position but as I try to to rotate camRotationToWatch from up to down it display(active) Canvas at very top position. How can I restrict canvas to show at same position (No matter player rotate from up to down or down to up) but display on front of the player object?
Kinda hard trying to figure out what exactly you want to do. But this did what I think you where trying to do
public GameObject follow; // The object you want to rotate around
public float distance = 2; // Distance to keep from object
private void Update() {
Vector3 forward = follow.transform.forward;
forward.y = 0; // This will result in Vector3.Zero if looking straight up or down. Carefull
transform.position = follow.transform.position + forward * distance;
transform.rotation = Quaternion.LookRotation(forward, Vector3.up);
}
I believe your "unexpected behavior" is due to the use of euler angles since they are not always entirely predictable. Try using Quaternions or Vector3.Angle() when possible.
If you want to limit the angle (say... if looking down or up more than 45° disable the object) you could do the following:
if (Vector3.Angle(forward, follow.transform.forward) > maxAngle) { ... }
This probably isn't a complete answer but something that might help. This line:
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
You are creating a position at a fixed distance from camRotationToWatch. But if that object is looking up or down, that position is not horizontally at navCanvasDisplayDistanceFromCam. If it's looking straight up, then this position is in fact directly above.
So when you do this to set a fixed vertical height:
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
you aren't getting the distance from camRotationToWatch that you think you are.
Instead of using camRotationToWatch.transform.forward, create a vector from it and zero out the Y component, and normalize before using it to offset the position. (You will need to watch out for zero length vectors with that though).
Whether that fixes your problem or not, it's too hard to guess but it should help improve your results some.
EDIT: Here is an example of how you can avoid the issue with the canvas being too close:
Vector3 camForward = camRotationToWatch.transform.forward;
camForward.y = 0;
if (camForward.magnitude == 0)
{
//TODO: you'll need to decide how to deal with a straight up or straight down vector
}
camForward.Normalize();
//Note: now you have a vector lying on the horizontal plane, pointing in
//the direction of camRotationToWatch
Vector3 navCanvas = camRotationToWatch.transform.position + camForward *
navCanvasDisplayDistanceFromCam;
//Note: if you want the canvas to be at the player's height (or some offset from),
//use the player's y
navCanvas = new Vector3(navCanvas.x, Player.transform.y, navCanvas.z);
navigationCanvas.transform.position = navCanvas;
Again, this might not fix all your issues but will help to ensure your canvas lies at a set distance horizontally from the Player and will also compensate for the player's up and down motion.
I'm working on a 2D game where the player can drag tiles around. It works in a way that the player clicks and hold a tile and depending in which direction the player moves the mouse from then on, the drag direction is decided.
The problem however is that this is overly sensitive. It might often be the case that the player starts dragging and wanted to drag vertically but due to the mouse sensitivity it turns out to drag horizontally (or vice versa).
Does anyone have an idea how to add a tolerance threshold to this dragging behavior? The relevant part in my code looks basically like this:
private void Update()
{
if (_isMouseDown && sourceTile != null)
{
_isDraggingTile = true;
/* Determine drag direction and drag target cell. */
Vector3 dragDistance = Input.mousePosition - _originMousePosition;
dragDistance.Normalize();
if (_dragDirection == DragDirection.None)
{
float f = Vector3.Dot(dragDistance, Vector3.up);
/* Mouse up drag. */
if (f >= 0.5f)
{
_dragDirection = DragDirection.Up;
_dragTargetCell = sourceTile.gridCell.upNeighbor;
}
/* Mouse down drag. */
else if (f <= -0.5f)
{
_dragDirection = DragDirection.Down;
_dragTargetCell = sourceTile.gridCell.downNeighbor;
}
else
{
/* Mouse right drag. */
f = Vector3.Dot(dragDistance, Vector3.right);
if (f >= 0.5f)
{
_dragDirection = DragDirection.Right;
_dragTargetCell = sourceTile.gridCell.rightNeighbor;
}
/* Mouse left drag. */
else if (f < -0.5f)
{
_dragDirection = DragDirection.Left;
_dragTargetCell = sourceTile.gridCell.leftNeighbor;
}
}
}
if (_dragTargetCell != null)
{
// Take care of moving the dragged tile!
}
}
}
Simply delaying the calculation of dragDistance by some frames doesn't turn out to work very well. I think what is needed is a solution to figure out the mouse movement and decide on which axes it moves farthest. Determining the drag direction as above will probably never work out well.
The problem with any collection of information is noise. In your case, the noise is defined by the wrong movement of the user. Nonetheless, it should be possible to minimize the effect of noise by averaging the values.
There are advanced algorithms used in DSP but I guess a basic averaging of the info should do in your case.
What you could try is that instead of moving in Update at once like you do, collect movement over several frames, then average all those frames and see if it goes better:
IEnumerator GetAverageMovement(Action<Vector3> result)
{
int frames = 0;
List<Vector3>list = new List<Vector3>();
while(frames < 30f) // half a second appr
{
list.Add(GetDirection());
frames++;
yield return null;
}
result(AverageAllValues());
}
GetDirection is just returning the delta between current and previous position, AverageAllValues simply adds all values in list and divides by list.Count (aka 30).
This should fix cases when the user move all the way right but a bit up at the end. The last bit should be canceled by the large right movement.
If that is still not enough, then you could add some logic within the method that if a value is too far gone from the average, discard it. I don't think you need this in there.
I think you should create a Queue of positions with limited size right after dragging .
by comparing final value of Queue and first value you can find the direction.
If you want to get better results you can get Variance of positions and get better results.
for my programm im programming a "clock like" behaviour. Meaning i
order some pictures in a circle (works)
if i click and drag on any item all items should rotate with the mouse (works)
But i get a weird bug. The first time i click and hold the mouse my images "jump" to different positions. if i hold the mouse down i can rotate my clock ust fine.
When i MouseUp and start dragin from the same image it works well. if i go to another image i get this "Jump" again.
When i only have a few images on my clock i see that it doesnt jump. but the start position seems to bee off.
When i only have one item, i can rotate it in a circle, but the moment i start to rotate it jumps away from my mouse and than i can rotate it as desired.
For me it seems to be a wrong "starting point" when first dragging an item. SInce it works fine when i than drag the same item again and again.
Unfortunately i cant find the damn bug, and im searching the whole day already.
#
public void SetLayoutHorizontal ()
{
Debug.Log ("LAYOUT");
for (var i =0; i < Rect.childCount; i++)
{
var PanelPrefab = Rect.GetChild (i) as RectTransform;
Transform ImageObject = PanelPrefab.GetComponentInChildren<Transform>().Find("Image");
if (PanelPrefab == null)
continue;
PanelPrefab.sizeDelta = CellSize;
PanelPrefab.anchoredPosition = new Vector2(radius * Mathf.Sin( CalculateCircleAngle(i) - deltaRadian),radius * Mathf.Cos(CalculateCircleAngle(i) - deltaRadian));
}
}
private float CalculateCircleAngle(int parts)
{
//parts == Number of parts the whole circle is to be cut into
return parts * (360/Rect.childCount) * (Mathf.PI/180);
}
public void OnDrag (PointerEventData eventData)
{
var diffX = eventData.position.x - _rect.rect.width/2; // MouseX - CenterScreenX
var diffY = eventData.position.y - _rect.rect.height/2; // MouseY - CenterScreenY
deltaRadian = Mathf.Atan2(diffY,diffX);
SetDirty();
}
Edit:
Ok i Edited the code but it still is not working.
I added the following method:
public void OnBeginDrag(PointerEventData eventData)
{
originalX = eventData.position.x;
originalY = eventData.position.y;
}
and i changed the drag method acordingly
public void OnDrag (PointerEventData eventData)
{
var diffX = eventData.position.x - originalX;
var diffY = eventData.position.y - originalY;
deltaRadian = Mathf.Atan2(diffY,diffX);
SetDirty();
}
The "Jumping" at the beginning of my drag event is gone, but the speed of the draggin is not on par with my mouse.
The closer i am to my starting point of the drag, the faster it moves, the further away i am the slower it gets.
I dont know if this brought me closer to a solution or further away :(
Edit2:
Ok i think the problem might be that my calculations were all done from the center point of view as 0,0 point.
Unity has the bottom left point as 0,0. So i somehow have to translate all those coordiantes first...
All that was needed was a transformation to kartesian coordinates
//Convert to kartesian coordinates with 0,0 in center of screen
var diffX = (eventData.position.x - _rect.rect.width / 2) % (_rect.rect.width / 2);
var diffY = (eventData.position.y - _rect.rect.height / 2) % (_rect.rect.height / 2);
and an addition of the delta instead of the subtraction
PanelPrefab.anchoredPosition = new Vector2(radius * Mathf.Sin(CalculateCircleAngle(i) + deltaRadian),radius * Mathf.Cos(CalculateCircleAngle(i) + deltaRadian));
Your mouse coordinates are relative to the control you click in. You could re-calculate them using the control's position within its container or you use absolute coordinates.
I don't think you are displaying all the relevant code, but your OnDrag function, specifically diffX, and diffY probably provide the answer for you.
I believe you're taking the absolute coordinates of the location you pick, and using them to generate your angle - which means that almost anywhere you click is a big jump from however the current angle is set. Your initial click handler should save off a starting coordinate, and your OnDrag should compare itself against that initial coordinate, based on how far you've dragged from that saved location.
Before you point out that there are other answers to this question, i have looked at if not all, most of the other answers to this question or a similar question and i haven't found the solution i require.
Basically all i want to be able to do is when the circle/ball collides with a rectangle, i want to determine which side of the rectangle this collision has occured at. I want to find this out so that i can enforce a bit more realistic physics, e.g. if the ball hits the top of the rectangle, inverse it's Y velocity only... instead of both.
I have tried comparing the X and Y positions of the ball and the rectangle and even the location of both of their bounding boxes... testing even if the bottom of the ball's box has intersected with the rectangles top... using 'if ball.boundingBox.Bottom >= rectangle.boundingBox.Top'.
I have attached a picture to this to show what i am trying to achieve... just in case it's a bit confusing, as it's not detailed... the red what look like v's is the path if the ball comes in from one side, i want the movement upon impact to travel in the opposite way but this depends on the side of the rectangle as to what component of the ball's velocity i will have to change...
FYI i have also looked at vector normalisation... i haven't used it before so forgive me if this could be solved using this...
Thanks v.much for reading
EDIT as i am in a rush, i have used an different image instead... this still shows the behaviour i am trying to achieve, as the physics shown on the diagram is how i want the ball to behave when it collides with the other sides...
LINK TO IMAGE: http://codeincomplete.com/posts/2011/6/12/collision_detection_in_breakout/bounce2.v283.png
This code might be more comprehensive than you need and can be refactored to suit your needs but it is a complete answer and is flexible to use with moving bounding rectangles along with moving circles.
here is a graphic to give a visual aid to what the code is doing.
the red circle is intersecting with the black rectangle. visualize two imaginary lines going through opposite corners. If you know which side of each of the 2 lines the circle is on, you can deduce the collided edge.
first declare class scope private members
Rectangle CollisionBoxRect;
Rectangle circleRect;
Dictionary<string, Vector2> corners;
In your update after you've moved the circle and set its location and the potential intersected box's location it does a basic check to see if the circle's bounding rect is involved with the block's bounding rect. If so, it then alters the ball's velocity with the appropriate collision normal depending on which side of the rect the circle collided with.
if (CollisionBoxRect.Intersects(circleRect))
{
ballVelocity = Vector2.Reflect(ballVelocity, GetCollisionNormal(CollisionBoxRect));
}
The following methods support getting the proper side (the normal actually). Some of these methods can be done once in the initialize phase if they never change (like the get corners method);
private Vector2 GetCollisionNormal(Rectangle boxBeingIntersected)
{
getCorners(boxBeingIntersected);
bool isAboveAC = isOnUpperSideOfLine(corners["bottomRight"], corners["topLeft"], getBallCenter());
bool isAboveDB = isOnUpperSideOfLine( corners["topRight"], corners["bottomLeft"], getBallCenter());
if (isAboveAC)
{
if (isAboveDB)
{
//top edge has intersected
return -Vector2.UnitY;
}
else
{
//right edge intersected
return Vector2.UnitX;
}
}
else
{
if (isAboveDB)
{
//left edge has intersected
return -Vector2.UnitX;
}
else
{
//bottom edge intersected
return Vector2.UnitY;
}
}
}
public bool isOnUpperSideOfLine(Vector2 corner1, Vector2 oppositeCorner, Vector2 ballCenter)
{
return ((oppositeCorner.X - corner1.X) * (ballCenter.Y - corner1.Y) - (oppositeCorner.Y - corner1.Y) * (ballCenter.X - corner1.X)) > 0;
}
private Vector2 getBallCenter()
{
return new Vector2(circleRect.Location.X + circleRect.Width / 2, circleRect.Location.Y + circleRect.Height / 2);
}
private void getCorners(Rectangle boxToGetFrom)
{
corners.Clear();
Vector2 tl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y);
Vector2 tr = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y);
Vector2 br = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y + boxToGetFrom.Height);
Vector2 bl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y + boxToGetFrom.Height);
corners.Add("topLeft", tl);
corners.Add("topRight", tr);
corners.Add("bottomRight", br);
corners.Add("bottomLeft", bl);
}
I'm sorry if question title was unclear, but with my cheap english, I cant find a way to ask it clearly.
But I can explain it in long way.
So I have realized if I design my world(and with world, I mean ENTIRE game, it will be one level) 10.000x10.000... it will be very enough, other than few another sprite(and I mean like 4 or 5 with maximum of 50x50, nothing big.)
So I thought, why dont I make my entire map as 10.000x10.000(or lets say tons of 512x512) picture ?
But I have one question, there is few things you can "interact". they will(with they, I mean the stuff that is in my "world.jpg") be always stay at same place, but player(which is actually a sprite as you know) will move, therefore my 10.000x10.000 will "move".
So look at picture below, there is black dot which is "player" and red dot, which is lets say, a door.
and world is always centered to black dot unless he goes to end of the world. as you can see, (look at picture part 1 and part 2) when he moves a little bit to east, red dot looks moved. but I just moved my 10.000x10.000 image. Thats what I meant with the stuff on 10kx10k pic will move.
Anyway, but as you can see in last part of pic, when he goes near red dot, I want to my "action"
How to do it ?
-part below is not really related to main question
Is it useful to use 10kx10 pic instead of another sprites appearing on world when he moves ? but If I want to do that, not just I will check if he is nearby, but I will also check his point to realize if I should or shouldnt show him sprite.
Will it be more useful if I show my stuff when he comes to coordinates I want, or is using one big picture is OK ?
Thanks.
I would suggest a structure of the map somewhat like this..
public class Map
{
public MapPoint[,] mapPoints; //the map
public Player player; //the player/user object
public Vector2 DrawHeroPosition;
//where at the screen the player is going to be drawn
public Vector2 RangeStart;
//what part of the map who is going to be drawn
public int SizeX; //number of mapPoints the screen can contain at one time
public int SizeY; //number of mapPoints the screen can contain at one time
//MapPoint represents a specific 512x512 point (mapPoint) its position at
//the map but also includes the sprite that is going to be drawn and objects
//that the player can interact with at that place (like the door)
//the player object includes reference to where in the world it is place
public Map(ContentManager theContentManager, int x, int y)
{
MapSizeX = x;
MapSizeY = y;
int ScreenSizeX = 9;
int ScreenSizeY = 9;
mapPoints = new MapPoint[MapSizeX , MapSizeY];
//ad code for generating/creating map...
//important that you store the MapPoints position inside each mapPoint
player = new Player(mapPoints[0,0]); //crate a player who knows where he is
}
public void Update()
{
//in the update method you do a lot of things like movement and so
//set what part of the map the game should draw if the game for example
//can show 9x9 512points at a single time
//give range value from the players position
RangeStart.X = player.PositionX;
//test if the maps position is in the left corner of the map
//if it is draw the map from the start..(RangeStart.X = 0)
if (player.PositionX - (ScreenSizeX / 2) < 0) { RangeStart.X = 0; }
//if not draw the hero in the mitle of the screen
else
{
RangeStart.X = player.PositionX - (ScreenSizeX / 2);
}
//if the hero is in the right corer, fix his position
while (RangeStart.X + ScreenSizeX > MapSizeX)
{
RangeStart.X--;
}
//the same thing for the Y axle
RangeStart.Y = player.PositionY;
if (player.PositionY - (ScreenSizeY / 2) < 0) { RangeStart.Y = 0; }
else
{
RangeStart.Y = player.PositionY - (ScreenSizeY / 2);
}
while (RangeStart.Y + ScreenSizeY > MapSizeY)
{
RangeStart.Y--;
}
//time to set the position of the hero...
//he works like the opposite of the range, if you move what part of the map
//you draw you dont change the heros draw position, if you dont move the range
//you have to move the hero to create the illusion of "moment"
//if you are in the left part you have to move the heros draw position..
if (player.PositionX - (ScreenSizeX / 2) < 0)
{ DrawHeroPosition.X = player.PositionX; }
//if you are in the right part
else if (player.PositionX+1 > MapSizeX - (ScreenSizeX / 2))
{
DrawHeroPosition.X = player.PositionX - (MapSizeX - ScreenSizeX);
}
//if you aint in a corner, just place the hero in the middle of the map
else
{
DrawHeroPosition.X = (ScreenSizeX / 2);
}
//the same thing for Y
if (player.PositionY - (ScreenSizeY / 2) < 0)
{ DrawHeroPosition.Y = player.PositionY; }
else if (player.PositionY+1 > MapSizeY - (ScreenSizeY / 2))
{
DrawHeroPosition.Y = player.PositionY - (MapSizeY - ScreenSizeY);
}
else
{
DrawHeroPosition.Y = (ScreenSizeY / 2);
}
}
public void Draw()
{
int x = (int)RangeStart.X;
int y = (int)RangeStart.Y;
for(int counterX = 0; x < ((MapSizeX)); x++, counterX++)
{
for (int counterY = 0; y < (MapSizeY); y++, counterY++)
{
if (mapPoints[x, y] != null)
{
mapPoints[x, y].Draw(spriteBatch, mapPoints[counterX,counterY].positonInMatrix);
//mapPoints[counterX,counterY] = where to draw
//mapPoints[x, y] = what to draw
}
}
y = (int)RangeStart.Y;
}
}
}
how i draw inside the MapPoint Class...
public void Draw(SpriteBatch theSpriteBatch, Vector2 positonOnScreen)
{
positonOnScreen = new Vector2(positonOnScreen.X * base.Scale * 16,
positonOnScreen.Y * base.Scale * 16);
//base.Scale is just a variable for have the ability to zoom in/out
//16 represents the original size of the picture (16x16 pixels)
theSpriteBatch.Draw(mSpriteTexture, new Rectangle((int)positonOnScreen.X,
(int)(positonOnScreen.Y), 64, 64),new Rectangle(0, 0, 16, 16), Color.White);
}
If you are asking for collision detection within a radius of your red dot. You can simply use the following test (pseudocode, I don't write C# :-)
if( (player.GetPosition() - point.GetPosition()).length() < radius )
{ /* Do code here */ }
This will detect if your player is within a certain radius of your dot, you can then perform whatever action you wish.
Hope this helps! :)
Ok, from what I understand of your question, you have a large image which contains different objects you want your player to interact with, yes? By which I mean, the image file itself has doors or hills or other things which the player would interact with.
This is a bad idea, honestly, so I hope I misunderstood. It is far better to have your background image just be something generic and make all interactive objects classes within your game. If you do this, then you can have your object classes contain behavior to intersect with each other either based on their distance (circle collision) or based on a bounding box you define for them.
Circle Collision:
if (Math.Abs(Vector2.Distance(player.Position - obj.Position)) < player.Radius + obj.Radius)
//do the action
Rectangle Collision:
if (player.Bounds.Intersects(obj.Bounds))
//do the action
Also, if you are planning on making a 10,000 x 10,000 pixel image, understand that the XNA Content Pipeline will not import an image greater than 4,000 pixels to a side.
If you are set on having the player interact with pixels in the background of the image, you can either make an array of interactive object locations manually or you can use the Texture2D.GetData() method to load in the colors of every single pixel in the image for processing-- but be aware that this will take a long time, especially for large or numerous textures.