Levelhelper sprite + SneakyJoystick - cocos2d-iphone

Basically i'd like to move a box2d body of a LHSprite that I created using LevelHelper.
I have tried moving the box2d body of the LHSprite, based on weather my SneakyJoystick is active (that part works fine) with the following code:
if(dpad.leftJoystick.velocity.x > 0){
b2Vec2 force;
force.Set(dpad.leftJoystick.velocity.x * 10.0f, 0.0f);
Player.body->ApplyForce(force, Player.body->GetPosition());
}
Can anyone see how I can get this working?
Thanks.

LHSPrite has these methods:
[sprite transformPosition:ccp(50,50)]; //will set the sprite position to 50,50 together with the physical body
[sprite transformRotation:240];//will rotate the sprite to angle 240, together with the physical body
you have to update LHSPrite postitions bassed on box2d body in update method (see examples).

Related

Drawing a minimap in SFML/C++

I understand that I can already create a minimap by modifying a view object, as outlined here, but what I want instead is a small rectangle that will have a box or an arrow representing the player, and other colored boxes that represent enemies or various objects. Is there a better way to do this than simply create a Minimap object that calculates where each enemy is and translates that into a representational object (box, arrow.. etc) that then gets drawn to the screen?
This is a general question more than anything, so I'm not really expecting sample code, even though it would be much appreciated. I'm outlining a minimap class now and I'll upload it here soon.
Here is what I'm doing in my draw loop:
minimap.setCenter(player.getPosition());
minimap.setViewport(sf::FloatRect(0.75f, 0.75f, 0.25f, 0.25f));
//Bottom right corner of screen
window.setView(minimap);
window.draw(player);
window.setView(view); //Return to default view
With a call to minimap.zoom(10); when the view is initiated.
Actually, I tried this:
window.setView(minimap);
sf::CircleShape object;
object.setRadius(200);
object.setFillColor(sf::Color::Blue);
object.setPosition(player.getPosition());
window.draw(object);
object.setFillColor(sf::Color::Red);
for (auto& e : enemies)
{
object.setPosition(e->getPosition());
window.draw(object);
}
window.setView(view);
And that worked. Obviously it would benefit from being in its own class, so that the circle didn't have to be recreated each loop etc..
If there's a better way to do this, be sure to mention it.
Here's a screenshot of the Minimap (Bottom Right):

Zooming in and out of Scene in Cocos 2D-X 3.2

I'm pretty new to Cocos 2D-X but have some decent background in C++. I have a sprite _rocket (tied to a Box2D body) that occasionally moves outside the visible view of my screen. I'd like for the view to automatically zoom out as the sprite approaches the edge of the screen, so that the sprite is always in the view. When the sprite returns to the original view frame, the view should scale back to its original size.
I was able to zoom out with the following code in the update function:
Size winSize = Director::getInstance()->getWinSize();
if ((_rocket->getPosition().x - _rocket->getContentSize().width/2 < 10.0) ||
(_rocket->getPosition().x + _rocket->getContentSize().width/2 > winSize.width - 10.0) ||
(_rocket->getPosition().y - _rocket->getContentSize().width/2 < 10.0) ||
(_rocket->getPosition().y + _rocket->getContentSize().width/2 > winSize.height - 10.0))
{
this->setScale(this->getScale()-0.005);
}
However, because winSize isn't updated, this essentially scales forever, until the sprite returns to the original view. I am not sure how to update winSize so that it can be used iteratively to find the screen's edge. There may also be a much easier way of approaching this.
i don't understand why the winSize should change.
if you mean the _rock's contentsize not change
you should use
auto size = _rocket->getBoundingBox().size;
They removed some useful camera functions in cocos2d-x 3.+
The workaround is to scale/move the layer containing the game instead of trying to move the camera.

How to access b2body of CCPhysicsSprite using its tag

