Cameras and "Sticking" Objects Together

Jun 28, 2009 at 9:51 PM

My first question- not particularly my most important as I can go on with coding my game... but something I took a sidetrip to do-  cameras.  Right now, I'm doing a basic Matrix transform and throwing it in the spriteBatch.begin() overload.  Problem-  when zooming in/out, if I dont pull the mouse (which is its own graphic) out, the mouse gets smaller/larger.  Easy solution-  I pulled it out and did its own spriteBatch rendering.  Now, the mouse cursor is independent and in its proper position.  I'm using a basic implementation of the mouse in the simplesamples where you click an object, and it creates a spring at that point. 

Problem-  when I pull the mouse out of the spritebatch, its clicking on where it would be clicking should the mouse be in the spritebatch as all its doing is zooming in/out.  I haven't figured out how to offset it yet, but I'm thinking to take the current scale and come up with a formula to offset the position of the point in the input.  If anyone has done this already, it'd help me out greatly.  Basically- I'm making a worms/tower defense style game.  Of course theres also going to be scrolling around the screen.  Am I going about it wrong to use a Matrix and just change the camera view for zooming/scrolling with a mouse while using Farseer?  Is there a better implementation I should use?  Any examples??

Now on with my more important question that has someone got me at a standstill until I get it figured out-  Part of my game is building your structure.  Not just clicking a "purchase" button and bam, it statically puts your upgrade there... but you need to manually place upgrades and such onto your structure in a dynamic location.  What would the best approach be to this with Farseer?  Would it best be to make a joint of some sort and give it a breakpoint?  Thanks in advance!

Jun 29, 2009 at 1:28 AM

Q1) There are two approaches you can take to this:

a) Draw the mouse in the same spritebatch as your other objects (i.e. with the camera matrix) and simply scale the mouse drawing to counter the camera zoom.

b) Draw the mouse in its own spritebatch (as you've already done) and calculate the world-position (as opposed to screen-position) of the mouse cursor. This is as simple as

mouseWorldPosition = cameraPosition + (mouseScreenPosition - screenSize/2) / cameraZoom;

Q2) I don't completely understand what you're trying to do. Are you asking about how to deal with manipulating dynamic objects with the mouse cursor? If so, an approach I use is; whenever I wish to move an object (by clicking it) I simply make it static and disable collisions and then change it's position according to the mouse (i.e. click and drag). It is important to disable collisions to stop it from interferring with other dynamic objects while moving, since you're manually changing the position this can cause errors in the simulation.

Jun 29, 2009 at 5:55 AM

Have you seen my Camera2D class? it is highly polished and comes with an input helper.

Jun 29, 2009 at 10:34 PM

Thanks for the quick replies!!

@RogueCommanderIX - Yes, I've seen it.  I'm using it for ideas.  As my physics/collision is already "premade", I want to try to program as much as I can on my own... I know XNA for the most part does most of the programming for me- its a little bit of a sense of accomplishment for me to program as much as I can.  Thanks tho! :)

@sterlingware - Q1) My current camera class I haven't exactly built up much yet has an update as such:

public void Update(int width, int height)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Z))
                scale *= 1.01f;    
            else if (Keyboard.GetState().IsKeyDown(Keys.C))
                scale /= 1.01f;
            if (Keyboard.GetState().IsKeyDown(Keys.A))
                offset -= 5;
            else if (Keyboard.GetState().IsKeyDown(Keys.D))
                offset += 5;

            camera_Pos.X = offset + (width - (width * scale)) / 2;
            camera_Pos.Y = (height - (height * scale)) / 2;

            transform = Matrix.CreateScale(scale) * Matrix.CreateTranslation(new Vector3(camera_Pos.X, camera_Pos.Y, 0));
        }

 

Basically, 'Z' zooms in, 'C' zooms out, 'A' moves the screen to the left (or in other words- scrolls you to the right), and 'D' does the opposite.  width/height is the screen size passed in to it.  "transform" is returned via a getter, and thrown into my spriteBatch.begin().  I know I need to handle this a little better in terms of getting the screen size- but for now, I want to get the basics and math down... then I can worry about cleaning it up and organizing.  I haven't had time to try to implement your formula or to mess around with it, but do you still think your worldposition formula you provided would work fine?

Q2)  I just re-read my question and I can see how it would confuse a little-  Basically, I have a "structure".  The structure is nothing but a large and heavy body/geom.  I also have various scraps/smaller parts/upgrades/weapons/etc...  I want to drag those smaller parts onto the structure, and have them stick to it.  I'm thinking I should use a weld joint to do as such.  I don't have a problem dragging/dropping for the most part as I'm just using the method in the simplesample (creating a spring at the click point).  I'm thinking it would be something like-

quick pseudocode:

if mouse == dragging a geom && geom collides with other geom

{

           weldjointlist.add(new weldjoint at collision points)

          set the weldjoint breakpoint // to allow dragging off, but needing a little bit of pull just to make sure its intentional

}

basically- I suppose I might need a little bit of clarification on obtaining the exact collision points.

Once I can get this thing out of the way of dragging/dropping the objects and letting them "snap" onto the structure (i suppose something like "world of goo" where the gooballs would "snap" onto the structure, and they can be pulled off with a little bit of force is another way to look at it), I know I can easily implement enough to get a good proof-of-concept done.  Then, the rest of my game would be nothing but creating maps, artwork, scripts for levels, and polishing it up.

 

 

Jun 30, 2009 at 2:51 AM

I highly urge you to take a look at my InputHelper class. it offers a complete abstraction of input, allowing you to simply make checks for button down, button pressed currently, and button up. I know you like to program on your own but i seem to recall a quote saying something to the effect of "programmer's favorite thing is reinventing the wheel" :) . Still, if you dont want to use it then it's not a problem.

Jun 30, 2009 at 6:56 AM

I think the best solution is to use a separate spritebatch section for mouse drawing, but calculate world coordinates. Instead of doing a manual world coordinate calculation though, I'd recommend using your existing transformation matrix to do it. Actually I think you need the inverse of your transformation matrix. I forget, it's been a long time, but yeah I think if you multiply the screen coordinates of the mouse (Z = zero) by the inverse of your camera's transformation matrix, then you'll get the world coordinates of your mouse. 

 

*The rest of this post is just me on a soap box again. Feel free to stop reading now*

Oh, and keep that attitude about learning how to do things yourself. As an exercise I wrote a lite version of SpriteBatch in Java using JOGL just to get a better understanding of how it works and how I could customize it if I needed to. If you don't know how to write your own solutions, you'll be stuck with what you're given, even if it doesn't exactly fit your needs.