Image flickering when moved (slick2d)

Hello! I’ve got an Image object (slick2d) in my game.

I created it like this: Image image = new Image (1000,1000)

I then got the Graphics from it and painted it. I flushed the graphics afterwards.

When I render it to the screen it looks great. However, when I move it, it flickers. It brightens for a slit second and then goes back to normal.

I must add that I’m not rendering the entire image. I always render a part of it, like this:

minimapImage.draw(X1, Y1, X2, Y2, x1, y1, x2, y2);

Like i said, it looks great when stationary, it’s only when the lovercase x & y are changed that I get flickering. Ideas anyone?

Does the flickering happen only when moving at float positions? Or do you already move the image at int positions. If your image is being rendered at float positions (0.23, 123,1233 etc), render the image with integers (0, 123)

Sadly, yes, all parameters are integers. Must be something else.

I get an ugly stripe across the image as well. Looks like a VHS-movie.

Do you have this problem with small images to?

I don’t know, will try and see. I am rendering 32*32 images that looks good, but using a different method for them. It looks better in fullscreen though, but still a bit ugly.

Showing us some rendering code may help us identify the problem.

… and some screenshots maybe

I remembered when I used Slick2D(you should really switch to LibGDX as you are wasting your time with that buggy crap). Rendering large images was glitchy.
It was solved by using the BigImage class.

Retro-Pixel Castles takes offense to that. :stuck_out_tongue:

and you don’t need BigImage for 1000x1000 images, I load 3 2048x2048 images I break down into about 3 dozen spritesheets in RPC with no issues what so ever.

While switching to LibGDX might be worthwile, calling Slick2D buggy crap is a big NONO and very disrespectful!

Have you tried rendering an image that’s a power of two? There could possibly be something in your rendering pipeline that hates non power of two images.

Slick doesn’t support non PoT textures, so that’s not an issue.

OP post some screenshots of what you mean! It may be texture bleeding if you are using sprite sheets but more will be needed to start debugging your issue.

I can’t really post screenshots, since I can’t capture the actual movement. But the bright colors in it glows and bleeds and a vertical stripe appears in the middle of the picture. I’m using it as a minimap for my 2d tile strategy game.

It’s created like this:

Constructor (){

Image minimap = new Image(mapTileSizeX, mapTileSizeY)

Graphics g = minimap.getGraphics();

//draw individual pixels
for (every tile Y)
for (every tile X)
g.drawRect(Color, Y, X, 1, 1)

g.flush

g.destroy.

}

Render (X1, X2, Y1, Y2, x1, x2, y1, y2){
minimapImage.draw(X1, Y1, X2, Y2, x1, y1, x2, y2);
}

That’s all there is to it.

Like I said, it looks ok in fullscreen, so maybe it’s a local problem on my GPU?

But perhaps I’m using the Image class wrong somehow? Perhaps it’s some setting in my container? My display? StartUse, EndUse?

You should post the actual code, so we can see if there’s any mistakes you’re not thinking about.

But, having said that; drawRect() draws an outline of a box, not a solid box. You should use fillRect()

buuut, having said that as well; you should not be drawing every single pixel of your map with geometry, that’s massively wasteful. Chances are it’s also the cause of the flicker when the floats positioning them are rounding off funny.

If you still want to draw out the map in this fashion (not knowing much about your game, I’ll just try to replicate what you’re doing) you should do this instead. This will create an offscreen buffer you can draw to, then draw to it and assign it to an image you can render in the game.


	int mapHeight = ??? //Your map height
	int mapWidth = ??? //Your map width
	Image mapImage;
	ImageBuffer mapBuffer = new ImageBuffer(mapWidth, mapHeight);

	private void createMap(){
		for (int x = 0; x < mapWidth; x++) {
			for (int y = 0; y < mapHeight; y++) {
				mapBuffer.setRGBA(x, y, red, green, blue, alpha);
			}
		}
		mapImage = mapBuffer.getImage(Image.FILTER_NEAREST); //I assume you want nearest neighbor filtering for this.
	}

	public void render(){
		mapImage.draw(x,y);
	}

Ok, just wanted to spare you this big chunk of code. This isn’t just the minimap. The minimap is just a variable of my actual tileMap. Feel free to point out any errors.



package model;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

import controller.MinimapWindow;
import controller.SettlementWindow;
import data.ActiveSettlementSettings;
import data.GlobalConstants;

