Scale and transform in LibGDX - libgdx

I have to do something like this in my Android App with LibGDX:
The ball is a Image that has a drag listener and added to a Stage:
ballImage.addListener(new DragListener() {
public void drag(InputEvent event, float x, float y, int pointer) {
ballImage.moveBy(x - ballImage.getWidth() / 2, y - ballImage.getHeight() / 2);
}
});
which works great. But I have a problem with scaling the ball. I can't scale the ball and maintain it's position and drag stop working normally (ball jump outside screen just on touch). I tried something like this:
massSlider.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
float x = ballImage.getX() - ballImage.getWidth() / 2;
float y = ballImage.getY() - ballImage.getHeight() / 2;
ballImage.moveBy(x, y);
ballImage.setScale(massSlider.getValue());
ballImage.moveBy(-x, -y);
}
});
Also, I was trying to use scaleBy()/setScale() and moveBy()/setPosition(), or to not move the ball at all before and after scaling, but nothing seems to work. What I do wrong?

Scaling is usually something that you want to (and easily can) avoid. It is nice to use scaling e.g. for actions to create a short pop out or pop in effect. But apart from that it's usually much better to adjust the size instead. So instead of using setScale(a) you do: setSize(a * unscaledWidth, a * unscaledHeight). Note that you will have to keep track of the unscaled width and height for this.

Related

glow effect with ShapeRenderer (libgdx)

I read about glow/particle effecta with sprites, which are working well.
Is there a simple way to create the similar blur effect with simple shaperender functionality like circles ?
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.end();
shapeRenderer.begin(ShapeRenderer.ShapeType.Point);
shapeRenderer.setAutoShapeType(true);
drawCircle();
shapeRenderer.end();
batch.begin();
}
private void drawCircle() {
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
// apply effect ??
shapeRenderer.circle(10,10,2);
}
You can't use textures with default ShapeRender.
There are several way to do this but the easiest is to use ShapeDrawer library. It adds some "ShapeRenderer like" capabilities to a SpriteBatch and more. see https://github.com/earlygrey/shapedrawer
Yes, you could create a "glow" effect, this could be achieved by drawing using decreasing alpha values past the boundaries.
Firstly, to define the glow-effect parameters, let's determine the maximum boundary of the glowing object, where the glow ends, as being auraSize for the size of the aura.
Next, we need to know the size of the solid portion of the object, the bit that doesn't glow, and let's call this objSize for the size of the object.
To draw this, we can use a simple for loop and some if statements:
private void drawCircle() {
shapeRenderer.set(ShapeRenderer.ShapeType.Filled);
//Draw circles upto the size of aura
for(int radius = 0; radius < auraSize; radius++) {
/*
* Checks if radius fits object size, sets colour to solid white if so
* Interpolates alpha value to 0 based on distance to aura covered by radius otherwise
*/
if(radius <= objSize) {
shapeRenderer.setColor(Color.WHITE);
} else {
shapeRenderer.setColor(new Color(1, 1, 1,
MathUtils.lerp(1, 0, (radius - objSize) / (auraSize / objSize))));
}
//Draws the circle at the current radius
shapeRenderer.circle(10, 10, radius);
}
}

Game takes up only the top right corner of the screen in LIBGDX

I am working on LIBGDX . My game takes up only the top right corner of the screen rather taking up the entire width and height.
In my update method of the screen, I have this code,
public void update(float dt) {
......
gamecam.position.x = this.gamehero.heroBody.getPosition().x; -- 1
gamecam.position.y = this.gamehero.heroBody.getPosition().y; -- 2
......
}
But, when I remove the second line of the code the game takes up the entire screen but the camera doesn't follow the player on y axis . I have attached the screen shot of the game when I include the second line of the code,
And, when I remove the second line of code, It takes up the entire screen
I don't know how to resolve it. Any suggestions would be better. Thanks
Create your camera with this:
gamecam = new OrthographicCamera(SCREEN_WIDTH, SCREEN_HEIGHT);
gamecam.position.set(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0);
Update camera gamecam.update() after each position editing.
public void update(float dt) {
gamecam.position.x = this.gamehero.heroBody.getPosition().x; // -- 1
gamecam.position.y = this.gamehero.heroBody.getPosition().y; // -- 2
gamecam.update(); // -- 3
}
Kolesnikovich is on the right track with the top of his code. But unfortunately positions the camera exactly like you in the end.
What you are actually doing is setting the centered position of the cam. So all you need to do is increment the camera's position coordinates by half the viewport width and height.
public void update(float dt) {
gamecam.position.x = this.gamehero.heroBody.getPosition().x +
gamecam.getViewportWidth / 2;
gamecam.position.y = this.gamehero.heroBody.getPosition().y +
gamecam.getViewportHeight / 2;
gamecam.update(); // -- 3
}

In libgdx, correct placement of ShapeRenderer begin and end

