2019년 8월 18일 일요일

GMS2 Room Transition (룸 전환 효과)



Room Transition 입니다.
최종 구현은 아래 gif 이미지 참고 바랍니다.
ROOM이 여러개 존재하고 Room이동시 이전 룸 화면과 새로운 룸의 화면이 겹치는 방식입니다. 구현을 위해서는 surface를 사용하게 됩니다.



전체 구조는 아래와 같습니다.

Sprites

sRoomChange : Player가 충돌되었을때 RoomChange 가 일어나는데 충돌이 되는 이미지
sPlayerIdle : Player의 이미지
stext : room0를 표기하기 위해 사용하는 이미지
stext1 : roomR을 표기하기 위해 사용하는 이미지
stext2 : roomL을 표기하기 위해 사용하는 이미지

Scripts

EaseOutQuad 함수 https://easings.net/ 여기 참고 바랍니다.
/// EaseOutQuad(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3;
return -argument2 * argument0 * (argument0 - 2) + argument1;

Objects

oRoomTransitionSMLeft 

Left로 이동 효과를 나타내는 object
persistent 이 값은 Room이 종료되더라도 남아있게 하기 위한 용도입니다.
만약 room 효과가 완전히 완료 되었을때 수동으로 종료가 필요합니다.
maxframes 값은 최대 frame수를 결정합니다. 숫자가 커질 수록 전환이 늦어집니다.
Create
/// @description Insert description here
// You can write your code in this editor
currentframe = 0
maxframes = 20

persistent = true; // when changing room keep this object alive

// copy the old room so we can display it on the second room
sur_oldroom = surface_create(surface_get_width(application_surface),surface_get_height(application_surface));
surface_copy(sur_oldroom,0,0,application_surface)

room_persistent = false;

Destory
/// @description Insert description here
// You can write your code in this editor
surface_free(sur_newroom)
surface_free(sur_oldroom)

moveobject.x = movex;
moveobject.y = movey;
moveobject.facing = movefacing;
destory 될때 특정 object를 특정한 위치에 이동 시키고자 할때 사용합니다.  facing은 여기에서는 특별한 의미로 사용되고 있지는 않지만 의도는 캐릭터의 방향을 전달하기 위한 목적입니다.

Step
currentframe++

if (currentframe > maxframes) {
    instance_destroy() // The transition has finished so destroy it
}


// We are now on the second room so record that room. 
if (currentframe == 2) { 
 moveobject.x = movex;
 moveobject.y = movey;
 moveobject.faceing = movefacing;
}
if (currentframe == 3) { 
    sur_newroom = surface_create(surface_get_width(application_surface),surface_get_height(application_surface));
    surface_copy(sur_newroom,0,0,application_surface)
}
frame이 3일때는 새로운 room 이 준비가 되었을것이므로 surface 를 복사합니다.

Draw GUI
if (currentframe > 2) {

    // convert the number of frames that have passed into a number between 0 and the room width
    var slideamount = EaseOutQuad(currentframe,0,surface_get_width(application_surface),maxframes)

    if (surface_exists(sur_oldroom)) {
        draw_surface(sur_oldroom,+slideamount,0)
    }

    if (surface_exists(sur_newroom)) {
        draw_surface(sur_newroom,-surface_get_width(application_surface)+slideamount,0)
    }
}


/// I do this to hide the flicker where the next room pops up for 1 frame 
if (currentframe <= 2 ) { 
    if (surface_exists(sur_oldroom)) {
        draw_surface(sur_oldroom,0,0)
    }
}
Draw GUId에서는 sur_oldroom, sur_newroom를 이용해서 적절히 복사하는 과정입니다. 이때 EaseOutQuad 함수를 이용하게 됩니다.

oRoomTransitionSMRight

Right로 이동 효과를 나타내는 object
Left와 거의 동일하나 Draw GUI 부분이 약간 다릅니다.
Create
/// @description Insert description here
// You can write your code in this editor
currentframe = 0
maxframes = 20

persistent = true; // when changing room keep this object alive

// copy the old room so we can display it on the second room
sur_oldroom = surface_create(surface_get_width(application_surface),surface_get_height(application_surface));
surface_copy(sur_oldroom,0,0,application_surface)

