|
test84
|
 |
« on: July 12, 2009, 05:08:07 AM » |
|
Hi,
I wanted to add scrolling to my 2D platformer but I had no idea what to do. Would someone please help?
|
|
|
|
|
Logged
|
|
|
|
|
Danmark
|
 |
« Reply #1 on: July 12, 2009, 05:39:51 AM » |
|
That's hard to answer without knowing which libraries you're using. Broadly speaking, you should subtract the camera position from objects' actual positions to find their screen space positions, and draw them there. Normally you'd set the camera position to the avatar position.
|
|
|
|
|
Logged
|
|
|
|
|
test84
|
 |
« Reply #2 on: July 12, 2009, 06:05:38 AM » |
|
I'm using XNA and using my own code for drawing the board.
|
|
|
|
|
Logged
|
|
|
|
|
Danmark
|
 |
« Reply #3 on: July 12, 2009, 06:34:23 AM » |
|
Hmm, I just tried to find an API reference for XNA, and apparently there is none (despite clear references to it including libraries). Using a non-trivial documented library is painful enough, let alone an undocumented one. I'd jump ship to something else, along the lines of Haaf's Game Engine. Otherwise, you're probably best off searching forums involving XNA.
|
|
|
|
|
Logged
|
|
|
|
|
test84
|
 |
« Reply #4 on: July 12, 2009, 06:38:32 AM » |
|
Thanks for the effort,
If I knew the basics on what to do, a little more detail than your initial post, I would implement it, like what I did for collision detection.
|
|
|
|
|
Logged
|
|
|
|
|
Dacke
|
 |
« Reply #5 on: July 12, 2009, 07:35:06 AM » |
|
It's hard to say exactly what to do, because it depends on what you have support for to begin with (I think).
A perspective that may prove helpful in understanding what is going on is this: You can think of the 2D game world as something that exists as a big image. But you can't view the entire image at the same time. So you create a small window, like a camera, that you look at the image through. If you were to do this in real life you'd have two options if you wanted to watch a certain part of the image. You could move the camera or move the image. Especially when doing 3D games you usually move the world, rather than the camera.
If you want to “move the world”, you can do this for every object you have in your game: 1) get the position of the object 2) from this, subtract the current camera position offset (the current position of the camera) 3) check if the object's new position is within the span: 0<x<windowWidth && 0<y<windowHeight (if so, the camera can see the object) 4) draw the object at the position calculated in step 2 (if the camera could see it in step 3)
Note that you should never actually move the object. Just use a temporary variable for storing the objects position with the camera offset subtracted from it. Also note that the instructions are simplified and does not consider the width and height of the objects in step 3.
|
|
|
|
|
Logged
|
|
|
|
|
Danmark
|
 |
« Reply #6 on: July 12, 2009, 07:56:21 AM » |
|
Dacke is right. But I'd suggest you leave step 3 on the backburner until you've gotten the more naive part right- especially since it actually makes sense to check whether something's on the screen before it's even translated, which will require fancier data structures. It's "just" an optimization (albeit an important one). Stick with the simple for now.
There's another immediate concern though. Since you want your camera represent the center of the screen, and assuming that within the XNA screen drawing functions (0,0) is the top-left corner and (screen width - 1, screen height - 1) is the bottom right as is typical (all in pixels- do check this because it might not apply), you also need to add (screen width / 2) to the X position and (screen height / 2) to the Y position of each object. No big deal.
Happy coding!
|
|
|
|
|
Logged
|
|
|
|
|
Dacke
|
 |
« Reply #7 on: July 12, 2009, 08:31:49 AM » |
|
Thank you for those additional comments 
|
|
|
|
|
Logged
|
|
|
|
|
Impossible
|
 |
« Reply #8 on: July 12, 2009, 09:04:50 AM » |
|
Hmm, I just tried to find an API reference for XNA, and apparently there is none (despite clear references to it including libraries).
Try harder next time. MSDN is a pain in the ass to search through, MS has a lot of APIs and the organization of their documentation is not very good, but there is this site called Google that tends to link you to the right place if you ask it nicely.
|
|
|
|
|
Logged
|
|
|
|
|
Danmark
|
 |
« Reply #9 on: July 12, 2009, 09:55:18 AM » |
|
Funnily enough the MSDN is the first place I checked, a search there didn't find it (?, could've browsed but it wasn't my first option), so I checked Google and immediate results were presumably old testimonies that it doesn't exist. I'd consider it pretty buried compared to the documentation for most engines/libraries etc.
|
|
|
|
|
Logged
|
|
|
|
|
Colonel Mustard
|
 |
« Reply #10 on: July 12, 2009, 11:25:24 AM » |
|
An easy way to do it with XNA is using a transformation matrix, an overload for the SpriteBatch.Begin has a parameter for one, I've set up mine as follows: I've got a Vector2 representing the current "viewport", how far from the map 0,0 (top left corner) I am, and then variables representing the width and height of the window (for easy access) Then during updates, if the object you're controlling moves too close to the edge of the viewport, you move the viewport accordingly. In my main draw method I've got the following: Matrix cameraMatrix = Matrix.CreateTranslation(new Vector3(-viewport.X, -viewport.Y, 0)); spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, cameraMatrix); And with that, you can draw your game objects with positions relative to the map, and the spritebatch will offset them with the cameraMatrix added.
|
|
|
|
|
Logged
|
|
|
|
|
test84
|
 |
