Java/Libgdx - How can I draw multiple circles without blinking effect? - java

Maybe my title doesn't fit very well but I will try to clearly explain.
In fact, I'm currently working on a little project using Libgdx. At the moment, the goal of this project is to be able to randomly display several circles on my screen.
I correctly displayed these circles on the screen but they are blinking.
#Override
public void render(float delta) {
renderer.begin(ShapeType.Filled);
if(!mapIsCreated)
{
Random rand = new Random();
int x, y;
for(int i=0;i<200;i++)
{
x = rand.nextInt(Gdx.graphics.getWidth());
y = rand.nextInt(Gdx.graphics.getHeight());
renderer.setColor(Color.DARK_GRAY);
renderer.circle(x, y, 5);
renderer.setColor(Color.GRAY);
renderer.circle(x, y, 3);
}
mapIsCreated = true;
}
renderer.end();
}
Are there any solutions to definitively fix them on the background without blinking/reloading effects ?
If more details are needed, please let me know.

You never seem to clear your screen.
You should call the following lines at the start of your render method:
// This is black, you can choose any color, technically one call is enough
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
// This line clears the screen (more precisely the color buffer, there are others but this one should be fine)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Now, since it looks like you only want to generate them randomly once create them once in your initialization method (like the create method) and save them in an array/Collection:
// Global field
Array<Vector2> circlePositions = new Array<>();
// initialization method
renderer = new ShapeRenderer();
Random rand = new RandomXS128();
for (int i = 0; i < 200; i++)
{
circlePositions.add(
new Vector2(
rand.nextInt(Gdx.graphics.getWidth()),
rand.nextInt(Gdx.graphics.getHeight())));
circlePositions.add(
new Vector2(
rand.nextInt(Gdx.graphics.getWidth()),
rand.nextInt(Gdx.graphics.getHeight())));
}
Then in your render method you can draw your circles like this:
Gdx.gl.glClearColor(0f, 0f, 0f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.begin(ShapeType.Filled);
for (int i = 0; i < circlePositions.size; i++)
{
Vector2 pos = circlePositions.get(i);
if (i % 2 == 0)
{
renderer.setColor(Color.DARK_GRAY);
renderer.circle(pos.x, pos.y, 5);
} else
{
renderer.setColor(Color.GRAY);
renderer.circle(pos.x, pos.y, 3);
}
}
renderer.end();
If you don't want to redraw everything at e.g. 60 fps, then take a look at non continues rendering.

Related

Processing - rendering shapes is too slow

I have been doing a small little project using Processing, and the effect I wanted to achieve was a kind of "mountains" forming and moving, using Perlin Noise with the noise() function, with 2 parameters.
I was originally using a image for the background, but for illustrational purposes, I made the background black, and it's basically the same effect.
My issue is that I want to have a "history" of the mountains because they should fade away after some time, and so I made a history of PShapes, and draw the history and update it each frame.
Updating it is no issue, but drawing the PShapes seems to take a lot of time, reducing the frame rate from 60 to 10 when the length of the history is 100 elements.
Below is the code I used :
float noise_y = 0;
float noise_increment = 0.01;
// increment x in the loop by this amount instead of 1
// makes the drawing faster, since the PShapes have less vertices
// however, mountains look sharper, not as smooth
// bigger inc = better fps
final int xInc = 1;
// maximum length of the array
// bigger = less frames :(
final int arrLen = 100;
int lastIndex = 0;
PShape[] history = new PShape[arrLen];
boolean full = false;
// use this to add shapes in the history
PShape aux;
void setup() {
size(1280, 720);
}
void draw() {
background(0);
// create PShape object
aux = createShape();
aux.beginShape();
aux.noFill();
aux.stroke(255);
aux.strokeWeight(0.5);
for (float x = 0; x < width + xInc; x = x + xInc) {
float noise = noise(x / 150, noise_y) ;
// get the actual y coordinate
float y = map(noise, 0, 1, height / 2, 0);
// create vertex of shape at x, y
aux.vertex(x, y);
}
aux.endShape();
// push the current one in the history
history[lastIndex++] = aux;
// if it reached the maximum length, start it over ( kinda works like a queue )
if (lastIndex == arrLen) {
lastIndex = 0;
full = true;
}
// draw the history
// this part takes the MOST TIME to draw, need to fix it.
// without it is running at 60 FPS, with it goes as low as 10 FPS
if (full) {
for (int i = 0; i < arrLen; i++) {
shape(history[i]);
}
} else {
for (int i = 0; i < lastIndex; i++) {
shape(history[i]);
}
}
noise_y = noise_y - noise_increment;
println(frameRate);
}
I have tried to use different ways of rendering the "mountains" : I tried writing my own class of a curve and draw lines that link the points, but I get the same performance. I tried grouping the PShapes into a PShape group object like
PShape p = new PShape(GROUP);
p.addChild(someShape);
and I got the same performance.
I was thinking of using multiple threads to render each shape individually, but after doing some research, there's only one thread that is responsible with rendering - the Animation Thread, so that won't do me any good, either.
I really want to finish this, it seems really simple but I can't figure it out.
One possible solution would be, not to draw all the generated shapes, but to draw only the new shape.
To "see" the shapes of the previous frames, the scene can't be cleared at the begin of the frame, of course.
Since the scene is never cleared, this would cause, that the entire view is covered, by shapes over time. But if the scene would be slightly faded out at the begin of a new frame, instead of clearing it, then the "older" shapes would get darker and darker by time. This gives a feeling as the "older" frames would drift away into the depth by time.
Clear the background at the initlization:
void setup() {
size(1280, 720);
background(0);
}
Create the scene with the fade effect:
void draw() {
// "fade" the entire view
blendMode(DIFFERENCE);
fill(1, 1, 1, 255);
rect(0, 0, width, height);
blendMode(ADD);
// create PShape object
aux = createShape();
aux.beginShape();
aux.stroke(255);
aux.strokeWeight(0.5);
aux.noFill();
for (float x = 0; x < width + xInc; x = x + xInc) {
float noise = noise(x / 150, noise_y) ;
// get the actual y coordinate
float y = map(noise, 0, 1, height / 2, 0);
// create vertex of shape at x, y
aux.vertex(x, y);
}
aux.endShape();
// push the current one in the history
int currentIndex = lastIndex;
history[lastIndex++] = aux;
if (lastIndex == arrLen)
lastIndex = 0;
// draw the newes shape
shape(history[currentIndex]);
noise_y = noise_y - noise_increment;
println(frameRate, full ? arrLen : lastIndex);
}
See the preview:

OpenGL GLUT teapot collision with camera

I am making a simple 3D Game in which I am moving in a maze. Now I want to implement collecting teapots which are randomly disturbed in the area. The random drawing of teapots is working perfectly. Now I need to make collisions. For that I would like to use AABB algorithm.
Here is how I initialize coords of teapots so they are disturbed in the maze where isn't wall:
for(int i=0; i<5;i++) {
x = random.nextInt(21);
y = random.nextInt(21);
while(wall[x][y]) {
x = random.nextInt(21);
y = random.nextInt(21);
}
if(!wall[x][y]) {
teapot[x][y] = true;
}
}
Here is how I render teapots:
gl.glLoadIdentity();
//render konviček
for(int i=0;i<21;i++) {
for(int j=0; j<21; j++) {
if(labyrinth.getDonut()[i][j]) {
gl.glTranslatef((float) i, 0f, (float) j);
wallTexture.disable(gl);
gl.glColor3f(1.0f, 0.0f, 0.0f);
glut.glutSolidTeapot(0.2);
gl.glTranslatef((float) -i, 0f, (float) -j);
}
}
}
My question is, how to simply implement the AABB algorithm. I know I am supposed to draw a cube around those teapots, however I can't figure out how to code it.
I already have my checkCollision(double X, double Z); method prepared, so I really just need to draw the box around the teapot and get its coordinates.

Set Camera out from screen libgdx

I am drawing with libgdx and using OrthographicCamera. During render I draw a bit more than the screen can contain. As OrthographicCamera is always centred my camera moves quickly to the last primitive a draw. That's not what I need. So I want my camera to move slowly
What I need is to draw a lot of squares they are in GameRoute.Level[] and to slowly "walk along them" with the camera
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
/*Drawing moving route*/
int x = 0, y = 0;
for(int i = 0; i < Route.Size; i++){
batch.draw(GameRoute.Level[i].Step, x, y);
if (GameRoute.Level[i].getDir() == 0) {
x += 64;
}
if (GameRoute.Level[i].getDir() == 1) {
y += 64;
}
}
camera.position.set(0, 0, 0);
GameRoute.ExpandLevel();
batch.end();
}
Solved, I remade the structure.
Now instead of having a huge moving route, I am moving a small object
Now future need in setting camera.

