• 13
• 18
• 19
• 27
• 10

# SDL camera problem

This topic is 3552 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ok, I am making a 2D sidescrolling shooter. Here is what I am trying to do. I have it so when I push the fkey a timer will start and the position where I want the bullet to fire from is set. When I release the fkey the timer stops and the ticks are put into a function that executes and fires the bullet, the power is based on how long the key was held. In the main game loop I have a function that shows the bullet and moves it along the x axis. The problem is that when my player jumps the bullet moves up along with the camera. For example, i put 300,300 for my playerfirebox.x and playerfirebox.y. It showed the bullet at the same point on the screen but not at 300,300. Why does the bullet move with camera and not just fire from where I tell it to? http://codepad.org/3aePBRZf There is all my code, I know it's painful to look through but bear with me. I am just a junior in high school with no lessons in computer programming except what I read out of books and from the internet. Please, help me.....

##### Share on other sites
One off topic thing I noticed: When you check the status variable to determine which position the player is in you might want to use if/else if instead of a bunch of if statements. I believe the first is quicker, since once you find the right one you don't need to check the others.

That is a lot of code to look through, but I believe you are probably mixing up screen coordinates with world coordinates. You want to move the camera, but keep the bullets in the same "world" coordinate. The best way I see to do this after skimming your code would be to apply the opposite transformation of what you are doing to the camera to all of your bullets. That is, if centering the camera means moving it up 100 pixels, then do so, but move the bullets down 100 pixels and they will have continued on their previous path.

Or, what might be easier, just update the bullets first, then move the camera. Though I haven't found that part of your code just yet. Found it now. I'd make that switch and see if that fixes your problem.

##### Share on other sites
"Or, what might be easier, just update the bullets first, then move the camera."

How exactly do I do that? In my main level loop, I update camera position and then later show the part of the level that the camera box includes. I tried putting level.ultroid.showfire(); above level.ultroid.set_camera(); but then I didn't see the bullet at all. I expected that to happen though, because when I show the level it paints over the whole screen. What part of my code were you looking at? Also, the other way you said I could fix it. How would I do that? How do I find the transformation of the camera?

##### Share on other sites
What you (IMO) ideally would want to do is update all objects before rendering anything. So in other words, each frame, before rendering, look at your input and move the player, bullets, camera, or whatever else, but without rendering them. Then actually draw everything. The biggest flaw with your code is that, for instance, your showFire() function doesn't only show the bullets, but updates their position. You should update everything's position first, then draw to avoid hangups like this.

When you move the camera up, you haven't really changed the coordinates of the screen. The first left-hand pixel is still zero, and the top pixel is still zero on the x-y coordinate grid, and the others extremes are still the width and height of the window. The reason your bullet is still in the same spot on the screen is because it is still at (300, 300) in the window. These are screen coordinates so moving the camera up doesn't affect the bullet. I see two fixes:

1) Since your camera moves the bullets as it is, just apply a reverse operation on the bullets of the one from the camera. That is, if you move the camera up 100 pixels, move the bullets down 100 pixels before drawing them. This will fix your problem, but you don't currently track the camera change, so you'd have to add that. You could do something like
int cameraDY;int prevX = camera.y;//move the cameracameraDY = camera.y - prevY//then in the bullet functionbullet.x += bulletvelocity;bullet.y += cameraDY;

2) Draw your scene onto a different Surface than the screen. Be sure to update the position of everything, then draw everything. You would be drawing to a surface larger than the window, meaning that you risk wasting time drawing things you can't see, but in most 2D platformers this isn't a big deal. Then have a rect which you use to copy the screen sized region you wish to actually see to the screen. This is just like what you are doing with your sprites. You just render the entire scene then cut out the rectangle you want to see. This is kind of like having a back-buffer. This way, everything is drawn wherever it should be (no camera class needed for this back-buffer) and moving the camera simply involves moving the clipping rect to a different height.

I am no expert, but I would say that the first solution is somewhat quick and dirty. It will do the job, but might be avoiding the real problem which lies elsewhere. It's like hiding it instead of fixing it. The second is probably more desirable from a coding standpoint, but will mean much more re-writing of code (though not that much). It will actually rid you of the problem. You choose whichever you want. It depends on your goals for this project.

##### Share on other sites
Sorry, I don't quite understand what your saying for the second solution.

Can you explain it again? How is it different then what I am doing now?

##### Share on other sites
Currently, when you are drawing, you are calling apply_surface(someSurface, screen). What I am saying to do is to create a surface (we will call it hiddenSurface), where hiddenSurface is the maximum size (or, height, I suppose) needed for the game, and change all rendering calls to apply_surface(someSurface, hiddenSurface). So, if your screen is 640x480, and your player can jump 20 pixels high, then make the height of hiddenSurface 500 pixels. Basically, you draw everything on the map to this surface. Then, when you are done with all of that, use an SDL_Rect which is acting as a "camera" to cut out the part you want to see, and blit hiddenSurface to screen. Make sense? Imagine you've got a large poster sized picture (in this case representing hiddenSurface) and you want to frame it, but only have a smaller sized frame (representative of screen). You would have to move the frame around to center it on what you want to show in it, just like you are doing with the screen surface to see what you want of hiddenSurface.

If you understand this, you might also then be worried about wasting time drawing things not on the screen. The best solution for this is to only re-draw things that have been updated. Performance should not be an issue.

##### Share on other sites
I am still not getting it. Here is what I did.

[Edited by - RisingForce on June 24, 2008 6:51:51 PM]

##### Share on other sites
You've missed the point again. The point is to render to a surface which is not your screen. Then render only what area you want from that surface to the screen. Here's an illustration (screenshot from random image search):

hiddenSurface represents a surface that you don't see, hence the name. Do your rendering to it. The smaller rectangle is the screen, a.k.a. your window. The yellow rectangle would be defined by an SDL_Rect. You would blit that Rect from hiddenSurface to screen. You don't need anything like double-buffering on hiddenSurface. It is just like an image that you've loaded, except it's one that you've created. The result in the window is the following:

This way, the only coordinates you are changing are those of the Rect. You don't accidentally move your bullets, and there is no confusion between screen coordinates and world coordinates. If you don't understand still, I really don't know what to say. I guess I don't know which part is unclear.

##### Share on other sites
"You would blit that Rect from hiddenSurface to screen."

How do I do that? Also, How do I move the Rect then? Could I use my Rect camera that I already have?

I am just not understanding how to create and deal with this Rect.

##### Share on other sites
An SDL_Rect has an x and a y value. These represent its positioning. It also has a w and h value, the width and height. These should match your window size. Each frame, move the rect with the x and y values. That easy. It is the exact same thing you do with your sprite sheets, so it ought to be very similar.