drawing random image libgdx - java

I am learning java game development with libgdx and have the following issue.
I have a Rectangle array which I iterate through and draw an image according to the position of the rectangle.
My Questions is how do I draw a random image every render but still keep drawing the same random image until it leaves the screen. currently it is drawing the same image but I would like know how to draw a different pipe image every iter.
Thank you
My Iterator
Iterator<Rectangle> upperIter = upperPipes.iterator();
while(upperIter.hasNext()) {
Rectangle upperpipe = upperIter.next();
upperpipe.x -= 8 * Gdx.graphics.getDeltaTime();
if(upperpipe.x < -32) upperIter.remove();
My draw method
public void drawPipes(){
batch.begin();
for(Rectangle upperPipe: Pipes.lowerPipes) {
batch.draw(Assets.pipeImg, upperPipe.x, upperPipe.y, upperPipe.width, upperPipe.height);
batch.end();
}

One great way to get repeatable random data is to use a Random object (java.util.Random is suitable for game usage), and provide it with a non-random seed. Each time you put in the seed and request the same sequence of number types+ranges, you will get the same (psuedo-)random numbers. When you want different numbers, just change the seed.
As an example:
Random rand = new Random(1234);
System.out.println(rand.nextInt()); // an int from Integer.MIN to Integer.MAX
System.out.println(rand.nextInt(100)); // an int from 0 to 100
Will always output the following, every single time.
-1517918040
33
But change the seed (in the constructor for Random), and the output values will change. rand.setSeed(seed) will reset the Random to start its sequence over.
You could use this to produce the same set of random numbers over and over while the rect is on screen.
However, a more direct and simple way would be to to just generate one random number for each rect when it is created, and store that number until it leaves:
public void drawPipes(){
for(int i = 0; i<Pipes.color.size; i++){
num = Pipes.color.get(i);
}
for(Rectangle bottomPipe: Pipes.lowerPipes) {
switch(num){
case 0:
batch.draw(Assets.redPipeImg, bottomPipe.x, bottomPipe.y, bottomPipe.width, bottomPipe.height);
break;
case 1:
batch.draw(Assets.yellowPipeImg, bottomPipe.x, bottomPipe.y, bottomPipe.width, bottomPipe.height);
break;
}
}
}

SOLVED!!
I created a custom pipe class and just created an array of pipes, each new pipe object that went into the array took a random image.
I iterated through the array, and called the draw method on each pipe object.
Simple and it works perfect

Related

how to add two coordinates (x,y) to a arraylist

My code reads all the pixels from the screen until it finds a pixel with the RGB value that I specified, which I managed to do, however if my screen has multiple pixels of that RGB value, I want to be able select a random pixel within that RBG value, instead of only working with the first pixel that my code finds I want to work with a random one. A workaround that I made generates a random number between 1 and 100 and everytime it checks a pixel it has a 1% chance of working with it, however this isn't the best method because of the way that my code scans the screen, (top-down, left-right) that means most of the time the pixel will end up on the upper left corner with isn't exactly random. I thought a good solution would be evertime the code goes through the if statement it stores the values x,y in a arraylist then I would get a random Index from that arraylist, but I couldn't figure out how to do that.
I appreciate any suggestions and help :)
int rng = new Random().nextInt(100) + 1;
if (color.equals(iron) && rng == 5){
if (r != 215 || g != 215 || b != 215){
Robot move = new Robot();
mousemoving.mouseGlide(x,y,1250,1000);
Runecraft.randomInt(35, 481);
move.mousePress(InputEvent.BUTTON1_DOWN_MASK);
move.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println(iron);
flag = true;
break;
how to add two coordinates (x,y) to a arraylist
Check out the Point or Point2D classes. They have exactly what you want.
Then
List<Point> points = new ArrayList<>();

How can i randomize delay of moving object

Recently i added that enemy shoots but unfortunately i cannot randomize delay of Shooting for every object.
Project 60 times in second :
update (all code here is connected to this part)
draw
sleep
Fragment of code :
Fragment of code.
public void createNewEnemyBullet(){
for(Enemy enemy: enemies){
EnemyBullet enemyBullet = new EnemyBullet(getResources());
randomShot = random.nextInt(60-40)+40;
System.out.println("Randomowy shot :"+ randomShot);
enemyBullet.x = (int) (((enemy.x+enemy.widthEnemy/2)-18)*screenRatioX);
enemyBullet.y= enemy.y+20;
enemyBullets.add(enemyBullet);
}
System.out.println("\n\n");
}
Screenshot of my result
enter image description here
Use Math.random(). It'll be your friend here. Compare (Math.random() <= epsilon) the output of random() with some number epsilon you want as your threshold for making an enemy shooting decision.
If enemyBullets is what the UI code uses to draw bullets, you may want to add a Thread.sleep(Math.random()) to add variable delay in adding them.
Solution for generating random delay of bullet is to change this delay when a enemy starship is shot.

Random x,y coordinate within an irregular polygon given a list of x,y-points, without being on such a corner-point nor edge

I'm trying to tackle the following use-case:
Input: A list of x,y-coordinates that will form an irregular polygon (they are guaranteed valid and lines will not intersect; it can however be concaved). Input-format is irrelevant, so I'm currently using two loose int-arrays for x and y respectively.
Output: A random x,y-coordinate within this polygon, which is NOT directly on top of a corner nor edge.
Using the following code, I have been able to tackle the random x,y-coordinate within the polygon:
// Currying Function with two int-arrays as parameters and double-pair return-type
X->Y->{
// Create a Path2D object
java.awt.geom.Path2D path = new java.awt.geom.Path2D.Double();
// Start at the first coordinate given
path.moveTo(X[0], Y[0]);
// Loop over the remaining coordinates:
for(int i=1; i<X.length; i++)
// And draw lines from corner to corner
path.lineTo(X[i], Y[i]);
// After the loop, close the path to finish the polygon
path.closePath();
// Create a Rectangle that encapsulates the entire Path2D-polygon
java.awt.Rectangle rect = s.getBounds();
// The resulting x,y-coordinate, starting uninitialized
double x,y;
// Do-while the Path2D polygon does not contain the random x,y-coordinate:
do{
// Select a random x,y-coordinate within the Rectangle
x = rect.getX() + Math.random()*rect.getWidht();
y = rect.getY() + Math.random()*rect.getHeight();
}while(!path.contains(x,y));
// After which we return this random x,y-coordinate as result:
return new double[]{x,y};
}
This all works as intended. Now I want to make sure that the random x,y-coordinate is not one of the input x,y-coordinates (this is pretty easily) AND is not on an edge/line of the Path2D. This second part I'm not sure how to tackle, and a quick google search wasn't given any useful information, hence this question.
NOTE: I know the chances that the random point is exactly on top of an edge/corner are astronomical small and could probably be ignored, but this is for a challenge, hence the need to implement it regardless.
After the tip of #Andreas in the comments to use a Line2D, I've modified the do-while to:
// The resulting x,y-coordinate, starting uninitialized
double x,y;
// Flag to indicate whether the random x,y-coordinate is on a corner or edge, starting truthy
boolean flag;
// Do-while the Path2D polygon does not contain the random x,y-coordinate:
do{
// Select a random x,y-coordinate within the Rectangle
x = rect.getX() + Math.random()*rect.getWidht();
y = rect.getY() + Math.random()*rect.getHeight();
// Set the flag to false:
flag = false;
// Loop over the pair of x,y-coordinates of the input:
for(int j=0; j<X.length; )
// Create a Line2D using the current pair of x,y-coordinates:
if(new java.awt.geom.Line2D.Double(X[j],Y[j++], X[j],Y[j])
// And if it contains the random x,y-coordinate:
.contains(x,y))
// Change the flag to true
flag = true;
}while(!path.contains(x,y) || flag);

2D Dynamic Lighting in Java

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

Find 5 Largest Values In A Linked List in Processing/Java

I got this code that gets x,y positions from a motion sensor tracking a hand. The app draws a circle in the middle of the screen and then detects whether the hand is outside the circle. While the hand is outside the circle, a function checks the distance of the hand from the center of the circle. I'm attempting to store the distance data while the hand is outside of the circle in a linked list.
I need to get both the top 5 largest values and the duration for each time the hand is outside the circle.
Here's my code thus far; I've left out a bunch of the code for setting up the motion sensor just for simplicity, so this is semi-pseudo code. In any case, my main issue is getting the values I need from the list. I have the circle class included as well. I do the outside of the circle calculation and how far outside of calculation inside of my circle class.
Please let me know if this makes sense! The motion sensor is reading in data at 200 fps, so efficiency is factor here. On top of that, I am only expecting the hand, going back and forth, to be outside of the circle for a few seconds at a time.
import java.util.*;
LinkedList<Integer> values;
public void setup()
{
size(800, 300);
values = new LinkedList<Integer>();
HandPosition = new PVector(0, 0); //This is getting x,y values from motion sensor
aCircle = new Circle(); //my class just draws a circle to center of screen
aCircle.draw();
}
public void draw()
{
if (aCircle.isOut(HandPosition)) /* detects if movement is outside of circle. Would it make more sense for this to be a while loop? I also need to start a timer as soon as this happens but that shouldn't be hard */
{
values.add(aCircle.GetDistance(HandPosition)); //gets how far the hand is from center of circle and adds it to linked list. Allegedly at least, I think this will work.
/*So I need to get the 5 largest value from inside of my linked list here.
I also need to start a timer*/
}
}
class Circle {
PVector mCenter;
int mRadius;
Circle()
{
// initialize the center position vector
mCenter = new PVector(0,0);
mRadius = 150;
mCenter.set((width/2),(height/2));
}
boolean isOut(PVector Position) //detects if hand position is outside of circle
{
return mCenter.dist(Position) <= mRadius;
}
float GetDistance(PVector Position) //detects how far the hand is from the center of circle
{
return mCenter.dist(Position);
}
void draw() {
ellipse(mCenter.x, mCenter.y, mRadius, mRadius);
}
}
I'm new to Processing as well so don't hold back if any of this works.
You can use Collections.sort(List); here, then take last five element from the list.
Collection.Sort()

Categories