Jump to content

  • Log In with Google      Sign In   
  • Create Account


2D scrolling game


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
16 replies to this topic

#1 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 10 March 2013 - 06:23 PM

I am gonna make a 2D scrolling game, kinda like Mario. What is the best way to move the screen? Move the player and update the camera accordingly or move the entire screen and let the player stay still?



Sponsor:

#2 willpowered   Members   -  Reputation: 479

Like
4Likes
Like

Posted 10 March 2013 - 07:37 PM

Move the player, and then move the camera to the same position. Then when you draw, draw everything at an offset based on the camera's position.



#3 mdias   Members   -  Reputation: 781

Like
2Likes
Like

Posted 10 March 2013 - 10:12 PM

I would go for a move the player and refresh camera position too, instead of moving the world. Otherwise:

  • it will be difficult to setup "effects" such as smooth camera following and so on...
  • it will be harder to accomplish scrolling since you'll have to update every object's position instead of just the player+camera
  • if you use a physics engine, it will be even harder to keep sprites and internal physics state in sync

I can't really think of an upside to moving the world instead...



#4 Servant of the Lord   Crossbones+   -  Reputation: 17060

Like
2Likes
Like

Posted 10 March 2013 - 11:11 PM

As Willpowerd said, draw your objects at "absoluteObjectPosition - absoluteCameraPosition", and trim out objects not in view. absoluteCameraPosition = absolutePlayerPosition, most of the time. This is fairly simple and easy to implement, but works very well for most 2D situations.


Edited by Servant of the Lord, 10 March 2013 - 11:12 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#5 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 14 March 2013 - 06:59 PM

I understand how to render objects relative to the camera. I'm not sure how I get the camera to follow the player, while keeping him centered.


Edited by Johnell, 14 March 2013 - 08:42 PM.


#6 Khatharr   Crossbones+   -  Reputation: 2818

Like
0Likes
Like

Posted 14 March 2013 - 09:10 PM

I think you're going to need to explain what it is that you're not getting more precisely. Maybe if you start by explaining to us your process so far and then stop at the point where you're stuck and explain why you don't know what to do.


void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

#7 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 15 March 2013 - 05:43 AM

I think you're going to need to explain what it is that you're not getting more precisely. Maybe if you start by explaining to us your process so far and then stop at the point where you're stuck and explain why you don't know what to do.

 

I wanna know how I can keep the player centered on the screen while moving him. I need the camera to "follow" the player so the camera's position is updated, but I dont know how I can accomplish this.


Edited by Johnell, 15 March 2013 - 05:44 AM.


#8 stannic   Members   -  Reputation: 173

Like
0Likes
Like

Posted 15 March 2013 - 08:54 AM

As state above

but you also need to center 0,0 to the middle of the screen in 2d so addhalf your screen dimension

 

camerapos = playerpos

 

for all objs

   draw obj at objpos-camerapos+(screenDimension/2)


Edited by stannic, 15 March 2013 - 08:59 AM.


#9 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 15 March 2013 - 09:51 AM

So instead of moving the player I should move the camera and just center the player in the camera?



#10 stannic   Members   -  Reputation: 173

Like
0Likes
Like

Posted 15 March 2013 - 11:42 AM

You move the player normally then center the camera onto the player (camerapos = playerpos)



#11 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 15 March 2013 - 07:30 PM

I am currently centering the player this way:

 

player.draw(playerX - cameraX + (screen.width/2), playerY - cameraY + 240);

 

 

This do indeed work, although i'm confused as to why it does. Since playerX = cameraX I am just drawing it at screen.width/2. Say screen.width/2 is 400px. If cameraX is at 800 the player will still be drawn at 400px, yet still be centered in the screen. Why is that?



#12 Servant of the Lord   Crossbones+   -  Reputation: 17060

Like
0Likes
Like

Posted 15 March 2013 - 08:18 PM

Because your cameraX is the top-right (or bottom-right) of the camera, and not the center of the camera.

 

You're mixing two different formulas into a single location:

A) You're calculating the center of the camera from the camera's position and the screen size.

B) You're calculating the player's on-screen position from his absolute (or 'world') position and the (now centered) camera.

 

I suggest you keep your camera position as the center point of the camera, I just find it easier that way. Then your function would just look like:

player.draw(playerX - cameraX, playerY - cameraY);

 

Further, holding a 2D 'position' is a very very common game task. It adds extra visual code clutter and extra opportunities for mistakes if for every 'position' you have two variables (one for x and one for y).

 

Instead, a position is a prime candidate for its own struct or class.

 

A 'Point' class, that contains an 'x' and 'y', and has built-in addition and subtraction functions. Instead of every function taking an 'x' and a 'y', now you just take a 'point'.

 

