Detecting collisions on a scrolling game - cocos2d-iphone

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
}

Related

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.

Centring Sprite or moving camera? C++/Opengl

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.

Tracking circular mouse movement in OpenGL

I am working on a simple mesh viewer implementation in C++ with basic functionality such as translation, rotation, scaling.
I'm stuck with with implementing the rotation of the object along z-axis using the mouse. What I want to implement is the following:
Click and drag the mouse vertically (almost vertical will do, as I use a simple threshold to filter slight deviations along the horizontal axis) to rotate the object along y-axis (this part is done).
Click and drag the mouse horizontally just as described above to rotate the object along x-axis (this part is done too).
For z-axis rotation, I want to detect a circular (or along an arc) mouse movement. I'm stuck with this part, and don't know how to implement this.
For the above two, i just use atan2() to determine the angle of movement. But how do I detect circular movements?
The only way to deal with this is to have a delay between the user starting to make the motion and the object rotating:
When user clicks and begins to move the mouse you need to determine if its going to become a straight line movement, or a circular one. This will require a certain amount of data to be collected before that judgement can be made.
The most extreme case would be requiring the user to make one complete circle first, then the rotation begins (in reality you could do much better than this). Just how small you are able to cut this period down to will depend on a) how precise you dictate your users actions must be, and b) how good you are with pattern recognition algorithms.
To get you started heres an outline of an extremely poor algorithm:
On user click store the x and y coordinates.
Every 1/10 of a second store the new coordinates and process_for_pattern.
in process_for_pattern you're looking for:
A period where the x coordinates and the y coordinates regularly both increase, both decrease, or one increases and one decreases. Over time if this pattern changes such that either the x or the y begins to reverse whilst the other continues as it was, then at that moment you can be fairly sure you've got a circle.
This algorithm would require the user to draw a quarter circle before it was detected, and it does not account for size, direction, or largely irregular movements.
If you really want to continue with this method you can get a much better algorithm, but you might want to reconsider your control method.
Perhaps, you should define a screen region (e.g. at window boundaries), which, when was clicked, will initiate arc movement - or use some other modifier, a button or whatever.
Then at a mouse click you capture the coordinates and center of rotation (mesh axis) in 2D screen space. This gets you a vector (mesh center, button down pos)
On every mouse move you calculate a new vector (mesh center, mouse pos) and the angle between the two vectors is the angle of rotation.
I don't think it works like that...
You could convert mouse wheel rotation to z-axis, or use quaternion camera orientation, which is able to rotate along every axis almost intuitively...
The opposite is true for quarternion camera: if one tries to rotate the mesh along a straight line, the mesh appears to rotate slightly around some other weird axis -- and to compensate that, one intuitively tries to follow some slightly curved trajectory.
It's not exactly what you want, but should come close enough.
Choose a circular region within which your movements numbered 1 and 2 work as described (in the picture this would be some region that is smaller than the red circle. However, when the user clicks outside the circular region, you save the initial click position (shown in green). This defines a point which has a certain angle relative to the x-axis of your screen (you can find this easily with some trig), and it also defines the radius of the circle on which the user is working (in red). The release of the mouse adds a second point (blue). You then find the angle this point has relative to the center of the screen and the x-axis (just like before). You then project that angle onto your circle with the radius determined by the first click. The dark red arc defines the amount of rotation of the model.
This should be enough to get you started.
That will not be a good input method, I think. Because you will always need some travel distance to discriminate between a line and a curve, which means some input delay. Here is an alternative:
Only vertical mouse having their line crossing the center of the screen are considered vertical. Same for horizontal. In other cases it's considered a rotation, and to calculate its amplitude, calculate the angle between the last mouse location and the current location relatively to the center of the screen.
Alternatively you could use the center of the selected mesh if your application works like that.
You can't detect the "circular, along an arc" mouse movement with anywhere near the precision needed for 3d model viewing. What you want is something like this: http://thetechartist.com/?p=80
You nominate an axis (x, y, or z) using either keyboard shortcuts or on-screen axis indicators that you can grab with the mouse.
This will be much more precise than trying to detect an "arc" gesture. Any "arc" recognition would necessarily involve a delay while you accumulate enough mouse samples to decide whether an arc gesture has begun or not. Gesture recognition like this is non-trivial (I've done some gesture work with the Wii-mote). Similarly, even your simple "vertical" and "horizontal" mouse movement detection will require a delay for the same reason. Any "simple threshold to filter slight deviations" will make it feel dampened and weird.
For 3d viewing you want 1:1 mouse responsiveness, and that means just explicitly nominating an axis with a shortcut key or UI etc. For x-axis rotation, just restrict it to mouse x, y-axis to mouse y if you like. For z you could similarly restrict to x or y mouse input, or just take the total 2d mouse distance travelled. It depends what feels nicest to you.
As an alternative, you could try coding up support for a 3D mouse like the 3dConnexion SpaceExplorer.

Finding object under mouse

I'm developing a game that basically has its entire terrain made out of AABB boxes. I know the verticies, minimum, and maximum of each box. I also set up my camera like this:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(Camera.rotx,1,0,0);
glRotatef(Camera.roty,0,1,0);
glRotatef(Camera.rotz,0,0,1);
glTranslatef(-Camera.x,-Camera.y,-Camera.z);
What I'm trying to do is basically find the cube the mouse is on. I thought about giving the mouse position a forward directional vector and simply iterating through until the 'mouse bullet' hits something. However this envolves interating through all objects several times. Is there a way I could do it by only iterating through all the objects once?
Thanks
This is usually referred to as 'picking' This here looks like a good gl based link
If that is tldr, then a basic algorithm you could use
sort objects by z (or keep them sorted by z, or depth buffer tricks etc)
iterate and do a bounds test, stopping when you hit the first one.
This is called Ray Tracing (oops, my mistake, it's actually Ray Casting). Every Physics engine has this functionality. You can look at one of the simplest - ODE, or it's derivative - Bullet. They are open-source so you can take out what you don't need. They both have a handy math library that handles all oftenly needed matrix and vertex operations.
They all have demos on how to do exactly this task.
I suggest you consider looking at this issue from a bigger perspective.
The boxes are just points at a lower resolution. The trick is to reduce the resolution of the mouse to figure out which box it is on.
You may have to perform a 2d to 3d conversion (or vice versa). In most games, the mouse lives in a 2d coordinate world. The stuff "under" the mouse is a 2d projection of a 3d universe.
You want to use a 3D picking algorithm. The idea is that you draw a ray from the user's position in the virtual world in the direction of the click. This blog post explains very clearly how to implement such an algorithm. Essentially your screen coordinates need to be transformed from the screen space to the virtual world space. There's a website that has a very good description about the various transformations involved and I can't post the link due to my rank. Search for book of hook's mouse picking algorithm [I do not own the site and I haven't authored the document].
Once you get a ray in the desired direction, you need to perform tests for intersection with the geometries in the real world. Since you have AABB boxes entirely, you can use simple vector equations to check which geometry intersects the ray. I would say that approximating your boxes as a sphere would make life very easy since there is a very simple sphere-ray intersection test. So, your ray would be described by what you obtain from the first step (the ray drawn in the first step) and then you would need to use an intersection test. If you're ok with using spheres, the center of the sphere would be the point you draw your box and the diameter would be the width of your box.
Good Luck!

Dizzy-like game level representation (format)

How would you store game level for a Dizzy-like adventure game? How would you specify walkable areas and graphics? Is it tile-based, pixel-based or walkable surfaces can be described by vectors?
Very old adventure games (like Sierra's quests from the 80s) used to actually maintain a separate bitmap of the entire screen that represented z-depth and materials to determine where your character could go and where it would be hidden. They would use pixel sampling to check where their small sprites would go.
Though current machines are faster, long side scrolling levels make this sort of approach impractical, IMHO. You have to go with more sparse representations.
One option is to "reduce" your game into invisible tiles, which are easier to represent. The main problem with this is that it can constrain your design (e.g., difficult to do diagonal platforms), and it can make the animations very shoddy (e.g., your characters' feet not actually touching the platform). This option can work IMHO for zelda-like adventure games, but not for action games.
A second option is to represent the game world via some vector representation and implement some collision detection. I would personally go with the second solution, especially if you can be smart about how you organize your data structures to minimize access time (e.g., have faster access to a subset of world elements close to your characters current position).
I wouldn't be surprised if there are available 2D game engines that provide this sort of capability, as there are definitely 3D engines that do it. In fact, you may find it easier to use an existing 3D game engine and use it to render 2D.
The Dizzy game is probably using a tile-based system. The game world is made up of a palette of tiles that are repeated throughout the level. Each tile would have three elements - the image drawn to the screen, the z-buffer to allow the main character to walk behind parts of the image and a collision map. The latter two would be implemented as monochrome images such that:
colour | z map | collision
-------|--------------------|---------------
black | draw dizzy infront | collide
white | draw dizzy behind | don't collide
Storing these are monochrome images save a lot of ram too.
You would have an editor to build level that would display a grid where tiles can be dragged and dropped.
That specific game is a tile-based game, with pixel perfect collision. The collision was controlled by a single bit in the colour byte of the tile (the brightness) and you could also mirror the tile by setting the flashing bit of the colour.
The tiles, however, could only be placed at even x,y coordinates (I suspect this was done to help the collision system a bit.)
The collision system involved a persistent check around the hero. The rules were roughly:
- If it finds a non-collision pixel row below the hero, it dropped the hero by 1 pixel.
- If there is a collision intersection with the hero, it raised the hero by 1 pixel.
- When moving left or right, it checks in that direction and if:
- if finds a wall (collision height more than 4 pixels), deny movement in that direction;
- if it finds a climbable box (collision height up to 4 pixels), allow movement in that direction.
- If there is enough headroom allow jumping, else, stop at the last possible free position.
When combining these simple rules, you obtained a very smooth collision negotiation able to walk even arbitrary slopes without extra taxing.
In creating such a game, I would use individual tiles, I would assemble them on layers (background, foreground etc...) and render them. I would assemble a separate collision map from the tiles attributes that indicate a collision tile, and I would use that separate map to negotiate the hero's collision and movement.
Similar to this demo: http://games.catevaclickuri.ro/