Centring Sprite or moving camera? C++/Opengl - c++

I'm self learning C++ and playing around 2D tile mapping.
I have been reading through this scrolling post here, which is based on this tiling tutorial.
Using the above tutorial and some help from the Pearson, Computer Graphics with OpenGL book I have written a small program that draws a 40x40 tiled world and a Sprite (also a tile).
In terms of drawing/render order, the map(or world) itself is that back layer and the Sprite is the forward most (or top) layer. I'm assuming that's a good way of doing it as its easier for 2 tiles to interact than a tile and a custom sprite or rectangle. Is that correct?
I have implemented a Keyhandling() function that lets you move the map inside the viewport using the keyboards arrow keys. I have a variable called offsetx, offsety that when a key is pressed increases or decreases. Depending on whether I assign the variable to the map or sprite, I can more one or the other in any direction on the screen.
Neither seems to work very well, so I assigned the variables to both (map and sprite) but with positive values for the sprite, and negative for the map. So upon a key press, this allows my Sprite to move in one direction whilst the map moves in the opposite direction.
My problem is, the sprite soon moves enough to leave the window and not enough to bring the more of the map into the scene. (The window only shows about 1/8th of the tiles at any one time).
I've been thinking all day, and I think an efficient/effective way to solve this issue would be to fix the sprite to the centre of the screen and when a key is pressed the map moves around... I'm unsure how to implement this though.
Would that be a good way? Or is it expected to move the viewport or camera too?

You don't want to move everything relative to the Sprite whenever your character moves. Consider a more complicated world where you also have other things on the map, eg other sprites. It's simplest to keep the map fixed, and move each sprite relative to the map, (if it's a movable sprite). It just doesn't make much sense to move everything in the world whenever your character moves around in the world.
If you want to render your world with your character always at the center, that's perfectly fine. The best thing to do is move the camera. This also allows you to zoom your camera in/out, rotate the camera, etc. with very little hassle in keeping track of all the objects in the world.
Be careful with your usage of the word "viewport". It means a very specific thing in OpenGL. (ie, look at the function glViewport). If your book uses it differently, that's fine. I'm just pointing this out because it's not 100% clear to me what you mean by it.

Related

Best way to detect the window coordinates of a drawn line in c++ Builder

Using moveto and lineto to draw various lines on a window canvas...
What is the simplest way to determine at run-time if an object, like a bit map or a picture control is in "contact" (same x,y coordinates) with a line(s) that had been drawn with lineto on a window canvas?
A simple example would be a ball (bitmap or picture) "contacting" a drawn border and rebounding... What is the easiest way to know if "contact" occurs between the object, picture or bitmap and any line that exists on the window?
If I get it right you want collision detection/avoidance between circular object and line(s) while moving. There are more option to do this I know of...
Vector approach
you need to remember all the rendered stuff in vector form too so you need list of all rendered lines, objects etc ... Then for particular object loop through all the other ones and check for collision algebraically with vector math. Like detecting intersection between bounding boxes and then with particular line/polyline/polygon or what ever.
Raster approach
This is simpler to mplement and sometimes even faster but less acurate (only pixel precision). The idea is to clear object last position with background color. Then check all the pixels that would be rendered at new position and if no other than background color present then no colision occurs so you can render the pixels. If any non background color present then render the object on the original position again as collision occur.
You can also check between old and new position and place the object on first non collision position so you are closer to the edge...
This approach need fast pixel access otherwise it woul dbe too slow. Standard Canvas does not allow this without using BitBlt from GDI. Luckily VCL GRaphics::TBitmap has ScanLine[] property allowing direct pixel access without any performance hit if used right. See example of it in your other question I answered:
bitmap rotate using direct pixel access
accessing ScanLine[y][x] is as slow as Pixels[x][y] but you can store all the pointers to each line of bitmap once and then just use that instead which is the same as accessing your own 2D array. So you really need just bitmap->Height calls of ScanLine[y] for entire image rendering after any resize or assigment of bitmap...
If you got tile based scene you can use this approach on tiles instead of pixels something like this:
What is the best way to move an object on the screen? but it is in asm ...
Field approach
This one is also considered to be a vector approach but does not require collision checks. Instead each object creates repulsive force the bigger the closer you are to it which is added to the Newton/D'Alembert physics driving force. When coefficients set properly it will avoid collisions on its own. This is used also for automatic placement of items etc... for more info see:
How to implement a constraint solver for 2-D geometry?
Hybrid approach
You can combine any of the above approaches together to better suite your needs. For example see:
Path generation for non-intersecting disc movement on a plane

How do you make a shape static while the camera moves C++ OpenGL?

I want to make a maze game, with shapes in the form of a maze and a person walking through ( or a square or something) in 2d. I know how to make the camera move, but what I don't know is how to make the person/square move with the camera. I'm using C++ with OpenGL, and at the moment I'm using freeglut but I realize this isn't the best thing to be using. I'm still a beginner, so if I can do it in freeglut and not have to download anything that would be optimal. Thanks!
So, I figured out the answer to my own question. I have already built the quad that takes parameters quadx and quad y for the bottom left vertex. I have built a function that moves the camera based on the key that is pressed, and to have the quad appear to stay with the camera, just have it move the same amount as the camera does.
P.S. Make sure to have the thing you want to move with the camera in view at the starting location of the camera, else it will never be on the screen because it will move away just as much as you look for it.

Mouse handling on PixelToaster lib

I'm using PixelToaster (a C++ library to draw to a framebuffer) for a simple 3D (ehm.. 2.5D) raycasting engine. I use the old school WASD key configuration to move the camera around (W=forward, S=backward, A=turn left, D=turn right) however I want to use the mouse for the modern freelock approach (WASD for moving and strafing, the mouse to turn head around).
I noticed that PixelToaster gives a mouselistener in which only the ABSOLUTE mouse coordinate x,y are given (relative to the window width,height). Using such coordinate system is not what I want because the turning stops as soon as the mouse x coordinate reaches the margin of the screen. (in all the commercial games you can turn around endlessly by swiping continuously the mouse in one direction).
How can I get the same behaviour using the PixelToaster mouse listener?
What you need is fairly simple to implement.
Simply reset the mouse pointer to the centre of the screen when you hit the margins.
Note that for this to work you should not "map" your 2D screen space coordinates to the angular rotation of your character. Instead have an accumulator that keeps adding up incremental changes in angle (calculated from 2D screen space movements of the mouse pointer).
Alternate Approach: You could detect when you are at the edges of your screen and keep rotating the character until you leave that edge. This way you don't need to reset the mouse pointer. For some reason I assumed that you wouldn't have a cross-hair in your game so I suggested my former approach first. :)

