2024년 11월 8일 금요일

시티즈 스카이라인 2 에서 내 도시 다른 사람에게 공유 / 다른 사람의 도시 받기

 영상으로 대신합니다.


먼저, 내 도시를 다른 사람에게 공유하는 방법




다른 사람 도시 받아 불러오는 방법





2024년 8월 11일 일요일

시티즈 스카이라인 2 세이브 폴더 찾기 Where is the "Cities Skylines 2" save files

 사진과 같이 ~


먼저, 폴더 창을 엽니다. 아무 폴더나 상관없음.

폴더창 상단에 보면 주소창이 있는데,

빈 곳을 클릭하면 키보드로 입력할 수 있게 바뀜.


%appdata% 라고 입력


Roaming 폴더로 들어가지는데, 그 상단의 AppData 폴더로 이동 
(아래 사진 참고)


LocalLow 폴더로 들어가기


시티즈 스카이라인 2 제작사인 Colossal Order





들어가면, 긴 숫자로 된 폴더가 하나, 혹은 여러개가 보인다.
실제로는, 스팀 계정 수만큼 폴더가 있는데, 
자기꺼 찾아야 됨.
혼자 쓰는 컴퓨터이면 폴더가 하나일 것.


들어가면
드디어 세이브 파일이 보인다.
이 곳에 다른 세이브 파일을 넣어도 되고
내 것을 여기서 찾아 공유해도 되고.

세이브 하나가 파일 2개로 되어 있음에 유의 ! cok, cid 파일 한쌍이 세이브 하나 !



샘플로 내 최초 100만 인구 달성 도시를 공유한다.


Paradox Mods 로 도시 공유가 가능해졌기 때문에, 그 링크를 먼저 남긴다.

https://mods.paradoxplaza.com/mods/87348/Windows



파일로 받고 싶어하시는 분들을 위해...

원드라이브 링크 : Gilbert_20241027_0017.zip





2024년 6월 30일 일요일

2024년 6월 21일 금요일

자바로 사운드, 음악 파일 (wav) 재생 Play sound or music file (wav) with java codes

 대뜸 예제 첨부

일단 아래와 같은 클래스를 만들어 둔다.


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;
    }
}



이제 이걸 써먹으면 된다.



File file = new File("fire_beam.wav");
new SoundClip(file.toURI().toURL()).play();



문제가 있는데, 사운드를 재생하는 동안 쓰레드를 독차지하고 있게 된다.

즉, 재생하는 동안 그 아래 코드들은 사운드 재생이 끝날 때까지 실행되지 않는다.

그래서 별도 쓰레드를 많이 만들어 두어서 재생 작업을 쓰레드에서 해야 된다.



2024년 6월 16일 일요일

Beton B-Day - The lesser (Beton B-Day 를 더 쉽게 !)

  기존 Beton Brutal 의 DLC Beton Bath 는 너무 난이도가 어려웠습니다.


Beton Brutal

https://store.steampowered.com/app/2330500/BETON_BRUTAL/


이 Beton Brutal 게임은 Custom Map 기능을 제공합니다.
그리하여, Beton B-Day 낙오자들을 위한 커스텀 맵을 만들었습니다.


Beton B-Day - The lesser










플레이 풀 영상