Spirte jump after collision with other sprite - c++

After collision using listener one, sprite1 should be destroyed and other sprite2 will jump. I destroy sprite1 but sprite2 is not jumping after collision with sprite1. Here is my code:
Update(float dt) {
if(collisionOccurs == 1)
{
CCJumpTo * myJump = CCJumpTo::create(1, ccp(winSize.width/6,winSize.height/8),winSize.height/2 ,1);
Sprite2->runAction(myJump);
collisionOccurs = 0;
if(Sprite1 != NULL && BodyofSprite1 != NULL)
{
BodyofSprite1->SetActive(false);
Sprite1->removeFromParentAndCleanup(true);
}
}
}

Related

Delay in drawing cursor position with SharpGL

I'm trying to draw the cursor position, with a square, when mouse moving.
I'm using SharpGL and the OpenGLControl, but there is a delay between cursor arrow and the drawn square.
On MouseMove event I store a square centered in the mouse position (mapped in _pointCursor that is a list of vertex), then in the Draw event of the control, I actually draw it:
private void DrawPointers(OpenGL gl)
{
if (_pointCursor == null)
return;
SetColor(gl, Color.LightGray);
gl.Begin(OpenGL.GL_LINE_LOOP);
foreach (var item in _pointCursor)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
}
Is there any trick,configuration or strategy in order to avoid this delay?
I think the problem is how everything is drawn. If I remove DrawAxis() and DrawGrid() there is not more delay. In this case it can depend on my drawing strategy, I use a lot of gl.Begin() and gl.End().
Another thing is that DrawGrid() and DrawAxis() continues to draw a fixed background. I don't use shaders.
This is the code:
private void MouseDrawCursors(XglVertex v)
{
if ((_view == ViewType._2D) && ((_status == EditStatus.Idle) || (_status == EditStatus.DrawLine)))
{
_pointCursor = v.DrawSquare(0.1f); //Return a list of vertex
_pointCross = v.DrawCross(20); //Return a list of vertex
}
}
private void openGLControl1_MouseMove(object sender, MouseEventArgs e)
{
if (_gl == null)
return;
double worldX = 0;
double worldY = 0;
double worldZ = 0;
_gl.GetWorldCoords(e.X, e.Y, ref worldX, ref worldY, ref worldZ);
XglVertex v = new XglVertex((float)worldX, (float)worldY, (float)worldZ);
MouseDrawCursors(v);
}
private void Draw()
{
if (_gl == null)
return;
//Enable 3D
if (_view == ViewType._2D)
_gl.Disable(OpenGL.GL_DEPTH_TEST);
else
_gl.Enable(OpenGL.GL_DEPTH_TEST);
_gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
//Enable Aplpha
_gl.Enable(OpenGL.GL_BLEND);
_gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
#region Projection
_gl.MatrixMode(OpenGL.GL_MODELVIEW);
_gl.LoadIdentity();
_gl.Scale(Params.ScaleFactor, Params.ScaleFactor, Params.ScaleFactor);
_gl.Translate(Params.X, Params.Y, Params.Z);
if (_status == EditStatus.Rotate)
_arc_ball_effect.ArcBall.TransformMatrix(_gl);
else
_gl.Rotate(Params.XAngle, Params.YAngle, Params.ZAngle);
_gl.MatrixMode(OpenGL.GL_PROJECTION); //matrice di proiezione
_gl.LoadIdentity(); //ripristina matrice identità
float worldWidth = Params.Width;
float worldHeight = Params.Height;
float near = Params.Near;
float far = Params.Far;
_gl.Viewport(0, 0, openGLControl1.Width, openGLControl1.Height);
if (_aspect_ratio >= 1.0)
_gl.Ortho(0, (worldWidth * _aspect_ratio), 0, worldHeight, near, far);
else
_gl.Ortho(0, worldWidth, 0, (worldHeight / _aspect_ratio), near, far);
#endregion
if (Params.ShowPointers)
DrawPointers(_gl);
if (Params.ShowAxis)
DrawAxis(_gl);
if (Params.ShowGrid)
DrawGrid(_gl);
_gl.Flush();
}
private void DrawPointers(OpenGL gl)
{
if (_pointCursor == null)
return;
if (_pointCursor.Count == 0)
return;
SetColor(gl, Color.LightGray);
gl.Begin(OpenGL.GL_LINE_LOOP);
foreach (var item in _pointCursor)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
if (_pointCross == null)
return;
SetColor(gl, Color.LightGreen);
gl.Begin(OpenGL.GL_LINES);
foreach (var item in _pointCross)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
}
private void DrawGrid(OpenGL gl)
{
if (_gl == null)
return;
if (_grid == null)
return;
if (!Params.ShowGrid)
return;
SetColor(gl, _grid.GridColor);
if (_grid.EnableXY)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.XY)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
if (_grid.EnableYZ)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.YZ)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
if (_grid.EnableZX)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.ZX)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
}