class ActiveMap {

	private Tile tiles[][];
	private Image tileImages[];
	private Image minimapImage;
	
	private final int WIDTH;
	private final int HEIGHT;
	private final int TILE_SIZE;
	
	ActiveMap(ActiveSettlementSettings settings, GlobalConstants gc) {
		
		WIDTH = settings.MAP_TILE_WIDTH();
		HEIGHT = settings.MAP_TILE_HEIGHT();
		TILE_SIZE = gc.GAME_SCALE()*gc.TILE_SIZE();
		tiles = new Tile[WIDTH][HEIGHT];
		
		try {
			tileImages = new Image[4];
			tileImages[0] = new Image("res/model/tiles/Sdirt1.png", false, Image.FILTER_NEAREST);
			tileImages[1] = new Image("res/model/tiles/Sdirt2.png", false, Image.FILTER_NEAREST);
			tileImages[2] = new Image("res/model/tiles/Sdirt3.png", false, Image.FILTER_NEAREST);
			tileImages[3] = new Image(32,32);
			
			minimapImage = new Image(WIDTH, HEIGHT);

		} catch (SlickException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//generates a random map
		for (int y = 0; y < tiles.length; y++){
			for (int x = 0; x < tiles[0].length; x++){
				tiles[y][x] = new Tile ((short) ((Math.random()*3) ));
				}
			}
		
		tiles[15][15].setType((short)3);
		tiles[15][16].setType((short)3);
		tiles[15][17].setType((short)3);
		
		tiles[50][50].setType((short)3);
		tiles[50][51].setType((short)3);
		tiles[50][52].setType((short)3);
		tiles[51][50].setType((short)3);
		tiles[52][50].setType((short)3);
		tiles[53][50].setType((short)3);
		
		tiles[500][500].setType((short)3);
		tiles[500][501].setType((short)3);
		tiles[500][502].setType((short)3);
		tiles[501][500].setType((short)3);
		tiles[502][501].setType((short)3);
		tiles[503][502].setType((short)3);
		
		//paints the minimap image
		try {
			Graphics g = minimapImage.getGraphics();
			for (int y = 0; y < HEIGHT; y++){
				for (int x = 0; x < WIDTH; x++){
					switch (tiles[y][x].getType()){
					case 0: g.setColor(Color.pink); g.fillRect(x,y,1,1);
						break;
					case 1: g.setColor(Color.gray); g.fillRect(x,y,1,1);
						break;
					case 2: g.setColor(Color.yellow); g.fillRect(x,y,1,1);
						break;
					default:g.setColor(Color.black); g.fillRect(x,y,1,1);
					}
				}
			}
			g.flush();
			g.destroy();
		} catch (SlickException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	void update(){
		
	}
	
	void render (SettlementWindow window){
		
		short tempType;
		
		int tileJump = (int) (TILE_SIZE*window.getZoom());
		int firstDrawX = (int) (window.getFrameX1() - (window.getX1()%TILE_SIZE)*window.getZoom());
		int firstDrawY = (int) (window.getFrameY1() - (window.getY1()%TILE_SIZE)*window.getZoom());
		
		int firstTileX = (int) Math.ceil(window.getX1()/TILE_SIZE);
		int firstTileY = (int) Math.ceil(window.getY1()/TILE_SIZE);
		
		int tilesToDrawX = (int) Math.ceil(((window.getFrameX2()-window.getFrameX1())-firstDrawX)/tileJump);
		int tilesToDrawY = (int) Math.ceil(((window.getFrameY2()-window.getFrameY1())-firstDrawY)/tileJump);
		
		//preparations
		
		for (int y = 0; y <= tilesToDrawY; y++){
			for (int x = 0; x <= tilesToDrawX; x++){
				tempType = tiles[firstTileY + y][firstTileX + x].getType();
				tileImages[tempType].draw(firstDrawX + x*tileJump, firstDrawY + y*tileJump, tileJump, tileJump);

			}
		}
		
		
	}
	
	void renderMini (MinimapWindow window){
		minimapImage.startUse();
		minimapImage.drawEmbedded(window.getFrameX1(), window.getFrameY1(), window.getFrameX2(), window.getFrameY2(), 
				window.getX1(), window.getY1(), window.getX2(), window.getY2());
		minimapImage.endUse();
	}
	
}