← 목록

mLua · Nemotron SDG 질문-응답 (SFT)

총 21,567개 · 페이지 517/719
🔀 랜덤
불러오는 중…

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | `AvatarRendererComponent`의 `GetBodyEntity` 메서드를 통해 얻은 바디 엔티티에 `ActionStateChangedEvent`를 보내며, `CoreActionName`과 `PartsActionName`을 "attack1"으로 설정하고 `SpriteAnimClipPlayType.Loop` 타입으로 재생 속도 1.5, 시작 프레임 0, 종료 프레임을 10으로 지정해 공격 애니메이션을 재생하는 스크립트를 작성해줘 [answer] | ```lua Method: [client only] void OnBeginPlay () { local body = self.Entity.AvatarRendererComponent:GetBodyEntity() local event = ActionStateChangedEvent("attack1", "attack1", 1.5, SpriteAnimClipPlayType.Loop, 0, 10) body:SendEvent(event) } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 각 애니메이션의 총 프레임은 **AvatarItem Editor**에서 확인할 수 있습니다. 위와 같이 총 프레임을 확인한 뒤, 크리에이터가 재생하기를 원하는 애니메이션 시작 프레임(StartFrameIndex)과 종료 프레임(EndFrameIndex)을 설정하면 됩니다. 프레임을 설정할 때는 다음 사항을 주의해야 합니다. * 프레임은 양수로 설정해야 합니다. * 시작 프레임은 종료 프레임보다 작거나 같아야 합니다. * 종료 프레임은 총 애니메이션 프레임보다 작거나 같아야 합니다. * 프레임값을 잘못 설정하면 보정됩니다. *

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 GetBodyEntity를 통해 바디 엔티티를 가져와 SpriteAnimPlayerChangeFrameEvent를 구독하고, 조건에 따라 이벤트 구독을 취소하는 클라이언트 스크립트를 작성해줘. [answer] | 아바타의 바디 엔티티를 통해 `SpriteAnimPlayerChangeFrameEvent`를 구독하고, 특정 프레임이 도달했을 때 구독을 취소하는 과정은 다음과 같이 구현할 수 있습니다. 아바타 애니메이션은 클라이언트에서 재생되므로, 모든 처리는 `[client]` 실행 공간에서 이루어져야 합니다. 구독을 시작하는 시점(예: `OnBeginPlay`)과 구독을 취소하는 로직(이벤트 핸들러)을 분리하여 작성합니다. ```lua Property: [None] any handler = nil Method: [client] void [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 3. 아까 저장한 **handler**를 통해 **SpriteAnimPlayerChangeFrameEvent** 구독을 취소합니다. `ChangeFrameEvent` 함수를 수정해 봅시다. ```lua [client] void ChangeFrameEvent(any event) { if event.FrameIndex == 2 then local body = self.Entity.AvatarRendererComponent:GetBodyEntity()

[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 카드 짝 맞추기 게임의 타이머와 게임 종료 로직이 어떻게 구현되어 있나요? [answer] | 카드 짝 맞추기 게임의 타이머와 게임 종료 로직은 클라이언트 측(`[client only]`)에서 `PlayTime`과 `RemainingTime` 프로퍼티를 관리하는 방식으로 구현됩니다. 구체적인 동작 흐름은 다음과 같습니다. 1. **게임 시작 시 초기화**: `OnBeginPlay` 생명주기 메서드가 호출되면 `StartGame` 메서드가 실행됩니다. 이때 `RemainingTime`을 총 플레이 시간인 `PlayTime`(기본값 60초)으로 설정하여 타이머를 초기화합니다. 2. **타이머 카운트다운**: `OnUpda [followup] | OnUpdate에서 RemainingTime이 0 이하가 될 때 EndGame이 호출되는 구체적인 조건과, EndGame에서 UI를 비활성화하는 과정은 어떤가요? [followup_answer] | `OnUpdate`에서 `RemainingTime`이 0 이하가 될 때 `EndGame`이 호출되는 구체적인 조건과 UI 비활성화 과정은 다음과 같습니다. ### 1. EndGame 호출 조건 `OnUpdate` 메서드는 매 프레임마다 실행되며, 전달된 `delta` 값만큼 `RemainingTime`에서 뺍니다. ```lua self.RemainingTime = self.RemainingTime - delta ``` 이 계산 후 `self.RemainingTime <= 0`인지를 확인합니다. `RemainingTime`이 **0 [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | IsEmpty 메서드의 로직을 검증하는 단위 테스트 코드를 주석으로만 작성해 주세요. [answer] | 참고 문서에 `IsEmpty` 메서드의 로직은 `CardSpawnRoot`의 자식들(`Children`) 중 `Visible`이 `true`인 카드가 하나라도 있으면 `false`를, 없으면 `true`를 반환하는 것으로 명시되어 있습니다. 요청하신 대로 실제 실행 가능한 테스트 코드가 아닌, 이 로직을 검증하는 시나리오를 **주석으로만** 작성한 mLua 스크립트 형식은 다음과 같습니다. ```lua Property: [None] Entity CardSpawnRoot = nil -- 테스트 대상이 될 CardSpawnRoot [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | [client only] void DeselectCard() { self.SelectedCard:CardOff() self.SelectedCard = nil } [client only] boolean IsEmpty () { local cards = self.CardSpawnRoot.Children for i = 1, #cards do if cards[i].Visible then return false end end

[task] | two_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 루아에서 변수의 유형은 어떻게 결정되며 `type()` 함수로 어떻게 확인할 수 있나요? [answer] | 루아에서 변수는 생성 시점에 유형을 명시하지 않으며, 변수에 대입되는 값에 따라 유형이 자동으로 결정됩니다. 예를 들어 숫자 값을 대입하면 number, 문자열을 대입하면 string, 참/거짓 값을 대입하면 boolean 유형이 됩니다. 변수의 유형을 확인하려면 `type()` 함수를 사용합니다. 이 함수에 변수를 인수로 전달하면 해당 변수의 유형을 문자열로 반환합니다. ```lua local a = 1 log(type(a)) -- number a = 1234.5678 log(type(a)) -- number a = "he [followup] | 배열의 인덱스가 1부터 시작하는 이유와 `table.insert()`를 이용해 중간에 값을 추가하는 코드 예시를 보여주세요. [followup_answer] | 루아에서 배열의 첫 번째 인덱스가 1부터 시작하는 이유는 문서에 명시된 문법 특성 때문으로, 대부분의 프로그래밍 언어에서는 첫 번째 인덱스로 0을 사용하는 것과 다릅니다. `table.insert()` 함수를 이용해 배열 중간에 값을 추가하려면, 함수의 두 번째 인수에 추가하려는 인덱스 값을 지정합니다. ```lua local testArray = {"A", "B"} -- 2번 인덱스에 "and"를 추가 table.insert(testArray, 2, "and") log(testArray[1]) -- A log(testArr [scores] | [judge_reason] | [source_doc] | 루아의 변수는 내부적으로 유형이 존재하기는 하지만 변수를 생성할 때 그 유형을 명시하지는 않습니다. 변수에 들어가는 값에 따라 그 유형이 정해집니다. | 변수 유형 | 설명 | | --- | --- | | nil | 값이 없음을 뜻합니다. 논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. | | boolean | true와 false 값만 갖습니다. 0, 1의 수치로 변환되지 않습니다. | | number | 64비트 실수입니다. | | integer | 64비트 정수입니다. |

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | CardPairGameLogic 스크립트에 PlayTime과 RemainingTime 프로퍼티를 추가하고, OnUpdate에서 RemainingTime을 delta만큼 감소시키며, StartGame 호출 시 RemainingTime을 PlayTime으로 초기화하는 로직을 작성해줘. [answer] | 요청하신 로직을 `CardPairGameLogic` 스크립트 형식에 맞춰 작성했습니다. 1. **Property** 블록에 `PlayTime`(초깃값 60)과 `RemainingTime`(초깃값 0)을 추가했습니다. 2. **Method** 블록의 `OnUpdate`에서 매 프레임마다 `delta`만큼 `RemainingTime`을 감소시키도록 구현했습니다. 3. `StartGame` 함수 내에서 `RemainingTime`을 `PlayTime` 값으로 초기화하도록 설정했습니다. ```lua Property: [None] num [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 타이머가 0초가 된 이후에도 음수로 계속 감소해서 게임이 종료되지 않는데, 어떻게 설정해야 0초에 UI가 꺼질까요? [answer] | 타이머가 0초 이하로 감소할 때 게임을 종료하고 UI를 비활성화하려면, `CardPairGameLogic` 컴포넌트에 `EndGame` 함수를 추가하고 `OnUpdate`에서 `RemainingTime`을 체크하는 로직을 적용해야 합니다. 아래 단계로 설정하면 됩니다. 1. **`EndGame` 함수 추가**: 클라이언트에서 실행되는 `[client only]` 메서드로, 해당 함수에서 `CardPairGameUI`의 `Enable` 속성을 `false`로 설정하여 UI를 끕니다. 2. **`OnUpdate` 로직 수정**: [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 타이머를 완성했지만 이번에도 한 가지 추가하면 좋겠습니다 타이머가 0초가 된 이후에 수가 음수로 계속해서 감소하고 있습니다. 일반적으로 수가 줄어드는 모습을 보면, 0초가 되었을 때 게임이 종료될 거라 기대합니다. 그러나 지금은 0초 이후 수가 음수로 줄어들고 있습니다. 0초가 되면 ui가 꺼지게 만들어 봅시다. 1. **CardPairGameLogic** 로직의 `EndGame` 함수에 아래와 같이 작성합니다. ```lua [client only] void EndGame () {

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | CardBoard 스크립트에 TimeText 프로퍼티를 설정하고, UpdateText 함수에서 _CardPairGameLogic의 RemainingTime을 math.floor로 변환하여 TimeText.TextComponent.Text에 표시하도록 작성해줘. [answer] | CardBoard 스크립트에 요청하신 내용을 반영하면 다음과 같습니다. ```lua Property: [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void UpdateText() { local remainingTime = _CardPairGameLogic.RemainingTime self.TimeText.TextComponent. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | `AvatarRendererComponent`의 `GetBodyEntity` 메서드로 바디 엔티티를 가져와 `ActionStateChangedEvent`를 전송할 때, `CoreActionName`과 `PartsActionName`을 "run"으로 설정하고 재생 타입을 `SpriteAnimClipPlayType.Once`로 지정하여 한 번만 실행되도록 하는 스크립트를 작성해줘 [answer] | `AvatarRendererComponent`의 `GetBodyEntity` 메서드로 바디 엔티티를 가져와 `ActionStateChangedEvent`를 전송하는 스크립트입니다. 요청하신 대로 `CoreActionName`과 `PartsActionName`은 "run"으로, 재생 타입은 `SpriteAnimClipPlayType.Once`로 설정했습니다. 재생 속도와 프레임 범위는 기본값을 사용하도록 파라미터를 생략했습니다. ```lua Method: [client only] void OnBeginPlay () { lo [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 각 애니메이션의 총 프레임은 **AvatarItem Editor**에서 확인할 수 있습니다. 위와 같이 총 프레임을 확인한 뒤, 크리에이터가 재생하기를 원하는 애니메이션 시작 프레임(StartFrameIndex)과 종료 프레임(EndFrameIndex)을 설정하면 됩니다. 프레임을 설정할 때는 다음 사항을 주의해야 합니다. * 프레임은 양수로 설정해야 합니다. * 시작 프레임은 종료 프레임보다 작거나 같아야 합니다. * 종료 프레임은 총 애니메이션 프레임보다 작거나 같아야 합니다. * 프레임값을 잘못 설정하면 보정됩니다. *

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | self.SelectedCard에 nil을 대입해도 다음 턴에 카드가 자동으로 선택 해제되지 않는 이유는 무엇인가요? [answer] | 제공된 참고 문서에는 `self.SelectedCard` 변수에 `nil`을 대입하는 것만으로 카드의 시각적 상태(색상 등)가 해제되지 않는 이유나, 카드 선택 해제에 사용되는 구체적인 메서드가 명시되어 있지 않습니다. 문서에 포함된 `DeselectCard` 메서드 예제를 보면, 단순히 `self.SelectedCard = nil`만 실행하는 것이 아니라 `self.SelectedCard:CardOff()`를 먼저 호출하여 카드의 색상(Color)을 변경한 후에 `nil`을 대입하고 있습니다. ```lua [client onl [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | [client only] void DeselectCard() { self.SelectedCard:CardOff() self.SelectedCard = nil } [client only] boolean IsEmpty () { local cards = self.CardSpawnRoot.Children for i = 1, #cards do if cards[i].Visible then return false end end

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 문서에 명시된 전역 변수와 지역 변수의 특징 및 메이플스토리 월드에서의 권장 사항을 3문장 이내로 요약해서 답변하세요. [answer] | 전역 변수는 아무 선언 없이 어디서든 접근 가능하지만 메이플스토리 월드에서는 사용을 권장하지 않으며, 대신 스크립트 프로퍼티를 활용할 것을 권고합니다. 지역 변수는 정의된 함수나 구문 범위 내에서만 유효하고 해당 범위의 실행이 끝나면 파괴됩니다. 따라서 값의 범위가 제한적일 때는 지역 변수를 사용하고, 스크립트 전체에서 참조해야 할 값은 프로퍼티로 관리하는 것이 좋습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | two_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 게임 시작 시 StartGame()에서 RemainingTime을 초기화하는 과정은 어떻게 진행되나? [answer] | 게임 시작 시 `StartGame()` 함수 내부에서 `RemainingTime` 프로퍼티에 `PlayTime` 프로퍼티의 값을 대입하여 초기화합니다. `CardPairGameLogic` 로직의 `StartGame()` 함수에 아래 코드가 포함됩니다. ```lua self.RemainingTime = self.PlayTime ``` 이 코드가 실행되면 `PlayTime`에 설정된 값(예: 60)이 `RemainingTime`에 저장되며, 이후 `OnUpdate`에서 `RemainingTime`이 감소하도록 사용됩니다. [followup] | 제작 중 빠른 확인을 위해 PlayTime을 작은 수로 설정했는데, 실제 배포 전 60초로 되돌리거나 테스트용 시간을 동적으로 변경할 수 있는 방법을 알고 싶다면 어떻게 해야 하나? [followup_answer] | 제공된 참고 문서에는 `PlayTime` 프로퍼티의 값을 런타임에 동적으로 변경하는 API나 방법을 설명하는 내용이 없습니다. 문서에 명시된 내용은 다음과 같습니다. 1. `PlayTime` 프로퍼티를 `[None]` 속성으로 선언하고 초깃값을 60으로 설정합니다. 2. 제작 중 빠른 확인을 위해 에디터에서 `PlayTime` 프로퍼티의 값을 직접 작은 숫자로 수정하여 테스트하라는 **팁(Tip)**만 제시되어 있습니다. 따라서 문서 기준으로는 배포 전 60초로 되돌리거나 동적으로 변경하려면, 에디터에서 `CardPairG [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | `AvatarRendererComponent`의 `GetBodyEntity` 메서드를 사용하여 `ActionStateChangedEvent`를 생성할 때 `CoreActionName`은 "idle"이고 `PartsActionName`은 "idle_arms"로 설정하되, 시작 프레임과 종료 프레임을 각각 5와 15로 입력하여 특정 구간만 루프 재생하도록 하는 스크립트를 작성해줘 [answer] | 요청하신 조건에 맞춰 `AvatarRendererComponent`의 `GetBodyEntity` 메서드로 몸통 엔티티를 가져온 후, `ActionStateChangedEvent`를 생성하여 해당 이벤트를 보내는 스크립트입니다. `ActionStateChangedEvent`의 인자 순서는 `CoreActionName`, `PartsActionName`, `Speed`, `PlayType`, `StartFrameIndex`, `EndFrameIndex`입니다. 시작 프레임(5)과 종료 프레임(15)을 지정하고, 루프 재생(`Spri [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 각 애니메이션의 총 프레임은 **AvatarItem Editor**에서 확인할 수 있습니다. 위와 같이 총 프레임을 확인한 뒤, 크리에이터가 재생하기를 원하는 애니메이션 시작 프레임(StartFrameIndex)과 종료 프레임(EndFrameIndex)을 설정하면 됩니다. 프레임을 설정할 때는 다음 사항을 주의해야 합니다. * 프레임은 양수로 설정해야 합니다. * 시작 프레임은 종료 프레임보다 작거나 같아야 합니다. * 종료 프레임은 총 애니메이션 프레임보다 작거나 같아야 합니다. * 프레임값을 잘못 설정하면 보정됩니다. *

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | `AvatarRendererComponent`의 `GetBodyEntity` 메서드를 활용해 `ActionStateChangedEvent`를 생성하고, `CoreActionName`은 "jump"이고 `PartsActionName`은 "jump_legs"로 설정하며, 시작 프레임 0, 종료 프레임 20, 재생 속도 2.0으로 설정해 점프 애니메이션을 빠르게 재생하는 스크립트를 작성해줘 [answer] | 아바타의 점프 애니메이션을 `ActionStateChangedEvent`로 빠르게 재생하는 스크립트입니다. `ActionStateChangedEvent`의 인자 순서는 `(CoreActionName, PartsActionName, Speed, PlayType, StartFrameIndex, EndFrameIndex)`입니다. 요청하신 설정에 맞춰 재생 속도(Speed)는 2.0, 재생 타입(PlayType)은 `SpriteAnimClipPlayType.PlayOnce`로, 시작 프레임은 0, 종료 프레임은 20으로 지정했습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 각 애니메이션의 총 프레임은 **AvatarItem Editor**에서 확인할 수 있습니다. 위와 같이 총 프레임을 확인한 뒤, 크리에이터가 재생하기를 원하는 애니메이션 시작 프레임(StartFrameIndex)과 종료 프레임(EndFrameIndex)을 설정하면 됩니다. 프레임을 설정할 때는 다음 사항을 주의해야 합니다. * 프레임은 양수로 설정해야 합니다. * 시작 프레임은 종료 프레임보다 작거나 같아야 합니다. * 종료 프레임은 총 애니메이션 프레임보다 작거나 같아야 합니다. * 프레임값을 잘못 설정하면 보정됩니다. *

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | CardBoard 스크립트의 OnUpdate 함수에서 매 프레임마다 UpdateText 메서드를 호출하여 UI에 남은 시간이 실시간으로 갱신되도록 작성해줘. [answer] | CardBoard 스크립트의 `OnUpdate` 함수에서 매 프레임마다 `UpdateText` 메서드를 호출하여 남은 시간을 UI에 실시간으로 반영하는 코드는 다음과 같습니다. 참고 문서에 제시된 `CardBoard` 컴포넌트의 `TimeText` 프로퍼티 설정과 `UpdateText` 함수 구현을 포함하여 전체 구조를 정리하면 다음과 같습니다. ```lua Property: [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 타이머 만들기 게임을 시작하면 1초씩 감소하는 타이머를 만들어봅시다. 1. **CardPairGameLogic** 로직에 게임 제한 시간으로 사용할 **PlayTime** 프로퍼티와 시간을 줄이기 위해 사용할 **RemainingTime** 프로퍼티를 추가합니다. PlayTime 초깃값은 **60**으로 설정합니다. ```lua Property: [None] number PlayTime = 60 [None] number RemainingTime = 0 ``` > **

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 SpriteAnimPlayerStartFrameEvent 이벤트를 구독하여 시작 프레임이 재생될 때 지정된 액션 이벤트를 전송하는 클라이언트 스크립트를 작성해줘. [answer] | 아바타 애니메이션은 클라이언트에서 재생되므로, `SpriteAnimPlayerStartFrameEvent`를 구독하고 액션을 변경하는 로직은 모두 `[client]` 공간에서 실행되어야 합니다. 참고 문서에 따르면 `SpriteAnimPlayerStartFrameEvent`의 사용법은 `SpriteAnimPlayerChangeFrameEvent`와 동일하며, 구독 취소 시 `DisconnectEvent`를 사용합니다. 시작 프레임이 재생될 때 특정 액션으로 전환하려면, 해당 이벤트 핸들러에서 `ActionStateChangedEv [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 3. 아까 저장한 **handler**를 통해 **SpriteAnimPlayerChangeFrameEvent** 구독을 취소합니다. `ChangeFrameEvent` 함수를 수정해 봅시다. ```lua [client] void ChangeFrameEvent(any event) { if event.FrameIndex == 2 then local body = self.Entity.AvatarRendererComponent:GetBodyEntity()

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 선택된 카드의 참조를 SelectedCard 프로퍼티에 저장하고 해당 카드 인스턴스의 CardOn 메서드를 호출하는 SelectCardCard 메서드를 작성해줘. [answer] | ```lua Method: [client only] void SelectCardCard (Card card) { self.SelectedCard = card card:CardOn() } ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate (number delta) { sel

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | StartGame에서 self.CardPairGameUI.Enable = true를 설정하는 것과 CardBoard의 SetCards() 호출 순서가 바뀌어도 문제가 없나요? [answer] | 제시된 문서의 코드 예제에서는 `StartGame` 메서드 내에서 항상 `self.CardPairGameUI.Enable = true`를 먼저 설정하고, 이후에 `CardBoard:SetCards()`를 호출하는 순서로 작성되어 있습니다. 문서에는 두 호출의 순서가 바뀌었을 때 발생하는 동작이나 오류에 대한 정보가 제공되지 않습니다. 따라서 제공된 문서만으로는 순서를 바꿨을 때 문제가 되는지 여부를 확인할 수 없습니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | cardboard:IsEmpty()가 true로 반환될 때 SetCards()를 다시 호출하는 로직의 의도는 무엇인가요? [answer] | 카드 짝 맞추기 게임에서 모든 카드가 소거되어 보드가 비어졌을 때, 즉시 새로운 카드를 배치하여 게임을 계속 진행할 수 있도록 하기 위한 의도입니다. `cardboard:IsEmpty()`가 `true`를 반환하는 순간은 현재 라운드의 모든 카드가 성공적으로 짝을 이루어 소거된 시점입니다. 이 시점에 `cardboard:SetCards()`를 다시 호출하면 플레이어는 잠시 대기하는 시간 없이 바로 다음 세트의 카드 짝 맞추기를 시작할 수 있습니다. 이는 게임의 흐름을 끊지 않고 몰입감을 유지하며, 플레이 시간을 효율적으로 사용하는 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | OnCardClicked 이벤트 핸들러에서 isvalid(card) 체크를 먼저 수행하는 이유는 무엇인가요? [answer] | `OnCardClicked` 이벤트 핸들러에서 `isvalid(card)` 체크를 먼저 수행하는 이유는, 클릭 이벤트가 발생한 대상 카드가 이미 삭제되었거나 존재하지 않는 비정상적인 상태일 때를 방지하기 위해서입니다. 코드를 살펴보면 `isvalid(card) == false`인 경우 바로 함수를 종료(`return`)하도록 처리되어 있습니다. 이는 카드가 유효하지 않을 때 이후 코드에서 `card`를 사용해 로직을 수행하다가 에러가 발생하는 것을 막기 위한 안전장치입니다. 카드가 유효한 상태인지 확인한 후에야 `CardBoard [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | #### CardPairGameLogic 로직 ```lua Property: [None] Entity CardPairGameUI = /ui/CardPairGameUI [None] number PlayTime = 60 [None] number RemainingTime = 0 Method: [client only] void OnBeginPlay() { self:StartGame() } [client only] void StartGame() { self.CardPairGameUI.Enable = true

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 사전의 Key-Value를 삭제할 때 Key 값을 nil로 설정해야 하는 이유와 `pairs()`를 활용한 순회 예제를 포함해 5줄 이내로 설명하세요. [answer] | 사전에서 Key-Value를 삭제하려면 해당 Key의 값을 `nil`로 설정해야 합니다. ```lua myDictionary.job = nil for key, value in pairs(myDictionary) do log(key, value) end ``` [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다. ```lua local array = {11, 22, 33, 44, 55} -- 1번 인덱스를 제거 table.remove(array, 1) log(array[1]) -- 22 ``` > **더 알아보기** > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다. > ## 사전(Dictionary) 사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.

[task] | code [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | `_CardPairGameLogic`의 RemainingTime 값을 매 프레임 갱신하여 TimeText 엔티티의 TextComponent.Text에 정수 형태로 표시하는 OnUpdate 메서드를 작성해줘. [answer] | `_CardPairGameLogic` 서비스의 `RemainingTime` 속성을 매 프레임 조회하여, `TimeText` 엔티티의 `TextComponent.Text`에 정수 형태로 표시하는 `OnUpdate` 메서드를 작성했습니다. ```lua Property: [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate(numbe [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | ```lua Property: [None] Entity CardSpawnRoot = /ui/CardPairGameUI/UI_Board/UI_Blocks/UI_Block_Group [None] Card SelectedCard = nil [None] Entity TimeText = /ui/CardPairGameUI/UI_Board/Background/Title/Timer_Background/UI_Time/UI_Time_Text Method: [client only] void OnUpdate (number delta) { sel

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 배열에서 특정 인덱스의 값을 제거하는 `table.remove()` 함수 사용법을 3문장 이내로 설명하세요. [answer] | `table.remove()` 함수는 배열에서 특정 인덱스에 위치한 값을 제거하는 데 사용됩니다. 첫 번째 인수로 배열을, 두 번째 인수로 제거할 인덱스를 전달하면 해당 값이 삭제됩니다. 제거 후 해당 인덱스 이후의 값들은 자동으로 한 칸씩 앞으로 이동합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다. ```lua local array = {11, 22, 33, 44, 55} -- 1번 인덱스를 제거 table.remove(array, 1) log(array[1]) -- 22 ``` > **더 알아보기** > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다. > ## 사전(Dictionary) 사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.

[task] | single_turn [pass] | ⏳ 미판정 [title] | 타이머 만들기 [question] | 카드가 Visible 속성으로 숨겨진 경우 IsEmpty에서 false를 반환하지 않고 true를 반환하도록 수정하려면 어떤 조건을 추가해야 하나요? [answer] | `IsEmpty` 함수의 로직을 분석하면, 현재 코드는 `CardSpawnRoot`의 자식 요소(`cards`)를 순회하면서 **`Visible` 속성이 `true`인 카드가 하나라도 존재하는지**를 확인합니다. ```lua for i = 1, #cards do if cards[i].Visible then -- Visible이 true인 카드가 있으면 return false -- false를 반환 (비어있지 않음) end end return true - [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | [client only] void DeselectCard() { self.SelectedCard:CardOff() self.SelectedCard = nil } [client only] boolean IsEmpty () { local cards = self.CardSpawnRoot.Children for i = 1, #cards do if cards[i].Visible then return false end end

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | OnBeginPlay 에서 이벤트를 연결할 때 핸들러를 self.handler 같은 프로퍼티에 저장해 두는 이유는 무엇이며, 이 값을 나중에 어떻게 활용해야 하나요? [answer] | `OnBeginPlay`에서 이벤트를 연결할 때 반환된 핸들러를 `self.handler` 같은 프로퍼티에 저장해 두는 이유는, 나중에 해당 이벤트 구독을 취소(해제)하기 위해서입니다. 이벤트 연결(`ConnectEvent`)은 단순히 함수를 등록하는 것뿐만 아니라, 그 연결 관계를 관리하기 위한 핸들러(또는 참조)를 반환합니다. 이 핸들러를 저장해 두지 않으면 나중에 특정 조건에서 이벤트를 더 이상 수신하지 않도록 해제할 수 없습니다. **나중에 활용하는 방법:** 보통 애니메이션이 변경된 후 원치 않는 중복 이벤트가 발생하는 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | `OnBeginPlay()` 함수 내에서 선언된 지역 변수 `a`와 `b`의 스코프 및 생명주기를 비교하는 표를 출력하세요. [answer] | `OnBeginPlay()` 함수 내에서 선언된 지역 변수 `a`와 `b`의 스코프 및 생명주기를 비교하면 다음과 같습니다. | 구분 | 지역 변수 `a` | 지역 변수 `b` | | :--- | :--- | :--- | | **선언 위치** | `OnBeginPlay()` 함수 본문 (구문 외부) | `if true then ... end` 조건문 블록 내부 | | **유효 범위 (Scope)** | `OnBeginPlay()` 함수 전체 | `if` 조건문 블록 내부만 | | **생명주기** | `OnBeginPlay()` 함 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | single_turn [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | ActionStateChangedEvent 를 생성할 때 파라미터로 전달하는 0.5 의 의미와, 2~3 프레임 반복 재생을 지정하는 숫자들의 역할을 각각 어떻게 이해해야 하나요? [answer] | `ActionStateChangedEvent` 생성 시 전달하는 파라미터의 의미는 다음과 같습니다. **1. `0.5`의 의미 (재생 속도)** `0.5`는 애니메이션의 **재생 속도(Play Speed)**를 나타냅니다. * 기본값 `1`은 정상 속도로 재생됨을 의미합니다. * `0.5`는 애니메이션이 **정상 속도의 절반(0.5배)**로 느리게 재생되도록 설정합니다. * 참고로, 애니메이션 재생 속도는 양수 실수 값으로 지정할 수 있으며, 값이 클수록 빠르게, 작을수록 느리게 재생됩니다. **2. `2`, `3`의 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 다음의 예제 코드를 보면서 **FrameEvent**의 사용법을 알아봅시다. 1. 어떤 아바타 애니메이션의 2번째 프레임이 재생될 때 다른 애니메이션으로 변경하고 싶다고 가정합니다. 그렇다면 **SpriteAnimPlayerChangeFrameEvent**를 활용할 수 있을 것입니다. `OnBeginPlay` 함수를 추가하고, 위에서 설명한 대로 이벤트를 **Body**와 연결합니다. 구독 취소를 대비해 연결한 이벤트의 핸들러는 프로퍼티로 가지고 있도록 합니다. ```lua Property: [None]

[task] | instruction_following [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 제공된 예제 코드를 그대로 복사하여, 각 `log()` 함수가 실행될 때 콘솔에 출력되는 값의 순서만 주석으로 달아 출력하세요. [answer] | ```lua Property: [Sync] integer testP = 0 Method: [server only] void OnBeginPlay() { log(self.testP) -- 0 self.testP = self.testP + 100 log(self.testP) -- 100 -- OnBeginPlay() 함수 내에서 유효한 지역 변수 a를 정의합니다. local a = "A" log(a) -- A if true then -- 지역 변 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | single_turn [pass] | ⏳ 미판정 [title] | 메이플스토리 월드 루아 기초 [question] | 메이플스토리 월드의 mLua 스크립트에서 값을 출력할 때 표준 루아의 print 대신 log 함수를 사용해야 하는 이유가 있나요? [answer] | 메이플스토리 월드에서는 원래 루아 문법에서 출력에 사용하는 `print` 명령 대신 가공된 `log()` 함수를 사용하도록 설계되어 있습니다. 따라서 스크립트에서 값을 콘솔 창에 출력할 때는 `log()` 함수를 활용해야 합니다. [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | # 학습 과정 소개 메이플스토리 월드에서는 **루아**라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 **루아**의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다. # 변수 변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다. ## 변수의 범위 루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다. | 변수 | 설명 | | --- | --- | | 전역(global) 변수 | 어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. **단, 메이플스토리

[task] | code [pass] | ⏳ 미판정 [title] | 아바타 애니메이션 제어하기 [question] | 아바타의 SpriteAnimPlayerEndFrameEvent 이벤트를 구독하여 종료 프레임이 재생될 때 애니메이션 재생을 중단하는 클라이언트 스크립트를 작성해줘. [answer] | 아바타의 애니메이션 종료 프레임을 감지하기 위해 `SpriteAnimPlayerEndFrameEvent` 이벤트를 구독하고, 해당 이벤트가 발생하면 애니메이션 재생을 중단하는 스크립트를 작성할 수 있습니다. 아바타 애니메이션은 클라이언트에서 재생되므로, 이벤트 구독 및 제어 로직은 모두 `[client]` 실행 공간에서 수행해야 합니다. 애니메이션 재생을 중단하기 위해서는 `ActionStateChangedEvent`를 사용하며, `SpriteAnimClipPlayType` 파라미터에 재생을 멈추는 값을 전달해야 합니다. 참고 문 [followup] | [followup_answer] | [scores] | [judge_reason] | [source_doc] | 3. 아까 저장한 **handler**를 통해 **SpriteAnimPlayerChangeFrameEvent** 구독을 취소합니다. `ChangeFrameEvent` 함수를 수정해 봅시다. ```lua [client] void ChangeFrameEvent(any event) { if event.FrameIndex == 2 then local body = self.Entity.AvatarRendererComponent:GetBodyEntity()

← → 방향키로 페이지 이동 · 숫자 입력 후 Enter로 점프