I don't see the animation of the sprite

This is code after includes:
Sprite player;
Texture playerTexture;
IntRect playerContainer(0, 0, 32, 32);
Vector2f playerPosition;
int playerDirection = 0; // 0 - fwd, 1 - back, 2 - stay
This is animation update method:
void updateAnims(Clock clock, float time) {
if(time > 0.3f) {
if(playerDirection == 0) playerContainer.top = 0;
else if(playerDirection == 1) playerContainer.top = 32;
else if(playerDirection == 2) playerContainer.top = 64;
if(playerContainer.left == 96) playerContainer.left = 0;
else playerContainer.left += 32;
player.setTextureRect(playerContainer);
clock.restart();
}
}
and this method is updated in "int main()" method.
int main() {
// Init window
RenderWindow window(VideoMode(800, 600), "RPG");
Clock gameClock;
Clock animClock;
float gameTime;
float animTime;
// Setting up the player
playerTexture.loadFromFile("player.png");
player.setTexture(playerTexture);
player.setTextureRect(playerContainer);
player.setScale(Vector2f(3.f, 3.f));
playerPosition.x = 30;
playerPosition.y = 120;
player.setPosition(playerPosition);
while(window.isOpen()) {
Event event;
while(window.pollEvent(event)) {
if(event.type == Event::Closed) {
window.close();
}
}
checkInputs(gameTime);
animTime = animClock.getElapsedTime().asSeconds();
updateAnims(animClock, animTime);
window.clear();
gameTime = gameClock.getElapsedTime().asMilliseconds();
gameClock.restart();
window.display();
}
return 0;
}
Turns out that sprite is created in main method, gets texture and texture shape, gets position, but not drawn. Why?
I think think the problem is in animation method but I tried different variations of solutions.
You should call window.draw(player) method between window.clear() and window.display() to actually draw player sprite on screen.

Should I need to unschedule my tick method?

