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();
I've recently been looking into LibGDX and seem to have hit a wall, seen in the picture, the blue dot represents the users finger, the map generation it self is where i seem to get stuck, does LibGDX provide a method of dynamically drawing curved objects? I could simply generate them myself as images but then the image is hugely stretched to the point of the gap for the finger can fit 3! But also would need to be 1000's of PX tall to accommodate the whole level design.
Is it such that i should be drawing hundreds of polygons close together to make a curved line?
On a side not i'll need a way of determining when the object has from bottom to top so i can generate another 'chunk' of map.
You don't need hundreds of polygons to make a curve like you drew. You could get away with 40 quads on the left, and 40 on the right, and it would look pretty smooth. Raise that to 100 on each side and it will look almost perfectly smooth, and no modern device is going to have any trouble running that at 60fps.
You could use the Mesh class to generate a procedural mesh for each side. You can make the mesh stay in one spot, locked to the camera, and modify it's vertices and UVs to make it look like you are panning down an infinitely long corridor. This will take a fair amount of math up front but should be smooth sailing once you have that down.
Basically, your level design could be based on some kind of equation that takes Y offset as an input. Or it could be a long array of offsets, and you could use a spline equation or linear equation to interpolate between them. The output would be the UV and X coordinates which can be used to update each of the vertices of your two meshes.
You can use the vertex shader to efficiently update the UV coordinates, using a constant offset uniform parameter that you update each frame. That way you don't have to move UV data to the GPU every frame.
For the vertex positions, use your Mesh's underlying float[] and call setVertices() each frame to update it. Info here.
Actually, it might look better if you leave the UV's and the X positions alone, and just scroll the Y positions up. Keep a couple quads of padding off top and bottom of screen, and just move the top quad to the bottom after it scrolls off screen.
How about creating a set of curved forms that can be put together variably. Like the gap in the middle will at the top and bottom of each image be in the middle (with the same curvature at end and beginning points)...
And inbetween the start and end points you can go crazy on the shape.
And finally, you can randomly put those images together and get an endless world.
If you don't want to stop in the middle each time, you could also have like three entry and exit points (left, middle, right)... and after an image that ends left, you of course need to add an image that starts left, but might end somewhere else...
At the moment I have a simple animation where a car (JPanel) approaches a junction where after it waits for traffic lights to turn green and continues straight on. However I'm going to the next step now where I want the car to turn 90 deg right in a smooth curve to turn onto the perpendicular road. I have sketched roughly how it looks and the curve represent the way I want the car to turn:
I'm not too sure how to do this. I suppose I would need to represent some sort of bezier curve? Or matrix transformation to rotate the car?
Can someone give advice on the best way to do this in Swing.
If you are new to graphics in Java, I recommend this tutorial. If I were to code what you are doing, I see two options.
First and easiest, you can model turning as "first driving straight, then turning 90º along the edge of a circle centred on the corner I am turning around, and then driving straight again". The easiest way to do this is to define a JPanel that draws your Image (yes, a JPanel; if you don't paint their background, you can layer JPanels on top of each other - and they will be painted in the correct order; make the background JPanel opaque so that it cleans up before drawing the next frame), and give it an AffineTransform that makes the image display in the position you want it to. You will need to adjust the increments in the transform so that the speed appears constant; trial and error, or a bit of geometry (90º of radius R implies R*pi/2.0 total travel along the curved path) , will help you out there.
The hard way is to consider the car's route to be an arbitrary Shape (which you can define using Bezier curves, for example), extract a flattened PathIterator from it, advance in equally-spaced jumps along that iterator, and calculate the rotation you need from the position along the curve and the heading at any given point (you can estimate the heading by taking 2 successive samples, and aligning the car according to these samples). This is harder than using the above method, but allows your car to follow arbitrarily complex paths.
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.
So I'm building the pacman game in Java to teach myself game programming.
I have the basic game window with the pacman sprite and the ghost sprites drawn, the pacman moves with the arrow keys, doesn't move beyond the walls of the window, etc. Now I'm trying to build the maze, as in this picture:
Without giving me the direct/complete solution to this, can someone guide me as to how this can be built? I'm talking only about the boundaries and the pipes('T' marks) here which you can't go through and you have to go around. Not the dots which the pacman eats yet.
Here are my questions:
1) What's the most efficient algorithm/method for creating this maze? Will it have to be drawn each time the paint() method is called or is there a way to draw it only at the start of the game and never again?
2) How will this actually be drawn to the screen? I assume the fillRect() will be used?
3) Any hints on collision detection (so the pacman/ghosts can't go through the walls) would be helpful.
4) Any hints on how the vacant space between the pipes will be calculated so the dots can be filled between them will also be very helpful.
Thanks
I wouldn't do it that way.
I'd draw the graphical map and then create a 2D data array which represents the map. The data map would be responsible for determining collisions, eating dots, where candy is and where the ghosts are. Once all the logic for everything is handled just use the 2D array to display everything in their proper pixel coordinates over the graphical map.
For example the user is pressing the left key. First you determine that pacman is at element 3, 3. Element 3, 2 contains information denoting a wall so you can implement the code to make him ignore the command.
EDIT:
Each element would represent about where a dot could be. For example:
No, looking at the board I would say the array would look something like this.
d,d,d,d,d,d,d,d,d,d,d,d,w,w,d,d,d,d,d,d,d,d,d,d,d,d
d,w,w,w,w,d,w,w,w,w,w,d,w,w,d,w,w,w,w,w,d,w,w,w,w,d
p,w,w,w,w,d,w,w,w,w,w,d,w,w,d,w,w,w,w,w,d,w,w,w,w,p
d,w,w,w,w,d,w,w,w,w,w,d,w,w,d,w,w,w,w,w,d,w,w,w,w,d
d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d
And so on. You might want to pick a more flexible data structure than just characters however since some areas need to contain a bunch of different information. IE even though the ghost spawning area is blank, pacman isn't allowed in there. The movement of the ghosts and pacman is different for the side escapes, the candy spawn point is a blank spot but if you want to remain flexible you'll want to denote where this is on a per map basis.
Another thing you'll want to remember is that pacman and the ghosts are often inbetween points so containing information that represents a percentage of a space they're taking up between 1,2 and 1,3 is important for collision detection as well as determining when you want to remove dots, powerups and candy from the board.
You can paint the map into a BufferedImage and just drawImage that on every paint(). You'll get quite reasonable performance this way.
If you are happy with the walls being solid, you can draw each square wall block with fillRect. If you wish to get the same look as in the picture, you need to figure how to draw the lines in the right way and use arcs for corners.
The Pacman game map is made of squares and Pacman and the ghosts always move from one square to the neighbouring square in an animated step (i.e. you press right, the pacman moves one square to the right). That means that collision detection is easy: simply don't allow moves to squares that are not empty.
I do not understand what you are trying to ask here.
1) Just to give my advice on redrawing. Something that you can do if you find redrawing the entire image is slow, is determine only the elements that have changed on the screen and redraw those. An approach for this would be the following: Determine the sprites that have moved. Determine (approximate) a rectangle around those sprites. Redraw those rectangles only. This way you are only refreshing parts of the screen and not the whole screen. This should result in an increase in performance over redrawing the entire screen.
The other answers have been reasonable for the other questions you have asked.