I am new to cocos2d-x.I am developing a game in xcode using cocos2d-x.
In my game, i have sprite animation(man) and moving obstacles and coins. I making collision with sprite animation & coins. When i get 10 coins, i am adding a life(adding a sprite for life).
My question is when collision is happening between sprite animation(man) & obstacles, life should decrease(i mean life sprite should remove) but it is not removed.
I am using the following code.
if(coincount%10==0)
{
lifecount=lifecount+1;
}
if(lifecount==1)
{
life = CCSprite::create("life.png");
life->setPosition( ccp(winwsize/2, winhsize/1.08) );
this->addChild(life, 5);
}
else if(lifecount==2)
{
life1 = CCSprite::create("life.png");
life1->setPosition( ccp(winwsize/1.8, winhsize/1.08) );
this->addChild(life1, 5);
}
else if (lifecount==3)
{
life2 = CCSprite::create("life.png");
life2->setPosition( ccp(winwsize/1.6, winhsize/1.08) );
this->addChild(life2, 5);
}
if (manRect.intersectsRect(obs5Rect))
{
if(lifecount>=1)
{
lifecount=lifecount-1;
this->scheduleOnce(schedule_selector(PlayScene::remove),0.5f);
}
void PlayScene::remove()
{
if(lifecount==0)
{
this->removeChild(life, true);
}
else if(lifecount==1)
{
this->removeChild(life1, true);
}
else if(lifecount==2)
{
this->removeChild(life2, true);
}
But sprite is not removing, when obstacle collide with sprite animation(man).
Please anyone could help me to find the solution. Thanks.
First setTag on Sprite like:
Sprite->setTag(111);
removeChildByTag(111);
OR
Sprite->removeFromParent();
I think your best bet is to do:
life1->setTag(99); // i made up the 99
and then when you want to remove it use removeChildByTag(99);
It seems that the problem is in your remove function. You create sprites life, life1, life2 when lifeCount is 1, 2 or 3 respectively. But in your remove method, you check if lifeCount is 0, 1 or 2. If it were 3, none of the sprites would be removed, as none of the conditions are met. Also you do not deacrease lifeCount anywhere.
Solution :
Either add --lifecount; at the beginning of remove(), or change your conditions appropriately and decrease the counter at the end.
Suggestions :
If I may suggest an improvemt to your code : you should keep your life sprites in an array, so that when you decide to add the possibility to have more lives it will be much easier.
Let me know if anything is not clear.
Related
I'm trying to make some animation with SDL2.
SDL2 has some bad performance, and my simple chess game was running at 10fps.
I don't want to redraw the whole screen every frames, it takes way to long. So in order to optimize my game I decided to code an Animation class ( a simple fade in/out effect) which only redraw some part of the screen everyframe (basicly redraw the selected piece)
void myGame::sdlLoop() {
SDL_Event events;
bool quit = false;
while (!quit) {
bool redraw = false; //We assume we don't want to redraw everything (yet)
while (SDL_PollEvent(&events)) {
switch (events.key.keysym.scancode) {
....
}
if(redraw) draw(); // Only redraw whole screen IF NEEDED
else drawAnimations(); // Better use that for better performance
}
}
}
void myGame::drawAnimations(){
int i = 0;
while(i < arr.size()){
....
drawThingsAtCertainsPixels(now_time, animation_start_time, animation_duration); //Basicly a simple fade effect, something like
//pixelColor = color1 * advancement + color2 * (1 - advancement)
}
// Show the window
SDL_RenderPresent( m_renderer );
}
So far so good, but I noticed a weird behavior.
The animation is "jerky", most of the frames are skipped
I ended up avec all of my fadeout unfinished because the last frame where skipped.
But, when I constantly move the mouse, everything goes right and no frame are dropped
I think it is linked to SDL wanting to optimize performance, and only run at 100% speed when someting important is going on (user inputting things or windows interacted).
Do you know why is this happening, and how to fix that ?
I mean how to have SDL2 computing every frame even if I don't move the mouse.
I feel a bit guilty for finding the solution right after posting this question (but I swear I tore my hair out a lot)
The solution is quite simple
while (!quit) {
bool redraw = false; //We assume we don't want to redraw everything (yet)
while (SDL_PollEvent(&events)) {
switch (events.key.keysym.scancode) {
....
}
if(redraw) draw(); // Only redraw whole screen IF NEEDED
else drawAnimation(); // Better use that for better performance
}
}
Just move the drawAnimations() function a bit lower, out of the while (SDL_PollEvent(&events)) {
while (!quit) {
bool redraw = false; //We assume we don't want to redraw everything (yet)
while (SDL_PollEvent(&events)) {
switch (events.key.keysym.scancode) {
....
}
}
if(redraw) draw(); // Only redraw whole screen IF NEEDED
else drawAnimation(); // Better use that for better performance
}
So, I had a test going on to see how collision operates in SFML. I have made this snippet of code:
if (floor.getGlobalBounds().intersects(SuperMario.getGlobalBounds())) // Floor
{
SuperMario.setPosition(SuperMario.getPosition().x, floor.getPosition().y - SuperMario.getOrigin().y);
IsTouching = true;
}
As the code suggests, Mario will change his position when he touches the floor object and will teleport above the floor.
However, this has the following side-effect, illustrated by the pictures below.
Note that the "green box" is the floor object I mentioned earlier. Also, ignore the word "left" in picture 1, I mean "right".
Of course, this behaviour is intended (i.e. is not a bug), but it is unwanted.
So my question is: How can I eliminate this "side-effect"? I mean, how can I modify my code, so Mario will not teleport above the floor, when he touches its sides(making platforming work like a proper platforming)? I want Mario to be stopped by the box, not to be teleported.
UPDATE: So now, I have this:
for (unsigned int i = 0; i <= solidObjects.size() - 1; i++)
{
if (solidObjects[i].getGlobalBounds().intersects(SuperMario.getGlobalBounds()))
{
if (SuperMario.getPosition().x - solidObjects[i].getPosition().x < SuperMario.getPosition().y - solidObjects[i].getPosition().y)
{
SuperMario.setPosition(solidObjects[i].getPosition().x - SuperMario.getOrigin().x, SuperMario.getPosition().y);
IsTouching = false;
}
else if (SuperMario.getPosition().y - solidObjects[i].getPosition().y < SuperMario.getPosition().x - solidObjects[i].getPosition().x)
{
SuperMario.setPosition(SuperMario.getPosition().x, solidObjects[i].getPosition().y - SuperMario.getOrigin().y);
IsTouching = true;
}
else if (SuperMario.getPosition().x - solidObjects[i].getTextureRect().width < SuperMario.getPosition().y - solidObjects[i].getPosition().y)
{
SuperMario.setPosition(solidObjects[i].getTextureRect().width + SuperMario.getOrigin().x, SuperMario.getPosition().y);
IsTouching = false;
}
}
else
{
IsTouching = false;
}
}
However, there is one problem. When Mario touches the sides of the floor, he sticks on them meaning he is unable to move right.
If I am not clear enough, please specify what i should add or clarify more.
This feels really weird, because you'd typically define solid areas rather than those the player can walk inside. You'll want your player to jump after all, rather than having them glued to the ground.
The rest is pretty straightforward:
Iterate over all solid objects and determine whether the player and the solid rectangle overlap.
If they do, determine which distance is smaller (x or y). This lets you determine which axis to move the player.
Determine which direction the player leaves the solid area quicker, i.e. which direction to push the player.
Push the player in the calculated direction and repeat the checks.
Depending on your map complexity this can become rather complex, so you'll most likely want some sorting/spatialisation to reduce the number of comparisons (e.g. skip checking impossible/far away shapes).
I been stuck on this issue for a few days now. I am hoping you guys can help me. I am creating a simple game following this tutorial: http://discuss.cocos2d-x.org/t/tutorial-series-use-the-cocos2d-x-3-0-game-engine-write-a-tile-map-game-part02/12991
and I got stuck on the collision detection part. The method getTileGIDAt() is ALWAYS returning 0, most likely I have found out that this is a Tiled related problem (maybe the tiles are not there, etc), but the problem is that the tiles are completely fine. Everything runs and loads smoothly, with this exception.
Thanks!
here is the code:
void HelloWorld::setPlayerPosition(Point position)
{
Point tileCoord = this->tileCoordForPosition(position);
int tileGid = _blockage->getTileGIDAt(tileCoord);
if (tileGid) {
auto properties = _tileMap->getPropertiesForGID(tileGid).asValueMap();
if (!properties.empty()) {
auto collision = properties["Blockage"].asString();
if ("True" == collision) {
return;
}
}
}
_player->setPosition(position);
}
I would try this tutorial and see how your code matches. I guess the main thing is to check that you have Tiled setup correctly for the different layers.
http://www.raywenderlich.com/29458/how-to-make-a-tile-based-game-with-cocos2d-2-x
Over the last few days I have been trying to implement simple collision detection of objects drawn using OpenGL.
With the aid of the Pearson, Computer Graphics with OpenGL I have managed to write the following function:
void move(){
if(check_collision(sprite,platform1) || check_collision(sprite,platform2)){ //if colliding...
if (downKeyPressed ){ y_Vel += speed; downKeyPressed = false;} //going down
else if(upKeyPressed ){ y_Vel -= speed; upKeyPressed = false;} //going up
else if(rightKeyPressed){ x_Vel -= speed; rightKeyPressed = false;} //going right
else if(leftKeyPressed ){ x_Vel += speed; leftKeyPressed = false;} //going left
} // always glitches on whatever is last else if above?!?!
else{ glTranslatef(sprite.x+x_Vel, sprite.y+y_Vel, 0.0); }
}
My sprite moves in accordance to keyboard inputs (the arrow keys). If it collides with a stationary object it stops moving and stays in its position.
So far, it works when colliding with the top, left side and bottom of the stationary object. Unfortunately (even though I use the same logic) the right hand side doesn't work and upon a collision the sprite is redrawn at its original x/y coordinates. I'm baffled.
As it turns out, which-ever is the last check in the move() function (the last else-if) is the one that doesn't work... I have swapped the left with the right and sure enough when left is then the last one and the one that plays up :(
Any advice or ideas on how I can improve this and stop it glitching?
Please excuse my naivety and amateur coding. I'm merely a self-taught beginning. Thanks.
You should not use an else if. There is a possibility that it is hitting a side and the top or the bottom in the same frame. Trying changing those to all ifs because you want to check each one. or at the least change it to this.
if( /* check top */)
{
}
else if( /* check bot */)
{
}
if( /* check right */ )
{
}
else if( /* check left */)
{
}
Also, you should avoid declaring global variables like Y_VEL and X_VEL as this creates confusion. You may just be doing this to get your feet wet but I would avoid it. Create a class for each object and then have the velocities as members of that class.
Well, it seems to me that you have an issue when it comes to translating the actual object.
Your move code states
if(there is a collision)
{
//do stuff
}
else
{
glTranslateF( );
}
SO, whenever there is a collision, the translate function never gets called.
My opinion is that you should pull the glTranslateF() call out of the else {...}, just have it get called every time. However, it seems you're using the exact same 'draw' function for every rectangle, not just the player sprite. You'll probably have to ind a way to distinguish between regular rectangles (such as the platforms) and the player rectangle. Perhaps the simplest way for you to implement this, would be to have two different drawSprite functions: one for regular platforms, and the other for the player. Only call the move() function from within the player's draw function (perhaps called drawPlayer()?)
I don't quite have the time to look over all of your code to make a more educated and specific suggestion at the moment; however, I'll be free later this evening if this question is still open and needing help.
As you've already figured out, the problem is related to glTranslate(). Since you operate on both sprite's position and velocity, you should repeatedly update the positions using the velocities. That is:
sprite.x += x_vel;
sprite.y += y_vel;
and do it simply all the time (i.e. by some timer or every frame, if the scne is redrawn repeatedly). A collision then is equivalent to changing the velocity vector (x_vel, y_vel) in some way to simulate the collision effect: either zero it to stop any movement at all, or change the velocity component sign (x_vel = -x_vel) to make it rebound in an absolutely elastic manner, or do something else that fits.
What happens now with glTranslate() is that x_vel, y_vel actually hold offsets from the starting position, but not velocities of movement.
i've been sitting here for hours now trying to figure out how collision could work for a platformer.. after doing a lot of research i found something useful in the internet.. but it doesn't work yet :/
my character seems to jump one time.. and then gets stuck a short distance above the ground
This is the function where i load my platforms from txt (by calling setupworld)
in my txt i define xstart (where the platform starts) xend (end of platform) ystart (bottom of platform) 2 unnused variables and the texture filter (0-4 atm)
each platform is then created by repeating 2x2 tiles in x direction
numblocks= number of platforms (sry for the bad variable name ^^)
number of blocks is calculated by taking the end coordinate of the platform - start coordinate and dividing by 2.0 (my platforms always have coordinates dividable by 2.. like.. 0 - 16.. or.. 8 - 16.. )
as u see.. the structure block is where all the data is saved to in setupworld() and it has nothing to do with the number of tiles displayed.. sry again for my weird names
GLvoid BuildLists()
{
texture[0]=LoadPNG("data/grass.png");
texture[1]=LoadPNG("data/gnd.png");
texture[2]=LoadPNG("data/pilz_test.png");
texture[3]=LoadPNG("data/rockwall.png");
texture[4]=LoadPNG("data/crate.png");
setupworld();
quad[0]=glGenLists(numblocks);
for(int loop=0;loop<numblocks;loop++)
{
GLfloat xstart,xend,ystart,u,v,u2,v2;
xstart=block.data[loop].xstart;
xend=block.data[loop].xend;
ystart=block.data[loop].ystart;
//u=block.data[loop].u;
//v=block.data[loop].v;
GLuint filter=block.data[loop].filter;
GLfloat blocks=(xend-xstart)/2.0f;
u=0.0f;
v=0.0f;
u2=1.0f*blocks;
v2=1.0f;
glNewList(quad[loop],GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, texture[filter]);
// Start Drawing Quads
for(int y=0;y<blocks;y++)
{
glBegin(GL_QUADS);
glTexCoord2f(u,v);
glVertex3f(xstart,ystart,-1.0f);
glTexCoord2f(u2,v);
glVertex3f(xstart+((y+1)*2.0f),ystart,-1.0f);
glTexCoord2f(u2,v2);
glVertex3f(xstart+((y+1)*2.0f),ystart+2.0f,-1.0f);
glTexCoord2f(u,v2);
glVertex3f(xstart,ystart+2.0f,-1.0f);
glEnd();
}
glEndList();
quad[loop+1]=quad[loop]+1;
}
}
This is where the key actions are processed..
DetectCollision() calls my function where i (try to) check for collisions
ymovement
ypos2=ypos; is just to remind the last position for repositioning
i jump until i reach 5.0f or a collision in y-direction is detected.. then locky turns TRUE; the else is to let my character get back to ground (cause no gravity) even when the player keeps w pressed
the same thing happens when w is not pressed.. and locky is being reset
xmovement
i add to (or subtract from) xpos for movement
as long as the character doesn't reach the border or a collision appears it should do the normal movement
if (active) // Program Active?
{
if (keys[VK_ESCAPE])
{
done=TRUE;
glDeleteTextures(1,&texture[0]);
glDeleteTextures(1,&texture[2]);
glDeleteTextures(1,&texture[1]);
}
if (keys['W'])
{
if(!locky)
{
DetectCollision();
ypos2=ypos;
ypos=ypos+0.2f;
if(ypos>=5.0f)
{
locky=!locky;
}
if(collisiony)
{
ypos=ypos2;
locky=!locky;
}
}
else
{
if(ypos>0.0f && !collisiony)
{
ypos=ypos-0.2f;
}
}
}
if (!keys['W'])
{
locky=!locky;
if(ypos>0.0f && !collisiony)
{
ypos=ypos-0.2f;
}
}
if (keys['A'])
{
if(xpos>0.0f && !collisionx)
{
xpos=xpos-0.2f;
}
}
if (keys['D'])
{
if(xpos< 50.0f && !collisionx)
{
xpos=xpos+0.2f;
xcam=xcam-0.1f;
}
}
glLoadIdentity();
glTranslatef(0,-7.0f,-25.0f);
DrawWorld(); //draws my platforms by calling the display lists compiled in build lists
DrawChar(); //draws the character
SwapBuffers(hDC);
}
Finally the code where i check for collisions
inPlatformx for checking x
is my character between left and right side of the platform being checked
-> function returns TRUE and is written into collisionx
inPlatformy for checking y
same for inPlatformy
bool inPlatformx(float xpos, BLOCK block, int i){
return xpos > block.data[i].xstart &&
xpos < block.data[i].xend;}
bool inPlatformy(float ypos, BLOCK block, int i){
return ypos > block.data[i].ystart &&
ypos < (block.data[i].ystart+0.2);
}
GLvoid DetectCollision(){
for(int i=0; i<numblocks;i++)
{
collisionx=inPlatformx(xpos,block,i);
collisiony=inPlatformy(ypos,block,i);
}
}
finally a screenshot
http://www.grenzlandzocker.de/test.png
I hope u can help me.. either fix my code or give me some tips on collisions.. since it's my first game with opengl :s
if u need any more detail or infos please ask ^^
and thanks in advance !
if (keys['W'])
{
//DetectCollision();
if(!locky)
{
ypos2=ypos;
ypos=ypos+0.2f;
if(ypos>=5.0f)
{
locky=!locky;
}
if(collisiony)
{
ypos=ypos2;
locky=!locky;
}
}
else
{
if(ypos>0.0f)
{
ypos=ypos-0.2f;
}
}
}
if (!keys['W'])
{
locky=!locky;
if(ypos>0.0f && !collisiony)
{
ypos=ypos-0.2f;
}
}
if (keys['A'])
{
//DetectCollision();
if(xpos>0.0f && !collisionx)
{
xpos2=xpos;
xpos=xpos-0.2f;
}
if(collisionx)
{
xpos=xpos2;
}
}
if (keys['D'])
{
//DetectCollision();
if(xpos< 50.0f && !collisionx)
{
xpos2=xpos;
xpos=xpos+0.2f;
xcam=xcam-0.1f;
}
if(collisionx)
{
xpos=xpos2;
}
}
THANKS :)
well i just edited the code for x movement and collision.. so it works properly.. (despite the flickering (but idc atm :) ).. i'm wondering why jumping doesn't work at all anymore.. it's just increasing till i'm stuck.. can't even get up once anymore :/
i put my detectCollision() in front of they key section.. which works for x AND y now (hopefully)..
and i also edited something in DetectCollision()
i had ystart+0.2 instead of ystart+2.0 which is the correct coordinate for the platforms top
but looks like it just got worse at y
i'm still totally confused..
oh and talking about those predefined api's and stuff.. since somebody first showed me some things with glut i tried to make the next step and initialize everything myself.. i guess detection is much easier using predefined stuff.. but i want to learn it and not just get one game to work :)
if u have any more suggestions for my code i would be really grateful.. and if u know any good books for starters till advanced lvl i would really appreciate
and yes.. i know.. display lists are deprecated since opengl 3.0 ^^
Unless I am not following your code correcty, once you reach the apex of your jump and set your locky to !locky, you start hitting your else statement, which never checks for collision. IF you are moving in the x or -x direction, you likely want to be doing this as the ground may not be in the same place as your origin of the jump.
Additionally, your locky check is checking if the ypos >= 5.0f , which will immediately be the case if you are already on some part of your game world above the 5.0 mark. You likely want this to be a variable such as limitY = ypos + 5.0f; and then check if ypos >= limitY, so it works regardless of origin.
As for the issue you are seeing now, it should be easy to debug and look at the current value of your y coordinate and see if there is anything obvious (such as not executing a final ypos -= 0.2f ) which is cause for you floating slightly above the ground after a jump. (I don't see an obvious error in the way you are doing your code, although I would not have designed it in the way you are doing it yourself.)
If you are developing this for Windows you may want to look into XNA development, which makes collision detection and resolution a lot easier.
Are you initializing locky to true or false? because all the code i can see inverts the state of locky, so depending on how the input is processed, your locky value is flipping every loop or possibly being set out of sync with your expectations.
I would recommend setting locky to true and false explicitly in the code you've shown, rather than using locky=!locky, it's clearer about the state of the system.