Poor render performance in LibGDX with hexagonal map

So I am making a simple game using LibGDX which involes a 150*150 hexagonal map, and various types of cell, rocky, clear etc.
Problem is when i load the map, my computer almost completely freezes up and any movement thats supposed to be fluid (character moving, button highlights) take 5+ seconds longer than they should.
Here's the relevant code:
public void render(float deltY){
Gdx.gl.glClearColor(255, 255, 255, 100);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
polygonSpriteBatch.begin();
for (int j = 0; j < 150; j++) {
for (int i = 0; i < 150; i++) {
offset = i%2 == 0 ? multipleX/2 : 0;
if (mc.getMap().getRow(i).getTile(j).getTileType().equals(TileType.Rocky)) {
drawCell(Color.BLACK, j, i);}
if (mc.getMap().getRow(i).getTile(j).getTileType().equals(TileType.Clear)) {
drawCell(Color.LIGHT_GRAY, j, i);}
}
}
polygonSpriteBatch.end();
stage.draw();
}
private void drawCell(Color color, int x, int y) {
polySprite = new PolygonSprite(makePoints(color));
polySprite.setX(mc.getMap().getRow(y).getTile(x).getTilePosition().get_x() * multipleX + offset);
polySprite.setY(mc.getMap().getRow(y).getTile(x).getTilePosition().get_y() * multipleY);
polySprite.draw(polygonSpriteBatch);
}
public PolygonRegion makePoints(Color color){
side = 5;
h = CalculateH(side);
r = CalculateR(side);
multipleX = (float)Math.sqrt(3)*side;
multipleY = side+(side/2);
float[] points = { // vertices
x, y,
x+r, y+h,
x+r, y+side+h,
x,y+side+h+h,
x-r, y+side+h,
x-r, y+h};
return new PolygonRegion(new TextureRegion(getTexture(color)),points
, new short[] { //4 triangles using vertices to make hexagon
0, 1, 5,
1, 4, 2,
5, 1, 4,
2, 3, 4});
}
public Texture getTexture(Color color){
Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pix.setColor(color);
pix.fill();
textureSolid = new Texture(pix);
return textureSolid;
}
I'm new to coding and LibGDX so there's probably something stupid i'm doing. Is there any way to render the map once and only redraw the polygons if they change?
Thanks
Looking at your code, you are computing a square root for each cell, for each rendering pass.
So your code currently involves more than 22500 square root operations for each frame you render and is creating as many objects, that's quite a lot !
You should compute the points for your hexagons only once.

