I want to scale ParticleEffect - Libgdx - libgdx

Basically my problem is simple - I have a ParticleEffect which looks nice on small screen but on my private phone (Samsung S4) it looks very small. My question is: How can I scale the effect?
I have already done something like this:
// Callback method
public void addEffect(Vector2 position, boolean special) {
// Callback Method for the particle effects
PooledEffect effect;
if (!special)
effect = (MathUtils.random(0, 1) == 0) ? yellow_star_pool.obtain()
: green_star_pool.obtain();
else
effect = special_star_pool.obtain();
effect.setPosition(position.x, position.y);
effect.scaleEffect(Values.Scalar_Width*1.3f);
effects.add(effect);
}
But the result is that the effect is scaling exponentially, something I don't want.
I just want the effect to be scaled so that it will look the same on all screens. How can I achieve that?

First, I want to explain why current approach doesn't work. Note that the method you use for scaling is named scaleEffect, not setScale. Every time you call it the effect will be scaled relative to its current state. When you use pooled particle effects you scale the effect as many times as the particle had been reused. That's why you see it scaling exponentially.
So, the solution is to scale only the particle effect that you use as a prototype for the pool. Something like:
prototypeEffect.scaleEffect(Values.Scalar_Width * 1.3f);
ParticleEffectPool yellow_star_pool = new ParticleEffectPool(prototypeEffect, 10, 100);
Then you didn't have to scale every particle effect you obtain.

Related

How do I scale a Libgdx Animation?

I an currently using Libgdx Animation class( com.badlogic.gdx.graphics.g2d.Animation) in a game. However I need the animation to grow in size on certain events. How do I accomplish this?
Animation is used to select the correct frame (TextureRegion) based on the time elapsed. It has nothing to do with how you render that frame. Therefor it is not different as how you render anything else.
You didn't provide enough information for that. But usually you'd render it something like this:
TextureRegion textureRegion = animation.getKeyFrame(time += delta);
spritebatch.draw(textureRegion, x, y, width, height);
So to change the size would be to change the width and height variables. You didn't provide enough information on how you'd like to do that. But you can do that for example using this:
width = 0.8f;
height = 1.9f;

How to render properly Box2DDebugRenderer