i`m working on a platformer game , i have A character who jumps on different platforms , until he reaches the end of the level.
one type of platform is a tree log floating on water. the log slowly moves up and down along the tide of water .
each platform is actually a b2body. here is how i define a platform :
b2Body *platformbody;
b2BodyDef platforbodydef;
b2FixtureDef platformfixdef;
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.5f, 0.5f);
platforbodydef.type=b2_staticBody;
platforbodydef.position.Set(BlockPlatX[i][j], BlockPlatY[i][j]);
platformbody= world->CreateBody(&platforbodydef);
platformfixdef.shape=&dynamicBox;
platformsprite=[CCPhysicsSprite spriteWithFile:#"TreeLog.png"];
dynamicBox.SetAsBox(platformsprite.texture.contentSize.width/PTM_RATIO/2,platformsprite.texture.contentSize.height/PTM_RATIO/2);
platformfixdef.friction=1;
platformfixdef.density=1;
platformfixdef.restitution=0;
platformbody->CreateFixture(&platformfixdef);
if(platforbodydef.position.y < watersprite.contentSize.height/2)
{
platforbodydef.position.Set(prevPlatX + 300, watersprite.contentSize.height/2 + 10);
CGPoint point=CGPointMake(platforbodydef.position.x,watersprite.contentSize.height/2);
CCMoveTo *waterMove=[CCMoveTo actionWithDuration:3 position:point];
point=CGPointMake(platforbodydef.position.x,watersprite.contentSize.height/2+ 10);
CCMoveTo *waterMoveBack=[CCMoveTo actionWithDuration:3 position:point];
CCSequence* sequence = [CCSequence actions:waterMove,waterMoveBack, nil];
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
[platformsprite runAction:repeat];
}
[platformsprite setPTMRatio:PTM_RATIO];
[platformsprite setB2Body:platformbody];
[platformsprite setPosition:CGPointMake(platforbodydef.position.x, platforbodydef.position.y)];
[self addChild:platformsprite z:4 tag: 10000 + i*100 + j];
i am using a loop ,so i create more than one of these platforms .
but the problem is that when the sprite runs the action sequence , the position of the b2body associated with it does`nt change and this obviously causes lots of problems.
is there anyway i can access the b2body of the sprite using its tag and change the position of the body instead?
First thing is that the sprite follows the body and not the other way round. When you are repositioning the b2Body via setTransform you have to be very careful as you can find some really odd behaviours. The collision is not being performed in the proper fashion, so if the moved body will intersect with something else some crazy stuff can happen.
Why are you using sequence to move the body on the water. You are much better off using a prismatic joint to push it along and at the end of the track place a sensor which will revert the motor of the joint to move it in the other direction. Let the physics engine deal with the movement. This way you allow the system to work in the way it was intended and the sprite will updates its position to the body automatically.
Edit: I would also advised using a visual box2d editor. You are using Cocos2d as an engine, so there is quite few to choose from. I would personally recommend "Really Useful Box2D Editor" or "R.U.B.E." in short.

CCParallaxNode adding childs while scrolling

I'am using a CCParallaxNode to scroll 3 backgrounds along with Ray Wenderlich's category to move the backgrounds when they go out of the screen.
It is working just fine, my problem is that i want to add childs (enimies) on the fly, like every 5 seconds. Normally i would just add the enemies to the parent layer using a CCMoveTo action to animate him over the screen but I want my enimies to follow the foreground of the parallax layer.
I'am increasing the scroll speed slowly as the game progresses.
I can't seem to figure out the right offset when calling
CGFloat offset = self.gameBackground.position.x;
[self.gameBackground addChild:enimy z:5 parallaxRatio:ccp(0.1, 0.1) positionOffset:ccp(offset, 85)];
Can someone help me out with this?
edit:
I'am doing this to move the background:
- (void)update:(ccTime)delta
{
self.speed -= 0.5f;
CGPoint backgroundScrollVel = ccp(self.speed, 0);
self.gameBackground.position = ccpAdd(self.gameBackground.position, ccpMult(backgroundScrollVel, delta));
}
Thanks
Rays article: http://www.raywenderlich.com/3611/how-to-make-a-space-shooter-iphone-game
Final solution:
I ended up just adding the enimies to the CCLayer instead of the Parallax. To move the enimies in the same speed as the foremost layer child in Parallax i did the following:
in update:(ccTime)delta:
CGFloat parallaxRatio = 0.1f;
CGPoint backgroundScrollVel = ccp((self.backgroundSpeed * - 1) * parallaxRatio, 0);
for(WKEnimy *enemy in self.enimies)
{
enemy.position = ccpAdd(enemy.position, ccpMult(backgroundScrollVel, delta));
}
You could add your enemy CCSprites to your foreground CCLayer (instead of directly adding them to your CCParallaxNode). Besides, I wouldn't recommend using actions (such as CCMoveTo) for this particular case; you may update your sprites positions as your doing with your gameBackground, and 'manually' check wether or not they're off the screen.