« Reply #11 on: July 14, 2009, 01:09:17 AM » |
|
Thanks,
I thought more on the subject and I found out that I have to somehow control how and where my camera is currently looking at, I wonder how I can control what my camera is currently showing.
(I did read the last post and I think its most of what I want, but I'm still lost on the subject).
tnx.
|
|
|
|
|
Logged
|
|
|
|
|
Danmark
|
 |
« Reply #12 on: July 14, 2009, 01:50:35 AM » |
|
You've been given the answer 3 times so I take it you're having conceptually difficulty. Imagine you're looking at a bookshelf. Like a 2D game camera, the direction of your view is fixed, perpendicular to the books. Now if you walk directly to your left, the books appear to move right. Walk to your right and they move left. This is the same no matter how short or far of a distance you walk. So the books always move in the opposite direction of your view. In other words, their apparent position is related to the inverse of your viewpoint's position: this is -camera.x and -camera.y. Of course, if all the books were at the point defined by (-camera.x, -camera.y), they would all be in the exact same place. You have to account for the objects' actual positions: this is (sprite.x, sprite.y). Put the coordinates together and you get the draw position (sprite.x - camera.x, sprite.y - camera.y) for each sprite. This defines where your camera is looking at, and implicitly controls what your camera is currently showing, because objects outside of the viewport won't be seen. When you've seen it working, next implement the offset your sprites as described here, so that they're drawn from their origins and not their top-left corners.
|
|
|
|
|
Logged
|
|
|
|
Alex May
...is probably drunk right now.
Level 10
hen hao wan
|
 |
« Reply #13 on: July 14, 2009, 01:55:24 AM » |
|
Thanks,
I thought more on the subject and I found out that I have to somehow control how and where my camera is currently looking at, I wonder how I can control what my camera is currently showing.
(I did read the last post and I think its most of what I want, but I'm still lost on the subject).
tnx.
A 2D camera can be thought of as an object that has a position and a rectangular view size (more properly called a 'frustum'). When you draw your game, what you want to draw is whatever the camera can see. In the simple case, you camera's view would be the same size as the screen. So if you were to imagine the camera's view as a rectangle, if would fit exactly on your screen. Let's say your view is Width units in width and Height units in height, and your camera's 'position' is a 2D vector called Position. Now, to find the top left of the camera's view, you would take the camera's position and take an offset equal to (Width/2, Height/2) to the top left. This assumes that your camera is pointing at the centre of the screen. Then you take the same offset to the right bottom of the camera's position. This gives you your visible rectangle on the screen. Now you have your visible rectangle, you can draw on the screen whatever the camera can see by testing its position against the rectangle, but you will need to translate it to make sure you're drawing it on the screen. Hope that helps.
|
|
|
|
|
Logged
|
|
|
|
|
lansing
|
 |
« Reply #14 on: July 14, 2009, 03:18:45 AM » |
|
Hmm, I just tried to find an API reference for XNA, and apparently there is none (despite clear references to it including libraries).
Try harder next time. MSDN is a pain in the ass to search through, MS has a lot of APIs and the organization of their documentation is not very good, but there is this site called Google that tends to link you to the right place if you ask it nicely. I have found the organisation quite good in the past, atleast for win32. Once you find a function simply expand the tree on the left it it splits into data structures / functions and a section which has an overview. Kudos to Microsoft.
|
|
|
|
|
Logged
|
|
|
|
|
test84
|
 |
« Reply #15 on: July 16, 2009, 08:38:51 AM » |
|
An easy way to do it with XNA is using a transformation matrix, an overload for the SpriteBatch.Begin has a parameter for one, I've set up mine as follows: I've got a Vector2 representing the current "viewport", how far from the map 0,0 (top left corner) I am, and then variables representing the width and height of the window (for easy access) Then during updates, if the object you're controlling moves too close to the edge of the viewport, you move the viewport accordingly. In my main draw method I've got the following: Matrix cameraMatrix = Matrix.CreateTranslation(new Vector3(-viewport.X, -viewport.Y, 0)); spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, cameraMatrix); And with that, you can draw your game objects with positions relative to the map, and the spritebatch will offset them with the cameraMatrix added. Thanks to *ALL* who contributed here, I managed to do it  via reading here, which has things that you said. I understood it all but the Camera translation Matrix. My question is why in the code: spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, cameraMatrix); , they use SpriteBlendMode.AlphaBlend and SpriteSortMode.Immediate. If my questions are too much XNA related, tell me so and I'll go there, I just feel better here. -test84
|
|
|
|
|
Logged
|
|
|
|
Alex May
...is probably drunk right now.
Level 10
hen hao wan
|
 |
« Reply #16 on: July 16, 2009, 01:30:00 PM » |
|
It is ages since I used XNA so these two might be a bit wrong.
Alphablend tells the computer to draw sprites taking into account their alpha channel and probably also the alpha of the sprite. It means the sprites can be transparent in places instead of opaque colour the whole way through.
Immediate I seem to recall just means "draw them in whatever order you find them", as opposed to "draw them in some kind of Z order or some shit".
|
|
|
|
|
Logged
|
|
|
|
|