I have a bunch of values and appropriate colours:
0 Black
20 Dark Grey
50 Light Grey
100 White
I want to create a LinearGradientPaint to demonstrate that gradient. I can easily calculate the fractions but the LinearGradientPaint also requires a starting X, Y and ending X, Y coordinates.
Is there a way I can apply the linear gradient paint to an arbitrarily sized rectangle without knowing the rectangle's size at the point at which the paint is created?
No, there is not a way to do this.
You will have to create this object at the time that you paint the rectangle. If you want to save object creation, my suggestion would be to cache this object when you create it, along with the starting and ending points used to create it. If the rectangle is still in the same place the next time you paint it, you can use the same paint object. Otherwise, you will need to create a new one at the new location.
Related
I'm creating a game with LibGDX using JAVA and I've hit a problem I can't solve even after a week's worth of trying. I have shapes being drawn with the ShapeRenderer class, and I have multiple classes and methods interacting with each other. A shape grows on the screen and when the user clicks the screen, the shape stops growing and the second shape begins to grow.
I have an array of ShapeRenderer's and Polygon's and I must draw each shape with a different ShapeRenderer and different Polygon. For example a triangle must be rendered using ShapeRenderer[1] and Polygon[1]. The next triangle on that level must be drawn with ShapeRenderer[2] and Polygon[2]. This is to avoid clashing values and rotations when drawing Polygons on the same ShapeRenderer.
My particular problem is one method I created, "DrawStar" is given a number (starts with 1 representing the first star) and draws that star using ShapeRenderer[1] and Polygon[1]. This means the first star is being drawn then when I click the screen, IDEALLY, the first star should stop growing and the second star should begin to be rendered with ShapeRenderer[2] and Polygon[2].
Here's the problem: Let's say this particular level has been written so that 2 stars are going to grow. The method "DrawStar" will be given the number "1" and draw the first star as it grows, then the method "DrawStar" is given the number "2" and it draws the second star (this isn't visually a problem yet since the star's polygon starts with values of 0 and doesn't increase until the second click so even if it is being drawn it's not visible) and it continues to draw the two stars simultaneously, it basically draws all the stars for that level one after the other i.e. DrawShape(1) then DrawShape(2) then DrawShape(1) then DrawShape(2) etc.
This is my code:
public void drawFiveStar(FiveStar star, int num) {
shapeRenderer[num].begin(ShapeType.Line);
shapeRenderer[num].setColor(Color.RED);
poly[num].setVertices(star.verticiesStar);
poly[num].rotate(1);
poly[num].setOrigin(star.originX, star.originY);
shapeRenderer[num].polygon(poly[num].getTransformedVertices());
shapeRenderer[num].end();
}
Star represents the star object passed through and num represents the shape number to draw, as explained in the above example with ShapeRenderer[1] and Polygon[1]. The problem is it will DrawFiveStar(Star1, 1), DrawFiveStar(Star1, 2), DrawFiveStar(Star1, 1), DrawFiveStar(Star1, 2).... UNTIL I click the mouse button and it moves onto the next star object DrawFiveStar(Star2, 1), DrawFiveStar(Star2, 2), DrawFiveStar(Star2, 1), DrawFiveStar(Star2, 2)....
The problem with the code above is that the whole point of using a ShapeRenderer array is so that for the second shape, a new, fresh ShapeRenderer is used. This code has it so that the first star object will use both ShapeRenderers and by the time I click to prompt the second star object to grow, both ShapeRenderers have been used to draw the first star object. Ideally it should be only the first ShapeRenderer used to draw the first star object and then when the second object begins to grow that is drawn with the second ShapeRenderer. I tried many solutions none of which produced the desired results of the ideal solution I just described.
It's a programming problem that I can't figure out because the code needs to be dynamic so that if it were 3 or 100 shapes the code would still use a different ShapeRenderer for each star object. Again, this is because drawing multiple shapes on one ShapeRenderer object and rotating them leads to really strange results with shapes flying everywhere, drawing multiple rotating shapes on separate ShapeRenderer objects solves this problem. That is what I'm trying to achieve here.
Read Level > See there are 2 shapes to be drawn > Use 2 shape renderers to draw these 2 shapes
It's kind of unclear what your issue is, but I'm guessing that you are conflating two different ideas into the num variable that is passed in, so it's not doing what you want.
Is num the shape renderer index you want to use, or is it the shape instance you want to draw? If these are distinct, you need to pass two different int values to your method, and use them appropriately.
That said, if you think you need more than one ShapeRenderer, you must be using it incorrectly. It is a very flexible class and should have no problems with drawing multiple types of shapes in the desired locations. Figure out what you're doing wrong and fix it, so you will only need one. A ShapeRenderer is kind of a heavy object. Each instance has a large backing array, has a mesh stored on the GPU, and loads a ShaderProgram. You definitely do not want to load 100 identical shaders to draw 100 shapes.
If using a single ShapeRenderer creates problems, maybe you are changing the transformation matrix, for example by using translations and rotations? In this case you need to save the original matrix first and restore it after the transformations.
Example
shapeRenderer.begin(ShapeType.Filled);
for(Shape shape: shapes)
{
Matrix4 tf = shapeRenderer.getTransformMatrix().cpy();
shapeRenderer.translate([...]);
shapeRenderer.rotate([...];
// ... create your shape ...
shapeRenderer.setTransformMatrix(tf);
}
shapeRenderer.end();
im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.
Let's say I have many small bitmaps and I draw a big circle around them but not necessary all bitmaps are inside of the circle (like some can be half way in or have their edges stick out) and I want to run on every single pixel of the bitmaps in the circle (meaning pixels that are outside of the circle wont be counted, only the parts that are inside), how do I go about doing that, I know how to run on every pixel of all the bitmap, but not in a specific shape..
You need to create an imaginary grid, or rather a grid that is only useful in that it will help you solve the problem at hand. This is the grid that you will assign all the bitmaps to a position on, imagining that the circle's center is to be located at (0,0).
You then use a little math
to find if a pixel as it is relative to its bitmap's position on the grid, is within the radius of the circle.
Of course the distance formuala is
Or if you rather it is the sqrt( a^2 + b^2 ). where 'a' is the difference in x and 'b' is the difference in y between 2 points.
I need to draw some graphics objects on a JPanel in a JApplet, they are Graphics2D objects.
Here is some visual help
1) I would like to draw circles near the boundaries of the panel at random coordinates so that every time the applet is started it looks different.
I would like in some way to say that exclude this part, don't draw there - blue circle in image.
2) Would be nice if I could evenly distribute them so that if there are 4 circles, then the distance between the circles is almost the same, but still random to some amount.
3) If the first 3 or 4 circles are drawn then draw the other smaller and random sized circles are drawn all over the panel that isn't used.
It seems like a strange idea but would it be possible to make an algorithm that gives you the centre coordinates based on some constraints like
(x-100)^2 + (y-100)^2 >200 && 0< x <400 && 0< y < 400
Now I do it like this:
divide the whole area into a grid where every slot in the gird is free or taken and inside that slot draw the circles at random coordinates, but still within that slot.
That idea doesn't look so good and I would like to do it better.
I'm implementing this in java but general ideas are also welcome.
If you have only circles, the "not overlapping" test is easy: Two circles are not overlapping if and only if the distance of there centers is bigger than the sum of their radiuses (for equality they are touching). For overlapping the border: the distance from the border must be bigger than the radius.
So, you could simply go on and generate random coordinates (either with fixed or random radiuses), then check if any are overlapping. If yes, either start again, or throw away only the overlapping ones and go on.
If you have not too many circles, this simple algorithm is enough. If it starts taking too long, you might think about using some spatial data structure, so you will only have to check the circles near to your new point.
You may want to create the list of circles to paint not inside of the paintComponent method, but instead in the init() or start() method (or some thread called from there), so the painting will not take too long, and the circles will not change for every (maybe even partial) repaint.
So I've got an assignment that takes two inputs, males and females, and outputs matingPairs, the product of the two.
In addition to that, the instructions ask to draw a shape using one of those variables.
I've decided to draw circles for each value.
I first draw matingPairs, followed by the smaller male and female circles on top of the original, larger matingPairs circle.
The problem I'm running in to is obviously representing the graphic in the applet. If the numbers go higher than say 100, the graphic becomes too large for the applet.
I'm looking for a way to basically have the matingPairs circle always fill the applet, then have males and females dynamically adjust so their size is scaled relative to the matingPairs circle size. I'm using JApplet.
Thank you very much for any guidance. I'm really looking for a solution, rather a push in the right direction.
May be you should provide more instruction about how are you drawing the circles in the Graphics object.
The idea is to manage two bi-dimensional spaces with different scales; the first one is the input data and the second one represents the available area to draw such data. The first one can have data on any location, such (5, 5), (0.2, 0.3)or (1200, 3400). The key is to map the original coordinates of the first space into the second, using the proper transformation: scale + translation.
This transformation must be calculated prior to start drawing and applies to any point drawn.
The idea is to map the rectangle where input data resides to the available area in the graphics. If the graphics area is 200x200 pixels and the data could be from (0, 0) to (400, 400), just divide by 2 the coordinates of the points to draw. If the original data is not centered in (0, 0), use a translation.
So, do you need to know how to get the size of the applets canvas or how to scale the male/female circles accordingly?
Edit:
Drawing a circle to fill the 600x600 area should be easy. Just keep in mind that you often specify the top left corner of the circle and the width and height (i.e. the diameter) when calling drawOval() / fillOval() or similar methods.
The next question is: what does represent the size of the input (males/females) and output (pairs), the area or the radius of the circles? Whatever it is, it should be easy to calculate the input/output ratio and then multiply the fixed size of the output circle with it in order to get the size of the input circle.