Processing: Trying to animate the drawing of lines without draw function - java

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).

Related

Libgdx: the render method

I don't think I understand how the render method works.
From what I read online / saw on youtube tutorials, I gathered that the render method is a looping function that you can use to keep your game updated and read users' inputs. When you want to draw something in the screen you do so in this method, and before drawing anything you clear the screen.
But if I want to draw something stationary, wouldn't it be better to draw it outside the render method (so the computer doesn't have to clear the screen and redraw everything many times)?
What am I missing?
You can't draw outside the render method, because it's the method called on the OpenGL thread. You can't draw to OpenGL from other threads.
If your entire screen is frequently static for more than a few ms, which might be the case in something like a card game, you can disable the continuous refreshing of the screen using Gdx.graphics.setContinuousRendering(false). This will save energy because the GPU and CPU won't have to work as hard. See here for instructions on using it.
As for why this typically isn't done:
Think of a "frame buffer" as a bitmap image in memory that can be drawn to and then shown on screen. Most mobile rendering is done with double-buffering. This means while one buffer is being drawn to (the back buffer), the front buffer that was drawn to on the previous frame is being rendered directly to the screen. They swap back and forth each frame for faster rendering.
The way graphics work is that each item that's drawn modifies the color of pixels in the frame buffer where the item is drawn. Items may be masked or be translucent, and these will alter the color of pixels behind them. The original color of those pixels are lost once something is drawn in front and modifies them
So, even if some item on your screen is static, if there are other items on the screen that move or change color, and they overlap the static item (either in front of or behind), you still have to redraw the whole screen every time anything changes.
If one area of the screen is static and never overlapped by dynamic objects, and the dynamic objects are contained entirely within a rectangle, you could potentially set a viewport that limits drawing to the dynamic area and avoid clearing the whole screen. However, GPUs are designed specifically to be efficient at clearing the whole screen. Because of double-buffering, if you don't clear the whole screen, it's actually likely to harm performance because if you don't clear it, the contents of the screen have to be copied between the front and back buffers before you can start drawing the next frame.
Another strategy is if you have a static object that is very complicated and taxing for the GPU to draw because it has lots of layers or a complicated shader, you could draw it to an off-screen frame buffer object (FrameBuffer class in libGDX) one time, and then render that FrameBuffer's texture to the screen on each frame like a sprite.

Is LibGDX SpriteBatch draw() smart enough not to redraw 100% exactly same sprite at each render() call?

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.

Does java graphics render only the window size or everything?

I am making a 2d path-geometry based game in java. If I have a bunch of large shapes (Path2D's) that I am rendering every frame, is java taking the time to process the whole thing, or is it only processing the parts actually in the window?
For example say I have an rectangle that is 1000 by 1000 with the top left corner at 10, 10. My window is only 100 by 100. Is java processing the whole thing, or only the part smaller than 100, 100?
Thanks in advance!
Rendering is clipped to the visible portion only.
Obviously.
The clip area of the Graphics2D (see getClip()) is set automatically to the visible portion, but at some moment "Java" will still "take time" to determine whether the generic shapes are inside this clip area.
So it might be a valid optimization technique if you don't draw the shapes that are outside the visible area. Or you could draw the static shapes to an image, and then render this image.
After receiving some information, I decided to test it myself.
I made a complex shape using Path2D and rendered with the whole shape inside the window. Then, I rendered the same thing 90% outside the window, with only a small part of the shape showing.
The one that was outside the window showed much higher performance (260 FPS) than the one entirely in the window (50 FPS).
This suggests that java only processes the part of the shape actually within the window boundaries.

How do I draw adjacent bitmaps to a canvas in Android?

I've spent all night trying to figure out why I can't draw a series of bitmaps completely adjacent to each other (with no gaps in between), using Android.
For context, I am building a spectrogram application which displays a vertical bitmap for each 'window' of audio data that comes in, providing the user with a heatmap of frequencies. At the moment I'm using pre-recorded audio so I can perform all my calculations before I have to display anything - I have an ArrayList of integer arrays, each of which represents one window's bitmap, which is drawn to a canvas using a timer thread.
I am aware that the approach below will ultimately break when the application tries to draw past the dimensions of the screen, but I am not worrying about that for now. The problem I would like to solve is that the below code results in a one-pixel (ish) gap between the drawn bitmaps, when I would actually like them to be absolutely adjacent.
This is the run() method for my timer thread:
public void run() {
Canvas c = null;
try {
c = sh.lockCanvas(null);
synchronized(sh) {
doDraw(c);
}
} finally {
if (c!=null) {
sh.unlockCanvasAndPost(c);
}
}
}
This is the doDraw() method which draws the bitmaps, and then skips along to the end of that drawn bitmap in order to draw the next one. It simply does so by incrementing the 'windowsDrawn' field:
private void doDraw(Canvas canvas) {
canvas.drawBitmap(spec.getBitmapWindow(windowsDrawn), 0, 1, windowsDrawn, 0, 1, h, false, null);
System.out.println("Windows drawn: "+windowsDrawn);
windowsDrawn++;
}
spec.getBitmapWindow(windowsDrawn) simply returns an integer array of pixel values for the vertical window to be drawn.
Here's a screenshot to show what I'm talking about.The image looks as if it is behind tiny prison bars and I would like to get rid of these.
Thanks!
I found out what I was doing wrong. The 'prison bars' effect was actually a side-effect of me writing incremental updates to the back-buffer, which was presumably being flipped every so often (hence losing some of my updates to the other buffer, giving the black vertical lines). The problem was solved by ensuring that I was instead writing to a buffer bitmap and then redrawing the entire frame each time. Incremental updates to the screen (like I was trying to do) are not allowed in Android.

Problem with Thread.sleep(x) in a for loop - Java

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.

Categories