My question is whether I should place sRenderer.begin(ShapeType.Filled); and sRenderer.end(); outside of Shape? so they're not called for every Shape.draw()
Or is the approach below ok in terms of performance?
Snippet from one of my Shapes ..
private Body body; // initialized elsewhere
private float width = 1.0f;
private float height = 1.0f;
public void draw(ShapeRenderer sRenderer) {
sRenderer.begin(ShapeType.Filled);
sRenderer.setColor(1.0f, 0.0f, 0.0f, 1.0f);
sRenderer.identity();
sRenderer.translate(getBody().getPosition().x, getBody().getPosition().y, 0);
sRenderer.rotate(0.0f, 0.0f, 1.0f, (float) Math.toDegrees(getBody().getAngle()));
sRenderer.rect(-getWidth(), -getHeight(), getWidth() * 2, getHeight() * 2);
sRenderer.end();
}
In my Level class, theres a draw() method called every frame e.g
for (Body body : bodies) {
if (body.getUserData() instanceof Shape){
((Shape) body.getUserData()).draw(getShapeRenderer());
}
}
Each time you call begin(),identity(), translate(), rotate(), or etc., it will trigger a new flush to the GPU the next time you draw something with the shape renderer. So in your case, moving begin() and end() out of the loop won't have a very significant impact.
If this is a bottle neck, you could try calculating your rectangle corners independently from the shape renderer and submitting four lines to the shape renderer, using world space coordinates instead of local coordinates like you're doing now. Then move begin() and end() out of the loop like you suggested and benchmark the difference. I'm not sure which would be faster in your case. This would reduce draw calls but you'd be translating more points on the CPU as well.

How to create sprite from RenderTexture cocos2d-x v3.2?

I'm trying to make a game that will take what users draw on their screens and create a sprite with a physics body. I looked around and I saw a tutorial that demonstrated this. Unfortunately the tutorial was made in Cocos2d-x v2.
http://build-failed.blogspot.com/2012/08/freehand-drawing-with-cocos2d-x-and.html
That is the tutorial that I am referring to.
http://www.cocos2d-x.org/wiki/Render_To_Texture
I tried to use that cocos2d-x tutorial to help me, but it has been labeled outdated (I tried it anyway and it didn't work). Is it still possible to allow the user to draw through this method? Or do I need to find another method to allow the user to draw the sprites? Any suggestions would be helpful. Thanks.
void GameScene::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event)
{
Point start = touch->getLocation();
start = Director::getInstance()->convertToGL(start);
Point end = touch->getPreviousLocation();
end = Director::getInstance()->convertToGL(end);
target->begin();
float distance = start.getDistance(end);
for (int i = 0; i < distance; i++)
{
float difx = end.x - start.x;
float dify = end.y - start.y;
float delta = (float) i / distance;
brush->setPosition(Point(start.x + (difx * delta), start.y + (dify * delta)));
brush->visit();
}
target->end();
}
void GameScene::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event)
{
myObjectSprite = Sprite::createWithTexture(target->getSprite()->getTexture());
myObjectSprite->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
this->addChild(myObjectSprite);
}
This is what I gathered from those links. I can draw but there are a few problems.
The first attempt to draw always reflects horizontally over the center of the screen.
After a few drawings the fps begins to drop, and the app begins to take up a lot of memory and CPU usage.
The for loop in the onTouchMoved method is used because the onTouchEnded method isn't called fast enough, so there is often a large gap between each point that the onTouchMethod obtains. The loop is used to draw the brush sprites in a line between each point to prevent the gaps. However, for some reason it is not drawing in between the gaps.
Additionally, in the first link the person uses b2PolygonShape and b2FixtureDef from box2d. What are the new names of the classes in cocos2d-x v3?

Camera movement in AS3

OK so i have a character that moves with the mouse. I need it to stay in the center of the screen(kind of like a platformer game). I can't figure out how to access the camera and move it. (Note: I have tried Vcam and moving all of the other objects but Vcam makes the file slow or something [or so i have heard] and moving the other objects in kind of like cheating [and for my needs is insufficient]) I don't have any code because i don't know where to start. Maybe someone can point me into the right direction.
Thanks,
Thor
One way is to store everyhting in one DisplayObject and then move that single object based on the camera movement. Instead of moving the camera, move the main container the opposite direction of the camera. I'm not sure why you seem to suggest a strategy like this is "cheating" as it is a perfectly suitable way to doing this.
This is my previous answer on a similar question found here.
What I do here is:
Create a Map class with a property camera which is another custom class MapCamera.
The MapCamera has five properties:
_x
_y
map - a reference to the instance of Map owning this MapCamera
offsetX
offsetY
The offset values represent the x and y spacing from the left and top edges of the screen, which should be set to half of the stage width and height so that the camera will centre on the stage correctly.
The _x and _y properties are private, and have getters and setters.
The getters are pretty basic:
public function get x():Number{ return _x; }
public function get y():Number{ return _y; }
The setters are where the viewport will be altered, like so:
public function set x(n:Number):void
{
_x = n;
map.x = -(_x + offsetX);
}
public function set y(n:Number):void
{
_y = n;
map.y = -(_y + offsetY);
}
From here, you add your children into the Map container and then can simply go:
map.camera.x = player.x;
map.camera.y = player.y;
Which will cause the player to always be in the centre of the screen.
Your camera is only a vector that modifies position of all renderable objects.
myMovieClip.x = movingClipPosition.x + camera.x
So if the camera.x is moved to the right, this will make the object move the left, giving the impression of a "camera".