Thứ Hai, 10 tháng 4, 2017

Youtube daily Apr 10 2017

Drake has got reasons to be happy now.

His album More Life remains number

1 on BillBoard 200 and he has also got someone to share his happiness with.

After dating a list of gorgeous women and publicly showing off his love drizzy is rumored

to be dating singer Jorja Smith in a low key manner.

The rapper collaborated with the 21-year-old, from Walsall, on his new song "More life".

And Drake turned heads when he was spotted at a local Co-op.

While Jorja was busy shopping for sweets the hotline blinge hitmaker posed for a picture

with a member of staff at the Broadway store.

Though it looks different this time and Drake is not a relationship person we hope it is

not just another fling for him.

For more infomation >> Drake Dating More Life Singer Jorja Smith - Duration: 1:15.

-------------------------------------------

OGGI HO IMPARATO A FARE HARDFLIP INDIE DAL BRAILLE DROP - Duration: 10:13.

For more infomation >> OGGI HO IMPARATO A FARE HARDFLIP INDIE DAL BRAILLE DROP - Duration: 10:13.

-------------------------------------------

Selena Gomez and The Weeknd Love Making TAPE LEAKED!! - Duration: 1:23.

After being in the news for her romance with the Weeknd, Selena Gomez became victim of

sex tape leak which has shocked everyone.

A website posted a video of the star which is claimed to be a leaked Instagram story

from the Weeknd's cell phone.

She looks tipsy in the videos making out with various African American men.

The fake video titled "Selena Gomez Black Sex Party," features footage's from the

good for you singer's Instagram and Snapchat accounts that were clubbed with pornographic

material.

Selena was not the only woman in the video.

She was seen with another blonde posing in for the clip.

The disney star is not the only one who have been victim to such explicit video leak. various

A- listers have been the targets of the leak.

Even after the sex tape have gone viral Sel haven't responded to the rumors.

For more infomation >> Selena Gomez and The Weeknd Love Making TAPE LEAKED!! - Duration: 1:23.

-------------------------------------------

Now you Pause and Resume in Xender Updated version | Resume your item any time in Xender - Duration: 2:09.

Subscribe MI Tech

Update Whatsapp

Need two smartphones

select send/recive

here to you pause and resume

enjoy the Xender

For more infomation >> Now you Pause and Resume in Xender Updated version | Resume your item any time in Xender - Duration: 2:09.

-------------------------------------------

GMnet: Server is king (Tutorial 006) - Duration: 1:22:57.

Before we begin you need to download GMnet template 003 or above (See description).

In this tutorial we will create a server is king architecture

This means that the server hold all the cards and the clients only send minor info to the server.

The server then process the data and only send back draw info.

First we remove stuff we dont need anymore.

htme_rom_demo

remove htme_obj_player

obj_create_network_objects>Create event

//instance_create(0,0,htme_obj_playerlist);

We first need a player object that is created on the server and controlled by the client.

duplicate htme_obj_player to obj_player

Remove persistent

Delete Create event

Delete Begin step event

Delete End step event

Delete draw event

Delete 1 key event

Delete 2 key event

Add a create event and a code block

/// Init pressed_jump = false; pressed_left = false; pressed_right = false;

Ok. This will be our basic player character. We will create a player for each player that join the server.

obj_client_handler

Every player have this synced object and a REMOTE on each other.

So when obj_client_handler is created on the server we can create a obj_player at the same time.

Create event add a code block.

// Create player CreatePlayer=true; // ID of the created player PlayerID=noone;

Step begin event add code block

/// Create player

if htme_isServer() { }

