tamaño sprites medidas hacer como art java box2d libgdx sprite

java - sprites - pixel art tamaño



Rotar múltiples sprites como uno(alrededor del mismo origen) (2)

Como puede ver en su ejemplo ''correcto'' en el diagrama, la posición de los sprites depende del ángulo del cuerpo, lo cual no está explicando.

b2Vec2 pos = ...; // center of the sprite relative to body (local coords) float ang = ...; // angle of the sprite relative to body (probably zero) //need to rotate image local center by body angle b2Rot rot( body->GetAngle() ); pos = b2Mul(rot, pos) + body->GetPosition(); ang += -body->GetAngle(); sprite.setRotation( ang * RADTODEG ); // RADTODEG = 57.295779513082320876f sprite.setPosition( PTM * pos.x, PTM * -pos.y);

Antes de eso, también he hecho:

sf::FloatRect rect = sprite.getLocalBounds(); sprite.setOrigin( 0.5 * rect.width, 0.5 * rect.height );

Tengo un conjunto de sprites formando T, y quiero racionarlos alrededor del mismo origen, en mi caso, el origen del cuerpo de box2D, así:

mi forma se define en una matriz como esta:

int array[][]= {{0,1,1,1,0}, {0,0,1,0,0}, {0,0,1,0,0}, {0,0,0,0,0}, {0,0,0,0,0}};

así es como creo el cuerpo:

