홀로라이브 운동회에서 할 무궁화 꽃이 피었습니다 게임을 대충 비슷하게 따라하고 싶으면 대충 이렇게 만들면 될거임
커맨드 블록으로 움직임을 감지하는 원리는 현위치를 과거 위치랑 비교해서 다르면 set, 같으면 clear로 두는 거임
좌표를 저장하기 위해 내 경우에는 스코어보드를 사용하는 튜토리얼을 참고했음
뭐 누군가는 플레이어의 NBT 태그 데이터에 과거 위치를 저장할 수도 있겠지만 나는 NBT 태그까지는 잘 몰라서 패스
스코어보드에 추가한 목표(변수)는 8개를 썼음
DetectMovement: 1로 지정된 플레이어나 엔티티의 움직임을 감지함
x, y, z: 플레이어/엔티티의 현재 좌표값
x1, y1, z1: 플레이어/엔티티의 과거 좌표값
Moved: 플레이어/엔티티의 움직임 여부
참고로 스코어보드에 들어가는 모든 목표값은 int형임
메인 감지 회로는 크게 세 포인트로 나뉨
과거 위치 저장 → 현 위치 저장 → 위치 변화 감지
맨 처음 보라색 커맨드 블록만 옵션을 으로 했고
이어지는 나머지 8개 블록은 옵션을 로 지정했음
각각에 들어가는 코드는 아래와 같음
execute as @e[scores={DetectMovement=1}] run execute store result score @s x1 run scoreboard players get @s x
execute as @e[scores={DetectMovement=1}] run execute store result score @s y1 run scoreboard players get @s y
execute as @e[scores={DetectMovement=1}] run execute store result score @s z1 run scoreboard players get @s z
execute as @e[scores={DetectMovement=1}] run execute store result score @s x run data get entity @s Pos[0]
execute as @e[scores={DetectMovement=1}] run execute store result score @s y run data get entity @s Pos[1]
execute as @e[scores={DetectMovement=1}] run execute store result score @s z run data get entity @s Pos[2]
execute as @e[scores={DetectMovement=1}] run execute unless score @s x = @s x1 run scoreboard players set @s Moved 1
execute as @e[scores={DetectMovement=1}] run execute unless score @s y = @s y1 run scoreboard players set @s Moved 1
execute as @e[scores={DetectMovement=1}] run execute unless score @s z = @s z1 run scoreboard players set @s Moved 1
이해하기 쉽게 풀어 쓰면
execute as @e[scores={DetectMovement=1}] run ... 스코어보드에서 DetectMovement=1인 엔티티에 대해 이하 내용을 실행 execute store result score @s x1 run ... 현재 선택된 엔티티의 x1 목표(스코어보드 변수)에 이하 내용을 실행한 결과 값을 저장 scoreboard players get @s x 현재 선택된 엔티티의 x 목표의 값을 반환
Pos(x_coord, y_coord, z_coord)
엔티티의 현재 좌표(double형), Pos[0]은 x 좌표값을 의미함
scoreboard players set @s Moved 1 현재 선택된 엔티티의 Moved 목표를 1로 설정함
추가로, 중간의 data 명령어의 경우에는 반환되는 결과값에 배율만큼 곱해줄 수 있음
(data get의 명령어 양식: data get entity [target] [path] [scale] )
이게 왜 중요하냐면 앞에서 말했지만 스코어보드는 값이 int값으로 저장됨
그래서 저 코드대로 하면 double인 좌표값에서 소수점을 전부 버림하니까 한 블럭 안에서 움직이는 정도는 감지하지 않음
작은 움직임까지 감지하고 싶다면 배율을 100000쯤 지정해서 아래와 같이 하면 더욱 정확한 값을 얻을 수 있음
execute as @e[scores={DetectMovement=1}] run execute store result score @s x run data get entity @s Pos[0] 100000
다만 int형의 범위가 -2,147,483,648 ~ 2,147,483,647(-231 ~ 231-1)라는 점을 염두하고 배율을 지정하셈
아무튼 Moved 목표가 1로 지정되면 다시 리셋해야되잖음
필요에 따라서 Moved만 리셋할 수도 있고 Moved = 1일 때 뭔가 액션을 취할 수도 있고
리셋만 할 때는 커맨드 블록으로 아래 명령어를 실행하면 됨
execute as @e[scores={Moved=1},sort=arbitrary] run scoreboard players set @s Moved 0
커맨드 블록 옵션은 (repeat, unconditional, needs redstone)으로 했는데, 여기서 Repeat를 Impulse로 바꿔버리면 한 번만 실행되고 마니까 무조건 Repeat으로 해야됨
무언가 액션을 취할 때, 예를 들어 누가 움직였다고 표시할 때는 반복 커맨드 블록이랑 체인 커맨드 블록을 쓰면 됨
보라색 반복 커맨드 블록은 명령어에 "execute as @e[scores={Moved=1},sort=arbitrary] run say @s moved!"를 넣고 옵션은 (repeat, unconditional, needs redstone)로 두었음
뒤에 연결된 초록색 체인 커맨드 블록은 명령어에 "execute as @e[scores={Moved=1},sort=arbitrary] run scoreboard players set @s Moved 0"을 넣고 옵션은 (chain, unconditonal, always active)로 두었음
마지막으로 무궁화 꽃이 피었습니다를 구현해보고 싶을 때,
나는 대충 6초 주기 반복회로랑 NOT 게이트, 커맨드 블록 네 개로 구현함
옵션이랑 명령어는 가장 왼쪽 커맨드 블록부터:
(impulse, unconditional, needs redstone), "say Red Light!"
(repeat, unconditional, needs redstone), "kill @e[scores={Moved=1},x=-14,y=64,z=-135,dx=2,dy=10,dz=2,sort=arbitrary]"
(repeat, unconditional, needs redstone), "execute as @e[scores={Moved=1},sort=arbitrary] run scoreboard players set @s Moved 0"
(impulse, unconditional, needs redstone), "say Green Light!"
명령어 kill @e[scores={Moved=1},x=-14,y=64,z=-135,dx=2,dy=10,dz=2,sort=arbitrary] 에서 좌표값이 가리키는 게 저 공간만큼임
가장 가운데 흑요석의 좌표가 (-14, 64, -135)고 여기서 x축 방향으로 ±2 블록, y축 방향으로 ±10블록, z축 방향으로 ±2 블록 만큼에 대해서 kill 명령어가 작동함
홀로라이브 운동회 연습 영상을 보면 크리에이티브 모드로 날아다니는 사람은 죽지 않는데, 크리에이티브인 사람은 안죽게하려면 조건에 gamemode=!creative를 추가하면 됨
짤에 보이는 것처럼 메시지를 플레이어 화면 한 가운데 띄우고 싶으면 이건 서버에 플러그인 설치해서 하셈
이것만큼은 모드나 플러그인 없는 바닐라 명령어 셋트만으로 안될거임
P.S 1) 보다 정밀한 동작감지를 원하면 엔티티의 Pos만 사용하는 대신 Pos와 Rotation을 사용할 수도 있음
Rotation은 수평면에 대한 시계방향의 각도(yaw), 수직면에 대한 시계방향의 각도(pitch)를 저장하고 있는 float형 배열임
Rotation의 변화량을 감지하는 구문을 추가하면 고개를 움직이는 것도 감지할 수 있음
이건 x, y, z 좌표랑 yaw, pitch에 배율 100000을 적용하고 실험한 결과임
고개만 까딱 돌렸는데 바로 죽는 걸 확인할 수 있을거임
고개를 안움직였더라도 한 발자국만 움직였으면 똑같이 죽었을거임
그리고 엔티티의 NBT 태그 데이터 중에 Motion이라는 값도 있는데 이건 엔티티에 '가해지는' 속도임
엔티티가 스스로 움직이는 경우에는 Motion값이 변하지 않고 TNT 폭발이나 다른 엔티티와 겹쳐져서 생기는 '외력'에 의한 속도만 적용됨
평소에는 중력만 적용되므로 데이터를 뽑아봐도 [0.0d, -0.0784000015258789d, 0.0d]만 반환될거임
아쉽지만 괜히 Pos값의 변화량을 계산하는 게 아님;;;;;;;;;;;
P.S 2) 어째 꺽쇠 표시한 것들이 전부 html 태그로 인식되서 지워지냐;;;; 지워진 내용 수정함
참고자료:
https://minecraft.fandom.com/wiki/Scoreboard
https://minecraft.fandom.com/wiki/Commands/scoreboard
https://minecraft.fandom.com/wiki/Commands/data
https://minecraft.fandom.com/wiki/Commands/execute
https://minecraft.fandom.com/wiki/Target_selectors
좌표값 저장해서 체크만 하는거니 구조자체는 단순하네
과학자인가
마크 커맨드 블록은 정말 모르겠다
그저 아는 것만 알 뿐이라구!
Very nice... 2021/11/06 02:27
과학자인가
테헤란 2021/11/06 02:29
그저 아는 것만 알 뿐이라구!
라이시너스 2021/11/06 02:28
프로그래머가 아니라서 스크롤내렸슴니다...
섹(시)스(타킹) 2021/11/06 02:28
마크 커맨드 블록은 정말 모르겠다
시마무라우즈키 2021/11/06 02:29
대충????하는 짤들
벨라모르 2021/11/06 02:33
음.. 이건 미코나 미오가 만들었을거라 생각이 들지 않네.. 전문 인력 같은 게 따로 있었으려나...
xnest 2021/11/06 02:34
좌표값 저장해서 체크만 하는거니 구조자체는 단순하네
테헤란 2021/11/06 02:41
ㅇㅇ 그저 int형 한계때문에 경기장 위치에 따라 배율 크기에 한도가 있고, 매 틱마다 계산하는 데 서버의 리소스가 좀 필요할 뿐이지
다만 생판 모르는 사람이 하기에는 좀 어려울 수 있을 것 같음
나태한자 2021/11/06 02:50
노력추
뷁투더퓨챠 2021/11/06 02:51
그러니까 이걸 마크에서 해야된다 이거지..?