Partage
  • Partager sur Facebook
  • Partager sur Twitter

Des Freezes courants dans mon jeu

    16 juillet 2019 à 22:21:39

    Bonjour, je suis entrain de coder un genre de petit Voxel. Je rencontre un problème avec la génération du terrain que je fais dans un thread appart. La génération marche très bien mais je rencontre des freezes souvent(environ toutes les 5 secondes) lorsque j'avance dans le monde. Voici les codes:

    public class World {
    
    	private int RENDER_SIZE = 8*Chunk.SIZE;
    	
    	private List<Chunk> chunks = new ArrayList<Chunk>();
    	private List<Vector2f> usedPos = new ArrayList<Vector2f>();
    	
    	SaveLoader sl = new SaveLoader("world");
    
    	public static Noise noise;
    	
    	public World(){
    		
    		noise = new Noise(new Random().nextLong(), 10);
    		
    		new Thread(new Runnable(){
    			
    			public void run(){
    				
    				while(!Main.closeDisplay){
    					
    					System.out.print("");
    					
    					for(int x = -RENDER_SIZE/16; x <= RENDER_SIZE/16; x++){
    						for(int z = -RENDER_SIZE/16; z <= RENDER_SIZE/16; z++){
    							
    							int xx = (int) (x + getPlayerChunk().x);
    							int zz = (int) (z + getPlayerChunk().y);
    							
    							if(usedPos.contains(new Vector2f(xx,zz))) continue;
    							
    							Chunk c = sl.getChunk(xx, zz);
    							
    							if(c == null) c = sl.addChunk(xx, zz);
    							
    							chunks.add(c);
    							usedPos.add(new Vector2f(xx,zz));
    							
    						}	
    					}
    					
    					for(int i = 0; i < usedPos.size(); i++){
    						
    						Vector2f pos = usedPos.get(i);
    						
    						int x = (int) Math.abs(pos.x - getPlayerChunk().x);
    						int z = (int) Math.abs(pos.y - getPlayerChunk().y);
    					
    						if(x > RENDER_SIZE/16 || z > RENDER_SIZE/16){
    							chunks.remove(i);
    							usedPos.remove(i);
    						}
    						
    					}
    					
    				}
    				
    			}
    			
    		}).start();
    		
    	}
    	
    	public static Vector2f getPlayerChunk(){
    		
    		int x = (int) (Main.xCam/Chunk.SIZE);
    		int z = (int) (Main.zCam/Chunk.SIZE);
    		
    		if(Main.xCam < 0) x -= 1;
    		if(Main.zCam < 0) z -= 1;
    		
    		return new Vector2f(x,z);
    		
    	}
    	
    	public void render(){
    		
    		/*for(int x = -RENDER_SIZE/16; x <= RENDER_SIZE/16; x++){
    			for(int z = -RENDER_SIZE/16; z <= RENDER_SIZE/16; z++){
    				
    				int xx = (int) (x + getPlayerChunk().x);
    				int zz = (int) (z + getPlayerChunk().y);
    				
    				Chunk c = sl.getChunk(xx, zz);
    				
    				if(c == null) c = sl.addChunk(xx, zz);
    				
    				c.render();
    				
    			}	
    		}*/
    		
    		
    		for(int i = 0; i < chunks.size(); i++){
    			chunks.get(i).render();
    		}
    		
    	}
    	
    	public void update(){
    		
    	}
    	
    }
    
    public class SaveLoader {
    
    	String worldName;
    	
    	public SaveLoader(String name){
    		this.worldName = name;
    		
    		File file = new File("worlds/"+worldName+"/");
    		
    		for(File f : file.listFiles()){
    			f.delete();
    		}
    	}
    	
    	public Chunk addChunk(int x, int z){
    		
    		File file = new File("worlds/"+worldName+"/"+x+";"+z+".cfile");
    		
    		try {
    			file.createNewFile();
    			
    			List<Block>  blocks = Chunk.generateChunk(x, z, World.noise);
    			
    			Chunk c = new Chunk(blocks, new Vector2f(x,z));
    			
    			FileWriter writer = new FileWriter(file);
    			BufferedWriter bw = new BufferedWriter(writer);
    
    			for(int i = 0; i < blocks.size(); i++){
    				
    				Block b = blocks.get(i);
    				
    				int xx = (int)b.pos.x;
    				int yy = (int)b.pos.y;
    				int zz = (int)b.pos.z;
    				
    				bw.write(xx+";"+yy+";"+zz+":"+b.getClass().getName());
    				if(i < blocks.size()-1) bw.newLine();
    			}
    			
    			bw.close();
    			writer.close();
    			
    			return c;
    		} catch (IOException e) {
    			e.printStackTrace();
    			return null;
    		}
    		
    	}
    	
    	public Chunk getChunk(int x, int z){
    		
    		File file = new File("worlds/"+worldName+"/"+x+";"+z+".cfile");
    		
    		if(!file.exists()) return null;
    		
    		try{
    			
    			List<Block> blocks = new ArrayList<Block>();
    			
    			BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
    			String line = reader.readLine();
    			
    			while(line != null){
    				
    				String[] coords = line.split(":")[0].split(";");
    
    				int blockX = Integer.parseInt(coords[0]);
    				int blockY = Integer.parseInt(coords[1]);
    				int blockZ = Integer.parseInt(coords[2]);
    				
    				Class c = Class.forName(line.split(":")[1]);
    				Constructor constructor = c.getConstructor(Vector3f.class);
    				
    				Block block = (Block) constructor.newInstance(new Vector3f(blockX,blockY,blockZ));
    				
    				blocks.add(block);
    				
    				line = reader.readLine();
    			}
    			
    			return new Chunk(blocks, new Vector2f(x,z));
    			
    		}catch(IOException | ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e){
    			e.printStackTrace();
    			return null;
    		}
    		
    	}
    	
    	
    }
    
    public class Chunk {
    
    	public static final int SIZE = 16;
    	public static final int HIGH = 90;
    	
    	private int vbo;
    	private FloatBuffer buffer;
    	private int bufferSize;
    	
    	public Vector2f pos;
    	
    	private Block[][][] blocks;
    	
    	public boolean isLoaded = false;
    	
    	public Chunk(List<Block> blocks, Vector2f pos){
    		this.pos = pos;
    		
    		this.blocks = new Block[SIZE][HIGH][SIZE];
    		
    		for(Block b : blocks){
    			
    			int posX = ((int)Math.abs(b.pos.x))%Chunk.SIZE;
    			int posY = ((int)Math.abs(b.pos.y));
    			int posZ = ((int)Math.abs(b.pos.z))%Chunk.SIZE;
    			
    			if(b.pos.x < 0) posX -= 1;
    			if(b.pos.z < 0) posZ -= 1;
    			
    			if(posX == -1) posX = Chunk.SIZE-1;
    			if(posZ == -1) posZ = Chunk.SIZE-1;
    			
    			
    			this.blocks[posX][posY][posZ] = b;
    		}
    		
    		loadChunk();
    	}
    	
    	public Vector2f getOrigin(){
    		return new Vector2f(pos.x*Chunk.SIZE,pos.y*Chunk.SIZE);
    	}
    	
    	public static List<Block> generateChunk(int posX, int posZ, Noise noise){
    		
    		List<Block> blocks = new ArrayList<Block>();
    	
    		for(int x = 0; x < SIZE; x++){
    			for(int z = 0; z < SIZE; z++){
    				
    				int xx = posX * SIZE + x;
    				int zz = posZ * SIZE + z;
    				int yy = (int) (noise.getNoise(xx+10000, zz+10000, 10)*5f) + 64;
    				//int yy = 64;
    				
    				for(int y = 0; y < yy; y++){
    					
    					/*float proba = 0.26f * yy/y < 0.32f ? 0.2f * yy/y : 0.32f;
    					
    					if(proba < 0.26f) proba = 0.26f;*/
    					
    					/*if(y > 7){
    						int octave = (int) (4 );
    						
    						if(noise.get3DNoise(xx, y, zz, octave) < 0.31f) continue;
    						
    					}*/
    					
    					Vector3f pos = new Vector3f(xx, y, zz);
    					
    					if(y == yy - 1)blocks.add(new GrassBlock(pos));
    					else blocks.add(new Stone(pos));
    				}
    				
    			}		
    		}
    		return blocks;
    	}
    	
    	public void loadChunk(){
    	
    		buffer = BufferUtils.createFloatBuffer(SIZE*HIGH*SIZE * 6*4*7);
    		
    		for(int x = 0; x < SIZE; x++){
    			for(int y = 0; y < HIGH; y++){
    				for(int z = 0; z < SIZE; z++){
    					
    					
    					Block block = getBlock(x,y,z);
    					if(block == null) continue;
    					
    					boolean right = false, left = false, up = false, down = false, front = false, back = false;
    					
    					left = getBlock(x-1,y,z) == null;
    					right = getBlock(x+1,y,z) == null;
    					up = getBlock(x,y+1,z) == null;
    					down = getBlock(x,y-1,z) == null;
    					front = getBlock(x,y,z+1) == null;
    					back = getBlock(x,y,z-1) == null;
    					
    					if(pos.x < 0){
    						left = getBlock(x+1,y,z) == null;
    						right = getBlock(x-1,y,z) == null;
    					}if(pos.y < 0){
    						front = getBlock(x,y,z-1) == null;
    						back = getBlock(x,y,z+1) == null;
    					}
    					
    					
    					
    					float[] data;
    					
    					if(left){
    						data = block.leftData();
    						buffer.put(data);
    						bufferSize += 4;
    					}if(right){
    						buffer.put(data = block.rightData());
    						bufferSize += 4;
    					}if(up){
    						buffer.put(data = block.upData());
    						bufferSize += 4;
    					}if(down){
    						buffer.put(data = block.downData());
    						bufferSize += 4;
    					}if(front){
    						buffer.put(data = block.frontData());
    						bufferSize += 4;
    					}if(back){
    						buffer.put(data = block.backData());
    						bufferSize += 4;
    					}
    					data = null;
    				}
    			}
    			
    		}
    		buffer.flip();
    		isLoaded = true;
    	}
    	
    	public void reload(){
    		unload();
    		loadChunk();
    	}
    	
    	public void unload(){
    		isLoaded = false;
    		bufferCreated = false;
    		glDeleteBuffers(vbo);
    	}
    	
    	public Block getBlock(int x, int y, int z){
    		if(x < 0 || x >= SIZE || z < 0 || z >= SIZE){
    			
    			int xx = (int) (Chunk.SIZE * pos.x + x);
    			int zz = (int) (Chunk.SIZE * pos.y + z);
    			
    			if(pos.x < 0){
    				xx = (int) (Chunk.SIZE * (pos.x+1) - x-1);
    			}if(pos.y < 0){
    				zz = (int) (Chunk.SIZE * (pos.y+1) - z-1);
    			}
    			
    			//return world.getBlock(xx,y,zz);
    			return null;
    		}if(y < 0 || y >= Chunk.HIGH) return null;
    		return blocks[x][y][z];
    	}
    	
    	boolean bufferCreated = false;
    	public void createBuffer(){
    		vbo = glGenBuffers();
    
    		glBindBuffer(GL_ARRAY_BUFFER, vbo);
    		glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
    		
    		bufferCreated = true;
    		
    	}
    	
    	public void render(){
    		
    		if(!bufferCreated) createBuffer();
    		
    		glEnableVertexAttribArray(0);
    		glEnableVertexAttribArray(1);
    		
    		glBindBuffer(GL_ARRAY_BUFFER, vbo);
    		glVertexAttribPointer(0, 3, GL_FLOAT, false, 7*4, 0);
    		glVertexAttribPointer(1, 4, GL_FLOAT, false, 7*4, 12);
    		
    		glDrawArrays(GL_QUADS, 0, bufferSize);
    		
    		glDisableVertexAttribArray(0);
    		glDisableVertexAttribArray(1);
    	}
    	
    	public void update(){
    		
    	}
    	
    }
    

    Je sais que ça fait beaucoup de code à lire mais si quelqu'un pouvait m'aider ce serait vraiment sympa :)

    Merci d'avance.



    -
    Edité par Rafa34 16 juillet 2019 à 22:23:12

    • Partager sur Facebook
    • Partager sur Twitter
      17 juillet 2019 à 11:17:31

      Bonjour,

      Lorqu'il y a beaucoup d'éléments affichés à l'écran et que l'on rencontre des ralentissements il y a plusieurs techniques pour résoudre le problème :

      1- Créer un nombre d'objets définis dans un tableau et les supprimer lorsqu'ils ne sont plus à l'écran (on fait ça pour les jeux en 2D). Exemple ici (voir board.java :

      http://zetcode.com/tutorials/javagamestutorial/collision/

      2- Utiliser le pattern MVC (modèle vue controler) lorsque l'on a beaucoup de classe, cela évite les ralentissements

      3- Utiliser des threads

      Dans ton cas, j'essaierai d'utiliser un deuxième thread pour les chunks ou de faire un nombre limité de block dans un tableau (sans forcément les effacer si c'est un jeu en 3D).

      • Partager sur Facebook
      • Partager sur Twitter

      Des Freezes courants dans mon jeu

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown