iOS cocos2D Chipmunk Body's velocity is invalid - objective-c

In cocos2d-spritebuilder 3.4 I've create my physicworld and my player like many of the official examples.
self.sprite.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:10 andCenter:self.anchorPoint];
self.sprite.physicsBody.type = CCPhysicsBodyTypeDynamic;
etc...
So, when I try to move my sprite to the right for example with
[self.sprite.physicsBody applyImpulse: CGPointMake(32,0)];
my app going in crash reporting this:
Aborting due to Chipmunk error: Body's velocity is invalid.
Failed condition: v.x == v.x && v.y == v.y
Source:.../Source/libs/cocos2d-iphone/external/Chipmunk/src/cpBody.c:106
Chipmunk source's have:
-(void)applyImpulse:(CGPoint)impulse { _body.velocity = cpvadd(_body.velocity, cpvmult(CCP_TO_CPV(impulse), 1.0f/_body.mass));}
So, I knew MASS was setted by default to 1.0f, but I want to try to set this value by hand..) :
self.sprite.physicsBody.mass = 1.0f
Same error, same results...
But if I try to set:
self.sprite.physicsBody.body.mass = 1.0f
It work great.
So, what's the differences btw these two parameters?
Why applyImpulse take only body.mass?

As far as I know, Chipmunk doesn't play nice when applying a "big" impulse. What you should try and do is build up velocity over several frames.
Edit: Check this link http://forum.cocos2d-swift.org/t/ccphysics-applyimpulse-not-working/12151/12

Related

glutSolidSphere lighting issue when further away

For some reason I get weird patchy lighting effects/flickering when using glutSolidSphere and the camera is relatively far away from the object. See below:
This also happens with glutSolidCube and I assume the others as well.
I've tried everything I could find in similar questions but no luck with that
Glusphere giving strange lighting
Lighting does not work with gluSphere
I've tried enabling all of the below and different combinations of the below and tried doing so in multiple places
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_NORMALIZE);
glDepthFunc(GL_LEQUAL);
And also removed all glEnable(GL_TEXTURE_2D); anyhere
The problem happens when I turn on lighting with glEnable(GL_LIGHT0); and occurs with glShadeModel(GL_SMOOTH) and glShadeModel(GL_FLAT) and also if I don't enable GL_COLOR_MATERIAL and even occurs with just a positional light like so:
float light_position[] = {100.0f, 100.0f, 100.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
What else could this be?
Finally figured out the problem after forever. Apparently using a very low value (even if above zero) for zNear in the gluPerspective view causes this problem.
The following fixed the problem:
gluPerspective(90, (float) width / (float) height, 0.1f, Z_RANGE);
See: https://gamedev.stackexchange.com/a/55516

libgdx camera position using viewport

I am rather experiences libgdx developer but I struggle with one issue for some time so I decided to ask here.
I use FillViewport, TiledMap, Scene2d and OrtographicCamera. I want the camera to follow my player instance but there are bounds defined (equal to mapsize). It means that camera will never ever leave outside of map, so when player comes to an end of the map camera stops following and he goes to the edge of the screen itself. Maybe sounds complicated but it's simple and I am sure that you know what I mean, it's used in every game.
I calculated 4 values:
minCameraX = camera.viewportWidth / 2;
minCameraY = camera.viewportHeight / 2;
maxCameraX = mapSize.x camera.viewportWidth / 2;
maxCameraY = mapSize.y - camera.viewportHeight / 2;
I removed not necessary stuff like unit conversion, camera.zoom etc. Then I set the camera position like this:
camera.position.set(Math.min(maxCameraX, Math.max(posX, minCameraX)), Math.min(maxCameraY, Math.max(posY, minCameraY)), 0);
(posX, posY is player position) which is basically setting camera to player position but if it's to high or too low it sets it to max or min defined before in right axis. (I also tries MathUtils.clamp() and it works the same.
Everything is perfect until now. Problem occures when aspect ratio changes. By default I use 1280x768 but my phone has 1280x720. Because of that bottom and top edges of the screen are cut off because of the way how FillViewport works. Because of that part of my map is cut off.
I tried to modify maximums and minimums, calculate differences in ratio and adding them to calculations, changing camera size, different viewports and some other stuff but without success.
Can you guys help?
Thanks
I tried solution of noone and Tenfour04 from comments above. Both are not perfect but I am satisified enough i guess:
noone:
camera.position.x = MathUtils.clamp(camera.position.x, screenWidth/2 + leftGutter, UnitConverter.toBox2dUnits(mapSize.x) - screenWidth/2 + rightGutter);
camera.position.y = MathUtils.clamp(camera.position.y, screenHeight/2 + bottomGutter, UnitConverter.toBox2dUnits(mapSize.y) - screenHeight/2 - topGutter);
It worked however only for small spectrum of resolutions. For strange resolutions where aspect ratio is much different than default one I've seen white stripes after border. It means that whole border was printer and some part of the world outside of border. I don't know why
Tenfour04:
I changed viewport to ExtendViewport. Nothing is cut off but in different aspect ratios I also can see world outside of borders.
Solution for both is to clear screen with same color as the border is and background of level separatly which gave satisfying effect in both cases.
It stil has some limitations. As border is part of the world (tiled blocks) it's ok when it has same color. In case border has different colors, rendering one color outside of borders won't be a solution.
Thanks noone and Tenfour04 and I am still opened for suggestions:)
Here are some screenshots:
https://www.dropbox.com/sh/00h947wkzo73zxa/AAADHehAF4WI8aJ8bu4YzB9Va?dl=0
Why don't you use FitViewport instead of FullViewport? That way it won't cut off your screen, right?
It is a little bit late, but I have a solution for you without compromises!
Here width and height are world size in pixels. I use this code with FillViewport and everything works excellent!
float playerX = player.getBody().getPosition().x*PPM;
float playerY = player.getBody().getPosition().y*PPM;
float visibleW = viewport.getWorldWidth()/2 + (float)viewport.getScreenX()/(float)viewport.getScreenWidth()*viewport.getWorldWidth();//half of world visible
float visibleH = viewport.getWorldHeight()/2 + (float)viewport.getScreenY()/(float)viewport.getScreenHeight()*viewport.getWorldHeight();
float cameraPosx=0;
float cameraPosy=0;
if(playerX<visibleW){
cameraPosx = visibleW;
}
else if(playerX>width-visibleW){
cameraPosx = width-visibleW;
}
else{
cameraPosx = playerX;
}
if(playerY<visibleH){
cameraPosy = visibleH;
}
else if(playerY>height-visibleH){
cameraPosy = height-visibleH;
}
else{
cameraPosy = playerY;
}
camera.position.set(cameraPosx,cameraPosy,0);
camera.update();

