본문 바로가기
GameMaker강좌[GMS2]/네트워크강좌

[게임메이커 강좌-네트워크][GMS2] 멀티플레이어 게임 만들기-6-플레이어의 공격 업데이트

by 타락카얀 2024. 12. 25.
728x90

 

 

GAME MAKER 강좌

 

KAYAN

 

 

 

 

 

 

◈ 플레이어의 공격 업데이트

 

다음은 플레이어 공격에 관한 업데이트입니다.

 

플레이어 오브젝트의 공격 이벤트를 찾아 총알 생성 위치를 공유하도록 합니다.

 
obj_player_1 오브젝트 - Step 이벤트
 
 
var inst;
if reload == 0{
if keyboard_check_pressed( ord( "Z" ) ){
 
inst = instance_create_depth( x, y, depth, obj_bullet );
inst.direction = direction;
inst.user_id = user_id;
 
reload = 1;
alarm[1] = 10;
 
//---------- ▼ 생성 위치 공유
 
buffer_seek( global.net_buffer, buffer_seek_start, 0 );
buffer_write( global.net_buffer , buffer_u16, 11 ); //패킷 이벤트 번호
buffer_write( global.net_buffer , buffer_u8, user_id );
buffer_write( global.net_buffer , buffer_f16, x ); //x
buffer_write( global.net_buffer , buffer_f16, y ); //y
buffer_write( global.net_buffer , buffer_f16, direction ); //direction
 
buffer_write( global.net_buffer , buffer_string, object_get_name( inst.object_index ) );
//---------- 클라이언트 유저
if global.select_server == 0{
network_send_packet( global.client_socket, global.net_buffer, buffer_tell( global.net_buffer ) );
}
//---------- 클라이언트 유저
//---------- 서버 유저
else{
for ( var i = 0; i<ds_list_size( global.socketlist ); i++; ){
network_send_packet( ds_list_find_value( global.socketlist, i ), global.net_buffer, buffer_tell( global.net_buffer ) );
}
}
//---------- 서버 유저
 
//---------- ▲ 생성 위치 공유
 
}
}
 

 

이 게임은 기본적으로 서버가 모든 정보를 취합해 먼저 처리하고 클라이언트에게 업데이트 정보를 보내 동기화하는 방식입니다.

먼저 클라이언트 유저의 정보를 서버에서 처리해봅시다.

클라이언트가 보낸 정보로 총알을 서버의 게임룸에 생성합니다.

그리고 그 정보를 다른 클라이언트에게도 공유하여 동일하게 생성(동기화)하도록 합니다.

 
obj_server_system 오브젝트 - Async - Networking 이벤트
 
 
case 11:
var _user_id, _x, _y, _obj, _dir, inst;
_user_id = buffer_read( t_buffer, buffer_u8 );
 
_x = buffer_read( t_buffer, buffer_f16 );
_y = buffer_read( t_buffer, buffer_f16 );
_dir = buffer_read( t_buffer, buffer_f16 );
 
_obj = buffer_read( t_buffer, buffer_string );
 
if object_exists( asset_get_index( _obj ) ){
with( obj_player_parent ){ if ( user_id == _user_id ){
inst = instance_create_depth( _x, _y, depth, asset_get_index( _obj ) );
inst.direction = _dir;
inst.user_id = user_id;
}}
}
 
 
//클라이언트에 패킷을 보내 적용
buffer_seek( global.net_buffer, buffer_seek_start, 0 );
buffer_write( global.net_buffer , buffer_u16, 11 ); //패킷 이벤트 번호
buffer_write( global.net_buffer , buffer_u8, _user_id ); //socket
buffer_write( global.net_buffer , buffer_f16, _x ); //x
buffer_write( global.net_buffer , buffer_f16, _y ); //y
buffer_write( global.net_buffer , buffer_f16, _dir ); //direction
 
buffer_write( global.net_buffer , buffer_string, _obj ); //object
 
for ( var i = 0; i < ds_list_size( global.socketlist ); i+ = 1; ){
if !( ds_list_find_value( global.socketlist, i ) == sock ){
network_send_packet( ds_list_find_value( global.socketlist, i ), global.net_buffer, buffer_tell( global.net_buffer ) );
}}
 
break;
 

 

다음은 클라이언트에서 업데이트 하도록 합니다.

서버에서 받은 정보로 총알을 생성합니다.

 
obj_client_system 오브젝트 - Async - Networking 이벤트
 
 
case 11:
var _user_id, _x, _y, _obj, _dir, inst;
_user_id = buffer_read( t_buffer, buffer_u8 );
_x = buffer_read( t_buffer, buffer_f16 );
_y = buffer_read( t_buffer, buffer_f16 );
_dir = buffer_read( t_buffer, buffer_f16 );
 
