I am attempting to create a very simple top-down game in Java, but I am unsure how to approach a problem dealing with program performance.
I used a 2D array to store certain values that represent certain things, such as the surrounding environment and the player's position. I then used the paint() method to draw a grid to the screen based on a section of the 2D array. The player is always in the center of the grid. I have it coded such that the player never truly "moves", but rather the environment around him "moves" (if you press a key to move up, a new section of the array is drawn that is the same as the past section except it has a new row at the top and the bottom-most row is now the past section's second-to-bottom row, all the while the player stays in the center, if that makes sense).
Thus, we have a situation where the whole screen needs to be redrawn each time the player moves. As you might have gathered, this is bad for the program's performance, since it has to iterate through a 2D array and draw it the screen each time I call repaint(). If the user hits the key to move upwards twice in succession, the program will lag and the screen will flicker as it redraws the whole section of the array.
How can I improve the performance issue, given that I want to keep the player in the center of the screen at all times and have the environment move around him? Should I instead investigate Jscrollpanes? Is iterating through arrays in the paint() method not the way to go?
Thank you so much for both your time and also helping an inexperienced programmer.
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'm trying to make a building game (~Age Of Empire :). So, I want to write a program that divides a JFrame (containing the map of my game) to squares. Then allows every square of the frame to be modified (to contain an image). For example, I want to put an image in square (1,1), then add an image in square (4,2) and keep the image that I had in square (1,1).
How can this be done?
To do this inside the JFrame just use a GridLayout, create a control to match a square on the map (for now you could just use a JLabel or JButton) and add them to the screen.
I can't really recommend using Swing for developing a game though, you'd be better off looking into one of the many 2D (or 3D) for that matter game engines out there. They will allow you to get much more impressive results and do some of the work for you.
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.