How to update part of a buffer with part of a surface

D

dmaroto

Guest
I am new to this forum, so hello to everyone. English is not my native language, so forgive if you sometimes find it strange what I write.

I am programming a game where players can modify the level (a sprite) in a way similar to what lemmings (the classic game from 1991) do while they dig.

I draw the sprite level on a surface, and every time a player modifies the level I draw it on that surface with bm_subtract blend mode. I also need to update the level sprite collision mask, so that the movement of the characters is consistent with the new level sprite.

At the beginning I tried using sprite_collision_mask to update it, but as the level sprite is the same size as the room (1280x480) performance drops dramatically.

Then I tried saving the surface data into a buffer and I changed the way I check collisions. Now I read the buffer to check collisions as I can no longer use sprite masks (the sprite level mask is not updated).

It seemed to solve my problem, but when I tried the game on a tablet (android) I found performance was also dropping (from 60 steps per second to 40 and even less). Keep in mind that I am not updating the level mask every step. I only do it when it is needed, and once per second at most.

I have found updating the buffer with the whole sprite data is still dropping performance, although it is working better than updating the sprite collision mask. I guess updating only part of the buffer, that corresponding to the space where the sprite has been modified, could be the final solution, but I am not sure how to get it.

I thought getting pixels data from the surface to update the buffer using surface_getpixel or any other similar one, but the documentation warns of the poor performance of these functions and discourages their use.

The only solution I can guess is copying part of the surface on another one with surface_copy_part, copying this second surface into a temp buffer, and then reading its data and updating the level collision mask buffer, but it’s a lot of programming for something that maybe I could get in an easier way or with some GameMaker’s functions.

Could you please help me with any suggestion? Here is the relevant code:

Code:
//Render Level and Init Mask
if !surface_exists(global.LevelSurface) {
global.LevelSurface = surface_create(room_width,room_height);
surface_set_target(global.LevelSurface);
draw_clear_alpha(0,0);
draw_sprite(sprite_index, 0, 0, 0);
surface_reset_target();
global.LevelMask = buffer_create(room_width*room_height*4, buffer_fixed, 1);
buffer_get_surface(global.LevelMask, global.LevelSurface, 0,0,0);
}

//Draw Level
if global.LevelModified {                                         
    surface_set_target(global.LevelSurface);
    draw_enable_alphablend(true);
    draw_set_blend_mode(bm_subtract);
    //Here comes everything about drawing on the surface (I omit it)
    draw_set_blend_mode(bm_normal);
    surface_reset_target(); 
    }

//Update Level Mask
if global.LevelMaskUpdate {
        //var _old_sprite = sprite_index; This all was for updating the sprite collision mask
        //sprite_index = sprite_create_from_surface(global.LevelSurface,0,0,sprite_width,sprite_height,false,false,0,0);
        //if (_old_sprite != spr_level0) sprite_delete(_old_sprite);
        //sprite_collision_mask(sprite_index, false,0,0,0,0,0,0,0); This is what I used before
        buffer_get_surface(global.LevelMask, global.LevelSurface, 0,0,0);
        }

//Draw Level
draw_surface(global.LevelSurface,0,0);
Edit:
I keep on testing and unfortunately I see just drawing the level on its surface every time it is changed causes a drop in performace even if I do not update the mask buffer when running on Android.
This means I can try updating only part of the mask buffer but it's not going to get much better. And I need surfaces for this.
Anyway, I will try it, and at the same time I will decrease the number of times it is necessary to update the Level Surface. I can not think of anything else.
 
Last edited by a moderator:
Top