public void setBody(int[][] blocks){ BodyDef def = new BodyDef(); def.type = BodyType.DynamicBody; def.position.set(new Vector2(0 * WORLD_TO_BOX, 0 * WORLD_TO_BOX)); Body body = world.createBody(def); body.setTransform(130*WORLD_TO_BOX, 200*WORLD_TO_BOX, -90*MathUtils.degreesToRadians); for (int x = 0; x < 5; x++) { // HARDCODED 5 for (int y = 0; y < 5; y++) { // HARDCODED 5 if(blocks[x][y] == 1){ PolygonShape poly = new PolygonShape(); Vector2 v = new Vector2((x*size/BOX_TO_WORLD),(y*size/BOX_TO_WORLD)); poly.setAsBox(size/2 * WORLD_TO_BOX, size/2 * WORLD_TO_BOX, v, 0); Sprite sprite = new Sprite(new Texture(Gdx.files.internal("data/block.png"))); sprite.setSize(size, size); sprites.add(sprite); orig.add(v); body.createFixture(poly, 1); poly.dispose(); } } } this.body = body; }

este es mi método de renderizado:

public void draw(SpriteBatch batch){ for (int i = 0;i< this.body.getFixtureList().size;i++) { Vector2 pos = this.body.getFixtureList().get(i).getBody().getPosition(); Sprite sprite = sprites.get(i); sprite.setOrigin(this.body.getWorldCenter().x,this.body.getWorldCenter().y); sprite.setPosition(pos.x*BOX_TO_WORLD+orig.get(i).x*32-16, pos.y*BOX_TO_WORLD+orig.get(i).y*32-16); sprite.setRotation(this.body.getAngle()*MathUtils.radiansToDegrees); sprite.draw(batch); } }


La forma más fácil de hacerlo es crear todos los accesorios, recordando cuál es su posición relativa para el cuerpo. Crea un sprite para cada accesorio y actualízalas usando body-> GetWorldPosition (centro de fijación) cada vez que se actualice la física. Finalmente, la rotación de los sprites es la misma que la rotación del cuerpo (excepto que es el negativo del ángulo).

Por ejemplo, para crear el cuerpo:

void MainScene::CreateBody() { Vec2 position(0,0); // Create the body. b2BodyDef bodyDef; bodyDef.position = position; bodyDef.type = b2_dynamicBody; _body = _world->CreateBody(&bodyDef); assert(_body != NULL); // Now attach fixtures to the body. FixtureDef fixtureDef; PolygonShape polyShape; vector<Vec2> vertices; const float32 VERT_SCALE = .5; fixtureDef.shape = &polyShape; fixtureDef.density = 1.0; fixtureDef.friction = 1.0; fixtureDef.isSensor = false; // Main Box vertices.clear(); vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE)); vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE)); polyShape.Set(&vertices[0],vertices.size()); _body->CreateFixture(&fixtureDef); _fixturePositions.push_back(CalculateAverage(vertices)); // Down one vertices.clear(); vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,-3*VERT_SCALE)); vertices.push_back(Vec2(1*VERT_SCALE,-3*VERT_SCALE)); polyShape.Set(&vertices[0],vertices.size()); _body->CreateFixture(&fixtureDef); _fixturePositions.push_back(CalculateAverage(vertices)); // Up One vertices.clear(); vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE)); vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE)); polyShape.Set(&vertices[0],vertices.size()); _body->CreateFixture(&fixtureDef); _fixturePositions.push_back(CalculateAverage(vertices)); // T Left Top vertices.clear(); vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(-3*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(-3*VERT_SCALE,1*VERT_SCALE)); vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE)); polyShape.Set(&vertices[0],vertices.size()); _body->CreateFixture(&fixtureDef); _fixturePositions.push_back(CalculateAverage(vertices)); // T Right Top vertices.clear(); vertices.push_back(Vec2(3*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE)); vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE)); vertices.push_back(Vec2(3*VERT_SCALE,1*VERT_SCALE)); polyShape.Set(&vertices[0],vertices.size()); _body->CreateFixture(&fixtureDef); _fixturePositions.push_back(CalculateAverage(vertices)); _body->SetAngularVelocity(M_PI/8); }

NOTA La función CalculateAverage (...) solo encuentra el promedio de los vértices. Para cuadrados, será el centro. Podía configurar manualmente los centros, pero no quería hacer una simple operación matemática, así que escribí una función rápida para manejarla.

Luego crea los sprites:

void MainScene::CreateSprites() { Viewport& vp = Viewport::Instance(); for(int idx = 0; idx < _fixturePositions.size(); idx++) { CCSprite* sprite = CCSprite::create("arrow.png"); sprite->setScale(1.0*vp.GetPTMRatio()/128); _fixtureSprites.push_back(sprite); addChild(sprite); } }

Luego actualiza los sprites después de cada actualización física:

void MainScene::UpdateSprites() { for(int idx = 0; idx < _fixturePositions.size(); idx++) { CCPoint spritePosition = Viewport::Instance().Convert(_body->GetWorldPoint(_fixturePositions[idx])); _fixtureSprites[idx]->setPosition(spritePosition); float32 bodyAngle = _body->GetAngle(); bodyAngle = MathUtilities::AdjustAngle(bodyAngle); _fixtureSprites[idx]->setRotation(-CC_RADIANS_TO_DEGREES(bodyAngle)); } }

NOTA La ventana gráfica tiene una función Convert (...) que toma un Vec2 y lo convierte a una posición de píxel en la pantalla. AdjustAngle simplemente pone el ángulo nuevamente dentro del rango de [-pi, pi). Todo el resto debe ser bastante sencillo, pero siéntase libre de preguntar.

He publicado una solución en git hub aquí para Cocos2d-x (C ++). Mira el código en MainScene.cpp.

Y así es como se ve en mi simulador:

(Afortunadamente) Nota final: la implementación aquí utiliza una clase "Viewport" para mapear entre el mundo Box2d (metros) y las coordenadas de pantalla (píxeles). Una consecuencia muy útil de esto es que puede ajustar automáticamente los tamaños de los sprites en función del tamaño que desee que tengan los cuerpos en metros y el tamaño del gráfico en píxeles. Esto es parte de un conjunto más grande de componentes que uso a menudo. Puede encontrar más información sobre ellos en esta publicación .

Fue esto útil?