I'm working on a game (with Cocos2d 3.0 and SpriteBuilder) in which a character smash another and gain impulse. To do this I'm trying the following:
-(BOOL)ccPhysicsCollisionPreSolve:(CCPhysicsCollisionPair *)pair hero:(CCNode *)hero goal:(CCNode *)goal {
[hero.physicsBody applyImpulse:ccp(0.0f, 9000)];
return TRUE;
}
And also:
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair hero:(CCNode *)hero goal:(CCNode *)goal {
[hero.physicsBody applyImpulse:ccp(0.0f, 9000)];
}
But when the collision method is called, the character doesn't receive the impulse always. I also tried including the following inside "PostSolve" (How to make a dynamic body static in Cocos2d v3.0 with Chipmunk):
[[_physicsNode space] addPostStepBlock:^{
[hero.physicsBody applyImpulse:ccp(0.0f, 9000)];
} key:hero];
...but I have the same result. Do you hace any advice? Thank you.
There was a rather embarrassing copy paste bug in apply impulse in v3 rc1. It's fixed in RC2 though.
Related
I am reading doc of cocos2dx on Actions (link: http://www.cocos2d-x.org/wiki/Actions). They mention reverse function on sequences and spawns at the bottom.
I am just a little confused what difference would reverse make on spawns, since according to what I understand spawns in cocos2d corporate actions together and make them happen at the same time? If this is true reverse would make almost no variations to spawns, at least visually? There is one (potential) line of explanation in the doc says "However it is not just
simply running in reverse. It is actually manipulating the properties of the original Sequence or Spawn in reverse too." Is it because of this "properties" that there is really some difference, probably somewhere in bottom level? Can someone explain this?
I don't think Spawn::reverse() is special. One thing I like Cocos2d-x is that I can see the source code by clicking F12.
Spawn* Spawn::reverse() const
{
return Spawn::createWithTwoActions(_one->reverse(), _two->reverse());
}
//Definition of Spawn
Spawn{
//...
protected:
//FiniteTimeAction is a derived class of Action
FiniteTimeAction *_one;
FiniteTimeAction *_two;
private:
CC_DISALLOW_COPY_AND_ASSIGN(Spawn);
};
Yes, the reverse will not make any visible visually as it will be reversing every action and there will be no movement.As I am giving an example of jumpBy and reversing the jumps of the sprite using a sequence.
auto jump = JumpBy::create(3,Vec2(100, 0),50,3);
auto jumpBack = jump->reverse();
sceneSprite->runAction(Sequence::create(jump,jumpBack, nullptr));
I’m using Cocos2d v3 and want to change a body from dynamic to static after colliding with another body. At the moment I’ve got:
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
_player.physicsBody.type = CCPhysicsBodyTypeStatic;
}
or
-(BOOL)ccPhysicsCollisionPreSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
_player.physicsBody.type = CCPhysicsBodyTypeStatic;
return YES;
}
but neither works. I get the error:
Aborting due to Chipmunk error: This operation cannot be done safely during a call to cpSpaceStep() or during a query. Put these calls into a post-step callback.
Failed condition: !space->locked
I then tried to make a joint at the point of collision but it doesn’t work right.
Is there a way to change a body to dynamic as soon as it collides in v3? I can do it in later versions using Box2D. I want to stop gravity and other forces so it doesn’t move. I want to make it look like it stuck to a surface.
Read a little on post-step callbacks but i'm unfamiliar with how to use them.
Any help would be appreciated.
As the error message states, you need to implement a post-step callback.
To do this on Cocos2d 3.0 and with Objective Chipmunk you first need to import a new header file to access advanced chipmunk properties:
#import "CCPhysics+ObjectiveChipmunk.h"
Then add the callback in your collision handler:
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair static:(CCNode *)nodeA wildcard:(CCNode *)nodeB
{
[[_physicsNode space] addPostStepBlock:^{
_player.physicsBody.type = CCPhysicsBodyTypeStatic;
} key:_player];
}
Note that I assume you have access to your CCPhysicsNode in _physicsNode.
The Chipmunk Space of CCPhysicsNodeis locked while the a physics step is calculated. During a calculation of a step collisions are resolved and objects are moved around - changing the body type during this calculation could result in unexpected behaviour.
Therefore you add the postStepBlockcallback. This is a place where a body type can be safely changed.
The key value you pass into the callback is used to ensure that the code is only called once (especially useful when removing objects, but it also makes sense in this case).
If also added an example implementation: https://www.makegameswith.us/gamernews/367/make-a-dynamic-body-static-in-cocos2d-30-with-chi
I am not sure how you are supposed to control a player character in Bullet. The methods that I read were to use the provided btKinematicCharacterController. I also saw methods that use btDynamicCharacterController from the demos. However, in the manual it is stated that kinematic controller has several outstanding issues. Is this still the preferred path? If so, are there any tutorials or documentations for this? All I found are snippets of code from the demo, and the usage of controllers with Ogre, which I do not use.
If this is not the path that should be tread, then someone point me to the correct solution. I am new to bullet and would like a straightforward, easy solution. What I currently have is hacked together bits of a btKinematicCharacterController.
This is the code I used to set up the controller:
playerShape = new btCapsuleShape(0.25, 1);
ghostObject= new btPairCachingGhostObject();
ghostObject->setWorldTransform(btTransform(btQuaternion(0,0,0,1),btVector3(0,20,0)));
physics.getWorld()->getPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
ghostObject->setCollisionShape(playerShape);
ghostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
controller = new btKinematicCharacterController(ghostObject,playerShape,0.5);
physics.getWorld()->addCollisionObject(ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
physics.getWorld()->addAction(controller);
This is the code I use to access the controller's position:
trans = controller->getGhostObject()->getWorldTransform();
camPosition.z = trans.getOrigin().z();
camPosition.y = trans.getOrigin().y()+0.5;
camPosition.x = trans.getOrigin().x();
The way I control it is through setWalkDirection() and jump() (if canJump() is true).
The issue right now is that the character spazzes out a little, then drops through the static floor. Clearly this is not intended. Is this due to the lack of a rigid body? How does one integrate that?
Actually, now it just falls as it should, but then slowly sinks through the floor.
I have moved this line to be right after the dynamic world is created
physics.getWorld()->getPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
It is now this:
broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
I am also using a .bullet file imported from blender, if that is relevant.
The issue was with the bullet file, which has since been fixed(the collision boxes weren't working). However, I still experience jitteryness, unable to step up occasionally, instant step down from to high a height, and other issues.
My answer to this question here tells you what worked well for me and apparently also for the person who asked.
Avoid ground collision with Bullet
The character controller implementations in bullet are very "basic" unfortunately.
To get good character controller, you'll need to invest this much.
Question is as simple as the tip of the question.
banner is working in test mode in device.(seems like so: "You re connected to the iAd Network").
declared -didFailToReceiveAdWithError, -bannerViewDidLoadAd and -bannerViewActionShouldBegin.
and ADBannverView1.delegate assigned to self (is a cocos2d CCLayer)
but these methods never called. I drop some breakpoints that never runs into.
have you any idea ?
Question 2: what is the difference between these property definations ? should I use weak, assign ? or IBOutlet is a necessarry ?I tried all 3 combination and all worked.
#property(nonatomic,retain) ADBannerView *iAdView;
#property(nonatomic,retain) IBOutlet ADBannerView *iAdView;
#property(nonatomic,assign) ADBannerView *iAdView;
For me the problem was that I also had this line in my code self.canDisplayBannerAds=YES;
After I removed it delegate method were called properly.
I am using the new Google Maps Android API v2 and need to detect latlng coordinates for the corners of my screen view. I use mMap.getProjection().getVisibleRegion() to do this, which works fine the first time I load the program, but if I leave the program and then re-open it (either via the back button or the home button) getVisibleRegion() returns latlng coordinates that are all (0.0, 0.0). I have a workaround where I save the VisibleRegion object as a global in the application class when I first open the program, but this seems like a bad idea. Anyone understand why the latlng coordinates go to zero (but not null) when re-opening? Thanks!
Edit: sometimes initial load gives a (0.0, 0.0) Visible Region so my workaround is not viable. Using getProjection().fromScreenLocation(point) also returns 0.
Okay, I think I solved it: I was guessing right: The map was not visible and therefore there is also no visibleRegion (in other words a region from 0,0,0,0 to 0,0,0,0). Similar to this question
Android Google Maps API v2 calling getProjection from onResume
I attached an onCameraChanged-Listener to my map. Everytime the map is moved (or the camera is available => There is a visibleRegion) this method is called.
private void initMap() {
mMap = getMap();
if (mMap != null) {
try {
mMap.setLocationSource(this);
mMap.setOnMarkerClickListener(this);
mMap.setOnCameraChangeListener(new OnCameraChangedListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
Log.d(TAG, "onCameraChange");
updateMapItems();
}
}
MapsInitializer.initialize(getActivity());
...
}
}
}
This listener makes sure that you have a visibleRegion.
UPDATE: Since the new update of the Google Maps API v2, there is a callback onMapReady(). I did not use it yet, but it seems to serve exactly the purpose of this question: https://developer.android.com/reference/com/google/android/gms/maps/OnMapReadyCallback.html