Keeping Velocity Constant and Player in Position - Sidescrolling

I'm working on a Little Mobile Game with Cocos2D-X and Box2D.
The Point where I got stuck is the movement of a box2d-body (the main actor) and the according Sprite. Now I want to :
move this Body with a constant velocity along the x-axis, no matter if it's rolling (it's a circleshape) upwards or downwards
keep the body nearly sticking to the ground on which it's rolling
keep the Body and the according Sprite in the Center of the Screen.
What I tried :
in the update()- method I used body->SetLinearVelocity(b2Vec2(x,y)) to higher/lower values, if the Body was passing a constant value for his velocity
I used to set very high y-Values in body->SetLinearVelocity(b2Vec2(x,y))
First tried to use CCFollow with my playerSprite, which was also Scrolling along the y-axis, as i only need to scroll along the x-axis, so I decided to move the whole layer which is containing the ambience (platforms etc.) to the left of my Screen and my Player Body & Player sprite to the right of the Screen, adjusting the speed values to Keep the Player in the Center of the Screen.
Well...
...didn't work as i wanted it to, because each time i set the velocity manually (I also tried to use body->applyLinearImpulse(...) when the Body is moving upwards just as playing around with the value of velocityIterations in world->Step(...)) there's a small delay, which pushes the player Body more or less further of the Center of the Screen.
... didn't also work as I expected it to, because I needed to adjust the x-Values, when the Body was moving upwards to Keep it not getting slowed down, this made my Body even less sticky to the ground....
... CCFollow did a good Job, except that I didn't want to scroll along the y-axis also and it Forces the overgiven sprite to start in the Center of the Screen. Moving the whole Layer even brought no good results, I have tried a Long time to adjust values of the movement Speed of the layer and the Body to Keep it negating each other, that the player stays nearly in the Center of the Screen....
So my question is :
Does anyone of you have any Kind of new Approach for me to solve this cohesive bunch of Problems ?
Cheers,
Seb
To make it easy to control the body, the main figure to which the force is applied should be round. This should be done because of the processing mechanism of collisions. More details in this article: Why does the character get stuck?.
For processing collisions with the present contour of the body you can use the additional fixtures and sensors with an id or using category and mask bits. For of constant velocity is often better to use SetLinearVelocity, because even when using impulse velocity gets lost at sharp uphill or when jumping. If you want to use the implulse to change the position of the body, then you need to use the code for the type of this:
b2Vec2 vel = m_pB2Body->GetLinearVelocity();
float desiredVel = mMoveSpeed.x; //set there your speed x value
float velChange = desiredVel - vel.x;
float impulse = m_pB2Body->GetMass() * velChange;
m_pB2Body->ApplyLinearImpulse( b2Vec2(impulse, mMoveSpeed.y), m_pB2Body->GetWorldCenter());
This will allow maintain a constant speed most of the time. Do not forget that these functions must be called every time in your game loop. You can combine these forces, depending on the situation. For example, if the at the beginning you need to make a small acceleration, it is possible to use ApplyForce to the body, and when a desired speed is to use ApplyLinearImpulse or SetLinearVelocity. How correctly to use it is described here: Moving at constant speed
If you use world with the normal gravity(b2Vec2(0, -9.81)), then it should not be a problem.
I answer for this question here: Cocos2D-x - Issues when with using CCFollow. I use this code, it may be useful to you:
CCPoint position = ccpClamp(playerPosition, mLeftBounds, mRightBounds);
CCPoint diff = ccpSub(mWorldScrollBound, mGameNode->convertToWorldSpace(position));
CCPoint newGameNodePosition = ccpAdd(mGameNode->getPosition(), mGameNode->getParent()->convertToNodeSpace(diff));
mGameNode->setPosition(newGameNodePosition);
P.S. If you are new to box2d, it is advisable to read all the articles iforce2d(tuts), they are among the best in the network, as well as his Box2D Editor - RUBE. At one time they really helped me.
I do not know if this is possible but I have an idea:
Keep the circle at a fixed position and move the background relatively. For example, during the course of the game, if the circle has a velocity of 5 towards left then keep circle fixed and move screen with velocity 5 towards right. If circle has 5 velocity towards left and screen has 3 velocity towards right, then keep circle fixed and move screen with 8 velocity towards left and so on. This should allow you to fix the circle at the center of the screen.
Another method would be to translate the entire screen along with the ball. Make everything on the screen an object that can have a velocity. And the x-component of the velocity of the ball (circle) should be the velocity of all other objects. This way, whenever the circle moves, all the other objects will try and keep up with it.