room_persistent = false

Destory
/// @description Insert description here
// You can write your code in this editor
surface_free(sur_newroom)
surface_free(sur_oldroom)
moveobject.x = movex;
moveobject.y = movey;
moveobject.facing = movefacing;

Step
currentframe++

if (currentframe > maxframes) {
    instance_destroy() // The transition has finished so destroy it
}


// We are now on the second room so record that room. 
if (currentframe == 2) { 
 moveobject.x = movex;
 moveobject.y = movey;
 moveobject.faceing = movefacing;
}
if (currentframe == 3) { 
    sur_newroom = surface_create(surface_get_width(application_surface),surface_get_height(application_surface));
    surface_copy(sur_newroom,0,0,application_surface)
}

Draw GUI
if (currentframe > 2) {

    // convert the number of frames that have passed into a number between 0 and the room width
    var slideamount = EaseOutQuad(currentframe,0,surface_get_width(application_surface),maxframes)

    if (surface_exists(sur_oldroom)) {
        draw_surface(sur_oldroom,-slideamount,0)
    }

    if (surface_exists(sur_newroom)) {
        draw_surface(sur_newroom,surface_get_width(application_surface)-slideamount,0)
    }
}


/// I do this to hide the flicker where the next room pops up for 1 frame 
if (currentframe <= 2) { 
    if (surface_exists(sur_oldroom)) {
        draw_surface(sur_oldroom,0,0)
    }
}


oPlayer


Step
var kLeft, kRight, kUp, kDown;

kLeft        = keyboard_check(vk_left)  || gamepad_axis_value(0, gp_axislh) < -0.4;
kRight       = keyboard_check(vk_right) || gamepad_axis_value(0, gp_axislh) >  0.4;
kUp          = keyboard_check(vk_up)    || gamepad_axis_value(0, gp_axislv) < -0.4;
kDown        = keyboard_check(vk_down)  || gamepad_axis_value(0, gp_axislv) >  0.4;

if( kLeft ){
 x = x - 4;
}

if( kRight ){
 x = x + 4;
}

if( kUp ){
 y = y - 4;
}

if( kDown ){
 y = y + 4;
}
키를 누르면 object를 이동 시킵니다.

oRoomChange

충돌 oPlayer
// have to set
//dir : "Left" "Right"
//moveobject;
//movex;
//movey;
//movefacing;
//gotoroom

room_persistent = false;
var inst;
if(dir=="Left"){
 inst = instance_create_layer(0,0,"Instances",oRoomTransitionSMLeft);
}else{
 inst = instance_create_layer(0,0,"Instances",oRoomTransitionSMRight);
}

inst.moveobject = moveobject;
inst.movex = movex;
inst.movey = movey;
inst.movefacing = movefacing;
room_goto(gotoroom)

미리 아래값을 설정해 두어야 합니다. 그렇지 않으면 오류가 발생합니다.
해당값은 room instance를 더블클릭하여 설정합니다.
//dir : "Left" "Right"
//moveobject;
//movex;
//movey;
//movefacing;
//gotoroom


Rooms

room0


room0 좌우측에 oRoomChange 를 배치합니다.
그리고 oRoomChange 를 각각 더블 클릭하여 Creation Code를 입력합니다.
우측은 다음과 같습니다.
// have to set
dir = "Right"
moveobject = oPlayer;
movex = 0;
movey = 150;
movefacing = 0;
gotoroom = roomR

좌측은 다음과 같습니다.
// have to set
dir = "Left"
moveobject = oPlayer;
movex = 300;
movey = 150;
movefacing = 0;
gotoroom = roomL;

roomR

roomR에서는 좌측에만 oRoomChange 가 존재하며 초기 코드는 아래와 같습니다. 좌측으로 이동하면 이동하는곳은 room0이어야 합니다.


// have to set
dir = "Left"
moveobject = oPlayer;
movex = 300;
movey = 150;
movefacing = 0;
gotoroom = room0;


roomL

roomL에서는 오른쪽에만 oRoomChange가 있습니다.

// have to set
dir = "Right"
moveobject = oPlayer;
movex = 0;
movey = 150;
movefacing = 0;
gotoroom = room0;





댓글 없음:

댓글 쓰기