Hey,
I am making Pinball game that utilizes a camera to detect "buttons" that control the flippers. I got the code for the game here. Now, the buttons are actually two pieces of felt fabric, it looks like this. And when one of the pieces are cover by your hand (blocking the view of the camera), the camera will detect that and activate the corresponding flipper. This part works perfectly, and I know this because I get the same problem in the original code.
Now my problem is when the ball hits the bumper, there is a 95% chance of it crashing the game. Sometimes for some reason, the code works and the game goes smoothly but that's a rare occurrence. Also, not of the collisions cause a crash; the wall and flipper collision work great, its just the bumper collision.
This is the Ball code:
class Ball extends Drawable
{
// Box2D body
Body pBody;
float diameter;
Vec2 startPos;
Ball(float diameter, Vec2 position)
{
--ballCount;
this.startPos = position;
this.diameter = diameter;
// Create circle shape
CircleShape shape = new CircleShape();
shape.m_radius = box2d.scalarPixelsToWorld(diameter/2);
// Create circle fixture
FixtureDef fixture = new FixtureDef();
fixture.shape = shape;
fixture.density = 1.0f;
fixture.restitution = 0.5f;
// Define physics body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DYNAMIC;
bodyDef.position.set(box2d.coordPixelsToWorld(position));
// Add body to world
this.pBody = box2d.createBody(bodyDef);
this.pBody.createFixture(fixture);
this.pBody.isBullet();
// set the callback data to this instance
this.pBody.setUserData(this);
}
void render()
{
super.render();
Vec2 ballPos = box2d.getBodyPixelCoord(this.pBody);
float angle = this.pBody.getAngle();
pushMatrix();
translate(ballPos.x, ballPos.y);
rotate(-angle);
ellipse(0, 0, diameter, diameter);
line(0, 0, 0, diameter/2);
popMatrix();
}
void bumpAway(float amount, Vec2 normal)
{
normal.normalize();
Vec2 pushForce = normal.mul(-amount);
this.pBody.applyLinearImpulse(pushForce, this.pBody.getPosition(), true);
}
boolean offScreen()
{
Vec2 ballPos = box2d.getBodyPixelCoord(this.pBody);
return ballPos.y > height;
}
}
And this the Bumper code:
class Bumper extends Drawable
{
// Box2D body
Body pBody;
PShape pShape;
color resetColor;
boolean inThread;
Bumper(Vec2 position, float radius)
{
// Create shape
PolygonShape shape = new PolygonShape();
Vec2[] vertices = new Vec2[8];
float angleStep = PI/4;
for (int i = 0; i < 8; i++)
{
vertices[i] = new Vec2(radius * cos(angleStep*i), radius * sin(angleStep*i));
}
// Create an array to temporarily store the box2D vertex coordinates
Vec2[] box2DVertices = new Vec2[vertices.length];
// Create a new PShape
pShape = createShape();
pShape.beginShape();
// Iterate through every vertex
for (int i = 0; i < vertices.length; i++)
{
float x = vertices[i].x;
float y = vertices[i].y;
// Add the vertex to the shape
pShape.vertex(x, y);
// Add the vertex (converted to box2D coords)
box2DVertices[i] = new Vec2(box2d.scalarPixelsToWorld(x), -box2d.scalarPixelsToWorld(y));
}
// End the PShape
pShape.endShape(CLOSE);
// Set the box2D vertices
shape.set(box2DVertices, box2DVertices.length);
// Define physics body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.STATIC;
bodyDef.position.set(box2d.coordPixelsToWorld(position));
// Add body to world
this.pBody = box2d.createBody(bodyDef);
this.pBody.createFixture(shape, 1);
// set the callback data to this instance
this.pBody.setUserData(this);
}
void render()
{
// Since we're using a PShape we can't just call fill and stroke
pShape.setFill(fillColor);
pShape.setStroke(strokeColor);
Vec2 ballPos = box2d.getBodyPixelCoord(this.pBody);
float angle = this.pBody.getAngle();
pushMatrix();
translate(ballPos.x, ballPos.y);
rotate(-angle);
shape(pShape);
popMatrix();
}
void collide(Ball ball, color ballColor, Vec2 normal)
{
// Physically bump the ball away
ball.bumpAway(100, normal);
// Create a new thread
Thread resetBumper = new Thread()
{
@Override
public void run()
{
// Wait one second and change
// The color back to it's original color
delay(250);
fillColor = resetColor;
inThread = false;
}
};
if (!inThread)
{
inThread = true;
// Store the current color
this.resetColor = fillColor;
// Change the current color
this.fillColor = ballColor;
// Set volume to max
gainValue.setValue(1.0f);
// Reset the scrubber on the sound to start position
dingSound.setToLoopStart();
// Play the ding sound!
dingSound.start();
// Run the new thread
resetBumper.start();
}
// Add to Player Score
playerScore += 10;
}
}
I have also attached the complete game so you can see what I am talking about.