I started playing with someone's else code and came across an interesting experiment. The program will work fine with the if statement. But I found out if I change the if statement into a while loop, the program runs but I could not close the program with the X button instead I had to press Eclipse terminate button. I am guessing this is a sign of an infinite loop or is it the fact that Java cannot repeatedly draw the same images over and over again?
// if you want to draw graphics on the screen, use the paintComponent method
// it give you a graphic context to draw on
public void paintComponent(Graphics g){
super.paintComponent(g);
// when the player is still in the game
if(inGame){
g.drawImage(apple, apple_x, apple_y, this);
for (int z = 0; z < dots; z++) {
if (z == 0)
g.drawImage(head, collisionX[z], collisionY[z], this);
else g.drawImage(tail, collisionX[z], collisionY[z], this);
}
Toolkit.getDefaultToolkit().sync();
// dispose graphics and redraw new one
g.dispose();
}
else gameOver(g);
}
Changing this line into a while statement
if (inGame) {
will not allow the variable to be reset to false, resulting in the infinite loop. Having while loops or any resource-heavy calls in paintComponent is a bad idea in general. Swing has concurrency mechanisms to deal with these.
If you want your UI to remain responsive, event handlers and repaints should finish within a reasonable amount of time. This means you shouldn't loop inside paintComponent() at all; instead you have to repeatedly trigger a repaint from somewhere else, like an animation timer.
Changing the if to a while, ie:
while(inGame){
will loop forever if inGame is true, because there would be only two ways to exit the loop:
inGame is set to false within the loop
the is a break statement in the loop
neither of which is found in the code.
fyi, the code pattern while(true) is a common way to create an infinite loop, which is needed for things like web services waiting for requests
Related
Is LibGDX SpriteBatch draw() smart enough not to redraw 100% exactly same sprite at each render() call?
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (shallFadeOut) { // becomes true when sound message finishes
doFadingOut();
showNextScreen();
dispose();
} else {
batch.begin();
// introSprite is a static image - it never changes a pixel (splash screen)
// I need to paint it once and then just wait until sound message finishes
// DON'T NEED TO REDRAW IT EVERY render() cycle 60 times/sec (~60 fpm)
introSprite.draw(batch);
batch.end();
}
}
In OpenGL, you typically redraw the whole screen on every frame. It doesn’t make sense to wonder if the batch is smart enough to avoid redrawing the same thing, because it has to redraw it to prevent it from disappearing.
If you want to avoid redrawing anything on the screen for a while to save battery on the device, you can use GDX.graphics.setContinuousRendering(false) but that means your render() method will stop getting called so you must set it back to true using a timer or input callback.
You could alternatively use a Boolean to decide whether to clear the screen with glClear and draw stuff, but under the hood, LibGDX will still be requesting OpenGL to copy the screen buffer data between the back buffer and the screen buffer.
Not that drawing a single sprite is super trivial and probably not worth a second of thought about optimizing it.
I am afraid that I do not think any accounting is done by the Batch between batching render steps to see if a texture was already loaded and is ready to be rendered, but the texture itself might.
The batching is intended for cases where you are drawing duplicates of the same thing in the same render step so that you are not unnecessarily context switching between sprites and having to reload data to your graphics card.
The batch is as I am sure you know defined by the begin and end calls you are using, and it depends on you actually rendering all of the sprites of a particular type one after the other without jumping to render something else. This can be seen int he batch draw code here, but for readability the relevant lines are below:
Texture texture = region.texture;
if (texture != lastTexture) {
switchTexture(texture);
} else if (idx == vertices.length) {
flush();
}
To take advantage of the batch - you should be grouping the rendering of all your sprite types, and between steps, the batch does not offer any efficiencies by design as far as I can tell.
But, between batching steps or game loops, when a texture is bound, it uses a fixed target and handle as can be seen here. This means that if all you are drawing is a single sprite for several render loops, libgdx should be using your memory and graphics card as efficiently as can be expected.
I have problem with Android. I'm trying make project where I draw circles on a random position. After touch on this circle you will get a score and the circle will disappear. But I have a problem, my object is spawned then disappears without touch and spawns in another location.
Here is my spawner code.
protected void spawner(Canvas canvas,int timer){
System.out.println(myThread.timer);
if (myThread.timer>100) {
int x = 200 - generator.nextInt() % (myThread.screenDimX / 2);
int y = 200 - generator.nextInt() % (myThread.screenDimY / 2);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setColor(Color.parseColor("#800000"));
canvas.drawCircle(x, y,50, paint);
myThread.timer=0;
}
}
myThread is my game loop thread.
Can anyone help me with this?
You're only drawing that circle for the instant myThread.timer is greater than 100. What you need to do is add it to an ArrayList, or whatever data structure you want, and then constantly loop over that ArrayList and draw all the circles.
One thing I can tell you in general, and I don't know if that's why you have a problem or not, is all UI components manipulation should happen on the UI thread, and not on your other thread.
It's unclear if you call this method on a callback from the timer thread or on the UI thread. If you're calling it from the UI thread then it might be that both the UI thread and the Timer thread write to myThread.timer, concurrently and the way it seems, you're not guarding it.
I'm trying to write a program that is under 140 characters(Twitter Char Limit). The program displays the final output I want but I don't understand why it's not showing the animation as it creates it. I thought it was because I don't have a draw function but I don't see why that matters if the drawing is all done within a For loop, anyways the draw function didn't help. I've tried bringing the framerate way down but yet for some reason it's only giving me a static final output. Any help is much appreciated.
int j=600, i=j/3;
size(j, j);
smooth();
translate(j/2, j/2);
for (i=1; i<12500; ) {
fill(i%j, i%j);
rotate(j%i*5);
line(i++%j, i++%j, i+++j, int(i/99)%99);
}
Processing uses double buffering, which means that when you draw "to the screen", you're actually drawing to an off-screen buffer. Since your code is not in the draw() function, this happens before the frame is even visible. Then when the frame becomes visible, it takes the entire off-screen buffer, and draws the whole thing to the screen.
That's why you only see the end result of the drawing. If you want to display an animation, you'll have to use the draw() function and timing of some kind (the millis() method, for example).
I'm developing some kind of videogame, so I am not interested in calling paint, repaint or any sort of those methods on each updating from keylistening, since they call also the update(Graphics g) method which cleans the whole screen. That's why I do want to #Override the update method, not allowing it to cleaning the screen at first. Doing this I can update what I want when I want.
However, sometimes it goes in a loop auto painting the components (such as jButtons) cleaning the screen(I couldn't track anything special happening whenever this occurs, I have already tried overriding some methods in order to catch which one's the troublesome and I couldn't find it, I'm likely missing something). I do not want this happening, because this auto painting cleans the screen which makes me draw everything once again. Moreover I don't feel comfortable with something looping until the player press any key. Do you have any clue? One solution could simply be using a timer with a boolean that each time a screen is completed and the next one is being loaded it calls update(g) from my JFrame (which contains the jPanel). But I would like something better..
Maybe I am doing something wrong, even if I tried to improve my painting methods thousand times surfing throughout the net and netbeans's suggs.
This is how my painting methods looks with some flags written and the ones that are called after running:
#Override public void paint(java.awt.Graphics g){
paintComponents(g);
System.out.println("Flag");
update(g);
}
#Override
public synchronized void update(Graphics g)
{
g.setColor(java.awt.Color.GREEN);
w.getDrawer().draw(g);
g.drawRect (0, 0, w.getActive().getW(), w.getActive().getH());
}`
The overriding on paint(Graphics g) method is not needed at all, just did it in order to see what was going on. I never called repaint() but update(getGraphics()) and it just spam Flags all around. Also thought that maybe I was making it run in a loop with paint and paintComponents, but deleting paintComponents(g) line helps not at all.
Any help would be welcome, since I am trying to make this project "serious". Thanks in advance.
Sergi.
By the way, w.getDrawer().draw(g); is just calling some entities (like 100) with something like g.drawImage(image, locationX, locationY, null) inside. I don't think it has anything to do with my prob.
..this auto painting cleans the screen which makes me draw everything once again.
Draw it to a BufferedImage displayed in a JLabel. When the data (the image) updates call label.repaint().
E.G. as seen in:
This answer to How to draw an image over another image?
This answer to Dynamic Graphics Object Painting.
I'm making a frame which contains a round rectangle. This rectangle is constantly (re)painting
itself with smaller values.
The plan is, First the rectangle decreases in width(x), after that the rectangle decreases in height(y).
But for now I just want to get the width decreasing done with. But I'm having troubles here already.
Please note, i'm only drawing the rectangle's borders, so I don't want to fill it.
I made a for loop as follows:
for (rectWidth = 470; rectWidth >= 0; --rectWidth) {
try {
//simply made to represent rectWidth's value, not really relevant
System.out.println("rectWidth is: " + rectWidth);
//draw the rectangle with it's new width, ignore the "rectHeight" for now.
g.drawRoundRect(5, 5, rectWidth, rectHeight, 10, 10);
//this Thread.sleep is messing up my frame which has an instance of this class added
//to it also, my program is uninterruptable when adding this Thread.sleep
Thread.sleep(500);
} catch (Exception ex) {
//rectangle's value will be returned here when interrupted.
}
}
My question is, how can I add a 'sleep' in my for loop in order to make the drawing not go all too fast,
withouth messing my frame. This thread.sleep is messing my frame up in a way that I don't even see
the rectangle anymore.
I want to achieve a smooth (re)painting of the rectangle. (And yes I know as this piece of code is now
it isn't repainting the rectangle but constantly painting a slightly smaller rectangle in the frame.)
The reason that the rectangle isn't getting displayed is that the display is updated on the EventDispatchThread which is probably the same one your loop is on. That is it can't paint the rectangle because it's too busy sleeping.
The solution is to use a Swing Timer which will run and happily sleep sending tasks to the EventDispatchThread when updating.
Also you can start drawing thread
#Override
public void run(){
while(shouldDraw())
this.wait(500);
yourCalculations(); // maybe setting fields in runnable object
SwingUtilities.invokeAndWait(yourRunnableObject); // or invokeLater if you prefer non blocking version
}
This code shows only conception (I've skipped synchronization and exception handling). SwingTimer looks more elegant but I've never used it.