Dynamic resizing of the body (LibGDX) - dynamic

I have a circle-shaped dynamic body and I need to resize it during the game (It appears like a point, then it grows to a circle and after that it starts moving). How should I do that?
I have an idea - it's to use some animation (Circle has the same radius, but due to animation it looks like the circle grows), but I'm not sure if it's right way or not. (Besides I don't know how to realize it)

For scaling circle, if you are using sprite just scale it sprite.setScale(float), if your sprite is attached to Box2d Circle-shape then get the Body's shape and set the radius
Shape shape = body.getFixture().getShape;
shape.setRadius(radiusValue);
and if you are using ShapeRenderer just multiply the points of ShapeRenderer.

I assume that you are talking about a Box2D body.
It is not possible to change a circle-shaped fixture with Box2D. Box2D is a rigid body simulator. What you would have to do is destroy the fixture and replace it with a smaller/bigger version of the circle. But this will cause a lot of problems, since you cannot destroy a fixture when there is still a contact for example.
It would be better to keep the circle the same size and just simulate a change in size with an animation of a texture on top.
If you cannot simulate that, then maybe try the following approach: Have several versions of that circle in different sizes and keep them on top of each other. Implement a ContactFilter which will only cause contacts for the one circle which is currently "active".

Inside any Object class with box2d, I use the following for dynamic resizing:
public void resize(float newradius) {
this.body.destroyFixture(this.fixture);
fixtureDef.density = (float) (this.mass/(Math.PI*newradius*newradius));
this.radius = newradius;
CircleShape circle = new CircleShape();
circle.setRadius(newradius);
this.fixtureDef.shape = circle;
circle.dispose();
this.fixture = body.createFixture(fixtureDef);
this.fixture.setUserData(this);
}
You can also see the following topic: How to change size after it has been created

Related

GTK+3 render rectangle with selection background color

