2016년 10월 1일 토요일

[GMS] Pushing Blocks! 블럭 밀기


GMS 강좌 블럭 밀기입니다.


제가 만든건 아닙니다만, 동영상을 보고 필요가 있을것 같아서 정리해 보았습니다.

동영상은 아래를 보면됩니다. 길기 때문에 설명으로 정리하였습니다.
https://www.youtube.com/watch?v=I-DR-RKMwZw




전체적인 구성

obj_block을 obj_player가 밀 수 있으며 벽은 밀수가 없습니다. 소코반이라는 고전 게임과 유사한 동작을 하게 됩니다.

sprites
spr_player, spr_block, spr_wall 3개를 32*32 이미지로 만듭니다.


Objects
obj_player, obj_block, obj_wall을 만들어서 sprite를 연결하고, obj_block의 부모는 obj_wall이 되도록 설정합니다.

Rooms
테두리를 obj_wall로 그리고 obj_block을 적당히 그리고, obj_player를 하나의 위치에 둡니다

Event

obj_player:Create event

hspd = 0;
vspd = 0;
spd = 4;

hspd는 좌우 속도를 의미합니다. 키를 누르면 좌우 속도를 저장하게 됩니다.
vspd는 상하 속도를 의미합니다.
spd는 상수값으로 속도에 곱해지는 값입니다.

obj_player:Step event

// get input
hspd = (keyboard_check(vk_right)-keyboard_check(vk_left))*spd;
vspd = (keyboard_check(vk_down)-keyboard_check(vk_up))*spd;

scr_push();

// move
scr_move(hspd,vspd);

step이벤트는 room 설정값에 의해 주기적으로 들어오게 됩니다. scr_push()함수를 이용해서 블럭을 밀게 됩니다. 그리고 scr_move()함수를 이용해 player를 이동시킵니다.

Scripts

/// scr_move()
var hspd = argument[0];
var vspd = argument[1];
// H
if ( place_meeting(x+hspd,y,obj_wall )){
    while (!place_meeting(x+sign(hspd),y,obj_wall)){
        x+=sign(hspd);
    }
    hspd = 0;
}
x+=hspd;
// V
if ( place_meeting(x,y+vspd,obj_wall )){
    while (!place_meeting(x,y+sign(vspd),obj_wall)){
        y+=sign(vspd);
    }
    vspd = 0;
}
y+=vspd;

scr_move함수는 가로세로, 상하 속도를 입력받아 이동하는데, 한번에 이동되어지는 좌표는 미리 설정해 놓은 spd 값만큼 이동하게 됩니다.
하지만 이동하고자 하는곳에 이미 벽이 있다면 이동을 못하게 해야되는데, 이때 검사하는 함수가 place_meeting함수 입니다. 좌표와 instance를 넣으면 충돌 여부를 알려줍니다.
한번에 이동해야 할 지점에 벽이 있다면, +1 증가하면서 갈 수 있는곳까지 진행을 해줘야 벽에 붙게 됩니다.
그 처리를 while loop를 돌면서 하게 됩니다. sign 함수의 리턴이 0,1,-1 이므로 하나씩 증가 또는 감소하면서 좌표를 이동하게 됩니다. (sign함수는 인자가 양의 값이면 1 음의 값이면 -1, 0이면 0의 값을 리턴하게 됩니다.)


// scr_push
// H
if(place_meeting(x+hspd,y,obj_block)){
    var block = instance_place(x+hspd,y,obj_block);
    with(block){
        scr_move(obj_player.hspd/2,0);
    }
    hspd/=2;
}

if(place_meeting(x,y+vspd,obj_block)){
    var block = instance_place(x,y+vspd,obj_block);
    with(block){
        scr_move(0,obj_player.vspd/2);
    }
    vspd/=2;
}

scr_push 함수는 이동하는곳에 블럭이 있는경우 어떤 블럭인지 알아내서(instance_place 함수) 속도의 절반으로 블럭의 좌표를 이동합니다.
이때 with 함수를 쓰며 with(block){을 사용하면 그이후 } 를 만날때 까지 해당 내용의 object member의 접근은 block 의 instance를 사용하게 됩니다.
이때 블럭을 밀고 있으니 움직이는 양을 절반으로 줄이도록 하며, block의 이동하는 양도 절반으로 줄이게 됩니다.





댓글 없음:

댓글 쓰기