영상으로 대신합니다.
먼저, 내 도시를 다른 사람에게 공유하는 방법
다른 사람 도시 받아 불러오는 방법
HJOW의 신버전 블로그입니다. 이 블로그는 제 관심사에 해당하는 기사, 동영상 등을 퍼오거나, 작성하는 곳으로, 마음껏 퍼가셔도 됩니다.
영상으로 대신합니다.
먼저, 내 도시를 다른 사람에게 공유하는 방법
다른 사람 도시 받아 불러오는 방법
사진과 같이 ~
먼저, 폴더 창을 엽니다. 아무 폴더나 상관없음.
폴더창 상단에 보면 주소창이 있는데,
빈 곳을 클릭하면 키보드로 입력할 수 있게 바뀜.
샘플로 내 최초 100만 인구 달성 도시를 공유한다.
Paradox Mods 로 도시 공유가 가능해졌기 때문에, 그 링크를 먼저 남긴다.
https://mods.paradoxplaza.com/mods/87348/Windows
파일로 받고 싶어하시는 분들을 위해...
원드라이브 링크 : Gilbert_20241027_0017.zip
대뜸 예제 첨부
일단 아래와 같은 클래스를 만들어 둔다.
import java.io.File;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
/** Class to play wav file */
public class SoundClip implements Serializable
{
    private static final long serialVersionUID = -4189707921602251694L;
    protected URL    url;
    protected double volume = 100.0;
    protected transient boolean flagStop = false;
    /** Create instance with URL to get wav file */
    public SoundClip(URL url)
    {
    	this.url = url;
    }
    /** Create instance with wav file */
    public SoundClip(File f) throws MalformedURLException
    {
    	this(f.toURI().toURL());
    }
    /** Play wav sound now */
    public void start()
    {
    	if(url == null) return;
    	flagStop = false;
    	AudioInputStream inp1 = null;
    	AudioInputStream inp2 = null;
    	SourceDataLine   line = null;
    	try
    	{
    		byte[] buffer = new byte[4096];
        	int reads;
        	
        	// Load wav from URL
        	inp1 = AudioSystem.getAudioInputStream(url);
    		
        	if(flagStop) return; // Return when stop() method called
        	
        	// Detect audio format of wav file and get converted input stream
    		AudioFormat formatBase = inp1.getFormat();
    		AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, formatBase.getSampleRate(), 16, formatBase.getChannels(), formatBase.getChannels() * 2, formatBase.getSampleRate(), false);
        	inp2 = AudioSystem.getAudioInputStream(format, inp1);
        	
        	if(flagStop) return; // Return when stop() method called
        	
        	// Create SourceDataLine to play wav
        	DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        	Mixer mixer = AudioSystem.getMixer(null);
        	line = (SourceDataLine) mixer.getLine(info);
    		
    		if(flagStop) return; // Return when stop() method called
    		
    		// Open SourceDataLine
        	line.open(format);
        	
        	// This must be in here (after line opened !)
    		FloatControl ctrl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN);
			ctrl.setValue((float) (20.0f * Math.log10(volume / 100.0)));
        	
			// Play Start
        	line.start();
        	
        	while(! flagStop)
        	{
        		reads = inp2.read(buffer, 0, buffer.length);
        		if(reads < 0) break; // Return when stop() method called
        		line.write(buffer, 0, reads);
        	}
        	
        	// END
        	line.drain();
        	line.stop();
    	}
    	catch(Exception ex)
    	{
    		ex.printStackTrace();
    	}
    	finally
    	{
    		try { line.close();  } catch(Exception ex) {}
        	try { inp2.close();  } catch(Exception ex) {}
        	try { inp1.close();  } catch(Exception ex) {}
        	flagStop = false;
    	}
    }
    /** Play wav sound now */
	public void play()
    {
    	start();
    }
	/** Stop playing */
    public void stop()
    {
    	flagStop = true;
    }
    /** Get volume (0 ~ 100) default 100 */
    public double getVolume()
    {
		return volume;
    }
    /** Set volume (0 ~ 100) default 100 */
    public void setVolume(double volume)
    {
	this.volume = volume;
	if(this.volume < 0) this.volume = 0;
    }
    /** Get URL of wav file */
    public URL getUrl() {
        return url;
    }
    /** Set wav file */
    public void setUrl(URL url) {
        this.url = url;
    }
}
이제 이걸 써먹으면 된다.
문제가 있는데, 사운드를 재생하는 동안 쓰레드를 독차지하고 있게 된다.
즉, 재생하는 동안 그 아래 코드들은 사운드 재생이 끝날 때까지 실행되지 않는다.
그래서 별도 쓰레드를 많이 만들어 두어서 재생 작업을 쓰레드에서 해야 된다.
기존 Beton Brutal 의 DLC Beton Bath 는 너무 난이도가 어려웠습니다.
Beton Brutal
https://store.steampowered.com/app/2330500/BETON_BRUTAL/