I have written a particle system applet; currently I am creating, and drawing each particle separately.
(Here is the code)
BufferedImage backbuffer;
Graphics2D g2d;
public void init(){
backbuffer = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
setSize(WIDTH, HEIGHT);
//creates the particles
for (int i = 0; i < AMOUNTPARTICLES; i++) {
prtl[i] = new particleO();
prtl[i].setX(rand.nextInt(STARTX));
prtl[i].setY(rand.nextInt(STARTY));
prtl[i].setVel(rand.nextInt(MAXSPEED)+1);
prtl[i].setFAngle(Math.toRadians(rand.nextInt(ANGLESPREAD)));
}
//other code
}
public void update(Graphics g) {
g2d.setTransform(identity);
//set background
g2d.setPaint(BGCOLOUR);
g2d.fillRect(0,0,getSize().width,getSize().height);
drawp();
paint(g);
}
public void drawp() {
for (int n = 0; n < AMOUNTPARTICLES; n++) {
if (prtl[n].getAlive()==true){
g2d.setTransform(identity);
g2d.translate(prtl[n].getX(), prtl[n].getY());
g2d.setColor(prtl[n].getColor());
g2d.fill(prtl[n].getShape());
}
}
}
It's performance was alright, I could get ~40FPS with 20,000 particles (although, I have a decent laptop). But after I added collision detection (see below), that number plummeted to less than 2000,
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
public boolean hasCollided(int prt1, int prt2){
double dx = prtl[prt1].getX() - prtl[prt2].getX();
double dy = prtl[prt1].getY() - prtl[prt2].getY();
int edges = prtl[prt1].getRadius() + prtl[prt2].getRadius();
double distance = Math.sqrt( (dx*dx) + (dy*dy) );
return (distance <= edges);
}
I have searched quite a bit for a better way of drawing the particles to the screen, but the examples either confused me, or were not applicable.
I am doing a boat load of calculations (too many). But I couldn’t think of another way of doing it, suggestions are welcome.
First of all, adding in something like collision detection always takes a lot of memory. However, let's look at your collision detection algorithm
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
Let's pretend there was only 2 particles, 1 and 2. You will check, in order
1,1
1,2
2,1
2,2
The truth is, you only really needed to check 1 vs 2 in this case. If 1 hits 2, 2 will also hit 1. So change your for loop skip previously tested, and the same number for that matter.
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = i+1; j < AMOUNTPARTICLES; j++) {
Another thing I notice is that you do a sqrt operation, but only to compare to what looks like a static number. If you remove that, and compare it to the number squared, you'll get a large improvement, especially with something you do so much.
double distance_squared = ( (dx*dx) + (dy*dy) );
return (distance <= edges*edges);
Keep looking for improvements like this. Then you might carefully look at other options, like using a different class, threading, etc, which all might improve the system. But make sure you optimize the code where you can first. Here is a list of other things that I would try, roughly in order.
Check to see if particle i is alive before you even calculate anything else after i comes into view.
Do a quick pass over the pairs, only even bothering to check in detail if they are close. A simple way would be to detect if they are within the x and y dimensions first, before taking a sqrt operation. Always do the cheapest test first, before doing complex ones.
Look at your code, to see if you really use all of the values calculated, or if you might be able to reduce the number of operations somehow.
Perhaps you could cluster the images on a regular basis with a broad stroke, then refine only objects which passed the initial cluster for a period of time, then do a broad cluster algorithm.
You could thread the collision detection. However, if you are going to do this, you should only thread the checking to see if something has collided, and after all of those threads are done, update the objects on the view.
Look into alternative architectures, which might speed things up some.
Painting is a complex process and paint requests can be triggered for any number of reasons, the OS might want the window to update, the repaint manager might want to repaint, the programer might want to repaint.
Updating the particles within the paint process is bad idea. What you want to do is update the particles in a separate thread on a separate buffer. When you're ready, request that the component responsible for painting the buffer perform a repaint, passing a new copy of the buffer to repainted (you don't want to be painting on the buffer that is begin updated to the screen, you'll end up with dirty paints).
It's hard to tell from you code, but it would appear you're using java.awt.Applet, personally, I'd upgrade to javax.swing.JApplet.
I'd move the painting to a java.swing.JPanel. Swing components provide double buffering (as well as other buffering strategies). The only job this panel has is to paint a buffer to the screen when the particles engine has a new frame.
The particles engine is responsible for updating all the particles and painting these results to a backing buffer (BufferedImage), this would then be handed to the panel and the panel would make a copy and schedule an update.
Swing is NOT THREAD SAFE. That is, you shouldn't make changes to the UI from any thread other then the Event Dispatching Thread. To this end, you might like to have a read through Concurrency in Swing for solutions to resync the off screen buffer to the client.
You are checking all particless colliding with all particlesand this is quite a requeriment, of the order of n^2 (2,000 particles means 4,000,000 combinations, for each frame).
The issue is not java but the algorithm. There must be better options, but to begin with you could reduce the comparations; if you have a maximum speed S and the time in your world increments by T, with T*S you get the maximum distance D of a particle that can collide with the particle you are considering. Reduce the search to those particle which are at a distance equal or less than that. Maybe it will be easier to restrict the search to those in an square centered in your particle an with height/widht D (this will include some particles that are too far, but will make the checks easier).
Additionally, in your code you are checking collisions of P1 vs P2 and P2 vs P1 which is the same, that is a redundance that you can avoid easily.
Related
Good evening everyone.
I've been messing a bit with isometric tile worlds and I have a few doubts about rendering the elements on it.
When I build a single height map I render it first and then add the diferent elements on top, and the displacement of the last seem right.
public void render(Graphics2D g2d) {
for(int i = 0; i < tileGrid.length; i++) {
Point isop = NeoMath.getInstance().cartToIso(i % yAmmount, i / yAmmount, GlobalDataStorage.tileWidth, GlobalDataStorage.tileHeight);
TileManager.getInstance().getTileByID(tileGrid[i]).render(g2d, isop.x, isop.y);
}
for(Entity entity : entityList) {
entity.render(g2d);
}
}
(The position of the entity is calculated inside it's update).
With this I have no problems as everything is rendered on the same height, the problem comes when I try to add other floors to it.
Let's say that I want it to have three heights. I have a list of list of tiles instead of the single array, and render every element on them:
public void render(Graphics2D g2d) {
int flag = 0;
for(int i = 0; i < tileGrid.size(); i++) {
Point isop = NeoMath.getInstance().cartToIso(i % yAmmount, i / yAmmount, GlobalDataStorage.tileWidth, GlobalDataStorage.tileHeight);
for(int k = 0; k < tileGrid.get(i).size(); k++) {
TileManager.getInstance().getTileByID(tileGrid.get(i).get(k)).render(g2d, isop.x, isop.y - (GlobalDataStorage.tileZ * k));
}
while(flag < currentList.size() &&
currentList.get(flag).getPosition().equals(new Point(i % yAmmount, i /
yAmmount))) {
currentList.get(flag).render(g2d);
flag++;
}
}
}
Where the currentList is the list of entities.
With this I have the problem that, when the entities move to a new position, they get overlaped by the tiles, as these are rendered after the entity, and the position of the entity does not change until it reached the destiny. I could change the position to the new one before rendering, but that implies that in the other axis the previous tile get rendered after the entity, making it disapear for a second due to the overlap.
This also mess when I try to draw selection rectangle as it get stuck behind the tiles being rendered. I don't want them to overlap the whole map so can't draw them after all the rendering has been done either.
Does someone know of another approach that I can try out?
Thank you beforehand.
Draw your entire floor layer in a first pass. Then in the second pass draw all walls and objects and moving entities.
I could change the position to the new one before rendering,
David Brevik, programmer on Diablo, mentions using this option in his GDC talk Diablo: A Classic Games Postmortem. It was his first "What Went Wrong" example!
Reference: https://www.youtube.com/watch?v=VscdPA6sUkc&t=20m17s
Turns out this is a classic hurdle in isometric games.
I have made a map on an image which I load in the game like this:
List<Block> tempBlocks = new ArrayList<Block>();
BufferedImage level = levels.get(currentLevel);
for (int x = 0; x < level.getWidth(); x++) {
for (int y = 0; y < level.getHeight(); y++) {
tempBlocks.add(new Block(x, y, new Color(level.getRGB(x, y))));
}
}
blocks = tempBlocks;
isLoading = false;
The array blocks is an array with all 1-pixel-blocks. Every single block renders like this:
g.setColor(color);
g.drawLine(x, y, x, y);
I call them like this:
for (int i = 0; i < getCurrentScene().blocks.size(); i++)
getCurrentScene().blocks.get(i).render(g);
It's 1280x720 blocks... Is it a better way to render this insane amount of blocks? Because I want it to load from an image, which is 1280x720. I get like 3 FPS now...
For what you're doing now, if you do that for every frame, you're creating new objects all over the place for every single frame, and only using them once before discarding and allowing the garbage collector to pick them up.
Create enough objects to represent how the screen is now.
Create enough objects to represent how the screen should be next.
Don't lose those. Don't create any more.
For the Color(int int int) thing you're doing? You can just do Color(int); new color(level.getRGB(x, y)) should work just fine; the java.awt.Color class can take a single int instead of three.
That said, you'd still be initializing Color a million times. If you have a limited number of Colors, it may be beneficial to call them directly or cache them in some way, instead of continually recreating new Color objects on the heap.
Shepard solved it in the comments. What I did was to render the image as g.drawImage(image, x, y); instead of rendering all of the pixels. I still use the blocks for collision detection, but that is way more efficient.
I am making a game that has campfire objects. What I want to do is to brighten all pixels in a circle around each campfire. However, looping through every pixel and changing those within the radius is not all that efficient and makes the game run at ~7 fps. Ideas on how to either make this process efficient or simulate light differently?
I haven't written the code for the fires but this is the basic loop to check each pixel/change its brightness based on a number:
public static BufferedImage updateLightLevels(BufferedImage img, float light)
{
BufferedImage brightnessBuffer = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
brightnessBuffer.getGraphics().drawImage(img, 0, 0, null);
for(int i = 0; i < brightnessBuffer.getWidth(); i++)
{
for(int a = 0; a < brightnessBuffer.getHeight(); a++)
{
//get the color at the pixel
int rgb = brightnessBuffer.getRGB(i, a);
//check to see if it is transparent
int alpha = (rgb >> 24) & 0x000000FF;
if(alpha != 0)
{
//make a new color
Color rgbColor = new Color(rgb);
//turn it into an hsb color
float[] hsbCol = Color.RGBtoHSB(rgbColor.getRed(), rgbColor.getGreen(), rgbColor.getBlue(), null);
//lower it by the certain amount
//if the pixel is already darker then push it all the way to black
if(hsbCol[2] <= light)
hsbCol[2] -= (hsbCol[2]) - .01f;
else
hsbCol[2] -= light;
//turn the hsb color into a rgb color
int rgbNew = Color.HSBtoRGB(hsbCol[0], hsbCol[1], hsbCol[2]);
//set the pixel to the new color
brightnessBuffer.setRGB(i, a, rgbNew);
}
}
}
return brightnessBuffer;
}
I apologize if my code is not clean, I'm self taught.
I can give you lots of approaches.
You're currently rendering on the CPU, and you're checking every single pixel. That's hardcore brute force, and brute force isn't what the CPU is best at. It works, but as you've seen, the performance is abysmal.
I'd point you in two directions that would massively improve your performance:
Method 1 - Culling. Does every single pixel really need to have its lighting calculated? If you could instead calculate a general "ambient light", then you could paint most of the pixels in that ambient light, and then only calculate the really proper lighting for pixels closest to lights; so lights throw a "spot" effect which fades into the ambient. That way you're only ever performing checks on a few of the pixels of the screen at a time (the circle area around each light). The code you posted just looks like it paints every pixel, I'm not seeing where the "circle" dropoff is even applied.
Edit:
Instead, sweep through the lights, and just loop through local offsets of the light position.
for(Light l : Lights){
for(int x = l.getX() -LIGHT_DISTANCE, x< l.getX() + LIGHT_DISTANCE, y++){
for(int y = l.getY() - LIGHT_DISTANCE, y < l.getY() + LIGHT_DISTANCE, y++){
//calculate light
int rgb = brightnessBuffer.getRGB(x, y);
//do stuff
}
}
You may want to add a check with that method so overlapping lights don't cause a bunch of rechecks, unless you DO want that behavior (ideally those pixels would be twice as bright)
Method 2 - Offhand calculation to the GPU. There's a reason we have graphics cards; they're specifically built to be able to number crunch those situations where you really need brute force. If you can offload this process to the GPU as a shader, then it'll run licketysplit, even if you run it on every pixel several times over. This will require you to learn graphics APIs however, but if you're working in java, LibGDX makes it very painless to render using the GPU and pass off a couple shaders to the GPU.
I am uncertain about the way in which you are going about calculating light values, but I do know that using the BufferedImage.getRGB() and BufferedImage.setRGB() methods is very slow.
I would suggest accessing the pixels of the BufferedImage directly from an array (much faster IMO)
to do this:
BufferedImage lightImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
Raster r = lightImage.getRaster();
int[] lightPixels = ((DataBufferInt)r.getDataBuffer()).getData();
Now, changing any pixel in this array will show on your image. Note that the values used in this array are color values in the format of whatever format you defined your image with.
In this case it is TYPE_INT_ARGB meaning you will have to include the alpha value in the number when setting the coloar (RRGGBB*AA*)
Since this array is a 1D array, it is more difficult to access pixels using x and y co-ordinates. The following method is an implementation of accessing pixels from the lightPixels array more easily.
public void setLight(int x, int y,int[] array,int width, int value){
array[width*y+x] = value;
}
*note: width is the width of your level, or the width of the 2D array your level might exist as, if it was a 2D array.
You can also get pixels from the lightPixels array with a similar method, just excluding the value and returning the array[width*y+x].
It is up to you how you use the setLight() and getLight() methods but in the cases that I have encountered, using this method is much faster than using getRGB and setRGB.
Hope this helps
I am using slick for java since a few days and got a serious problem.
If i run a completely empty apllication (it just shows the fps) with a solution of 800x600 i get a fps count between 700 and 800.
If I now draw an array with 13300 entries as a grid of green and white rectangles, the fps drop to something around 70.
With more entries in the array it becomes really slow.
For example in a solution of 1024x768 and an array with 21760 entries the fps drop to 40.
How i draw a single entry:
public void draw(Graphics graphics){
graphics.setColor(new Color(getColor().getRed(), getColor().getGreen(), getColor().getBlue(), getColor().getAlpha()));
graphics.fillRect(getPosition().x, getPosition().y, getSize().x, getSize().y);
Color_ARGB white = new Color_ARGB(Color_ARGB.ColorNames.WHITE);
graphics.setColor(new Color(white.getRed(), white.getGreen(), white.getBlue(), white.getAlpha()));
}
And this is how I draw the complete array:
public void draw(Graphics graphics) {
for (int ix = 0; ix < getWidth(); ix++) {
for (int iy = 0; iy < getHeight(); iy++) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
In my opinion 21760 is not that much.
Is there anything wrong with my code or is slick just too slow to draw so much rectangles?
You only want to draw rectangles that are on the screen. If your screen bounds go from 0 to 1024 in the x direction and from 0 to 768 in the y direction, then you only want to loop through rectangles that are inside those bounds and then only draw those rectangles. I can't imagine you are trying to draw 21760 rectangles inside those bounds.
If you are, then try creating one static rectangle and then just try drawing that ONE in all of the different positions you need to draw it at rather than creating a new one every time. For example, in a game I am making, I might have 1000 tiles that are "grass" tiles, but all 1000 of those share the same static texture. So I only need to reference one image rather than each tile creating its own.
Each rectangle can still have a unique state. Just make your own rectangle class and have a static final Image that holds a 5*5 image. Each rectangle will use this image when it needs to be drawn. You can still have unique properties for each rectangle. For example, private Vector2f position, private boolean isAlive, etc
You're probably not going to be able to draw individual rectangles any faster than that.
Games that render millions of polygons per second do so using vertex buffer objects (VBO). For that, you'll probably need to code against the OpenGL API (LWJGL) itself, not a wrapper.
Not sure if Slick will allow it, but if this thing looks anything like a chessboard grid... you could draw just 4 rectangles, grab them and use the resulting image as a texture for your whole image. I'm not even a java programmer just trying to come up with a solution.
Since you're only repeatedly using just a few colors creating a new Color object for every single one is bound to be slow... use new only once for each different color used and store the re-usable colors somewhere in your class, than call the functions with those, constantly allocating and freeing memory is very slow.
And while this might not be as much a benefit as not using new each time but have you considered caching the results of all those function calls and rewriting code as
public void draw(Graphics graphics) {
int ixmax = getWidth();
int iymax = getHeight();
for (int ix = 0; ix < ixmax; ix++) {
for (int iy = 0; iy < iymax; iy++) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
Or if you'd prefer not to declare new variables
public void draw(Graphics graphics) {
for (int ix = getWidth() - 1; ix >= 0; ix--) {
for (int iy = getHeight() - 1; iy >= 0; iy--) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
Just noticed in another answer you have an integral size grid (5x5) ... in this case the fastest way to go about this would seem to be to draw each item a single pixel (you can do this directly in memory using a 2-dimensional array) and scale it to 500% or use it as a texture and draw a single rectangle with it the final size you desire ... should be quite fast. Sorry for all the confusion caused by previous answers, you should have said what you're doing more clearly from the start.
If scaling and textures are not available you can still draw in memory using something like this (written in c++, please translate it to java yourself)
for( int x = 0; x < grid.width(); x++ ) {
for( int y = 0; y < grid.height(); y++ ) {
image[x*5][y*5] = grid.color[x][y];
image[x*5][y*5 + 1] = grid.color[x][y];
image[x*5][y*5 + 2] = grid.color[x][y];
image[x*5][y*5 + 3] = grid.color[x][y];
image[x*5][y*5 + 4] = grid.color[x][y];
}
memcpy(image[x*5+1], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+2], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+3], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+4], image[x*5], grid.height() * sizeof(image[0][0]) );
}
I'm not sure, but perhaps for graphics the x and y might be represented in the reversed order than used here, so change the code accordingly if it that's the case (you'll figure that out as soon as a few iterations run), also your data is probably structured a bit differently but I think the idea should be clear.
I am making a 2d platformer in Swing java, and I am wondering how to reduce the lag I get from it. I mean, it doesnt lag too bad but it is noticable that it slows down sometimes. I have a Swing timer ticking at 12 milliseconds, a cycle function, and a paint function.
public void cycle() {
if (guy.getJumpState() == false) {
if (canExecuteMovement(0, 4)) {
onGround = false;
if (guy.getY() > 300) {
// if you are in the middle, move the platforms.
for (int i = 0; i < platformCount; i++) {
platform[i].setY(platform[i].getY() - 4);
}
} else {
// or just move the guy if not.
guy.moveY(4);
}
} else {
onGround = true;
}
} else {
if (canExecuteMovement(0, -8)) {
if (guy.getY() < 300) {
// if you are in the middle, move the platforms.
for (int i = 0; i < platformCount; i++) {
platform[i].setY(platform[i].getY() + 8);
}
} else {
// or just move the guy if not.
guy.moveY(-8);
}
jumpCount++;
if (jumpCount >= 15) {
jumpCount = 0;
guy.setJumpState(false);
}
} else {
jumpCount = 0;
guy.setJumpState(false);
}
}
if (guy.getDirection() == "left") {
if (canExecuteMovement(-3, 0)) {
if (guy.getX() < 450) {
// if you are in the middle, move the platforms.
for (int i = 0; i < platformCount; i++) {
platform[i].setX(platform[i].getX() + 3);
}
} else {
// or just move the guy if not.
guy.moveX(-3);
}
}
} else if (guy.getDirection() == "right") {
if (canExecuteMovement(3, 0)) {
if (guy.getX() > 450) {
// if you are in the middle, move the platforms.
for (int i = 0; i < platformCount; i++) {
platform[i].setX(platform[i].getX() - 3);
}
} else {
// or just move the guy if not.
guy.moveX(3);
}
}
}
}
public void paint(Graphics g) {
super.paint(g); // something important
Graphics2D g2d = (Graphics2D) g;
// draw platforms
for (int i = 0; i < platformCount; i++) {
if (platform[i].getX() > -50 && platform[i].getX() < 950 && platform[i].getY() > -50 && platform[i].getY() < 650) {
g2d.drawImage(platform[i].getImage(), platform[i].getX(), platform[i].getY(), this);
}
}
// draw guy
g2d.drawImage(guy.getImage(), guy.getX(), guy.getY(), this);
// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
What can I do to optimize this and cause less lag? When I make a thread for the cycle function itself, the platforms sometimes seperate for a split second. I assume because since the thread is asynchronous, half of it is done while the paint function goes on.
Some loose thoughts (it's been years since I did some animation in Swing), and you didn't posted some compilable code.
Have you tried do paintComponent() --- paint does a lot of other stuff. And then maybe you need to add repaint() to tick function. Every time I reloaded paint it enden in a mess.
Also try increasing tick time --- youll waste less time repaiting.
Also I assume you are doing ticks by Timers.
I have no idea why you dispose graphics object
Also try just dropping sync (Ive done animations that work on many oeses without it) Toolkit.getDefaultToolkit().sync()
If it doesn't help use profiler to find a bottleneck. Visual VM is quite nice. Also Visual VM is part of the jdk for some time --- just go into bin folder and launch jvisualvm.
EDIT: (thread issues)
Some people suggested using threads --- which I diasgree. If you want do some work outside EDT please use SwingWorker
I assume you are not calling paint() but just call repeaint(). If you do call paint() (whatever black magic you also make to make it work) please just call repaint() that will schedule repaing on appropriate time.
First of all, this bit here is a problem:
// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();
In general, disposing a resource you did not create is probably a bad idea. In this specific case, the Graphics passed into paint() is probably used by all other components in the hierarchy, so this could cause really odd results.
Calling Toolkit.sync() here is I think your attempt to eliminate the tearing you were seeing when moving things in the background. But all that it does is to flush any pending draw instructions. That has no effect here because you are probably drawing to a back-buffered Swing component that will be drawn fully later.
The correct way to eliminate tearing is to perform any updates on the event thread, so that you are not changing the screen data while drawing it. One simple way to implement this would be to have your timer just call repaint(), and have the paint() method call cycle() before doing anything.
For dealing with lag, one solution might be to allow a variable frame rate. Instead of moving everything a fixed distance each frame, calculate the time since the last frame and move everything accordingly.
I would create your variables outside the method so that it is not being created every time you call that method. The best way to program games is to re-use things instead of destroying and creating because destroying & creating cost a lot of computing power.
Graphics2D g2d = (Graphics2D) g; <---declare it outside your method.
And also try to find redundant conditionals. I saw one where you say (if direction right then ..., else if direction left ...); just say (if direction right then ... else ...). Conditionals do not cost much but when you're calling that conditional 1000 times a second I think it adds up. (idk though, but I do it just in case and for making things fluid)
Where you say setjumpstate(false) it's redundant because no matter what, it is executed - just move it outside the conditional.