I have a body with a polygonshape created using .setasbox but when I run my game the box is a bit bigger than my sprite.
I know setasbox uses half height and half width, I used my scaling constant to convert meters to pixels and I know the sprite has the origin of the axis on the bottom left as well. Despite of that I still have a box with a width a bit larger than the sprite and this gap is the same however I change the size of the box...
This is the code I use to create my box (160 is the constant to scale meters to pixels):
public Block(World w, float halfWidth, float halfHeight, Vector2 position, Texture tex){
world = w;
bodyd = new BodyDef();
bodyd.type = BodyDef.BodyType.KinematicBody;
bodyd.gravityScale = 0;
shape = new PolygonShape();
shape.setAsBox(halfWidth, halfHeight);
fixtured = new FixtureDef();
fixtured.shape = shape;
fixtured.density = DENS;
fixtured.friction = FRIC;
fixtured.restitution = REST;
bodyd.position.set(new Vector2(position.x, position.y));
body = world.createBody(bodyd);
fixture = body.createFixture(fixtured);
body.setUserData(this);
texture = tex;
sprite = new Sprite(texture);
sprite.setSize(halfWidth * 2 * 160, halfHeight*2*160);
sprite.setPosition((body.getPosition().x - halfWidth) * 160, (body.getPosition().y - halfHeight) * 160);
}
can you try using Box2DSprite? its very easy..
https://bitbucket.org/dermetfan/libgdx-utils/wiki/net.dermetfan.gdx.graphics.g2d.Box2DSprite
http://www.java-gaming.org/index.php?topic=29843.0
I don't see anything wrong with your code
did you consider that the size that you put for your sprite is the size of the full sprite not the size of the block inside your sprite
I think this is why your brick sprite is smaller than your brick physic :
unless the your brick has the full size of the sprite then may be the problem is related to something else
hope that was helpful !
Related
I have two bitmaps that I draw onto the center of a canvas:
One is only a background, it's a spirit level in top view which doesnt move. The second one is a bitmap looking like a "air bubble". When the user tilts the phone, the sensors read the tilt and the air bubble moves according to the sensor values along the x-axis. However, I need to make sure that the air bubble doesnt move too far, e.g out of the background-bitmap.
So I tried to which x coordinate the bubble can travel to,
before I have to set xPos = xPos -1 using trial and error
This works fine on my device.
To clarify: On my phone, the air bubble could move to the coordinate x = 50 from the middle of the screen. This would be the point, where the bitmap is at the very left of the background spirit level.
On a larger phone, the position x = 50 is too far left, and therefore looking like the air bubble travelled out of the water level.
Now I've tried following:
I calculated the area in % in which the air bubble can move. Let's say that
is 70% of the entire width of the bitmap. So I tried to calculate the two x boundary values:
leftBoundary = XmiddlePoint - (backgroundBitmap.getWidth() * 0.35);
rightBoundary = XmiddlePoint + (backgroundBitmap.getWidth() * 0.35);
...which doesnt work when testing with different screen sizes :(
Is it possible to compensate for different screen sizes and densities using absolute coordinates or do I have to rethink my idea?
If you need any information that I forgot about, please let me know. If this question has already been answered, I would appreciate a link :) Thanks in advance!
Edit:
I load my bitmaps like this:
private Bitmap backgroundBitmap;
private static final int BITMAP_WIDTH = 1898;
private static final int BITMAP_HEIGHT = 438;
public class SimulationView extends View implements SensorEventListener{
public SimulationView(Context context){
Bitmap map = BitmapFactory.decodeResource(getResources, R.mipmap.backgroundImage);
backgroundBitmap = Bitmap.createScaledBitmap(map, BITMAP_WIDTH, BITMAP_HEIGHT, true;
}
and draw it like this:
protected void onDraw(Canvas canvas){
canvas.drawBitmap(backgroundBitmap, XmiddlePoint - BITMAP_WIDTH / 2, YmiddlePont - BITMAP_HEIGHT / 2, null);
}
backgroundBitmap.getWidth() and getHeight() prints out the correct sizes.
Calculating like mentioned above would return following boundaries:
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
//which prints out width = 2392
xMiddlePoint = width / 2;
// = 1196
leftBoundary = xMiddlePoint - (BITMAP.getWidth()* 0.35);
// = 531,7
However, when I use trial and error, the right x coordinate seems to be at around 700.
I've come across a great explanation on how to fix my issue here.
As user AgentKnopf explained, you have to scale coordinates or bitmaps like this:
X = (targetScreenWidth / defaultScreenWidth) * defaultXCoordinate
Y = (targetScreenHeight / defaultScreenHeight) * defaultYCoordinate
which, in my case, translates to:
int defaultScreenWidth = 1920;
int defaultXCoordinate = 333;
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
displayWidth = displayMetrics.widthPixels;
leftBoundary = (displayWidth / defaultScreenWidth) * defaultXCoordinates
I want to randomly generate sprites on circumference of circle , but even after research of several hours , I couldn't come up with any solution.
That's what I can made till now
I've used this formula for it :
Sprite * pin = Sprite::create("pin.png");
pin->setPosition(Vec2((_circle->getContentSize().width/2)*(0.7/3), _circle->getContentSize().height*0.7));
Sprite * pin2 = Sprite::create("pin.png");
pin2->setPosition(Vec2((_circle->getContentSize().width/2)*(0.6/3), _circle->getContentSize().height*0.6));
Sprite * pin3 = Sprite::create("pin.png");
pin3->setPosition(Vec2((_circle->getContentSize().width/2)*(0.8/3), _circle->getContentSize().height*0.8));
Sprite * pin4 = Sprite::create("pin.png");
pin4->setPosition(Vec2((_circle->getContentSize().width/2)*(0.9/3), _circle->getContentSize().height*0.9));
Sprite * pin5 = Sprite::create("pin.png");
pin5->setPosition(Vec2((_circle->getContentSize().width/2)*(1/3), _circle->getContentSize().height));
_circle->addChild(pin);
_circle->addChild(pin2);
_circle->addChild(pin3);
_circle->addChild(pin4);
_circle->addChild(pin5);
But I want something like that(with correct angle which I couldn't do in sample image)
Please suggest some precise solution for it. Thanks for your time!
Basic trig stuff -- sin and cos are your friends.
Example:
const float circle_x = ...;
const float circle_y = ...;
const float circle_radius = ...;
const float angle = ...;
const float x = cos(angle)*circle_radius + circle_x;
const float y = sin(angle)*circle_radius + circle_y;
// Draw stuff at (x, y).
First, it's "circumference" not "circumstance" (that will help with your searches)
Second, you are using the size of the image, not the circle inside the image.
Third, you will need to use basic trigonometry for the solution. Determining points on a circle require the use of sin and cos functions. After you find the center of the circle and it's radius, these should be easy to calculate with just a little bit of research.
one more problem facing that getContentSize() return zero width and height.
i have created circle using Drawnode and than get its content size but return zero.
My working code is
where rad=100;
DrawNode *drawnode = DrawNode::create();
for ( int i = 0 ; i <100; i ++)
{
float rads = i * M_1_PI; // radians
Circle [i] .x = rad * cosf (rads); //vertex x
Circle [i] .y = rad * sinf (rads); //vertex y
}
drawnode->setPosition(Director::sharedDirector()->getVisibleSize().width/2,Director::sharedDirector()->getVisibleSize().height/2);
drawnode->drawPolygon(Circle,100,Color4F(0,0,0,0),1,Color4F(1,122,153,1));
CCSprite *spr = CCSprite::create(image);
spr->setPosition(ccp(drawnode->getContentSize().width/2,0));
drawnode->addChild(spr);
CCLog("Draw node width : %f",this->getContentSize().width);
float p = (100/spr->getContentSize().width)+0.5;
spr->setAnchorPoint(ccp(0,p));
auto rotate = RotateBy::create(3,360);
spr->runAction(CCRepeatForever::create(rotate));
this->addChild(drawnode);
please give me solution for better work.
Thanks in advance
Rishabh Shah
Since your node is a container here, therefore your have to calculate content size explicitly. Only Node (Sprite) having texture returns the actual content size otherwise you will get a CCPointZero.
You have to calculate content on the basis on bounding box of DrawNode and you can easily calculate using circle radius, here is a sample.
drawNode->setContentSize(CCSizeMake(2*Radius, 2*Radius))
I am using LibGDX and Box2d to build my first Android game. Yay!
But I am having some serious problems with Box2d.
I have a simple stage with a rectangular Box2d body at the bottom representing the ground, and two other rectangular Box2d bodies both at the left and right representing the walls.
A Screenshot
Another Screenshot
I also have a box. This box can be touched and it moves using applyLinearImpulse, like if it was kicked. It is a DynamicBody.
What happens is that in my draw() code of the Box object, the Box2d body of the Box object is giving me a wrong value for the X axis. The value for the Y axis is fine.
Those blue "dots" on the screenshots are small textures that I printed on the box edges that body.getPosition() give me. Note how in one screenshot the dots are aligned with the actual DebugRenderer rectangle and in the other they are not.
This is what is happening: when the box moves, the alignment is lost in the movement.
The collision between the box, the ground and the walls occur precisely considering the area that the DebugRenderer renders. But body.getPosition() and fixture.testPoint() considers that area inside those blue dots.
So, somehow, Box2d is "maintaining" these two areas for the same body.
I thought that this could be some kind of "loss of precision" between my conversions of pixels and meters (I am scaling by 100 times) but the Y axis uses the same technique and it's fine.
So, I thought that I might be missing something.
Edit 1
I am converting from Box coordinates to World coordinates. If you see the blue debug sprites in the screenshots, they form the box almost perfectly.
public static final float WORLD_TO_BOX = 0.01f;
public static final float BOX_TO_WORLD = 100f;
The box render code:
public void draw(Batch batch, float alpha) {
x = (body.getPosition().x - width/2) * TheBox.BOX_TO_WORLD;
y = (body.getPosition().y - height/2) * TheBox.BOX_TO_WORLD;
float xend = (body.getPosition().x + width/2) * TheBox.BOX_TO_WORLD;
float yend = (body.getPosition().y + height/2) * TheBox.BOX_TO_WORLD;
batch.draw(texture, x, y);
batch.draw(texture, x, yend);
batch.draw(texture, xend, yend);
batch.draw(texture, xend, y);
}
Edit 2
I am starting to suspect the camera. I got the DebugRenderer and a scene2d Stage. Here is the code:
My screen resolution (Nexus 5, and it's portrait):
public static final int SCREEN_WIDTH = 1080;
public static final int SCREEN_HEIGHT = 1920;
At the startup:
// ...
stage = new Stage(SCREEN_WIDTH, SCREEN_HEIGHT, true);
camera = new OrthographicCamera();
camera.setToOrtho(false, SCREEN_WIDTH, SCREEN_HEIGHT);
debugMatrix = camera.combined.cpy();
debugMatrix.scale(BOX_TO_WORLD, BOX_TO_WORLD, 1.0f);
debugRenderer = new Box2DDebugRenderer();
// ...
Now, the render() code:
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
world.step(1/45f, 6, 6);
world.clearForces();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
debugRenderer.render(world, debugMatrix);
}
Looks like the answer to that one was fairly simple:
stage.setCamera(camera);
I was not setting the OrthographicCamera to the stage, so the stage was using some kind of default camera that wasn't aligned with my stuff.
It had nothing to do with Box2d in the end. Box2d was returning healthy values, but theses values were corresponding to wrong places in my screen because of the wrong stage resolution.
I am trying to create simple tennis game. Each side has a wall. There are also a box and a ball. My environment doesn't have gravity. The box and the ball don't have any velocity. When the box contacts the ball(I move this by mouse with different speed), it(the ball) just changes its position and doesn't continue moving and sometimes these objects don't collide with each other:
I want the box can strike the ball using different angle and strength.
How can I do this? What should I change in the properties of the ball and the box?
The code snippet is below:
public void createBall(Vector2 position, Vector2 velocity, float angle, Object userData){
// First we create a body definition
BodyDef bodyDef = new BodyDef();
// We set our body to dynamic, for something like ground which doesnt move we would set it to StaticBody
bodyDef.type = BodyType.DynamicBody;
// Set our body's starting position in the world
bodyDef.position.set(position);
// Create our body in the world using our body definition
Body body = world.createBody(bodyDef);
body.setUserData(userData);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(10f);
PolygonShape poly = new PolygonShape();
poly.setAsBox(12, 12);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.2f;
fixtureDef.restitution = 1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = body.createFixture(fixtureDef);
f.setUserData("ball");
circle.dispose();
}
private Body createBox(World world, float width, float height, float density) {
BodyDef def = new BodyDef();
def.type = BodyType.KinematicBody;
Body box = world.createBody(def);
PolygonShape poly = new PolygonShape();
poly.setAsBox(width/2, height/2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = poly;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = box.createFixture(fixtureDef);
f.setUserData("platform");
poly.dispose();
return box;
}
public void createWall(World world, Vector2 position, float hx, float hy){
// Create our body definition
BodyDef groundBodyDef =new BodyDef();
// Set its world position
groundBodyDef.position.set(position);
groundBodyDef.type=BodyType.StaticBody;
// Create a body from the defintion and add it to the world
Body groundBody = world.createBody(groundBodyDef);
// Create a polygon shape
PolygonShape groundBox = new PolygonShape();
// Set the polygon shape as a box which is twice the size of our view port and 20 high
// (setAsBox takes half-width and half-height as arguments)
groundBox.setAsBox(hx, hy);
// Create a fixture from our polygon shape and add it to our ground body
groundBody.createFixture(groundBox, 0.0f);
// Clean up after ourselves
groundBox.dispose();
}
You are moving your box by changing its position. But an important part of collision resolution is velocity. And your box's velocity is always zero (from box2d look point). Thus you experience strange collision resolution
I think your screen width and height are too large... if that's the case try using world width and height ... 20x12 units.. not 800x480 something .
Box2D doesn't like bodies, which fixtures has density 0. Usual, simulation performs somehow, but behaviour is not correct. Try value 0.3 for example.
Overlap problem may be solved by setting flag b2BodyDef::bullet. There description from Box2D reference:
bool b2BodyDef::bullet
Is this a fast moving body that should be prevented from tunneling through other moving bodies? Note that all bodies are prevented from tunneling through kinematic and static bodies. This setting is only considered on dynamic bodies.
Warning:
You should use this flag sparingly since it increases processing time.