How is it possible to render a rectangle with the background color of selections in GTK+3. I cannot find any API to do that:
static gboolean draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
{
auto state=reinterpret_cast<State*>(data);
auto width = gtk_widget_get_allocated_width (widget);
auto height = gtk_widget_get_allocated_height (widget);
auto context = gtk_widget_get_style_context (widget);
gtk_render_background(context,cr,0,0,width,height);
cairo_rectangle(cr,0,height*(1.0 - state->max),width,height*(state->max - state->min));
cairo_set_source_rgb(cr, 0.05,0.6,0.15); //What color should be used here?
cairo_fill (cr);
cairo_set_source_rgb(cr,0.01,0.3,0.07); //And here
auto mid=height*(1.0 - 0.5*(state->min + state->max));
cairo_move_to(cr,0, mid);
cairo_line_to(cr,width,mid);
cairo_stroke(cr);
return FALSE;
}
Use gtk_render_frame() and gtk_render_background(), and set up the GtkStyleContext you obtain from the GtkWidget instance with the CSS state you want to replicate.
If you want to adhere to the theme, then you cannot draw yourself; and CSS does not have "colors": each CSS state can have multiple layers that include images, gradients, and complex blend modes.
Well, here is my hack:
ColorRGBA get_ambient_color(GtkWidget* widget)
{
auto surface=cairo_image_surface_create(CAIRO_FORMAT_ARGB32,4,4);
auto cr=cairo_create(surface);
while(widge!=NULL)
{
auto context=gtk_widget_get_style_context(widget));
gtk_render_background(context,cr,0,0,1,1);
cairo_surface_flush(surface);
auto content=cairo_image_surface_get_data(surface);
if(content[3]==255)
{
auto ret=ColorRGBA{content[2]/255.0f,content[1]/255.0f,content[0]/255.0f,content[3]/255.0f};
cairo_destroy(cr);
cairo_surface_destroy(surface);
return ret;
}
// Surface is not opaque yet. Continue to parent container.
widget_handle=gtk_widget_get_parent(GTK_WIDGET(widget_handle));
}
cairo_destroy(cr);
cairo_surface_destroy(surface);
return ColorRGBA{1.0f,1.0f,1.0f,1.0f};
}
It seams that I have failed to convince people, why you need the ambient colour, so here are two use-cases:
Determine if we are using a dark/light theme. For some applications, this is sufficient. Querying the state only works if the theme supports dark/light modes. This proves the actual result.
Use as input colour for simulating global illumination. The shading of widgets should be affected by the ambient, hence the name. Another good name would be get_average_background. Themers: please don't use gradients with high contrast.
Case 1: A plot
Now you say that the colour of cursors and function graphs should be themable. That is simply not possible: The user of this plot widget can add as many curves and cursors as he wishes, and the easiest way to differentiate them is to use distinct colours.
What about curve and cursor lightness? If the background is dark, then the curve should be light and vice versa. And what background should be chosen? Ideally, something close the the background of the parent widget, but if the theme is regular, white for light, and black for dark would work. Do you notice that the curves are darker in the second figure?
Case 2: A checkbox that looks like a metallic toggle switch button
With the following technique, I have created a switch that looks exactly as if it were rendered through the Cycles path tracer. This is implemented in Gtk+2, but the algorithm is the same.
The two input images
The code
GtkAllocation alloc;
gtk_widget_get_allocation(widget,&alloc);
auto width=alloc.width;
auto context=CairoContext( gdk_cairo_create(gtk_widget_get_window(widget)) );
auto w_in=cairo_image_surface_get_width(light);
auto h_in=cairo_image_surface_get_height(light);
// Render direct lighting
auto surf_temp=CairoSurface( cairo_image_surface_create(CAIRO_FORMAT_ARGB32,w_in,h_in) );
auto context_temp=CairoContext( cairo_create(surf_temp) );
cairo_set_source_surface(context_temp,light,0,0);
cairo_set_operator(context_temp,CAIRO_OPERATOR_OVER);
cairo_paint(context_temp);
//Render ambient reflections
auto surf_temp_2=CairoSurface( cairo_image_surface_create(CAIRO_FORMAT_ARGB32,w_in,h_in) );
auto context_temp_2=CairoContext( cairo_create(surf_temp_2) );
cairo_set_source_surface(context_temp_2,background,0,0);
cairo_set_operator(context_temp_2,CAIRO_OPERATOR_OVER);
cairo_paint(context_temp_2);
cairo_set_operator(context_temp_2,CAIRO_OPERATOR_MULTIPLY);
//Multiply reflections with the background color
cairo_set_source_rgb(context_temp_2, color_bg.r, color_bg.g, color_bg.b);
cairo_rectangle(context_temp_2, 0, 0, w_in, h_in);
cairo_mask_surface(context_temp_2,surf_temp,0,0);
//Add the results
cairo_set_source_surface(context_temp,surf_temp_2,0,0);
cairo_set_operator(context_temp,CAIRO_OPERATOR_ADD);
cairo_mask_surface(context_temp,surf_temp,0,0);
//Scale and move things into place
auto s=static_cast<double>(width)/static_cast<double>(w_in);
cairo_translate(context,alloc.x,alloc.y);
cairo_scale(context,s,s);
cairo_set_source_surface(context,surf_temp,0,0);
cairo_set_operator(context,CAIRO_OPERATOR_OVER);
cairo_paint(context);
Thoughts
The first example boils down to a light/dark query which is currently missing. Maybe querying colours is not required for this to work, but then there has to be an API controlling the shape and blending mode when rendering the background. For example, to render the ambient reflection, I use multiply rather than over. Also, gtk_render_background appears to be a no-op, since GtkDrawingArea has zero opacity (that's why I needed the loop). To be useful, it must use the background as it appears on screen, not the background of the current widget.

libgdx camera position using viewport

I am rather experiences libgdx developer but I struggle with one issue for some time so I decided to ask here.
I use FillViewport, TiledMap, Scene2d and OrtographicCamera. I want the camera to follow my player instance but there are bounds defined (equal to mapsize). It means that camera will never ever leave outside of map, so when player comes to an end of the map camera stops following and he goes to the edge of the screen itself. Maybe sounds complicated but it's simple and I am sure that you know what I mean, it's used in every game.
I calculated 4 values:
minCameraX = camera.viewportWidth / 2;
minCameraY = camera.viewportHeight / 2;
maxCameraX = mapSize.x camera.viewportWidth / 2;
maxCameraY = mapSize.y - camera.viewportHeight / 2;
I removed not necessary stuff like unit conversion, camera.zoom etc. Then I set the camera position like this:
camera.position.set(Math.min(maxCameraX, Math.max(posX, minCameraX)), Math.min(maxCameraY, Math.max(posY, minCameraY)), 0);
(posX, posY is player position) which is basically setting camera to player position but if it's to high or too low it sets it to max or min defined before in right axis. (I also tries MathUtils.clamp() and it works the same.
Everything is perfect until now. Problem occures when aspect ratio changes. By default I use 1280x768 but my phone has 1280x720. Because of that bottom and top edges of the screen are cut off because of the way how FillViewport works. Because of that part of my map is cut off.
I tried to modify maximums and minimums, calculate differences in ratio and adding them to calculations, changing camera size, different viewports and some other stuff but without success.
Can you guys help?
Thanks
I tried solution of noone and Tenfour04 from comments above. Both are not perfect but I am satisified enough i guess:
noone:
camera.position.x = MathUtils.clamp(camera.position.x, screenWidth/2 + leftGutter, UnitConverter.toBox2dUnits(mapSize.x) - screenWidth/2 + rightGutter);
camera.position.y = MathUtils.clamp(camera.position.y, screenHeight/2 + bottomGutter, UnitConverter.toBox2dUnits(mapSize.y) - screenHeight/2 - topGutter);
It worked however only for small spectrum of resolutions. For strange resolutions where aspect ratio is much different than default one I've seen white stripes after border. It means that whole border was printer and some part of the world outside of border. I don't know why
Tenfour04:
I changed viewport to ExtendViewport. Nothing is cut off but in different aspect ratios I also can see world outside of borders.
Solution for both is to clear screen with same color as the border is and background of level separatly which gave satisfying effect in both cases.
It stil has some limitations. As border is part of the world (tiled blocks) it's ok when it has same color. In case border has different colors, rendering one color outside of borders won't be a solution.
Thanks noone and Tenfour04 and I am still opened for suggestions:)
Here are some screenshots:
https://www.dropbox.com/sh/00h947wkzo73zxa/AAADHehAF4WI8aJ8bu4YzB9Va?dl=0
Why don't you use FitViewport instead of FullViewport? That way it won't cut off your screen, right?
It is a little bit late, but I have a solution for you without compromises!
Here width and height are world size in pixels. I use this code with FillViewport and everything works excellent!
float playerX = player.getBody().getPosition().x*PPM;
float playerY = player.getBody().getPosition().y*PPM;
float visibleW = viewport.getWorldWidth()/2 + (float)viewport.getScreenX()/(float)viewport.getScreenWidth()*viewport.getWorldWidth();//half of world visible
float visibleH = viewport.getWorldHeight()/2 + (float)viewport.getScreenY()/(float)viewport.getScreenHeight()*viewport.getWorldHeight();
float cameraPosx=0;
float cameraPosy=0;
if(playerX<visibleW){
cameraPosx = visibleW;
}
else if(playerX>width-visibleW){
cameraPosx = width-visibleW;
}
else{
cameraPosx = playerX;
}
if(playerY<visibleH){
cameraPosy = visibleH;
}
else if(playerY>height-visibleH){
cameraPosy = height-visibleH;
}
else{
cameraPosy = playerY;
}
camera.position.set(cameraPosx,cameraPosy,0);
camera.update();