This further reduces and simplifies your code to:

player.draw(playerPos - cameraPos);

 

It has the extra same code costs, but alot less visual clutter, and alot less potential for bugs, and alot easier maintenance, and alot easier readability.

Here's the interface for my point class: http://ideone.com/lH9X3B

Here's the source file: http://ideone.com/G5aAst

 

Many people (and different libraries) have their own custom point class. It's a very useful thing to have.

I suggest you make yourself a Point, a Size, and a Rect (which contains a Point and a Size).


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#13 stannic   Members   -  Reputation: 173

Like
0Likes
Like

Posted 15 March 2013 - 09:40 PM

if playerpos = (400,0) and camerapos = (800,0) and the player is still centered on the screen, then something is wrong.

It should be drawing the player at (-400,0) relative to the center of the screen, which should be on the left side of the screen.

 

As to why it works, since playerpos = camerapos, playerpos-camerapos = (0,0). So then when you add half your screenDimension, which is the center of the screen, it will center the player onto the screen.



#14 Johnell   Members   -  Reputation: 352

Like
0Likes
Like

Posted 16 March 2013 - 05:30 AM

Because your cameraX is the top-right (or bottom-right) of the camera, and not the center of the camera.

 

You're mixing two different formulas into a single location:

A) You're calculating the center of the camera from the camera's position and the screen size.

B) You're calculating the player's on-screen position from his absolute (or 'world') position and the (now centered) camera.

 

I suggest you keep your camera position as the center point of the camera, I just find it easier that way. Then your function would just look like:

 

player.draw(playerX - cameraX, playerY - cameraY);

 

Further, holding a 2D 'position' is a very very common game task. It adds extra visual code clutter and extra opportunities for mistakes if for every 'position' you have two variables (one for x and one for y).

 

Instead, a position is a prime candidate for its own struct or class.

 

A 'Point' class, that contains an 'x' and 'y', and has built-in addition and subtraction functions. Instead of every function taking an 'x' and a 'y', now you just take a 'point'.

 

This further reduces and simplifies your code to:

 

player.draw(playerPos - cameraPos);

 

It has the extra same code costs, but alot less visual clutter, and alot less potential for bugs, and alot easier maintenance, and alot easier readability.

Here's the interface for my point class: http://ideone.com/lH9X3B

Here's the source file: http://ideone.com/G5aAst

 

Many people (and different libraries) have their own custom point class. It's a very useful thing to have.

I suggest you make yourself a Point, a Size, and a Rect (which contains a Point and a Size).

 

"I suggest you keep your camera position as the center point of the camera." Hmm, not sure I follow. Isn't the camera view camera.x + camera.width and camera.y + camera.height? Also I'm not sure I entirely understand the difference between world position and screen position. 

 

Say object A and B is at (50, 50) 

 

If I draw them like this:

 

A.draw(50, 50);
B.draw(50 - camera.x, 50 - camera.y);

 

A will be at (50, 50) within the screen all the time. B will be drawn at (50, 50) world position. Is the coordinates within the screen always the same?



#15 Servant of the Lord   Crossbones+   -  Reputation: 17060

Like
3Likes
Like

Posted 16 March 2013 - 11:36 AM

"I suggest you keep your camera position as the center point of the camera." Hmm, not sure I follow.
Isn't the camera view camera.x + camera.width and camera.y + camera.height?
 
Also I'm not sure I entirely understand the difference between world position and screen position. 

Say object A and B is at (50, 50)
 
If I draw them like this:
 

A.draw(50, 50);
B.draw(50 - camera.x, 50 - camera.y);
 
A will be at (50, 50) within the screen all the time. B will be drawn at (50, 50) world position. Is the coordinates within the screen always the same?