Detecting collisions on a scrolling game

How does one have a scrolling map and detect collision on it?
I have tried a tile map but dont want to use this technique.
I would like to learn how a games background can be scrolled as well as object are detected for collision.
One example would be this game.
If one is not using tilemaps for this, how is the world scrollable as well as having physical objects detecting collision with the character sprite?
Please point me in the right direction on this topic.
Simple collision detection is done by checking to see if bounding boxes (or sometimes, bounding circles) overlap. That is, given object A and object B, if their bounding boxes overlap, then a collision has occurred.
If you want to get fancy, you create polygons for your objects and determine if the bounding polygons overlap. That's more complicated and harder to get right, and also involves considerably more processing.
It's not really much different from using a tilemap. With a tilemap, you're doing collision detection against the tiles. Without a tilemap you're doing collision detection against the bounding boxes of individual objects. The logic is almost identical.
Additional info:
I think the problem you're struggling with is that you're thinking in terms of screens. It's important when writing a game to separate the concept of the game world (the model) from the presentation (the screen).
For example, a simple side scroller game might consist of many "screens" full of information. Whereas the screen might be 1000 units wide, the game's world could be 10,000 or 100,000 units wide. Note that I say "units" rather than "pixels". A game's unit of measure could be inches, centimeters, miles, or whatever. All of your game logic should work in terms of world coordinates. How you project that onto the view (the screen) is irrelevant to what goes on in the world.
Every object in the world is assigned a position in world coordinates. That includes the player sprite, which is moving around in the world. All collision detection and other interaction of objects in the world is done in terms of world coordinates.
To simplify things, assume that there is a one-to-one mapping between world units and screen units. That is, your world is 10,000 pixels wide, and your screen is 1,000 pixels wide. The world, then is "ten screens" in size. More correctly, the screen can view 1/10 of the world. If that's the case, then your view can be defined by the left-most world coordinate that's visible. So if the world coordinate 2,000 is at the left of your screen, the rightmost column of pixels on your screen will be world coordinate 2,999.
This implies that you need world-to-screen and screen-to-world transformation functions. For this case, those functions are very simple. If we assume that there's no vertical scrolling, then only the x coordinate needs to be transformed by subtracting the world x coordinate from the view x coordinate. That is, world.x - viewOrigin.x. So in the case above, the screen coordinate of an object that's at world x coordinate 2,315 would be (2,315 - 2,000), or 315. That's the x coordinate of the object's position on the screen. In the current view.
The screen-to-world is the opposite: add the object's screen coordinate to the view's origin: 315 + 2,000 = 2,315.
I can't stress how important it is to maintain this separation between world and view coordinates. All of your game logic should operate in terms of world coordinates. You update the view to show you what's happening in the world. In a side scroller, you typically move the view left and right based on the player's actions. If the player moves left, you move the view origin left. If the player moves right, you move the view origin to the right.
Once you internalize this idea, things become much simpler. Everything done in the game world happens in the world. You make sure that the world state is consistent, and then you worry about displaying a view of the world.
There's no easier way (that I know of) to build a game that's larger than the screen. No matter how you build it, you have to have some concept of showing just part of the world on the view. By formalizing it, you separate the presentation from the game logic and things get much, much simpler.
You are going to want to set you camera dimensions to the dimensions of your level that you want to be rendered. You can get the level coordinates according to whatever you camera is supposed to be fixed on, say your hero.
Sprite collision is relatively easy. Use the two sprites' height/width you're testing against (IDK about cocos2d, but most api's sprites' position are at the upper left corner of the sprite):
if(player.Pos.x <= (object.Pos.x + object.width) || (player.Pos.x + player.width) >= object.Pos.x)
{
if(player.Pos.y >= (object.Pos.y - object.height) || (player.Pos.y - player.height) <= object.Pos.y)
//collision detected
}