I've some problem for render Box2D Debug with Box2DDebugRenderer.
I've 2 OrthographicCamera, one for render the world (named Cam) and one for the HUD (healthBar, Armor, ...) (named hudCam).
I've tried to render :
b2dr.render(world, cam.combined); -> I can't see the Box2D
b2dr.render(world, cam.projection);
b2dr.render(world, hudCam.combined);
b2dr.render(world, hudCam.projection);
b2dr.render(world, new OrthographicCamera().combined); and b2dr.render(world, new OrthographicCamera().projection)
I can't find a way to render the Box2D exactly like cam, to see the edge of all bodies.
If somebody understand my problem, please help me !
Thx.
Unfortunately some tutorial out there suggest to use a meter-to-pixel-conversion when using Box2D. This is not neccessary (at least with Libgdx), as this conversion can be done by using a camera.
The problem in your case is, that you are using a meter-to-pixel-conversion when rendering the Sprites, while the Box2DDebugRenderer renders everything 1:1.
To solve this problem you have to get rid of the meter-to-pixel conversion and use the camera or the viewport to "scale" the things.
THis way, the Box2DDebugRenderer and your SpriteBatch can (and should) use the same camera to render.
For the camera/viewport:
The constructor has the params width and height. Those params are often set as Gdx.graphics.getWidth() and Gdx.graphics.getHeight(), which in my optinion is not right, the game should be resolution-independent.
You should instead select those values depending on how big your player (or any other visible entity) is in real life and how big it should be on screen.
Let's say you have a little characte, like in your game. It is 1m tall in real live and should take 1/13 of the screen height (more or less like in your first picture, where the screen is about 13 times as high as the character).
So your cameras height should be 13, your characters height (also it's Box2Ds Body height) should be 1m. Next you need to define the width. For that i like to think about my desired aspect ratio. Lets assume the game should focus on 16/9 devices, the width is then (13/9)*16=23.
Now your camera should be created like this:
camera = new OrthographicCamera(23, 13);

libGDX - How to clip

I have one SpriteBatch in my game, between whose batch.begin() and batch.end() I draw...
a large static background image
several game sprites
I want to clip the area in which the sprites are seen, which I've read is done using ScissorStack.
The problem is that ScissorStack appears to clip the entire SpriteBatch that's sent to the GPU. The result is that it clips my game sprites and the background image.
Question:
Must I have two separate batch.begin() and batch.end() cycles, one without clipping for the background, and another with clipping for the sprites? Or is there a way of clipping just the sprites without using ScissorStack?
If the former, then isn't it rather expensive flushing the SpriteBatch twice as many times simply in order to clip a few sprites, or is it really nothing to worry about in terms of performance?
Related question:
The calculateScissors() method in the latest source code has more parameters than I've seen documented anywhere...
calculateScissors(camera, viewportX, viewportY, viewportWidth, viewportHeight, batchTransform, area, scissor)
What is the purpose of the viewportX, viewportY, viewportWidth, viewportHeight when they appear to be duplicating the camera's viewport and area information, and are not mentioned in any docs?
Basically, I'm really confused... even after (or especially after!) testing the behaviour of different values for each of these parameters.
Any advice sought.
Instead of using a ScissorStack I resorted to using using glScissor to get the results I needed.
#Override
public void render(float delta) {
GameStage.INSTANCE.act(Gdx.graphics.getDeltaTime());
GameStage.INSTANCE.setViewport(GameGeometry.width, GameGeometry.height,
true);
GameStage.INSTANCE.getCamera().translate(
-GameStage.INSTANCE.getGutterWidth(),
-GameStage.INSTANCE.getGutterHeight(), 0);
Gdx.gl.glScissor(
(int) GameStage.INSTANCE.getGutterWidth() * 2,
(int) GameStage.INSTANCE.getGutterHeight(),
(int) Gdx.graphics.getWidth()
- (int) (GameStage.INSTANCE.getGutterWidth() * 4),
(int) Gdx.graphics.getHeight());
Gdx.gl.glDisable(GL10.GL_SCISSOR_TEST);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glEnable(GL10.GL_SCISSOR_TEST);
GameStage.INSTANCE.draw();
}
Hope this helps.

libGDX zoom implementation isn't working right

I would like to achieve a zoom effect that is similar to "Clash of Clans". I'm currently implementing zoom in a way that pretty much all the tutorials online do. There are of course a my camera specific constants to make it zoom at good speeds for my camera.The code DOES WORK.
#Override
public boolean zoom(float initialDistance, float distance) {
float zoomAmount = -1*(distance - initialDistance)/10000;
cameraHelper.addZoom(zoomAmount);
return true;
}
The camera helper class does this simple stuff:
public void addZoom(float amount) {
setZoom(zoom + amount);
}
public void apply(OrthographicCamera camera) {
camera.zoom = zoom;
camera.update();
}
So this does work. When I fling two fingers in one continuous motion and then stop moving the fingers on the screen, let's say I zoom in with zoomAmount = x, zoom gets called once and the zoom is done.
Problem:
However, if I then wiggle one, or both, of the fingers just a tiny bit, zoom gets called again with that same value for zoomAmount = x. So by wiggling a finger, it will simply keep adding to zoom and keep zooming in or out (depending on the current state of zoomAmount).
Question:
How do I make libgdx or java remember my original camera.zoom much like initialDistance in the zoom() method. OR, is there any other trick that I can do to have a responsive and smooth zoom (without removing fingers from the screen) much like the game "Clash of Clans".
Extra info:
I have tried pinch, same effect. I have thought about having a base zoom value and then some kind of percentage multiplier, however because I have to update the camera by setting its zoom (camera.zoom = zoom;) I can't think of a clever trick with adding or subtracting any values that will not be effected by zoom() being constantly called. Any thoughts anyone?

Rotating a Model in Away3D

Here's what i want to do:
I want to load a model (most likely .3ds) into my .swf and be able to rotate it with the mouse.
This works fine at first glance, but there's problem, the rotations 'switch' over. Or to say it differently:
Imagine we have a model in the shape of a pipe.
If we drag the mouse to the right, the model rotates along its X-Axis to the left, mouse to the left, X-Axis rotation to the right, moving the mouse up, Y-Axis rotation downward, mouse down, Y-Axis rotation upward.
Now, lets say we turn the pipe to the right or left, until we face the (former) 'backside' of the pipe, and then we move the mouse down. The model will rotate downward instead of upward.
I hope you understand what i mean with this. I've been looking around for a good while now and never found a satisfying solution. There was talk about quaternions, but i can't grasp them.
Another suggestion i read somewhere is the following:
create a Matrix3D object, apply rotation on it, then multiply it with the desired Matrix3D of my 3d-Model.
I tried to do it, but the result stays the same, the directions of rotation switches depending on what side i'm facing.
private function update(e:Event):void
{
xCalc = (0.3*(stage.mouseX - lastMouseX));
yCalc = (0.3*(stage.mouseY - lastMouseY));
if(move)
{
var objTransform:Matrix3D = new Matrix3D();
objTransform.prependRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.prependRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = multiply3DMatrices(mesh.transform, objTransform);
}
lastMouseX = stage.mouseX;
lastMouseY = stage.mouseY;
view.render();
}
multiply3DMatrices simply multiplies two 4x4 Matrices together.
objC is the ObjectContainer3D that holds my model. For some reason i cannot rotate it properly, unless i manipulate the rotationX/Y/Z properties.
mesh is the mesh inside of the Model (which is very simple, a single mesh).
Also, i'm aware that i could try another Framework for this (like papervision) but this project requires me to use Away3D.
Solved it by myself, the problem was that i created a new Matrix3D Object every time. The fixed code looks like this:
private function update(e:Event):void
{
...
if(move)
{
var objTransform:Matrix3D = mesh.transform;
objTransform.appendRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.appendRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = objTransform;
}
...
}
And yes, the user bwroga was actually right, i should've used appendRotation instead of prependRotation, as well.