Sprite-kit - Facing the hero? ( rotating to the direction of another node)

I have two spriteNodes hero and the enemy, both with rectangular physicsBody applied.
In the update, when the hero gets to the certain point, e.g hero.position.y <= 300 I want the enemy to rotate and face the the hero as it moves down.
the only sample code I found was the Adventure from Apple which has a faceTo class but I found it very complicated to use. I am looking for a nice and clean solution for it.
Thanks in advance.
The most basic implementation should look something like this:
- (void)rotateNode:(SKNode *)nodeA toFaceNode:(SKNode *)nodeB {
CGFloat angle = atan2f(nodeB.position.y - nodeA.position.y, nodeB.position.x - nodeA.position.x);
if (nodeA.zRotation < 0) {
nodeA.zRotation = nodeA.zRotation + M_PI * 2;
}
[nodeA runAction:[SKAction rotateToAngle:angle duration:0]];
}
It's important that you understand what is happening. Look up and read about atan2 (http://en.wikipedia.org/wiki/Atan2) and try to understand how the code above works.
You can use the xScale property of SKNode to make the sprite face the other way. This can be done by setting:
sprite.xScale = -1.0;
However, this has been proved to cause problems with the physicsBody, as can be seen from this question:
Flipped x-scale breaks collision handling (SpriteKit 7.1)
The solution for this problem is given there itself by JKallio.
He suggests keeping your sprite as a child of another SKNode (to which you apply the physicsBody) and changing the xScale property of the child node where needed. This is what I am using in my own project as well.

Variable Jump Height

