Using 'small' values in progressBar with 9 patch looks bad - java

I'm using libGDX ProgressBar. I create it with the next code:
style = new ProgressBar.ProgressBarStyle();
style.background = new SpriteDrawable(backgroundImage);
NinePatch fillImage = new NinePatch(new TextureRegion(img2, 1, 1, img2.getWidth(), img2.getHeight()), 25, 26, 30, 30);
style.knobBefore = new NinePatchDrawable(fillImage);
style.knobBefore.setMinWidth(0);
style.knobBefore.setRightWidth(0);
style.knobBefore.setLeftWidth(0);
progress = new ProgressBar(0, 30, 0.1f, false, style);
When I set a value to a big number, for example 15 this is how it looks:[1]
but when I set a small value 1/30 (smaller the the basic 9 patch image) it looks bad:
Any ideas how to handle this problem?

You are setting your NinePatch width to be less than the minimum. The left and right do not change, so the minimum width your NinePatch can be is 25 + 26 = 51px. Any less than this you will get erroneous results. I believe the reason it looks like that is because your sides are actually pushing through each other, creating a negative width for the centre, which is still completely acceptable to draw with. (You can see in your image that the right is at the very far left, the left is most likely at the very far right but behind the reversed middle) The simplest solution would just be to limit the progress bar width to the proper minimum with something like this (if progress value is between 0 and 1);
//convert min width to a ratio
float minProgress = style.knobBefore.getMinWidth() / progressBarLength;
float progress = Math.max(progress, minProgress);
getMinWidth() would probably tell you it is 51/52px. You also shouldn't force setMinWidth(), setLeftWidht(), setRightWidth().

Related

What's the best way to implement a color cycling background?

What's the best way to cycle the color of a background smoothly (as well as other things) using cos or sin in java, without using more than one file? I've tried using randomness and increasing each individual r, g, and b value separately to make this look kind of normal, but it's jittery, not smooth, and the colors are horrid. Right now, it's just plain white. I included only the necessary code, and I am using Processing 3.
//background
int bg1 = 255; //r
int bg2 = 255; //g
int bg3 = 255; //b
void draw() {
fill(bg1,bg2,bg3);
}
You've got the general idea down. It's a three-step process:
Step 1: Declare variables at the top of your sketch.
Step 2: Use those variables to draw your scene.
Step 3: Change those variables over time.
This is the basic approach to create any animation in Processing. Here is a tutorial with more information.
Here is a small example that shows a window that cycles between white and black:
float c = 0;
float cChange = 1;
void draw(){
background(c);
c += cChange;
if(c < 0 || c > 255){
cChange *= -1;
}
}
You would need to do something similar, but with 3 color values instead of 1. Note that I'm only changing the color by a small amount each time, which makes it appear smooth instead of jittery.
If you're still having trouble, please post an updated MCVE in a new question and we'll go from there. Good luck.
If you specifically want to use a sine wave as input rather than the sawtooth wave then you need to map your input (e.g. time) to some color range. For example:
every 2000 milliseconds value increases from 0 to 2.0
value ranges from -1 to 1.
the output of sin(value) ranges from -1 to 1.
map the output to a color range.
map() works well for mapping values, but you can also use colorMode() for mapping color ranges -- so rather than moving your sine output values around, just make your output 0-2.0 and set the max RGB or HSB value to 2.0 rather than 255.
Here are some examples, all running simultaneously in one sketch:
float val;
float out;
void draw() {
background(0);
val = TWO_PI * (millis()%2000)/2000.0; // every 2000 milliseconds value increases from 0 to 2PI
out = sin(val);
// white-black (256-0)
pushStyle();
fill(128 + 128*out);
rect(0,0,50,50);
popStyle();
// red-black (255-0)
pushStyle();
colorMode(RGB, 255);
fill(255*(out+1), 0, 0);
rect(50,0,50,50);
popStyle();
// hue rainbow (0-2)
pushStyle();
colorMode(HSB, 2.0);
fill(out+1, 2, 2);
rect(0,50,50,50);
popStyle();
// hue blue-green (3 to 5 / 9)
pushStyle();
colorMode(HSB, 9);
fill(out+4, 9, 9);
rect(50,50,50,50);
popStyle();
translate(width/2,height/2 - out * height/2);
ellipse(0,0,10,10);
}
Don't understand what you mean by cos and sin in relation to background color. But maybe something like this is what you want?
void draw(){
int H = frameCount%1536;
background(color(abs(H-765)-256,512-abs(H-512),512-abs(H-1024)));
}

Center a minus on the screen in java

I am trying to center a minus sign on the screen using the following code:
text = "-";
textPosition = new Point();
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
paint.setTextAlign(Paint.Align.CENTER);
textPosition.x = (int) (myArea.left + myArea.width() / 2);
textPosition.y = (int) (myArea.top + myArea.height() / 2 + bounds.height() / 2);
canvas.drawText(text, textPosition.x, textPosition.y, paint);
This code works like a charm when "text" is something else (for example a plus sign), but in this case the minus sign is positioned too high on the screen.
EDIT:
Here is the result for four different operators.
And... the funny thing is, that I created my own font to display these operators. So I know, that it should be centered correctly.
PS: Now that I look at it, all off them seem a little off, though the minus-sign is the worst...
Okay, I fixed it. Not by changing the code, but by changing the font. I have now aligned all characters on the baseline and that seems to work.

how to calculate image gradient

My instructor gave us the pseudocode:
grad = abs(im(x+1,y)-im(x-1,y)) + abs(im(x,y+1)-im(x,y-1))
to calculate the gradient of an image for an edge detector we are making. I thought that the way this pseudocode would look like is:
int grad = Math.abs(img.getRGB(i+1,j)-img.getRGB(i-1,j)) +
Math.abs(img.getRGB(i,j+1)-img.getRGB(i,j-1));
he said this code would only get the R value of a color. I'm having trouble understanding this. Could someone help me understand how to use this formula to get an entire color gradient? (this formula would go in a nested for loop and apply to every pixel)
Your instructor means that you need to get the Red for each pixel. You can either fiddle with the bits that are returned from getRGB(x, y) to get just the red, or you can put the RGB value into a Color and extract it that way.
public int getRed(BufferedImage image, int x, int y)
{
// Color color = new Color(image.getRGB(x, y), true); if you care about alpha
Color color = new Color(image.getRGB(x, y));
return color.getRed();
}
This will give you a value between [0, 255]. If you want a value between [0, 1], then you need to divide by 255.0.
Bit shifting would be a faster solution, but this is the easier solution and it is likely fast enough. For reference, red would be bits [16, 23].

libGDX: Textfield with BitmapFont(true) renders the text outside the borders

I'm experimenting with TextField and having problems with it when flipping the font. My orthographic camera is set to yDown = true. With that settings, the text is flipped so I came up with a solution to set BitmapFont's flip constructor parameter to true. But then when I try the code below. The text "Hello World" is rendering outside it's ninepatch borders. Here's a screenshot of it:
TextFieldStyle tfs = new TextFieldStyle();
NinePatch np = new NinePatch(new Texture(Gdx.files.internal(ResourceConstants.IMAGE_NINEPATCH)), 8, 8, 8, 8);
tfs.font = new BitmapFont(true);
tfs.fontColor = Color.BLACK;
tfs.background = np;
TextField tf = new TextField("Hello World", tfs);
tf.x = 50;
tf.y = 90;
tf.width = 100;
tf.height = 32;
addActor(tf);
tf.pack();
The problem is in the method where draw is being called on tfs (which is where the coordinates are set). The cartesian y coordinates for font are opposite other GDX objects, I think because typesetting needs to work a certain way.
So if you call
myFont.draw(spriteBatch, "Hello World", 0, 0);
Then you would expect the message to be drawn right in the bottom left hand side. But this is wrong! The fonts themselves are drawn from the top left, so your message will be drawn on the bottom left corner of the screen, below the bottom edge. We wont even be able to see the message.
But if we change the coordinates:
myfont.draw(spriteBatch, "box2d x: " + String.format("%2.2f", x), 10, 20);
We will see the message because we've given it enough room in the negative y direction to be displayed.
Given that the misbehaving font is misbehaving in the Y direction, and rendering below where you expect it to, I suspect that the above misconception is indeed the problem.
If you're not controlling any of the drawing coordinates of the bitmapfont itself, and this is solely handled by the TextField class, and the font is always out of bounds, no matter the size of your text field, then I would suspect a bug in GDX. You might try asking the forums about that.
I had the same effect. If you add TextField, and after, for example, add CheckBox and for this widget set setScale, then you will see this effect
TextField textfield = new TextField("Text field",skin);
stage.addActor(textfield);
CheckBoxStyle checkBoxStyle = skin.get(CheckBoxStyle.class);
checkBoxStyle.font.getData().setScale(2f);
CheckBox checkbox = new CheckBox("CheckBox", checkBoxStyle);
stage.addActor(checkbox);

Resizing an Arrow shape

I have an arrow:
Arrow ballArrow = new Arrow("Ball Arrow", 2, 0.175f);
And I want to resize it to make it longer whenever a key is pressed (say Key_5).
Which method would I call to resize it as when i'm calling .setLength() and .setWidth() they keep getting slashed out and i'm not sure what that means.
BTW i'm using jMonkeyEngine 2 not 3.
Looking at the Arrow API, setLength and setWidth are deprecated. To do the resizing, you should be doing:
Arrow ballArrow = new Arrow("Ball Arrow", 2, 0.175f);
....
float newLength = (somevalue);
float newWidth = (somevalue);
ballArrow.updateGeometry(newLength, newWidth);
Hope this helps.

Categories