_obj = asset_get_index( buffer_read( t_buffer, buffer_string ) );
 
if ( object_exists( _obj ) ){
with( obj_player_parent ){ if ( _user_id == user_id ){
inst = instance_create_depth( _x, _y, depth, _obj );
inst.direction = _dir;
inst.user_id = user_id;
break;
}}
}
 
break;
 

 

 

 

 

◈ 플레이어 파기 이펙트 생성

 

플레이어 오브젝트가 파기 될 때, 이펙트를 플레이어 위치에 생성해봅시다.

(▲ 이펙트)

 

이펙트 오브젝트(obj_destroy_effect)를 하나 만들고, 이펙트 이미지를 지정합니다.

 

[Animation End 이벤트]를 추가하고, 애니메이션이 끝났을 때 파기하도록 합니다.

 
obj_destroy_effect 오브젝트 - Animation End 이벤트
 
 
instance_destroy( );
 

 

플레이어 오브젝트에 [Destroy 이벤트]를 추가하고, 이 이펙트를 체력이 0이하일 때 생성합니다.

 

 
obj_player_1 오브젝트 - Destroy 이벤트
 
 
if ( HP< = 0 ){
instance_create_depth( x, y, depth-1, obj_destroy_effect );
}
 

 

서버는 파기될 때, 다른 클라이언트들에게 해당 플레이어 캐릭터의 체력값을 공유하여 서버와 같은 동작을 하도록 유도합니다.

 

obj_player_1 오브젝트 - Destroy 이벤트
 
 
if ( HP< = 0 ){
 
instance_create_depth( x, y, depth-1, obj_destroy_effect );
 
//---------- ▼ 서버
if ( global.select_server == 1 ){
 
buffer_seek( global.net_buffer, buffer_seek_start, 0 );
buffer_write( global.net_buffer , buffer_u16, 17 ); //패킷 이벤트 번호
buffer_write( global.net_buffer , buffer_u8, user_id );
buffer_write( global.net_buffer , buffer_f16, x ); //x
buffer_write( global.net_buffer , buffer_f16, y ); //y
buffer_write( global.net_buffer , buffer_f16, direction ); //direction
buffer_write( global.net_buffer , buffer_f16, HP );
 
for ( var i = 0; i<ds_list_size( global.socketlist ); i++; ){
network_send_packet( ds_list_find_value( global.socketlist, i ), global.net_buffer, buffer_tell( global.net_buffer ) );
}
}
//---------- ▲ 서버
}
 

 

클라이언트 오브젝트의 [네트워크 비동기 이벤트]에서 서버로 받은 정보를 업데이트해줍니다.

 
obj_client_system 오브젝트 - Async - Networking 이벤트
 
 
case 17:
var _user_id, _x, _y, _dir, _HP;
_user_id = buffer_read( t_buffer, buffer_u8 ); //user_id 0 = server 1 ~ = client
_x = buffer_read( t_buffer, buffer_f16 );
_y = buffer_read( t_buffer, buffer_f16 );
_dir = buffer_read( t_buffer, buffer_f16 );
_HP = buffer_read( t_buffer, buffer_f16 );
with( obj_player_parent ){
if ( _user_id == user_id ){
move_x = _x;
move_y = _y;
direction = _dir;
HP = _HP;
break; }
}
break;
 

 

 

 

 

 

◈ 총알의 플레이어 피격 설정

 

총알의 피격 설정을 만들어 봅시다.

(▲ 이펙트)

 

먼저 피격 이펙트 오브젝트(obj_damage_effect)를 하나 만듭니다.

 

총알 오브젝트(obj_bullet)에 [플레이어와의 충돌 이벤트]를 추가합니다.

총알과 충돌하는 플레이어가 자신을 생성한 플레이어가 아닌 경우에 이벤트를 발동하도록 합니다.

 

 
obj_bullet 오브젝트 - 플레이어와의 충돌 이벤트( obj_player_parent )
 
 
if !( other.user_id == user_id ){ //자신을 생성한 플레이어가 아닌경우
//총알 파기
instance_destroy( );
 
//이펙트 생성
instance_create_depth( x, y, depth-1, obj_damage_effect );
 
//서버는 상대 체력을 변경함.
if ( global.select_server == 1 ){ other.HP- = 10; }
}
 

 

총알이 플레이어와 충돌하면 총알 자신은 파기하고, 이펙트를 생성하게 됩니다.

클라이언트는 이펙트만 생성하고, 서버는 상대 플레이어의 체력을 변경합니다.

 

 

 

 

 

 

 

 

 

300x250

댓글