In libgdx, correct placement of ShapeRenderer begin and end - libgdx

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.

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);
}
}

Scale and transform in 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.

How I can calculate the endpoint of a line, if I have the starting point, the angle and length of the line?

Point 1, say it is (0, 0) and I have another point that should turn around at a distance of 10f. Then I'll adding degrees angle to make it rotate. I be wanting to know how to calculate that point that this turning around each other ..
I will use the raycasting, I need to rotate the ray (clockwise) to detect collisions
So you say you have point1 and point2, both separated by a distance of 10f where point2 will be rotating around point1, and you want to know if between this separation an object at some point is intersecting them, something like the following image:
There are tutorials to get the maths for rotate a point arount another one in internet, like this one, and since you can't specify an origin for a Vector2, a translated version of the code proposed in the previews link to java should be something similar to:
public Vector2 rotatePoint(Vector2 center, Vector2 point, float angle) {
angle = angle * MathUtils.degreesToRadians; // Convert to radians
float rotatedX = MathUtils.cos(angle) * (point.x - center.x)
- MathUtils.sin(angle) * (point.y - center.y) + center.x;
float rotatedY = MathUtils.sin(angle) * (point.x - center.x)
+ MathUtils.cos(angle) * (point.y - center.y) + center.y;
// rotated new position:
return new Vector2(rotatedX, rotatedY);
}
As for the rest of the code (the intersection between objects), I guess you are looking for the RayCastCallback interface:
// initial position
Vector2 point1 = new Vector(0, 0);
// Max lenght of view
Vector2 point2 = new Vector(0, 10);
// Position of collision if occur
final Vector2 collisionPoint = new Vector();
#Override
public void render(float delta) {
//...
point2 = rotatePoint(point1, point2, 10); // rotate 10ยบ
// to detect if object at position point1 is seeing something
world.rayCast(new RayCastCallback(){
#Override
public float reportRayFixture(Fixture fixture, Vector2 point,
Vector2 normal, float fraction) {
// what do the object saw? -> fixture
// where do the object saw it? -> point
collisionPoint.set(point);
return 0; // <- return 0 to stop raycasting
}
}, point1, point2);
//... rotation and other stuffs...
}
The return parameter of reportRayFixture have this documentation:
Called for each fixture found in the query. You control how the ray cast proceeds by returning a float: return -1: ignore this fixture and continue return 0: terminate the ray cast return fraction: clip the ray to this point return 1: don't clip the ray and continue. The Vector2 instances passed to the callback will be reused for future calls so make a copy of them!
** Emphasis added.
Basically it says that you can check for all the intersections one by one, but if you care only for the first one, return 0 immediately. This is useful when you want to know if an object is being blocked by another one. In this case, I return 0 and copy the value of point to collisionPoint to let you do whatever you want to do with this value.
A very nice example can be found in this video.
Hope you find this useful.
You should consider using Intersector class to check if the line from your actor intersects with the body shape.
To calculate end of "sight" line use Vector2 that you will be rotating according to your actor rotation (which is actually answer for your question)
It should looks like:
Vector2 sightVector = new Vector2(10f, 0); //the 10f is actually your sight max distance
sightVector.rotate(actor.getRotation());
...
#Override
pblic void render(float delta) //it can be also act of the actor
{
sightVector.rotate(actor.getRotation());
Vector2 endOfLine = new Vector2(actor.getX() + sightVector.x, actor.getY() + sightVector.y); //here you are calculating the end of line
Polygon bodyShape = getBodyShape( theBody ); //you should create a method that will return your body shape
if( Intersector.intersectLinePolygon(new Vector2(actor.getX(), actor.getY()), endOfLine, bodyShape) )
{
//do something
}
...
}
Intersector has method to check intersection with circles etc also so your body Shape doesn't need to be polygon

How to tween alpha of a BitmapFontCache in libgdx?

I am animating some text in my libgdx application and would like a label text to fade-in and move (e.g. similar to this jsfiddle).
I can move, and change alpha of other objects (e.g. Sprites) and can move BitmapFontCaches. However I can't get alpha of the BitmapFontChage to change.
Declaration:
message = new BitmapFontCache(messageFont, true);
message.setWrappedText("some text", 10.0f, 10.0f, 10.0f);
message.setAlphas(0.0f);
In my screen class, I override the render method, and call .draw() on a renderer class, which is (among other things) essentially just a message.draw(batch); call.
#Override
public void render(float delta) {
...
try{
batch.begin();
feedbackRenderer.draw(batch);
tweenManager.update(delta);}
finally{
batch.end();
}
}
Then as a part of a timeline I call these two Tweens. (yes, they are wrapped in .push( ) and I do start my tweenManager:)
Tween.to(message, BitmapFontCacheAccessor.POSITION_X, animationDuration)
.target(35.0f)
Tween.to(message, BitmapFontCacheAccessor.ALPHA, animationDuration)
.target(1.0f)
The BitmapFontCacheAccessor tries to setAlphas() of the BitmapFontCache as such:
public class BitmapFontCacheAccessor implements TweenAccessor<BitmapFontCache> {
public static final int POSITION_X = 1;
public static final int ALPHA = 2;
#Override
public void setValues(BitmapFontCache target, int tweenType, float[] newValues) {
switch (tweenType) {
case POSITION_X:
float y = target.getY();
target.setPosition(newValues[0], y);
break;
case ALPHA:
target.setAlphas(newValues[0]);
break;}
}...
It moves the label (==> .setPosition(x, y) works!), but does not even touch the alpha. This exact same approach works for Sprites, which fade in nicely.
Is there perhaps some catch when tweening alpha for the BitmapFontCache? Is it possible?
Many thanks!
After a good hour of debugging I have found the reason for this funny behavior.
Libgdx's BitmapFontCache does not have a getAlphas() method
Therefore, to get the alpha channel I used getColor().a
However, these two are not always synced. The behavior is quite random, I myself am not quite sure when it syncs and when it doesn't (f.ex. in the question above, the fade-outs would work, but fade-ins wouldn't)
The solution is to change and declare BOTH alpha channels.
Definition of BitmapFontCache:
message = new BitmapFontCache(messageFont, true);
message.setColor(1,1,1,0);
message.setAlphas(0);
and inside TweenAccessor:
case ALPHA:
//first alpha channel
target.setAlphas(newValues[0]);
//second alpha channel
Color c = target.getColor();
c.a = newValues[0];
target.setColor(c);
break;
To you, hopeless SO wanderer, I address this answer so that you can spend some of the finite number of minutes of your life better than I did.

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?