change CAMetalLayer background color

My CAMetalLayer background color is black, even if i'm assigning new color as the backgroundColor property.
Am i missing something? Thanks!
Link to the original project :
https://github.com/audiokit/MetalParticles
This project takes a rather unconventional approach to clearing the drawable's texture each frame: it replaces the textures contents with an array of zeros that is the same size as the texture (width * height * 4). Subsequently, it encodes some compute work that actually draws the particles. This is almost certainly not the most efficient way to achieve this effect, but if you want to make the smallest change that could possibly work (as opposed to experimenting with making the code as efficient as possible), Just fill the blankBitmapRawData array with your desired clear color (near line 82 of ParticleLab.swift).
I have gone through your code and can not see a place where you are setting background Color.
The metal layer is added as a sublayer to it, so you have to set it explicitly.
Add this line at the end of your init method in ParticialLab class and see if it works.
self.backgroundColor = UIColor.redColor().CGColor
I found that self.isOpaque = false was needed on the layer.

How to zoom a pdf to the mouse position in javafx 2

I have to zoom a pdf-file thats inside of a ScrollPane.
The ScrollPane itself is inside of a StackPane.
In the beginning I scale my pdf to fit the width of my ScrollPane. As a result of that the pdf-height doesn't fit the ScrollPanes height.
I already managed to zoom, by changing my scaleFactor when using the mousewheel. Unfortunately I can't zoom into a specific point.
I guess I have to change the ScrollPanes values depending on the mouse coordinates, but I just can't find the correct calculation. Can somebody please help me?
For example I tried
scrollPane.setVvalue(e.getY() / scrollPane.getHeight())
With this line of code my view just jumps up or down, depending on whether I click on the upper bound or the lower bound of my viewport.
I also understand that it has to behave like that, but I can't figure it out what has to be added/changed.
I use Jpedal to display my pdf
Hope you understand what I am looking for.
Tell me if you need more information.
Edit:
Here is a snipped of how I managed to drag.
eventRegion.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
dragStartX = e.getX();
dragStartY = e.getY();
});
eventRegion.addEventFilter(MouseEvent.MOUSE_DRAGGED, e -> {
double deltaX = dragStartX - e.getX();
double deltaY = dragStartY - e.getY();
scrollPane.setHvalue(Math.min(scrollPane.getHvalue() + deltaX / scrollPane.getWidth(), scrollPane.getHmax()));
scrollPane.setVvalue(Math.min(scrollPane.getVvalue() + deltaY / scrollPane.getHeight(), scrollPane.getVmax()));
e.consume();
});
I think zooming to the mouse position could be done in a similar way, by just setting the Hvalue and Vvalue.
Any ideas how I can calculate these values?
This example has JavaFX 8 code for a zoomable, pannable ScrollPane with zoom to mouse pointer, reset zoom and fit to width of a rectangle which can really be any Node. Be sure to check out the answer to the question to get fitWidth() to work correctly. I am using this solution for an ImageView now, and it is slick.
just for all related questions about "zooming where the mouse is".
I had the same problem and I came up with the following code snippet.
public void setZoom(final double x, final double y, final double factor) {
// save the point before scaling
final Point2D sceneToLocalPointBefore = this.sceneToLocal(x, y);
// do scale
this.setScaleX(factor);
this.setScaleY(factor);
// save the point after scaling
final Point2D sceneToLocalPointAfter = this.sceneToLocal(x, y);
// calculate the difference of before and after the scale
final Point2D diffMousePoint = sceneToLocalPointBefore.subtract(sceneToLocalPointAfter);
// translate the pane in order to point where the mouse is
this.setTranslateX(this.getTranslateX() - diffMousePoint.getX() * this.getScaleX());
this.setTranslateY(this.getTranslateY() - diffMousePoint.getY() * this.getScaleY());
}
The basic idea is to move the underlying Pane to that point where it was before scaling. Important is the fact, that we calculate the mouse position to the local coordinate system of the Pane. After scale we do this just another time and calculate the difference. Once we know the difference we are able to move back the Pane. I think this solution is very easy and straightforward.
My setup in JavaFX is following: I have a javafx.scene.layout.BorderPane as root for my javafx.scene.Scene. In the center I put a Pane. This will be the Pane where I act on (i.e. put other Nodes in..zoom, move..etc.) If anyone is interested in how I actually did it, just mail me.
Good programming!