I'm trying to simulate a flick in cocos2d and I need to create a ball every time the users touch is ended, but I can't get the ball to move during the tick method, and I can't destroy the ball (which is a b2body) afterwards without unscheduling the method every time.
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
touch = [touches anyObject];
location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
endPoint = location;
force = b2Vec2(endPoint.x - startPoint.x ,endPoint.y - startPoint.y);
if ((force.x != 0) || (force.y != 0)) {
if (ballCount == 0) {
ball.position = startPoint;
[self createBall]; - Here i create the ball every time
[self schedule: #selector(tick:)]; -I schedule the tick method right after the ball is created
[self scheduleOnce:#selector(kick) delay:0]; - This is the only place the ball will launch. For some reason I can't get the kick method to work any where else
}
}
- (void)kick
{
int speed = 30;
float32 setSpeed = speed/sqrt(powf(force.x,2) + powf(force.y, 2));
b2Vec2 ballSpeed = b2Vec2(force.x * setSpeed, force.y * setSpeed);
_ballBody->SetLinearVelocity(ballSpeed);
}
- (void)tick:(ccTime) dt {
_world->Step(dt, 10, 10);
ballData = (__bridge CCSprite *)_ballBody->GetUserData();
ballData.position = ccp(_ballBody->GetPosition().x * PTM_RATIO,
_ballBody->GetPosition().y * PTM_RATIO);
ballData.rotation = -1 * CC_RADIANS_TO_DEGREES(_ballBody->GetAngle());
std::set<b2Body *>toDestroy;
//takes collisions from contact listener
std::vector<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
bodyA = contact.fixtureA->GetBody();
bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
spriteA = (__bridge CCSprite *) bodyA->GetUserData();
spriteB = (__bridge CCSprite *) bodyB->GetUserData();
contactPositionX = spriteA.position.x;
contactPositionY = spriteB.position.y;
if (spriteA.tag == kCurrentItem && spriteB.tag == 8)
{
NSLog(#"contact");
[self removeChild:spriteA cleanup:YES];
[self removeChild:spriteB cleanup:YES];
toDestroy.insert(bodyA);
toDestroy.insert(bodyB);
[self unschedule:#selector(tick:)]; (i unschedule the tick method every time which in turn messes up my other sprites.)
}
}
}
for(std::set<b2Body *>::iterator pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2)
{
b2Body *body = *pos2;
_world->DestroyBody(body);
}
toDestroy.clear();
}

Box2d Body can not destroy when touch with another body

I am using box2d based game and it detect my player body collied with enemy body but when i write destroybody method for enemy at collied point that time my enemy can not destroy and gives error and my apps crashed.
I show you my code
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
for(pos = contactListener->_contacts.begin();
pos != contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL)
{
CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
if (spriteA.tag == 1 && spriteB.tag == 2)
{
// SpriteA = PlayerSprite
// SpriteB = EnemySprite
NSString *t=[NSString stringWithFormat:#"Game Over"];
label.string=t;
[self removeChild:spriteB cleanup:YES];
world->DestroyBody(bodyB);
}
else if (spriteA.tag == 2 && spriteB.tag == 1)
{
//toDestroy.push_back(bodyB);
NSLog(#"Enemy Touch");
}
}
}
Here my spriteB can not destroy.
One more thing is enemy sprite is into the Enemy.mm file.
Please help me i am stuck with this problem.
Thanks in advance
Your making a fundamental error of handling enemy contact with player different from player contact with enemy(its just the order of thing), you should treat both case the same because you cant know what order they arrive.
Also you arent using toDestroy properly.
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
for(pos = contactListener->_contacts.begin();
pos != contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL)
{
CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
if ((spriteA.tag == 1 && spriteB.tag == 2) ||(spriteA.tag == 2 && spriteB.tag == 1))
{
// SpriteA = PlayerSprite
// SpriteB = EnemySprite
NSString *t=[NSString stringWithFormat:#"Game Over"];
label.string=t;
[self removeChild:spriteB cleanup:YES];
toDestroy.push_back(bodyB);
}
}
}
//iterate and delete everything from toDestroy

Animating sprite while jumping

How to animate a sprite while jumping?
i.e, moving the eyes or animating the sprite using CCAnimate
CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFrames("AnimBear.plist");
this._bear = CCSprite.sprite("bear1.png", true);
spritesheet1 = CCSpriteSheet.spriteSheet("AnimBear.png");
spritesheet1.addChild(_bear, 1);
addChild(spritesheet1, 1);
ArrayList<CCSpriteFrame> animFrames = new ArrayList<CCSpriteFrame>();
CCSpriteFrameCache.sharedSpriteFrameCache();
for (int i = 1; i <= 8; i++) {
CCSpriteFrame frame = CCSpriteFrameCache
.spriteFrameByName(
"bear" + i + ".png");
animFrames.add(frame);
}
CCAnimation anim = CCAnimation.animation("AnimBear", .175f,
animFrames);
_bear.setPosition(CGPoint.make(_bear.getContentSize().width, 50));
CCIntervalAction action=CCAnimate.action(0.1f, anim, false);
this.walkAction = CCRepeatForever.action(action);
_bear.runAction(walkAction);
and moving on touch
public boolean ccTouchesEnded(MotionEvent event) {
CGPoint touchLocation = CCDirector.sharedDirector().convertToGL(
CGPoint.make(event.getX(), event.getY()));
float bearVelocity = 480.0f/3.0f;
CGPoint moveDifference = CGPoint.ccpSub(touchLocation, _bear.getPosition());
float distanceToMove = CGPoint.ccpLength(moveDifference);
float moveDuration = distanceToMove / bearVelocity;
if (moveDifference.x < 0) {
_bear.flipX_= false;
} else {
_bear.flipX_ = true;
}
_bear.stopAction(moveAction);
if (!_moving) {
_bear.runAction(walkAction);
}
CCMoveTo actionMove=CCMoveTo.action(moveDuration, touchLocation);
CCCallFuncN actionMoveDone1 = CCCallFuncN.action(this, "bearMoveEnded");
CCSequence actions = CCSequence.actions(actionMove, actionMoveDone1);
_bear.stopAllActions();
this.moveAction = actions;
_bear.runAction(moveAction);
_moving = true;
return CCTouchDispatcher.kEventHandled;
}
In this animation complete first and after this if you touch on the screen then the activity you want it'll happen.....
If you want the animation n move the sprite simultaneously, complete your all code in the
public boolean ccTouchesEnded(MotionEvent event) {
}