if CreatePlayer { {

// Create player PlayerID=instance_create(90,500,obj_player); // Only create one player CreatePlayer=false;

We also need to destroy the obj_player when the obj_client_handler is destroyed

Add a destroy event and a code block

/// Destroy if PlayerID>-1 with PlayerID instance_destroy();

When a player disconnect the obj_client_handler is destroyed and obj_player with it.

We also need to set PlayerID to noone if the obj_player is destroyed by an enemy.

obj_player

Add a destroy event and a code block

/// Reset player with obj_client_handler { if PlayerID=other.id PlayerID=noone; }

We loop all obj_client_handler and check if PlayerID is the same as the destoyed.

If it's the same the player id who was destroyed it belonged to that clients. So we reset it.

Ok. The client will send info to steer his player. We do this by RPC. For that we need a script.

Create a new group in scripts named Network

First we need to create some help scripts

Create a new script named htme_get_instance_hash

/// htme_get_instance_hash() return htme_mp_player;

htme_mp_player is the player hash of a synced instance. All synced instances got this variable to define the owner of it.

Create a new script named htme_get_last_rpc_hash

/// htme_get_last_rpc_hash(); return obj_htme_rpc.Last_From;

Last_From is a variable from the RPC object that hold the last received player hash.

Ok. Now for the steer script.

Create a new script named scr_Network_Steer_player

/// scr_Network_Steer_player(data string);

var data_string=argument0;

// Find right obj_client_handler with obj_client_handler { }

// Check if this instance belong to the RPC sender if htme_get_instance_hash()=htme_get_last_rpc_hash() { }

// Give player id the info if PlayerID>-1 { }

with PlayerID { }

pressed_jump = real(string_char_at(data_string,1)); pressed_left = real(string_char_at(data_string,2)); pressed_right = real(string_char_at(data_string,3));

Ok. This script will take a string with data and each number in the string represent a command state.

This dont make sense yet. But we now come to the key logger.

The keylogger log keys we press and send them to the server and to our player there.

Create a object group named Network

Create a new object obj_player_keylogger

Add Create event and a code block

/// init

// Init logger pressed_jump[0] = false; pressed_left[0] = false; pressed_right[0] = false;

// Last value logger pressed_jump[1] = false; pressed_left[1] = false; pressed_right[1] = false;

Add a step event and a code block

/// Logger

Logger_new[0] = keyboard_check(vk_space); Logger_new[1] = keyboard_check(vk_left); Logger_new[2] = keyboard_check(vk_right);

// Check if different from last send and generate send string var FoundChange=false var SendString="";

for (var i=0; i<array_length_1d(Logger_new); i+=1) { }

// Check for change if Logger_new[i]!=Logger_last[i] { }

FoundChange=true;

// Add to send string SendString+=string(Logger_new[i]); // Save last Logger_last[i]=Logger_new[i];

// Send if FoundChange { }

htmerpc_send(htme_hash(),scr_Network_Steer_player,obj_server_handler.htme_mp_player,SendString);

First we get the new key states and save them.

We compare them to the last sended values and generate a send string.

The string is simply a 1 or 0 depending on the key state and we just put them in a string.

If there is a change in the keys we send the string to the server that give our player new info.

We dont need a return value from the RPC so we dont use a RPC handler. We simply use the RPC send script.

We need to create the key logger in the room.

obj_create_network_objects

This object will create and destroy the instance when needed.

Create event

instance_create(0,0,obj_player_keylogger);

Destroy event

with obj_player_keylogger instance_destroy();

We are now ready for a first test.

Create a server.

A obj_client_handler is created that also create a obj_player and we "link" the client_handler and the obj_player by saving the obj_player id in obj_client_handler.

The obj_player_keylogger was also created and when we press a key it detect the change and send it to the server.

Press the arrow keys.

The server get the info and search for the obj_client_handler that give us the obj_player id.

The server now set the info to the obj_player and we start to move the player.

When we dont press any keys the change is detected and send a new info string to the server.

As you know P1 is the server so when we send the RPC the engine will detect that and not actually send anything.

It will just simulate it and run the script.

Now connect P2

When P2 is connected a obj_client_handler is created on P2 and then synced to P1 as a REMOTE.

When the obj_client_handler REMOTE object was created on the server it created a obj_player.

P2 also created a obj_player_keylogger to check changes and send a info string to the server.

Use the arrows to move the player.

You see that we can move our player on the server but we dont see anything on P2.

Thats because the obj_player is only created on the server.

Now we will make the server send draw info to the clients. And make the client draw the info.

First we must collect all players positions, sprite_index and image_index.

Bundle everything together and send it.

The client can then use that info and draw it on his screen.

We can use obj_server_handler to collect and draw the info for the clients.

But first we need to collect and bundle the draw info

obj_server_handler

Create event

// Define collector variables Collector_que=noone saved_arrays=noone;

We will use this later in the destroy event. So we must init it first.

Add a new code block in the create event

/// Collector if htme_isLocal() { }

// Collect queue Collector_que=ds_queue_create();

// Objects to collect Collector_objects_array[0]=obj_player;

// Sync variable data_chunk=""; data_chunk_last="";

// Steps to collect before send Collector_collect_steps=1; Collector_collect_counter=0;

// Buffers to use

Collector_buffer_array[0]=buffer_s16; // x (-32,768 to 32,767)

Collector_buffer_array[1]=buffer_s16; // y (-32,768 to 32,767)

Collector_buffer_array[2]=buffer_u16; // sprite_index (0-65,535)

Collector_buffer_array[3]=buffer_u8; // image_index (0-255)

We will collect all data in a queue. We put the objects we want to collect data from in an array.

Last we set a counter for one step before we will send the info. We will experiment with this later :-)

We create an array for the buffer types depending on what value we will collect.

We also need to clean if destroyed

Add a destroy event add a code block

/// Clean if htme_isServer() { }

if Collector_que>-1 { }

ds_queue_destroy(Collector_que);

Step begin event

Add a new code block

/// Collector if htme_isServer() { }

// Loop object to count them var collect_id_list=ds_list_create();

for (var i=0; i<array_length_1d(Collector_objects_array); i+=1) { }

with Collector_objects_array[i] ds_list_add(collect_id_list,id);

// Loop objects to sort them depending on ther depth // Create grid to hold id and depth so we can sort it later

var instance_grid=ds_grid_create(2,ds_list_size(collect_id_list));

// Define temp var var temp_instance;

for (var i=0; i<ds_list_size(collect_id_list); i+=1) { }

temp_instance=collect_id_list[| i]; instance_grid[# 0,i]=temp_instance; instance_grid[# 1,i]=temp_instance.depth;

// Sort the grid after depth ds_grid_sort(instance_grid,1,false);

// Loop instances and collect current info for (var i=0; i<ds_list_size(collect_id_list); i+=1) { }

// Get instance from grid temp_instance=instance_grid[# 0,i];

// Get info from instance with temp_instance { }

// Collect info chunk ds_queue_enqueue(other.Collector_que,x,y,sprite_index,image_index);

// Clean ds_list_destroy(collect_id_list); ds_grid_destroy(instance_grid);

// Count up collected steps Collector_collect_counter+=1;

// Create send string when countdown is done if Collector_collect_steps<=Collector_collect_counter { }

// Reset countdown Collector_collect_counter=0;

// Check if we collected something if ds_queue_empty(Collector_que)=false { }

// Create buffer var myBuffer=buffer_create(2048,buffer_grow,1); // Temp variable var theValue=0;

// Count the buffer array so we know how big each collection chunk is var infoChunk=array_length_1d(Collector_buffer_array);

// Loop collected info and turn it to a buffer while (!ds_queue_empty(Collector_que)) { }

// Loop buffers we use and get chunk values for (var j=0; j<infoChunk; j+=1) { }

// Get the value from the queue theValue=ds_queue_dequeue(Collector_que);

// Put the value in the buffer with the buffer type we set in the create event

buffer_write(myBuffer,Collector_buffer_array[j],theValue);

// Convert the buffer to a string data_chunk=scr_Buffer_To_String(myBuffer,true); EDIT: also add: // Clean buffer_delete(myBuffer);

// Check if different from last send if data_chunk!=data_chunk_last { }

// Send to all players htmerpc_send(htme_hash(),scr_Network_Draw_Info,"",data_chunk);

// Save as last data_chunk_last=data_chunk;

else { }

// Send empty to all players htmerpc_send(htme_hash(),scr_Network_Draw_Info,"","");

else { }

// Add new step chunk // This will work as a stop when the client process the data

ds_queue_enqueue(Collector_que,-1000,-1000,0,0);

Ok. What do we do here?

// Loop object to count them

We need to sort the instances after depth so we can collect the info in the depth order. Else depth wont work.

// Loop objects to sort them depending on the depth

We create a grid and save id and depth then we sort after the depth

// Loop instances and collect current info

Loop all instances in the depth order and collect info

// Count up collected steps

Count up the step counter by 1

// Create send string when countdown is done

If the step counter is done we create and send the string

// Add new step chunk

If the step counter is not done we save a special "new step" set. When the client read this he knows we sent more than one step.

// Check if we collected something

We check if we collected something, who knows all players may be gone.

// Send empty to all players

If all players is gone we just send an empty string to the clients so they stop draw.

// Create buffer

We create a buffer that will hold our collected info.

// Loop collected info and turn it to a buffer

We loop the collected info and step each chunk that is now 4 pieces (x,y,sprite_index,image_index)

// Loop buffers we use and get chunk values

We loop the buffer array and add each value collected and get the buffer type from the buffer array

// Convert the buffer to a string

Convert the buffer to a string so we can send it via RPC to the clients

// Check if different from last send

If the send is different from the last time we send it else we dont need to send it.

Ok. Now we collect and send the data to the clients. But the client need to process the received info.

We need to setup some variables in the obj_server_handler when the REMOTE is created on the clients.

obj_server_handler>Create event

else { }

// draw_array[x]. Each index hold another array with one draw chunk. This is what we draw to the screen

Draw_array=noone;

// Saves all incomming data chunks, each queue got a draw_array[x] that contain chunk arrays.

saved_arrays=ds_queue_create();

We also need to clean this if it get destroyed

Destroy event

else { }

if saved_arrays>-1 { }

// Destroy saved arrays ds_queue_destroy(saved_arrays);

Ok. The server will make the client run scr_Network_Draw_Info and provide a string with info.

Create a new script scr_Network_Draw_Info in the Network group

/// scr_Network_Draw_Info(data_string);

// If server then exit if htme_isServer() exit;

// Get data chunk var data_string=argument0;

// Check if empty if data_string!="" { }

// Convert to buffer var MyBuffer=scr_String_To_Buffer(data_string);

// Continue in the obj_server_handler with obj_server_handler { }

// buffer value array define var theValue_array=noone; // define draw array var new_draw_array=noone;

// Count the buffer array so we know how big each collection chunk is var infoChunk=array_length_1d(Collector_buffer_array);

// Loop buffer while (buffer_tell(MyBuffer)<buffer_get_size(MyBuffer)) { }

// Loop buffers we use and get chunk values for (var j=0; j<array_length_1d(Collector_buffer_array); j+=1) { }

// Get value from buffer theValue_array[j]=buffer_read(MyBuffer,Collector_buffer_array[j]);

// Check if new step chunk if theValue_array[0]=-1000 and theValue_array[1]=-1000 and theValue_array[2]=0 and theValue_array[3]=0 { }

// Found new step chunk // Put the draw array into the saved arrays ds_queue_enqueue(saved_arrays,new_draw_array);

// Reset new draw array, so its ready for next step info new_draw_array=noone;

else { }

// Draw info, save in new draw array if is_array(new_draw_array) { }

// Add value array to new draw array new_draw_array[array_length_1d(new_draw_array)]=theValue_array;

else { }

// Set first value array in draw array new_draw_array[0]=theValue_array;

// Unlink the array from the new draw array theValue_array=noone;

// Put new draw array into the saved arrays ds_queue_enqueue(saved_arrays,new_draw_array);

// Clean buffer_delete(MyBuffer);

else { }

// Continue in the obj_server_handler with obj_server_handler { }

// Add noone in saved ds_queue_enqueue(saved_arrays,noone);

Ok. What do we do here?

// Check if empty

We check if we got an empty draw then we set to draw a empty step.

// Convert to buffer

We convert the string back to a buffer to get info from.

// Loop buffer

We loop the buffer and step one chunk (4 pieces in each chunk right now)

// Loop buffers we use and get chunk values

Read the buffer and get the buffer type from our buffer array. We add the value to an array.

// Check if new step chunk

If it has the special "new step" values we save the new draw array we generated until now and start with a empty new draw array for the next step in the buffer.

// Draw info, save in new draw array

Save the value array to the new draw array

// Put new draw array into the saved arrays

Save the last draw array

Ok. Now we processed the received draw info and saved all the new draw arrays in a queue.

We now need to get the first draw array from the queue and draw it on the screen.

obj_server_handler

Create a draw event and add a code block

/// Draw

// Only draw if not on the server if !htme_isServer() { }

// Get new draw array from the save queue, if any if ds_queue_empty(saved_arrays)=false { }

// Get next step to draw Draw_array=ds_queue_dequeue(saved_arrays);

// Get later step if we got too many while (ds_queue_size(saved_arrays))>Collector_collect_steps*2 { }

// Get next step to draw Draw_array=ds_queue_dequeue(saved_arrays);

// Check if draw array got info if is_array(Draw_array) { }

// define draw chunk var chunk_array;

// Loop array and draw each chunk for (var i=0; i<array_length_1d(Draw_array); i+=1) { }

// Get a chunk chunk_array=Draw_array[i];

// Draw chunk draw_sprite(chunk_array[2],chunk_array[3],chunk_array[0],chunk_array[1]);

Ok. What do we do here?

// Get new draw array from the save queue, if any

If there is a draw array saved in the queue we get it, else draw the last one

// Check if draw array got info

It may be noone if there is nothing to draw so we check for that

// Loop array and draw each chunk

Loop the draw array and grab a chunk and draw it

Ok. Now we can test it.

Now the client can see the players too.

Now for the pros and cons.

The cons is that you may notice that when P2 move. It takes about 20-40 milliseconds before the player actually move. This is fine in LAN but in Online you will notice it even more.

You can only have one room. So if you want shops or other floors in your game you need to add them in other sections in the same room.

The pros is that all objects will always be in perfect sync. You don't need to resolve paradoxes.

We want to keep these pros because they are simply too good. But we want to make the game work online too.

So how do we do that?

Well it depends on what game you are creating.

In the next tutorials we will add our server architecture to some games.

But before we do that we need to set GMnet to use delta time.

With delta time enabled you dont need to worry if the game lag and clients sudenly disconnects.

Scripts>Gmnet>htme>htme_config

use_delta_time=true;

Ok. Thats it.

We want to add our server to the extension so we can import it to the games we will make go multiplayer.

Extensions>GMnet>Export resources

First remove everything

Then click add all.

We dont want to import the htme demo so remove:

Sprites>htme_demo

Fonts

objects>htme_demo>game We keep the menu object.

Rooms>htme_rom_demo

Rooms>htme_rom_demo2

We keep the Lobby and the menu rooms.

Save

Ok. Now we export the extension as GMnetServerIsKing

We also export WinDev so we can use the dual windows.

Ok. We now have two extensions ready to be imported to a game.

In the next tutorial we will import it to one of the demo games in Game maker.

For more infomation >> GMnet: Server is king (Tutorial 006) - Duration: 1:22:57.

-------------------------------------------

Как повысить ФПС (FPS) в играх? 3 практических шага! - Duration: 7:26.

For more infomation >> Как повысить ФПС (FPS) в играх? 3 практических шага! - Duration: 7:26.

-------------------------------------------

Top 15 cầu thủ bị "hói đầu" nổi tiếng nhất trong bóng đá. Ngôi sao bóng đá trước và sau khi hói đầu - Duration: 2:21.

Top 15 Footballers Before They Were Bald

Không có nhận xét nào:

Đăng nhận xét