Drawing on Canvas and refreshing

I'm new to Android programming and now I'm trying to make a simple Sea Battle game for one person. Ships are places, player hits the field and see whether the shot hit or not.
Basically, the field looks like this:
The code is:
public void onDraw(Canvas canvas) {
if (getWidth() > getHeight()) {
rebro = getHeight();
} else {
rebro = getWidth(); // the smaller size of screen is "rebro"
}
rebro_piece = rebro / 10; // divide the screen by 10 (to get 10x10 field)
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.game_background));
canvas.drawRect(0, 0, rebro, rebro, background); // draw background
Paint divider = new Paint();
divider.setColor(getResources().getColor(R.color.divider_black));
// drawing divider lines
for (int i=0; i<11; i++) {
canvas.drawLine(0, i*rebro_piece, rebro, i*rebro_piece, divider); // horizontal
canvas.drawLine(i*rebro_piece, 0, i*rebro_piece, rebro, divider); // vertical
}
canvas.drawLine(rebro-1, 0, rebro-1, rebro, divider);
}
That's how I make the "field."
In another class I have a method that collects numbers x and y of a 10×10 array that represents where the ships are placed. For debugging, I need to draw them on my field. Ship coordinates are retrieved in a cycle.
So I wrote a drawShip(int x, int y) method.
On Stack Overflow I've founded a question about "Why I can't paint outside onDraw()?" and I've changed my method to this:
public void drawShip(int x, int y) {
myX = x; //global
myY = y; //global
needToPaintShip = true; //boolean
invalidate(); // refreshing?
needToPaintShip = false;
}
Here needToPaintShip decides whether the redrawing of canvas is needed or not.
Also I've edited the onDraw(Canvas canvas) method:
if(needToPaintShip == true) {
Paint ship = new Paint();
ship.setColor(getResources().getColor(R.color.ship_color));
Log.d(TAG, "onDraw(): rebro_piece = " + rebro_piece + " , myX = "+ myX + " , myY = " + myY); // I only get the last coordinates!
Rect r = new Rect(myX*(rebro_piece),myY*rebro_piece, myX*(rebro_piece+1), myY*(rebro_piece+1));
canvas.drawRect(r, ship);
}
but the result is awful:
Guys, I'm desperate. How can I fix this and make "ships" be drawn on the field?
Why do you set needToPaintShip = false; after calling invalidate()? Don't you need to draw the ship again in subsequent frames?
Also, it seems like this item:
Rect r = new Rect(myX*(rebro_piece),myY*rebro_piece, myX*(rebro_piece+1), myY*(rebro_piece+1));
should probably be:
Rect r = new Rect(myX*(rebro_piece),myY*rebro_piece, (myX+1)*rebro_piece, (myY+1)*rebro_piece));
As for why the ship always appears in the bottom right corner, that depends on what you pass to drawShip(x,y), which isn't shown. Is it possible that you are passing pixel coordinates instead of something in the range [0-10)?

Categories