Animate Sprite From Tile Map

I would like to animate a sprite at a specific location on an isometric tilemap. I can animate a sprite on a given layer, but not when its a sprite from a tilemap. For example the following works just fine:
// make a frame cache
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"spellanim.plist" textureFile:#"spellanim.pvr.ccz"];
// create a sprite
CCSprite *effectSprite = [CCSprite spriteWithSpriteFrameName:#"spell_strength__33.png"];
// set sprite at center of screen
CGSize screenSize = [[CCDirector sharedDirector] winSize];
effectSprite.position = CGPointMake(screenSize.width / 2, screenSize.height / 2);
// create animation using an animation helper (since animationWithName:delay:frames: will be deprecated)
CCAnimation *animation = [CCAnimation animationWithFrame:#"spell_strength__" frameCount:13 delay:0.3f startAt:33];
CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
// run animation on sprite
[effectSprite runAction:animate];
// add sprite as a child of the layer
[self addChild:effectSprite];
Now the following does not work, I assume it has to do with how tile maps work (I get an assertion failure in CCSprite setTexture:):
// add one to x to offset the spell animation from the player
CGPoint tileCoord = CGPointMake(player.entityTileCoordinate.x + 1, player.entityTileCoordinate.y);
// get the effects layer from the tile map
CCTMXTiledMap *tileMap = (CCTMXTiledMap *)[[TileMapLayer sharedTileMapLayer] getChildByTag:TileMapNode];
CCTMXLayer *effectsLayer = [tileMap layerNamed:#"Effects"];
// get a sprite from the effects layer
CCSprite *effectSprite = [effectsLayer tileAt:CGPointMake(0, 0)];
// move the sprite to the desired location (this works just fine)
CGPoint pointPixel = [effectsLayer positionAt:tileCoord];
[effectSprite runAction:[CCMoveTo actionWithDuration:0.0f position:pointPixel]];
// now animate the sprite
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:#"spellanim.plist" textureFile:#"spellanim.pvr.ccz"];
CCAnimation *animation = [CCAnimation animationWithFrame:#"spell_strength__" frameCount:13 delay:0.3f startAt:33];
CCAnimate *animate = [CCAnimate actionWithAnimation:animation];
[effectSprite runAction:animate];
My guess it is because the animation sprites aren't a part of the tile set for that layer of the tile map. Is there a way to dynamically add these animation sprites to some cache used to draw on that layer (basically modify the tile set at runtime)? Can I later then remove these sprites from that modified tile set? Is there still a 1024x1024 limitation when you modify a tileset at runtime?
At the end of the day I really want to be able to have an animated sprite move from one tile to another on the tile map but I'm just not sure how to do that in the most efficient way. It seems really clunky to have an effects layer on the tile map and a tile set with all spell animations (especially if you can't fit them in 1024x1024) as assembling an animation would be chaining together tile GID updates as the effect moves across the tile map.
I know I can do what I want when the layer isn't a part of a tilemap - I can animate and move a sprite using screen coordinates, but when what I know are tile coordinates, translating those to screen coordinates (if the tile is even visible on the screen) has evaded my understanding so far. How do you determine what tiles the screen can actually 'see'? What then is the pixel coordinate on the screen of a visible tile?
I appreciate any thoughts on how to go about this process.
what you guess is the real cuase of the problem, tile maps are created using spritebatchnode. spritebatchnode is just like a layer with higher performance that you can only add sprites to it but there is a single restriction all the sprites in a spritebatchnode must share their textures. so when you are trying to change a tile to show an animation you are trying to draw something from diffrent texture alongside other tiles (which have default tile texture) and it causes crashes or malfunctioning. i didn't test it myself but i think if you try putting all your frames in a same texture you put other tiles, the problem would be solved.