I have been having great difficulty creating a jumping system whereby the user can tap the jump button for a small jump and hold it down for a higher jump.
I stumbled upon this topic:
https://gamedev.stackexchange.com/questions/13277/variable-height-jumping-in-side-scrollers
Which greatly helped me develop the following code:
PlayerMovementTimer = [NSTimer scheduledTimerWithTimeInterval:0.005 target:self selector:#selector(movePlayer) userInfo:nil repeats:YES];
[JumpButton addTarget:self action:#selector(jumpPlayer:) forControlEvents:UIControlEventTouchDown];
[JumpButton addTarget:self action:#selector(stopJump:) forControlEvents:UIControlEventTouchCancel | UIControlEventTouchUpInside | UIControlEventTouchDragExit];
- (void)movePlayer
{
CGFloat playerY = Player.center.y + PlayerYV;
if(playerY > 264) {
PlayerYV = 0;
playerY = 264;
}
if(playerY < 264) {
PlayerYV += 0.048f - PlayerYD;
}
if(HoldingJump && PlayerYV < 0 && PlayerYD + 0.0018f < 0.048f) {
PlayerYD += 0.0018f;
}
Player.center = CGPointMake(Player.center.x + PlayerXV, playerY);
}
- (IBAction)jumpPlayer:(id)sender
{
if(Player.center.y == 264) {
PlayerYD = 0;
PlayerYV = -2.25;
HoldingJump = true;
}
}
- (IBAction)stopJump:(id)sender
{
HoldingJump = false;
}
The code seems to work (some of the values need a bit of fine tuning but I haven't gotten round to that yet). The only problem is that the movement appears to be slightly jerky (even on the real device) and that when the player is at the top of the jump they accelerate really slowly and no values I put seem to be able to get the jump to look smooth like on Mario games.
Please take a look at the code and see if I am missing something obvious, or if there is a more efficient method of controlling movement than an NSTimer calling a void function. Also, is setting a UIImageView's position to a float value bad?
Thanks.
So there are quite a few things wrong here. First, yes, you should never be setting the origin of an ImageView or any other UI element to a coordinate position that is a fractional pixel. This causes sub-pixelling which will blur your image. To avoid this, all CGFloats should be rounded to the nearest whole number using roundf() or other similar rounding functions.
Another issue I can see is that you're setting Player.center. I hope for your sake that Player is not an ImageView cause you're going to be making your life harder. As mentioned above, when the origin of a frame is not set to a CGFloat that is a round number, you'll get sub-pixelling. When you use the center property, you can easily cause yourself to get on a bad origin value. For example, if I have a 11 by 11 image and set it's center to (11,11), the origin will get set to (5.5,5.5) and will cause sub-pixelling. Easy ways to avoid this is just do the math to place the origin correctly and make sure to round the CGFloats that you feed into it (or use CGRectIntegral on the frame before you set it).
A third issue here is that the timer is being called 0.005 seconds. Let's assume you want this game to run with 60 FPS. 60 FPS translates to about 0.0167 seconds. The timer is calling the method three times more often then it would need to even if you wanted 60 FPS and additionally, calling this method so often could be causing some of your jerky motion.
Now in terms of getting a "Mario" like jump, what you really need to do is look at getting a dedicated physics engine since if you're using the code above, you don't appear to have one. What a physics engine would do is it would apply a constant "gravity" which will help make the player jumps look and act more realistically. You would, when a player presses a button, apply an impulse up on the player character. The use of impulses would also simplify your work as you could apply impulses in different ways depending on how long they hold the button, etc. The code above is simply trying to get around this problem instead of addressing the real issue of you not having a physics engine.
Go investigate cocos2D and Box2D as a possible physics engine you could use. There are a wealth of resources on cocos2D+Box2D and there is a developer who even has made a tutorial on using cocos2D to create a Super Mario clone that should give you some basic understanding of how physics engines work: http://www.raywenderlich.com/15230/how-to-make-a-platform-game-like-super-mario-brothers-part-1

Generate a random Y for a sprite

I need some help (duh). I want to generate a random Y position for my game in cocos2d.
So the situation goes like this:
The game spawns a platform every 0.2 second. The iPhone / iPad is in landscape mode. Platform appear on the right of the screen (bigger x than width so that the platform appears outside the screen) and starts moving towards the left end of the screen using CCMoveTo.
I pick a random Y for every platform. The problem is that I do not want to spawn a platform on top of another. This means that I need to make a randY which is not "already taken".
The code I've tried so far is this:
//this is a part of code from my addPlatform function. This part in particular cares for the generation of my Y coordinate.
int randY = arc4random() % (int)(3 * (winSize.height/4)); //This prevents to spawn a Y larger than 3/4 of the screen
//here I would like to loop long enough to find a good Y
while (![self isGoodPlatformY:randY])
{
randY = arc4random() % (int)(3 * (winSize.height/4));
}
The next part is my isGoodPlatformY function
- (bool)isGoodPlatformY:(int)platY
{
CGSize winSize = [[CCDirector sharedDirector] winSize];
int padding = 100;
bool ok = true;
for (CCSprite *body in [self children])
{
if (body.tag > platformBody)
{
if (body.position.x < (winSize.width - padding))
{
if (abs(body.position.y - platY) < 20)
{
ok = false;
}
}
}
}
return ok;
}
I loop through all the bodies with larger tag than my platform. I have different types of platform which I separate by using tag. If the body is a platform I first check the X coordinate. If the platform is enough away (padding) I can spawn a new one at that exact point so I check the next one. If not I want to check the Y of that platform. If the Y coordinate is less than 20 pixels in this case I must find a new Y so thats why set the bool to false and return it after the for loop.
I know there is no need for those curly brackets but I was testing some other stuff, thats why I put them there.
This doesn't seem to work. Hope I made myself clear what I want to accomplish. Any help from your side would be much appreciated. Hope I didn't miss something too newbie style :)
I tagged the question in other languages to because this problem could occur "everywhere".
Assuming that all the spawned platforms have the same tag as you mentioned that you are using tags to separate different types of platforms.
All previous platforms will not return true for this line
if (body.tag > platformBody)
because they all have the same tag, you will compare (1 > 1) which is false.
Therefore your method will always return YES (which is your default value for ok) and will never check to see if the platforms collide with each other.
I recommend stepping through the method to see if this is the case.
Now I have discovered that I can answer my own questions :) (silly me). So yeah, the problem was fixed a long time ago but to anyone who might be reading this, the solution was to change the line:
if (body.position.x < (winSize.width - padding))
To:
if (body.position.x > (winSize.width - padding))