looping a sprite vertically objective C sprite builder

Note: for this I am using a program called spritebuilder, which allows me to create a game with less code than would normally be needed. If you know a solution that's just all code, then by all means feel free to share it :)
Also, for this question, I followed a tutorial at this link: Build Your Own Flappy Bird Clone. Just scroll down to the part that says: "Loop the Ground"
So here's my problem. Im currently working on a game, and I created a camera which scrolls vertically long with the character sprite i created, however i need a certain image to loop. When the image leaves the bottom part of the screen I would like it to loop around to the top of the screen, infinitely. For this i created two identical images (in this case its the bark of a tree). One will be on screen, while the other will be offscreen, so as the first image leaves the screen, the second will replace it (seamlessly). I created two objects for the images, and assigned them the name _ground1, and _ground2, and I also created an NSArray in which to store them in. (Please refer to the link above if it is somewhat confusing)
Here is the code that I have:
CCNode *_ground1;
CCNode *_ground2;
NSArray *_grounds;
for (CCNode *ground in _grounds) {
// get the world position of the ground
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.y <(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
For some reason when I try this, it doesnt seem to work. what happens is that, the camera will travel vertically as it is meant to do, but the images do not loop. Once the two images leave the bottom of the screen, no new images replace them.
i also done this project as above tutorials. it work fine but you have some mistake to set variable in spritebuilder. in your above code replce code as and try it. you only put less than may be it issue.
if (groundScreenPosition.y <=(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
You are using CCNode objects as _ground1and _ground2.
CCNode objects usually do not have a contentSize, they will return 0 unless you explicitly set them inSpriteBuilder`.
Make sure that you are using CCSprite objects in SpriteBuilder and in your code.
Also, as a friendly hint you should also consider refactoring (renaming) your sprites with more meaningful names for your use case like _treeBark1 and treeBark2 for example.