APIs usually have their drawing code takes positions relative to the screen (well, relative to the screen's 'view', which is then stretched to fit the screen). So A.draw(50,50) always means (50,50) within the screen (i.e. in 'screen space'). A.draw(-50,-50) will always draw (-50, -50) outside of the screen (still in 'screen space' coordinates).
 
Positions in space are always relative to some known point. Putting a position in 'screen space' is making it relative to the screen/camera/view.
 
'world space' or 'world positions' or 'absolute positions' (Whatever you want to call it, the terms aren't standardized) mean that the positions are relative to the center of your 'world', whatever you define the 'world' as. (It could be the current level you have loaded, or the entire game world, or only the current fraction of the area that's actually loaded around the player).
 
Your camera position is always in 'world space' coordinates.
So if your camera is at (100, 100), then it really means 'world space origin' + (100,100), but 'world space origin' is (0,0) and so not mentioned.
 
When drawing, you want to convert to screen space. Screen space's origin is cameraPos.
 
Since you should keep your entities in world space (since the entities are within the world, unlike your GUI):
 

EntityAPos = (500, 500) //This is actually (0,0) + (500,500), since the entity's position is in world space.
CameraPos = (400, 400) //This is actually (0,0) + (400, 400), since the camera's position is in world space.

positionOfEntityAInScreenSpace = EntityAPos - CameraPos 

 
This is now (100, 100)... it's but converted to screen space, because 'cameraPos' is the origin of screenspace.
Since your drawing functions take screenspace coordinates, this is what you pass to those functions.
 
Some APIs, like SFML, handle these conversions for you. Others don't.
 
Have you ever generated a random number using (rand() % 50) + 25 ?
It generates a number from 25 to 74.
First you generate a number from 0 to 49. This is in the 'domain' (or as I've been calling it above, the 'space') of 0 - 49.
Then, you shift it over to a new 'domain', making '25' be the origin instead of 0. So the new domain is from '25 to 74'.
The range (50) stayed the same, the origin just shifted. We shifted it from one "space" or "domain" to a new "space" or "domain".
 
When we convert the entity's position from world-space to screen-space, everything stays the same, but the origin shifts to be relative to the camera, instead of relative to the world.
 
If you aren't understanding, this isn't because it's a difficult subject, it's simply because I'm doing a butchered job of explaining it! laugh.png

 

Maybe graphs will help me illustrate:
worldspacegraph1.png

worldspacegraph2.png


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#16 taten3n   Members   -  Reputation: 135

Like
0Likes
Like

Posted 16 March 2013 - 04:24 PM

Servant of the Lord it's not a bad way to explain it, but it's not that clear either. I'm not saying this because I could explain it better, but because i was trying to learn from your example but..I feel that I got a little closer to understanding it , but ... biggrin.png

About the screen/ camera space it says infinite in every direction, is this mistake or am I not undestanting something here. As screen space is definetly finite?


Edited by taten3n, 16 March 2013 - 04:37 PM.


#17 Servant of the Lord   Crossbones+   -  Reputation: 17060

Like
1Likes
Like

Posted 16 March 2013 - 08:26 PM

My forte` isn't explanations. Someone else could (and hopefully will) explain it in less words and clearer.

 

Just because the screen isn't infinite (let's say it's 800 x 600), the screen space is a Cartesian grid with x, y, axes that can go negative or positive.

 

Even if your screen is from (0,0) to (800, 600), the position (-100, -700) is outside of the screen's rectangle, but still in 'screen space' coordinates, because it's still relative to the same origin as the screen.

 

Everything in space is relative to some other position. There's no such thing as a 'position' except as a measurement relative to another point (the origin of your measurement).

 

A 'position' of an object is the distance between the object and the origin of the 'space' it is being measured in.

 

Where is the Earth located? You can give me the distance of the Earth from the Sun. That would make the Sun the origin, and you measuring the Earth's position in what we'll arbitrarily decide to call 'Sun-space'. Or you can give me the location of the Earth relative to the center of our Galaxy, making the center of the galaxy the origin.

Or you can give me the distance relative to the center of the universe, making the center of the universe the origin.

 

None of these are incorrect answers - they all refer to the same location (the location of the earth) but are in different coordinate spaces.

To convert between these spaces:

earthPosInGalaxySpace = earthPosInSolarSystemSpace + originOfSolarSystemInGalaxySpace

earthPosInUniverseSpace = earthPosInGalaxySpace + originOfGalaxyInUniverseSpace

 

Any 'space' is something that we make up. They only exist, because we can't measure anything (not position, not size) without measuring it relative to something else.

 

With 2D sprites, we measure 'size' at the pixel scale. We measure 'position' in a variety of ways, and we frequently convert between them as the need requires:

origin of the entire game world

origin of the area within the game world ("Green Forest")

origin of the subportion of the area that happens to be loaded around us

origin of the camera

 

These are just several possible coordinate spaces. At the very least, in almost every 2D game, you have 'world space' (what you keep your entity locations in) and 'camera space' (what is visible onscreen). Different people have different names for these - the names don't matter, the concept does.

 

If you say something is at position (0,0), you probably mean either relative to the game world, or relative to the camera - but it's important to understand which you want. Likely, all your API draw functions take screen-space coordinates. Likely, you'll want to keep all the objects in world-space coordinates. So knowing how to convert between spaces is important.

 

Thankfully, the formula is very simple:

originInNewSpace = (positionInCurrentSpace + originOfCurrentSpace)

 

In Johnell's case:

posInWorldSpace = (positionInCameraSpace + originOfCameraSpace)

posInCameraSpace = (positionInWorldSpace - originOfCameraSpace)


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS