일부 JSL을 관리하는 프로젝트를 시도해 보겠습니다.
오래 전에 나는 횡스크롤러 작성을 제안했습니다. https://community.jmp.com/t5/Uncharted/Wild-Road-Map/bc-p/20996/highlight/true#M5 . 80년대에 게임을 하지 않았다면 https://en.wikipedia.org/wiki/Parallax_scrolling 몇 가지 예가 있습니다. 사이드 스크롤러는 캐릭터가 왼쪽에서 오른쪽으로 이동하고 배경에는 3D 깊이감을 주기 위해 다양한 속도로 미끄러지는 여러 레이어가 있는 2D 게임입니다. 다른 변형은 수직 스크롤 크기가 있는 플랫폼 점퍼일 수도 있습니다.
해결해야 할 문제가 있습니다:
- 게임 개발(JMP를 사용하면 작성하기가 더 쉬워질 수 있나요?)
- 게임 그래픽(어떻게 생겼나요?)
- 게임 오디오(들으셨나요?)
- 게임 입력 (어떻게 움직이나요?)
- 게임 플레이(무슨 일이 일어났나요?)
1. 게임 개발
저는 JMP 프로젝트를 사용하고 있습니다(최근에는 JMP 16 독립형 프로젝트로 전환했습니다.). 5~10개의 독립 파일이 있는 프로젝트 중 독립형 프로젝트가 마음에 들기 시작했습니다. 여기에는 열린 파일에 대한 탭과 로그 창에 대한 도킹 지점이 있습니다. 자체 포함 프로젝트는 모든 것을 하나의 파일(zip, 덮개 아래)에 저장하고 열거나 닫을 때 자동으로 압축을 풀고 다시 포장합니다.
그래픽용 파일과 오디오용 파일, 게임 플레이용 파일이 별개의 상대적으로 작은 파일이기 때문에 이 게임을 실행하는 것이 더 쉬웠습니다. 이를 통해 게임 캐릭터 간의 게임 플레이를 관리하는 JSL과 같은 항목을 쉽게 찾을 수 있습니다. 프로젝트는 다음과 같이 탭에 파일을 표시합니다.
A JMP project with several files.A JMP project with several files.A JMP project with several files.A JMP project with several files.A JMP project with several files.여러 파일이 포함된 JMP 프로젝트.
이 프로젝트가 열리자마자 9개의 파일이 열립니다. 게임 내 뱀파이어에 대한 클래스 정의가 포함된 파일이 현재 표시됩니다. 파일이 프로젝트에 다시 저장될 때와 프로젝트가 아직 저장될 때 완전히 익숙하지 않기 때문에 프로젝트를 닫기 전에 왼쪽 상단에 강조 표시된 아이콘을 사용합니다. 나는 또한 왼쪽 하단에 로그를 도킹했습니다. 프로젝트는 JMP의 나머지 부분 및 서로 분리되어 있는 것처럼 보이므로 자체 로그가 있습니다.
MakeAddin 파일은 게임의 일부가 아니지만 게임 개발의 일부입니다. 해당 탭이 열려 있고 ^R(실행)하면 추가 기능이 다시 생성됩니다. 다른 탭을 실행하면 어떻게 되나요? JSL이 실행되는데, 이는 게임 로직의 시작이 아닐 수도 있습니다. 하지만 저는 항상 실수로 그렇게 했기 때문에 다음과 같이 고쳤습니다.
- 합리적인 순서로 다른 모든 파일을 포함하는 기본 파일인 game.jsl이 있습니다.
- 대부분의 파일은 독립적이며 클래스나 네임스페이스만 만듭니다.
- Sidescroller.jsl 파일에는 로드된 다른 모든 파일이 필요합니다(메인 게임 루프입니다).
독립 파일은 모두 끝 ~와 함께
try(include("game.jsl"),if(!contains(char(exception_msg),"includes itself through a closed path"),show(exception_msg)));현재 파일 다음에 game.jsl 파일이 실행됩니다. game.jsl 파일은 현재 파일을 다시 포함하려고 시도하고 무시되는 재귀 포함 오류 또는 보고되는 다른 오류를 발생시킵니다. 마지막에 있어야 하는 횡스크롤러 파일에는 try 문이 있습니다. 첫 번째 선. 이렇게 하면 횡스크롤러 파일의 나머지 부분이 실행되기 전에 game.jsl 파일에 다른 모든 항목이 포함됩니다.
game.jsl 파일은 다음과 같습니다
files = {"AUDIO.jsl", "RGBA.jsl", "ASSETS.jsl", "LAYERS.jsl", "VAMPIRE.jsl", "BEAR.jsl",
// currently SIDESCROLLER contains the game logic. All of the files include this file,
// at the end, except for SIDESCROLLER which include it at the start. SIDESCROLLER is
// dependent on all of the other files being loaded. The other files are not order-dependent.
"SIDESCROLLER.jsl"};
For( iFile = 1, iFile <= N Items( files ), iFile += 1,
Try(
Include( files[iFile] ), // this exception is EXPECTED if you start one of the other files; it is OK!
If( !Contains( Char( exception_msg ), "includes itself through a closed path" ),
Show( files[iFile], exception_msg )
)
)
);이제 편집된 파일을 실행할 수 있습니다. 단...두 개 이상의 파일을 편집하는 경우 명시적으로 실행되지 않는 파일을 저장해야 합니다! 포함은 편집 탭 복사본이 아닌 디스크 복사본을 가져옵니다. 그러나 하나의 파일만 변경하는 경우 위에 포함이 설정된 방식으로 인해 저장하지 않고도 현재 편집 탭 복사본을 사용하게 됩니다.
위시리스트:
- 실행하기 전에 모두 저장하십시오(또는 편집 탭 복사를 사용하여 포함시키십시오).
- 프로젝트 실행 시 시작 파일 지정(on-project-load 파일 아님)
- 탭 저장과 프로젝트 저장이 어떻게 동일하거나 다른지 문서화하십시오.
- JSL에서 프로젝트의 모두 저장 명령을 실행하는 방법
2. 게임 그래픽
이 프로젝트는 JSL 생성 그래픽과 다운로드된 비트맵 그래픽을 모두 사용합니다. 아래에는 푸른 하늘과 산, 나무, 자갈길이 JSL로 만들어졌습니다. 바위 벽면은 타일 비트맵이고 뱀파이어, 박쥐, 곰은 애니메이션 비트맵 시퀀스입니다. 끝에 크레딧이 있습니다.
The little bear is idling; the vampires are releasing bats or disappearing.The little bear is idling; the vampires are releasing bats or disappearing.The little bear is idling; the vampires are releasing bats or disappearing.The little bear is idling; the vampires are releasing bats or disappearing.The little bear is idling; the vampires are releasing bats or disappearing.작은 곰이 한가하게 놀고 있어요. 뱀파이어가 박쥐를 풀어주거나 사라지고 있습니다.
RGBA.jsl 파일은 JSL 그래픽의 중요한 부분입니다. JMP는 그래프에 투명도를 적용하여 그릴 수 있고 그래프에 투명도가 포함된 비트맵을 사용할 수 있지만, 예를 들어 투명한 배경에 선 그래프를 만들고 투명한 배경에 해당 비트맵을 가져오는 쉬운 방법은 없습니다. (그래프를 제외한 모든 항목을 투명하게 저장하는 보고서 PNG 이미지의 투명 배경 옵션이 있습니다. 저장된 SVG를 편집하여 배경을 제거할 수 있지만 이를 투명한 배경에서 다시 PNG로 바꾸려면 다른 프로그램이 필요합니다.)
위시리스트
- <<프레임 상자의 경우 BackgroundColor("none").
RGBA 파일은 아무것도 그려지지 않은 투명한 픽셀로 비트맵을 생성하기 위한 클래스를 만듭니다. 좋아하는 기본 요소를 확장해야 할 수도 있습니다. 불투명하지 않은 나뭇잎과 나뭇잎 사이에 틈이 있는 나무를 확인하세요. Path()를 사용하는 베지어 트리 나무를 그리는 방법은 설명하지만 알파 채널은 사용하지 않습니다. 산은 서로 다른 매개변수를 사용하는 언덕 그리기 알고리즘의 여러 레이어이며, 하늘은 불투명한 파란색에서 검정색으로 음영처리된 직사각형입니다. 자갈 길은 생성 속도가 상당히 느릴 수 있지만 일단 달리면 충분히 빠릅니다. 자갈의 각 비트는 비트맵에 그려집니다.
ASSETS.jsl 파일은 게임에서 사용하는 비트맵 자산, 이를 여는 방법, 정규화하는 방법 및 이름을 지정하는 방법에 대해 알고 있습니다. 애니메이션은 서로 다른 사람들에 의해 그려지기 때문에 동일한 방식으로 중앙에 배치하려면 정규화가 필요합니다. 해당 정보는 다음과 같은 구조로 유지됩니다.
Assets:vampire_images["hit"] = {{"attack/hit_1",.,.,0.80,0.5},이는 매우 넓은 애니메이션을 처리하기 위해 비트맵에서 뱀파이어 방출 박쥐가 이동된 것을 보여줍니다(다른 경우에는 .80 대 .5). 뱀파이어와 곰은 사이드 스크롤러에서 자체 레이어를 가지며 투명도를 통해 더 멀리 있는 레이어도 볼 수 있습니다.
게임이 실제로 그래프로 되어 있기 때문에 확대/축소 도구를 사용하여 들여다보면 레이어를 이해할 수 있습니다. 여기에서는 축소되어 있으며 하늘이 창보다 왼쪽에서 오른쪽으로 더 크지 않은 것을 볼 수 있습니다. 스크롤되지 않습니다. 그러나 레이어가 점점 더 가까워질수록 더 넓어지고 넓어져서 더 많이 스크롤할 수 있습니다.
Normally the sky fills the display, left-to-right. Zoomed out, see the vampire about to enter the stage.Normally the sky fills the display, left-to-right. Zoomed out, see the vampire about to enter the stage.Normally the sky fills the display, left-to-right. Zoomed out, see the vampire about to enter the stage.Normally the sky fills the display, left-to-right. Zoomed out, see the vampire about to enter the stage.Normally the sky fills the display, left-to-right. Zoomed out, see the vampire about to enter the stage.일반적으로 하늘은 왼쪽에서 오른쪽으로 디스플레이를 채웁니다. 축소하면 뱀파이어가 무대에 들어오려는 모습이 보입니다.
꼬마곰이 오른쪽으로 걸어가면서 비트맵의 위치가 조정됩니다...
Not afraid.Not afraid.Not afraid.Not afraid.Not afraid.두려워하지 마세요.
딱 중간을 지나서..
The NPCs animate even when off the display.The NPCs animate even when off the display.The NPCs animate even when off the display.The NPCs animate even when off the display.The NPCs animate even when off the display.NPC는 디스플레이가 꺼져 있는 동안에도 애니메이션을 적용합니다.
그리고 맨 끝에는...
The little bear has reached the right-hand end of his world.The little bear has reached the right-hand end of his world.The little bear has reached the right-hand end of his world.The little bear has reached the right-hand end of his world.The little bear has reached the right-hand end of his world.작은 곰은 세상의 오른쪽 끝에 도달했습니다.
뱀파이어는 곰보다 느리게 걷는다. 그들은 따라잡을 것이다. 그리고 여기 배경과 전경 이미지 중 일부가 삭제되었습니다.
Without all the layers, the characters seem to float.Without all the layers, the characters seem to float.Without all the layers, the characters seem to float.Without all the layers, the characters seem to float.Without all the layers, the characters seem to float.모든 레이어가 없으면 캐릭터가 떠 있는 것처럼 보입니다.
3. 게임 오디오
사운드는 몰입형 경험의 중요한 부분입니다. 나는 이 게임의 사운드를 만들기 위해 LMMS를 사용했는데, 적절한 사운드 디자이너라면 훨씬 더 잘할 수 있을 것입니다. 하지만 소리가 서로 끊기지 않고 겹칠 수 있기 때문에 여전히 꽤 좋습니다. Windows에서. Mac을 사용하는 사람이 사운드를 재생할 수 있는 명령줄 프로그램을 찾는다면 아마도 Mac일 것입니다. 감사해요 @Jeff_Perkinson Mac 오디오 코드를 도와주셔서 감사합니다. Windows의 경우 AUDIO.jsl 파일은 RunProgram을 사용하여 Windows 사운드 시스템에 액세스할 수 있는 PowerShell을 실행합니다. Mac에서는 명령줄 사운드 플레이어인 /usr/bin/afplay를 사용합니다. 모든 재생 사운드가 끝나기 전에 JMP를 종료하려고 하면 JMP가 중단될 수 있습니다. 마지막 진행률 표시줄이 시작된 모든 사운드의 재생을 마치도록 하세요.
4. 게임 입력
이 게임은 게임을 담는 그래프 상자 주위에 MouseBox를 배치하여 키보드를 입력 장치로 사용합니다.
New Window( "overlay",
mb = MouseBox(
V List Box(
hlistbox(
leftSpacer=spacerbox(size(5,windowy),color("black")),
gb = Graph Box(
suppressaxes,
framesize( windowx + 1, windowy + 1 ),
X Scale( -1, windowx ),
Y Scale( -1, windowy )
),MouseBox는 키 입력을 키와 시간을 기억하는 작은 함수로 전달합니다.
lastkey=empty();
lastkeyexpire=tickseconds();
spriteRunner = function({key},{},
lastkey=key;
lastkeyexpire=tickseconds()+1;
);다른 곳에서는 1초 후에 오래될 때까지 키의 동작이 반복됩니다.
While( go,
if( tickseconds() > lastkeyexpire,
lastkey="";
);
…열쇠는 작은 곰을 조종합니다. 이는 Bear의 유한 상태 머신(FSM)에서 구현됩니다. 곰을 유휴 상태에서 걷기 상태로 변경하는 예는 BEAR.jsl Cycle() 함수에 있습니다.
If( begin,
laststate=m_state;
if( keystroke=="LEFT" & ( pFaceLeft=="faceright" | (pFaceLeft=="faceleft" & pName=="idle") ),
m_state = m_stateWalkLeft;Begin은 현재 애니메이션 주기가 시작 부분에 있으면 true이며, 이는 상태를 변경하기에 좋은 장소입니다. 점프하는 애니메이션의 중간을 아이들링 애니메이션에 남겨 두는 것이 이상해 보입니다. 곰이 왼쪽을 바라보고 유휴 상태일 때만 왼쪽으로 움직이기 시작해야 하지만, 오른쪽을 바라보면... 그냥 왼쪽으로 가기 시작해야 한다는 논리를 쓴 지 꽤 되었습니다. 나는 그것이 걸을 때 즉각적인 반전을 허용하고 아마도 다른 방법으로도 처리될 수 있는 동일한 상태로의 변경을 방지할 수 있다고 생각합니다.
5. 게임 플레이
매력적인 게임을 만드는 것은 나에게 어려운 부분이다. 이야기를 하고, 목표를 만들고, 퍼즐을 추가합니다. 이 게임은 대부분 스토리텔러를 기다리는 환경입니다. 그러나 나는 약간의 게임 플레이를 추가했습니다.
,/*else if*/ keystroke=="DOWN" & m_NumRocks<6 & (m_state == m_stateWalkLeft | m_state==m_stateIdleLeft),
m_state = m_statePickLeft;
m_NumRocks = min(6,m_NumRocks+1);
// use SPACE to HIT
,/*else if*/ keystroke==" " & (m_state == m_stateWalkRight | m_state==m_stateIdleRight),
if(m_NumRocks,
m_NumRocks = max(0,m_NumRocks-1);
m_state = m_stateHitRight;
m_RockThrownRightFrom = m_x;
);아래쪽 화살표를 누르면 바위를 집어들 수 있습니다. 작은 곰은 최대 6개까지 수용할 수 있습니다. 스페이스바를 누르면 바위가 바라보는 방향으로 던집니다. 곰은 던진 돌을 메모합니다. 록던지는오른쪽에서 또는 던진 바위 왼쪽 에서 이는 뱀파이어와 곰을 볼 수 있는 메인 루프의 코드로 확인됩니다.
// check for interaction between bear and vampire
if(!ismissing(bearPlayer:m_RockThrownRightFrom),
if(bearPlayer:m_RockThrownRightFrom<GETPOS></GETPOS>
뱀파이어를 돌로 치면 50픽셀 뒤로 밀려납니다. (실제로 제가 쓴 것처럼 일석이조로 뱀파이어 두 마리를 얻을 수 있습니다.) 뱀파이어는 아마도 두 마리 이상을 지원할 수 있는 목록에 있어야 할 것입니다. 실제로 모든 NPC(비플레이어 캐릭터)는 목록에 있어야 하며 공통 기본 클래스에서 하위 클래스로 분류되어 루프 대신에 순환()을 호출해야 합니다.
vampire1:cycle(stagepos);
vampire2:cycle(stagepos);
bearPlayer:cycle(stagepos,lastkey);
하지만 그렇게 하면 이 간단한 예제가 어떻게 작동하는지 모호해질 뿐입니다.
두 개의 첨부 파일이 있어야 합니다: 프로젝트 파일과 추가 기능 파일. (지금은 프로젝트를 커뮤니티에 첨부할 수 없지만, 애드인을 설치하면 애드인 디렉터리에 프로젝트 복사본이 있습니다.)
미술 학점
오픈 게임 아트 사이트에는 다양한 품질의 훨씬 더 많은 콘텐츠가 있습니다.