i have set 2 bodies, a world with gravity,a tick method with step,and all the bodies are moving just fine,and i can apply forces on them, gravity is also working.
but no collision.
when body1 hit the ground he just go out of screen and not hit it and jump like a real ball.
when body1 hit body2 the just continue movement as nothing was happen.
the bodies have shape ,the world have edges, but no collision.
what am i missing here ?
here are some functions that i call from the init :
- (void)addBoxBodyForSprite:(CCSprite *)sprite {
b2BodyDef spriteBodyDef;
spriteBodyDef.type = b2_dynamicBody;
spriteBodyDef.position.Set(sprite.position.x/PTM_RATIO,sprite.position.y/PTM_RATIO);
spriteBodyDef.userData = sprite;
spriteBody = world->CreateBody(&spriteBodyDef);
b2PolygonShape spriteShape;
spriteShape.SetAsBox(sprite.contentSize.width/PTM_RATIO/2,sprite.contentSize.height/PTM_RATIO/2);
b2FixtureDef spriteShapeDef;
spriteShapeDef.shape = &spriteShape;
spriteShapeDef.density = 10.0;
spriteShapeDef.isSensor = true;
spriteBody->CreateFixture(&spriteShapeDef);
}
-(void)worldEdge
{
CGSize winSize = [CCDirector sharedDirector].winSize;
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
b2Body *groundBody = world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundBox;
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
}
-(void)tick:(ccTime) dt
{
world->Step(dt,10,10);
for(b2Body *b=world->GetBodyList(); b; b=b->GetNext())
{
if(b->GetUserData() !=NULL )
{
CCSprite *sprite=(CCSprite *) b->GetUserData();//every b of the world will be update his position
sprite.position=ccp( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO ) ;
sprite.rotation=-1*CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
everything is moving allright but no collision ever.
The specific problem is this line:
spriteShapeDef.isSensor = true;
In box2d, when you set an fixture as a sensor, it will not collide with other fixtures.
Related
I'm making a game in Unity2D where are 4 roads that tanks drive on, tanks spawn in random positions, I want to make sure that a tank can't spawn in a position that another tank is already in. When I start the game the Unity Editor crashes I think there is a problem somewhere in the do while loop but I haven't found it, hoping I described it right.
Thanks.
{
public GameObject tank;
public float spawnTime = 1f;
float positionX;
float positionY;
private bool check;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("TankSpawn", 1f, spawnTime);
}
void TankSpawn()
{
do
{
int rndY = Random.Range(1, 5);
float rndX = Random.Range(20.5f, 35.0f);
if (rndY == 1)
{
positionY = -3.5f;
positionX = rndX;
}
else if (rndY == 2)
{
positionY = 0.5f;
positionX = rndX;
}
else if (rndY == 3)
{
positionY = 4.5f;
positionX = rndX;
}
else if (rndY == 4)
{
positionY = 8.5f;
positionX = rndX;
}
GameObject[] tanks = GameObject.FindGameObjectsWithTag("tank");
foreach (GameObject tank in tanks)
{
if (tank.transform.position.x == positionX && tank.transform.position.y == positionY)
{
check = false;
}
else
{
check = true;
}
}
} while (check != true);
Instantiate(tank, new Vector2(positionX, positionY), transform.rotation);
}
}```
Firstly the problem that is doing you in:
By default bool variables. like check, are false. The while loops when check is false. The only way for check to be set to true is thru the forloop if the generated coordinates don't match any tank positions. The problem with that is that if there are no tanks in the scene the forloop is never even started meaning that there is no way for check to become true, ergo your while loop keeps looping and hangs up your editor.
A quick solution would be to check the length of found tanks array and if it is zero set check to true.
if (tanks.Length == 0)
{
check = true;
}
Sidenotes:
There is name ambiguity between the tank in the forloop and the tank in the prefab. Its good practice to avoid that.
It is extremely hard to match two float values with == due to rounding. They might be extremely close, but are still different.
With your method tanks will still overlap. I would recommend to check if a position is truly free, by using Physics2D.OverlapBox or Physics2D.OverlapCircle
If a lot of tanks spawn there might not be any valid positions. You should think of a way to timeout or impose some other limit, else you'll get softlocked in the while loop again.
I'm working in Swift and have created an SKSpriteNode to be the ground in my game. I've set it to the proper position and made the physics body as wide as the screen:
//Ground
var groundTexture = SKTexture(imageNamed: "groundBar")
var groundBar = SKSpriteNode(texture: groundTexture)
groundBar.setScale(2)
groundBar.position = CGPointMake(self.size.width/2, self.size.height/2)
groundBar.hidden = true
self.addChild(groundBar)
var ground = SKNode()
ground.position = CGPointMake(0, groundTexture.size().height)
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width, groundTexture.size().height*2))
ground.physicsBody?.dynamic = false
self.addChild(ground)
Then I have another SKSpriteNode that is the character in my game, and when tapped I have this character jump up and to the right:
//Savior character
var saviorTexture = SKTexture(imageNamed: "character")
saviorTexture.filteringMode = SKTextureFilteringMode.Nearest
savior = SKSpriteNode(texture: saviorTexture)
savior.setScale(1)
savior.position = CGPoint(x: self.frame.size.width * 0.5, y: self.frame.size.height * 0.4)
savior.physicsBody = SKPhysicsBody(circleOfRadius: savior.size.height/2)
savior.physicsBody?.dynamic = true
savior.physicsBody?.allowsRotation = false
self.addChild(savior)
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
savior.physicsBody?.velocity = CGVectorMake(0, 0) //pt it returns to?
savior.physicsBody?.applyImpulse(CGVectorMake(5, 30)) //direction/height that it jumps }
Before it is tapped, the character sits on the ground node and therefore doesn't fall off the screen. When tapped, however, the character jumps up and falls off the screen. It's as if it doesn't come in contact with the ground.
I've tried resizing the ground, repositioning the ground, but the character still falls off the screen. Mind you that when the vector is (0,30) and it just jumps straight up, it doesn't fall off the screen.
What is happening here?
In your view controller you can do skView.showsPhysics = true and see if the physics bodies are where you think they are. Also, be sure that their physicsBody.collisionBitMask are not the same.
#import "MainScene.h"
static const CGFloat _scrollSpeed = 80.f;
#implementation MainScene {
CCSprite *_hero;
CCPhysicsNode *_physicsNode;
CCNode *_ground1;
CCNode *_ground2;
NSArray *_grounds;
}
- (void)didLoadFromCCB {
_grounds = #[_ground1, _ground2];
}
- (void)update:(CCTime)delta {
_hero.position = ccp(_hero.position.x + delta * _scrollSpeed, _hero.position.y);
_physicsNode.position = ccp(_physicsNode.position.x - (_scrollSpeed *delta), _physicsNode.position.y);
// loop the ground
for (CCNode *ground in _grounds) {
// get the world position of the ground
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.x <= (-1 * ground.contentSize.width)) {
ground.position = ccp(ground.position.x + 2 * ground.contentSize.width, ground.position.y);
}
}
}
#end
And in this line
if (groundScreenPosition.x <= (-1 * ground.contentSize.width)) {
I have this 2 issues
Expected expression
Use of undeclared identifier 'lt'
thats my problem
plis help me, I really need it before possible
Wherever you copied your code from, it percent-escaped a less than sign, so it put in < instead of <. So just replace the < with <.
I need help with canvas because of one problem that Im trying to solve for about a day. Here is part of code that I am testing.
var imgpos = 0;
function drawshape(context, shape, fill, bb) {
context.beginPath();
context.save();
context.translate( 0, 130);
context.scale(1, 0.65);
context.shadowOffsetX = 0;
context.shadowOffsetY = 10;
context.shadowBlur = 9;
context.shadowColor = "black";
context.arc(shape.x, shape.y, shape.r, shape.sa, shape.ea, shape.cc);
context.lineWidth = shape.lw;
// line color
context.strokeStyle = fill;
context.stroke();
context.restore();
// not working :( ---------------
context.save();
for(var lg = 0; lg < shape.ic; lg++) { //
var imagesel = new Image();
imagesel.src = '/images/themes/default/capsules/'+imgpos+'.png';
imagesel.onload = function(){
if(imgpos==0){xx=70;yy=320;}
if(imgpos==1){xx=120;yy=260;}
if(imgpos==2){xx=140;yy=320;}
if(imgpos==3){xx=160;yy=320;}
if(imgpos==4){xx=180;yy=320;}
if(imgpos==5){xx=200;yy=320;}
if(imgpos==6){xx=220;yy=320;}
if(imgpos==7){xx=240;yy=320;}
if(imgpos==8){xx=260;yy=320;}
context.drawImage(imagesel, xx, yy);
}
if(imgpos != 8){imgpos++;} else {imgpos=0;}
}
context.restore();
// till here :( ---------------
if(shape.link != 'Limited'){
context.save();
context.scale(1, 0.65);
context.translate(500,660);
context.font = "bold 15pt Arial";
context.fillStyle = "WHITE";
if(bb <= 2){
context.textAlign="right";
context.rotate((((shape.sa+shape.ea)-0.1)/2)-Math.PI);
context.fillText(shape.link, -170, 0);
}
if(bb > 2){
context.textAlign="left";
context.rotate((((shape.sa+shape.ea)+0.1)/2)-2*Math.PI);
context.fillText(shape.link, +170, 0);
}
context.restore();
}else{
context.save();
context.scale(1, 0.65);
context.translate( 0, 130);
context.textAlign="center";
context.font = "bold 15pt Arial";
context.fillStyle = "WHITE";
context.fillText(shape.link, shape.x, shape.y-10);
context.restore();
}
}
So this code (except of part not working) draws arcs in style of halfcircle, but each of them is separated and shaded etc... My problem is that I want to put pictures in all of them BUT not the same number of pictures (thats the reason for cycle <- must be right, tested and working with alert!...). In first should be one picture, in second two, in third one ... and finaly in ninth two. But if i try this code, pictures are all drowe on one place and all of them are changing position if this function runs... I dont know what to do with that..
Firstly I wanted to add them to the path (each of paths have link, but thats another function, working properly too), than I tryied to do it separated from that function but nothing worked for me. Important part of code is only not working part, averything else is working perfectly.
Thanks for help.
It looks like you're fooled by the infamous loop variable issue. JavaScript variables live per function, not per block. So, your imagesel / imgpos variables only exist once in fact, which means you only have one image at one location. The variable is overwritten each loop iteration.
You should wrap the appropriate loop code in a function to actually create separate variables. Also, you haven't declared xx / yy anywhere with var.
for(var lg = 0; lg < shape.ic; lg++) {
(function(imgpos) {
var imagesel = new Image();
imagesel.src = '/images/themes/default/capsules/'+imgpos+'.png';
imagesel.onload = function(){
if(imgpos==0){xx=70;yy=320;}
if(imgpos==1){xx=120;yy=260;}
if(imgpos==2){xx=140;yy=320;}
if(imgpos==3){xx=160;yy=320;}
if(imgpos==4){xx=180;yy=320;}
if(imgpos==5){xx=200;yy=320;}
if(imgpos==6){xx=220;yy=320;}
if(imgpos==7){xx=240;yy=320;}
if(imgpos==8){xx=260;yy=320;}
context.drawImage(imagesel, xx, yy);
}
})(imgpos);
if(imgpos != 8){imgpos++;} else {imgpos=0;}
}
i create a race game using spritkit
well i create button if the user click on it then it will pause the game , well my problem is that the Scene stop from moving but the car will stop slowly like the real car , i want to make stop without gravity
this is my code
physicsWorld.gravity = CGVectorMake(0.0,0.3);
physicsWorld.contactDelegate = self
this is player code
playerNode = SKSpriteNode(imageNamed: "car")
playerNode!.position = CGPoint(x: size.width / 2.0, y: 120.0)
playerNode!.physicsBody =
SKPhysicsBody(circleOfRadius: playerNode!.size.width / 2)
playerNode!.physicsBody!.dynamic = true
playerNode!.physicsBody!.linearDamping = 1.0
playerNode!.physicsBody!.allowsRotation = true
playerNode!.physicsBody!.categoryBitMask = CollisionCategoryPlayer
playerNode!.physicsBody!.contactTestBitMask =
CollisionCategoryPowerUpOrbs
playerNode!.physicsBody!.collisionBitMask = 0
foregroundNode!.addChild(playerNode!)
and finally this is the pause function
if (pasueornot){ // true or false
physicsWorld.gravity = CGVectorMake(0.0,gravitySpeed)
}
else{
physicsWorld.gravity = CGVectorMake(0.0,0.0) // the Scene stop from moving but the car will stop slowly like the real car pasueornot
}