을 적절한 자막 표시의 경우 (텍스트의 벽을 사전에 죄송 아래 설명) 다음과 같은 일을 할 수있는 :
String[] subtitles = loadStrings("subtitles.txt");
int currentFrame = 0;
int subtitleIndex = -1;
int startFrame = -1, endFrame = -1;
int fontSize = 10; //change to suit your taste
String[] currentSubtitle;
...
//draw loop start:
//video drawing code goes here
if(currentFrame > endFrame){ //update which subtitle is now/next
subtitleIndex++;
startFrame = int(subtitles[subtitleIndex].split("\\}\\{")[0].substring(1));
endFrame = int(subtitles[subtitleIndex].split("\\}\\{")[1].split("\\}")[0]);
currentSubtitle = subtitles[subtitleIndex].split("\\}")[2].split("\\|");
}
if(currentFrame >= startFrame && currentFrame <= endFrame){
for(int i = 0; i < currentSubtitle.length; i++){
text(currentSubtitle[i], width/2, height - fontSize * (currentSubtitle.length - i));
}
}
currentFrame++;
//draw loop end
것은 아마 그, 그래서 여기에 당신에게 꽤 협박 보이는 일부 워크를 통해 해설입니다. 프로그램 유형은 state machine입니다. 자막을 표시하는 상태인지 여부입니다. 나중에 코드를 디자인 할 때이를 염두에 두겠습니다. 먼저 변수를 선언하고 초기화해야합니다.
첫 번째 줄은 loadStrings() 함수를 사용하며이 함수는 텍스트 파일을 읽고 String
배열을 반환합니다. 배열의 각 요소는 파일의 한 줄입니다. 물론 파일에 맞게 파일 이름을 변경해야합니다.
코드에서 current_frame
이라는 변수를 사용합니다.이 코드는 매우 좋은 아이디어이지만 자바 코딩 규칙에 맞게 currentFrame
으로 이름을 변경했습니다. 0부터 시작하고, 나중에 코드가 모든 프레임 디스플레이에서 증가합니다. 이 변수는 자막 시퀀스에있는 위치와 표시 할 메시지 (있는 경우)를 알려줍니다.
각 자막이 시작하고 끝나는 프레임의 정보가 문자열로 인코딩되기 때문에이를 코드에 통합하는 것은 약간 까다 롭습니다. 지금은 "현재"자막 - 현재 표시 중이거나 다음에 표시 될 자막 - 시작 및 종료 시점을 나타내는 변수를 만들어 보겠습니다.또한 subtitles
배열의 어떤 요소가 "현재"자막인지를 추적하는 색인을 생성합니다. 이 변수는 모두 -1
에서 시작하며 약간 이상하게 보일 수 있습니다. currentFrame
을 0
으로 초기화했지만, 실제로는 "초기"값이 아닙니다. 0
을 선택한 경우 첫 번째 부제가 프레임 0
에서 시작되고 끝나지 않을 수 있고 다른 양수가 많은 의미가 없으므로 사실이 아닙니다. -1
은 종종 변수가 실제로 사용되기 전에 대체 될 더미 인덱스로 사용되기 때문에 여기서도이를 수행 할 것입니다.
이제 최종 변수는 currentSubtitle
입니다. 즉각적인 생각은이 배열을 String
배열이 아닌 보통 String
이어야한다는 것입니다. 그러나 각 자막은 파이프 (|
) 기호로 분할해야 할 수도 있으므로 각 자막은 실제로 여러 줄의 텍스트를 나타낼 수 있으므로 안전을 위해 배열을 만듭니다. 일부 자막은 단일 요소 배열 일 수도 있지만 괜찮습니다.
이제 어려운 부분을 위해!
아마도 코드가 (조건이 충족 될 경우) 각 반복에서 해당 비디오 프레임이 화면에 그려되고 그 루프의 일종을해야합니다, 자막은 그것의 맨 위에 그려집니다. 나는 당신의 질문의 일부가 아니므로 비디오 부분을 생략했습니다.
우리는 뭔가를하기 전에 변수의 일부가 아직 실제 값을 가지고 있지 않다는 것을 기억해야합니다. 전에 나온 -1
의 값을 설정해야합니다. 드로잉 루프의 기본 논리는 1) 자막을 그릴 필요가 있는지 파악한 후 그려야하며, 2) "현재"자막을 배열의 다음 자막으로 이동해야하는지 파악합니다. 루프를 통해 처음으로 아직 그것에 대해 아무것도 모르기 때문에 # 2 먼저 해봅시다! 다음 자막으로 이동하기위한 기준 (일반적으로)은 현재 제목의 끝까지 지나친 것입니다 : currentFrame > endFrame
. 그것이 사실이라면 우리는 모든 변수를 다음 부제로 옮겨야합니다. subtitleIndex
은 쉽습니다. 우리는 하나를 추가하고 완료했습니다. 나머지는 쉽지 않습니다. 나는 그것이 역 겨 운다는 것을 안다. 그러나 나는 흐름을 깨지 않기 위해 끝 부분에서 이야기 할 것이다. 그냥 기다릴 수없는 경우 아래쪽으로 건너 뜁니다.
(필요한 경우) 모든 변수를 현재 자막과 관련되도록 변경 한 후에는 실제 표시해야합니다. 두 번째 if
문은 현재 자막의 프레임 경계 안에 "있는지"여부를 확인합니다. currentSubtitle
변수는 지금 바로 표시되어야하는 자막을 참조 할 수 있거나 시퀀스의 다음 자막 만 참조 할 수 있으므로이 프레임에 대해 어느 것이 적합한 지 확인하기 위해 몇 가지 검사를 수행해야합니다. 그것은 두 번째입니다. if
성명서 - 우리가 시작을 지나서 끝나기 전에 부제를 표시해야합니다! 우리의 currentSubtitle
변수는 배열이므로, 직접 표시 할 수는 없습니다. 우리는 그것을 반복하고 각 요소를 별도의 줄에 표시해야합니다. text()
명령에 대해 언급 했으므로 여기서는 깊이 들어가지 않을 것입니다. 까다로운 비트는 여러 행에 있어야하기 때문에 텍스트의 y 좌표입니다. 첫 번째 요소가 두 번째 요소보다 위에 있고 세 번째 요소 위에 있어야합니다. 이렇게하려면 y 좌표는 우리가 어느 요소에 있는지에 따라 달라지며, i
으로 표시됩니다. fontSize
의 값을 변경하여 행간의 차이를 조정할 수 있습니다. 그게 당신의 취향에 달려 있습니다. 당신이 설정 한 숫자가 픽셀 단위의 선 높이와 동일하다는 것을 알아라.
위의 설명을 원하지 않는 지저분한 비트가 있습니다. 이 코드는 String
의 split() 메서드에 따라 달라지며 분할하려는 문자열에 대해 수행되며 문자열을 분할하는 방법 (regex)을 나타내는 매개 변수로 문자열을 사용합니다.파일의 자막 줄에서 startFrame을 가져 오려면 중괄호를 통해 분할해야합니다. 그 이유는 숫자 사이의 구분선이기 때문입니다. 첫째, 우리는 "} {"이 발생하는 모든 곳에서 첫 번째 숫자 바로 다음 (그리고 두 번째 바로 전에) 문자열을 분할합니다. split()
은 배열을 반환하기 때문에 대괄호 사이의 인덱스를 사용하여 배열에서 하나의 문자열을 참조 할 수 있습니다. 첫 번째 숫자는 "} {"로 분할하여 첫 번째 문자열 반환에 포함되므로 색인 0
을 사용합니다. split()
은 분리하려는 것을 제거하기 때문에 (예를 들어) "{1234"를 반환합니다. 이제 첫 번째 문자 다음에 오는 substring을 가져와 int()을 사용하여 int로 변환해야합니다. 이제 끝났습니다!
두 번째 숫자는 비슷한 방법을 사용할 수 있습니다. "} {"로 다시 나눠서, 이번에는 반환 된 배열에서 두 번째 (인덱스 1) 요소 만 가져옵니다. 자, 우리는 "9331} 그 스윙은 댕글입니다 ...", 다시 을으로 나눠서 배열의 첫 번째 문자열을 선택하고 int로 변환하면 끝났습니다! 두 경우 모두 우리는 처음에 loadStrings()
을 사용하여로드 한 파일의 원시 입력을 나타내는 원래 문자열로 subtitles[subtitleIndex]
을 사용하고 있습니다. 이 모든 분할 중에 subtitles
의 원래 문자열은 변경되지 않습니다. split()
, substring()
등은 새 시퀀스 만 반환하고 호출 한 문자열은 수정하지 않습니다.
당신은 split()
전화를 어지럽히고 백 슬래시의 무리가있는 것을 볼 수 있습니다, 그 순서의 마지막 줄 :
마지막으로 어떻게 작동하는지 알아 내기 위해 당신에게 그것을 떠날거야. split()
은 간단한 문자열이 아닌 정규식을 사용하기 때문입니다. 정규 표현식은 여기에 들어 가지 않는 많은 특수 표기법을 사용하지만, "}{"
과 같은 것으로 split()
을 전달한 경우에는 정규 표현식을 해석하려고 시도하며 예상대로 동작하지 않습니다. 문자가 escape이고 문자가 split()
일 때 특수 문자로 해석되지 않도록하고 문자 자체를 원한다고 말하면됩니다. 그렇게하기 위해, 이스케이프해야하는 문자 앞에 백래시를 사용합니다. 그러나 백 슬래시 자체는 또 다른 특수 문자이므로 이스케이프 처리해야합니다. 이 결과는 "\\{"
과 같습니다. 첫 번째 백 슬래시는 세 번째 문자가 무엇이든간에 이스케이프 처리되는 두 번째 이스케이프 문자를 이스케이프합니다. |
문자도 이스케이프 처리해야합니다.
죄송 텍스트의 벽! 지능적이고 정중하게 질문 된 질문을 보는 것이 좋으므로 좋은 답을 줄 것이라고 생각했습니다.
환상적인 답변! – mdomino