Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mensajes - Jeffrey Faper

46
lo que me intereso de este script  fue comprobar si realmente valia la pena usarlo y he comparado ambos jugadores con los diferentes sistemas de animacion, las unicas diferencias que encontre fue  que con el script se pueden crear animaciones mas susceptibles al ojo humano y ademas se tiene un mayor control sobre las acciones del jugador durante las mismas animaciones,  lo cual esta bien, claro si mi juego fuese algo mas complicado como un juego de peleas o un hack'n slash, pero es un simple juego de plataformas asi que ya lo he descartado al menos para el jugador pero tal vez lo use para animar jefes o algo por el estilo....

Como lo sospechaba la persona que creo el script es un programador que trabajaba en un juego de peleas llamado kerffufle al parecer todo le salio mal quizo abarcar demasiado y crear un juego unico nada generico al final su proyecto dio mas problemas que alegrias y termino cancelandolo....aqui les dejo algunos tutoriales de esta persona llamada Nathan Ranney,  por si alguien le interesa hacer juegos simples de pelea o beat'em ups
https://developer.amazon.com/es-mx/docs/gamemaker/hitboxes-hurtboxes.html
47
Navegando por ahi me encontre con este script que permite controlar la duracion de cada frame de nuestra animacion usando listas, lo probe en un proyecto de prueba y funciona bien ahora toca  adaptarlo a mi proyecto para ver que tal funciona si me complica la vida no dudare en descartarlo y volver a lo clasico usar un monton de if aqui les dejo el script por si alguien le interesa

Evento create:
[gml]
frameSpeed = 1;     //The speed in FPS that the game counts through the frames to be displayed. Default is 1.
frameCounter = 0;   //Increases every frame by the frameSpeed.
currentFrame = 0    //The frame of the sprite currently being drawn on the screen.
frameData =-1;      //Current list of frame data the game is reading from, based on the animation that needs to play. Idle, run, attack, etc.
frameDuration = 0;   //Total number of in game frames to display the current sprite frame.
maxFrames = 0;      //The total number of frames in any given sprite.
animSprite =-1;     //The actual name of the sprite resource in GameMaker. sprMomo_Idle, for example.
frameDataIdle = ds_list_create();
frameDataAttack1 = ds_list_create();
[/gml]

setAnimation:
[gml]
//setAnimation(frameData,spriteIndex);
frameData = argument0;
animSprite = argument1;
maxFrames = sprite_get_number(animSprite)-1;

if(currentFrame>=maxFrames-1 && frameCounter==frameDuration){
   frameReset();
   }
   
   frameCounter += frameSpeed;
   frameDuration = ds_list_find_value(frameData,currentFrame);

if(frameCounter==frameDuration){
   currentFrame ++;
   frameCounter = 0;
   }
[/gml]

frameReset:
[gml]
frameCounter = 0;
currentFrame = 0;
[/gml]

EJEMPLO COMO USARLO:
[spoiler]
[gml]
currentAnim = animSprite;

switch ( state ) {
     case normal:
          //if the player is pushing left, or right, change to run sprite
          if ( left || right )
          {   
               ds_list_insert(frameDataIdle,0,300);  //data_animation, image_index , tiempo que durara el frame
               ds_list_insert(frameDataIdle,1,30);
              ds_list_insert(frameDataIdle,2,30);
              ds_list_insert(frameDataIdle,3,30);
              ds_list_insert(frameDataIdle,4,30);
              ds_list_insert(frameDataIdle,5,30);
               animation_set ( frameDataRun, runSprite );
               //if the player isn't pushing any buttons, change to idle sprite
          } else {
               animation_set ( frameDataIdle, idleSprite );
          }
     break;

     case dash:
          //if the player is in the dash state, change to the dash sprite
          animation_set ( frameDataDash, dashSprite );
     break;
}

//check the current animation against the last animation.
//If these animations are NOT the same, reset frameCounter and currentFrame to 0.

if(lastAnim != currentAnim)
{
     frame_reset();
     lastAnim = currentAnim;
}
[/gml]
[/spoiler]

48
necesito consejos para conseguir mejores animaciones, por el momento uso image_speed pero me estoy plantenado usar otro tipo de metodo..alguna recomendacion?
49
puede hacerlo de muchas maneras con alarmas ,  temporizadores o timelines
las alarmas tienen el inconveniente, que esta limitado a 12 alarmas.
los timers tiene que activarlos, desactivarlos o resetearlos usted mismo dan mas trabajo en comparacion a una alarma.
las timelines jamas las he usado.
[gml]
//ejemplo alarma
//evento create
alarm[0] = room_speed*2;  //tiempo de espera del codigo
//evento alarm 0
  //ejecuta codigo

//ejemplo timer
//evento step
//timer por segundos. como solo va hacer funcion de activador no hace falta crear la variable en el evento create
var codeAwaits = 0+floor(current_time/1000);
if(codeAwaits>=tiempoDeseado ){
    //ejecuta codigo
   
   }
[/gml]
como no puso codigo es lo menos que le puedo ayudar

50
el jugador no se queda encima de la plataforma, funciona bien con plataformas solidas
ya lo solucione me faltaba esto vspd>0 en el codigo de colisiones , ya funciona correctamente con ambos tipos de plataformas pero me surgio otra duda como hago para controlar velocidades  de plataforma menores a 1 como 0.5;

PLATAFORMAS MOVILES :
EDITABLE SI ENCUENTRA BUGS AVISE :
https://drive.google.com/file/d/1zF4Se-PHWXp8nTsLLBUh6S3TYtZhxEFq/view?usp=sharing
[spoiler]
[gml]
//creditos para youtuber Art Games and Tech
//EVENT CREATE
platformType = 0;
initx = x;
inity = y;
hspd = 0;
vspd = 0;
radius = 60;
platDir = 1;
platAng = irandom(360);

//EVENT END STEP
switch(platformType){

//HORIZONTAL PLATFORM
case 0:
var platormSpeed = 0.5;
if(platAng mod(360)==0){
    platAng =-platAng;
    }
    platAng += platormSpeed*platDir;
    hspd = initx+lengthdir_x(radius,platAng)-x;
   
    with(parPlayers){
        if(!place_meeting(x,y,other) && place_meeting(x,y+1,other)){
            if(!place_meeting(x+other.hspd,y,parSolid)){
                x += other.hspd;
                }
            }
    }
    x += hspd;   
break;

//VERTICAL PLATFORM
case 1:
var platormSpeed = 0.5;
if(platAng mod(360)==0){
    platAng =-platAng;
    }
    platAng += platormSpeed*platDir;
    vspd = ceil(inity+lengthdir_y(radius,platAng)-y);
   
    with(parPlayers){
        if(!place_meeting(x,y,other) && place_meeting(x,y+abs(other.vspd),other)){
            if(!place_meeting(x,y+other.vspd,parSolid)){
                y += other.vspd;
                }
            }
    }
    y += vspd;   
break;
   
//CIRCULAR PLATFORM
case 2:
var platormSpeed = 0.5;
if(platAng mod(360)==0){
    platAng =-platAng;
    }
    platAng += platormSpeed*platDir;
    hspd = initx+lengthdir_x(radius,platAng)-x;
    vspd = ceil(inity+lengthdir_y(radius,platAng)-y);
   
    with(parPlayers){
        if(!place_meeting(x,y,other) && place_meeting(x,y+1,other)){
            if(!place_meeting(x+other.hspd,y,parSolid)){
                x += other.hspd;
                }
            }
        if(!place_meeting(x,y,other) && place_meeting(x,y+abs(other.vspd),other)){
            if(!place_meeting(x,y+other.vspd,parSolid)){
                y += other.vspd;
                }
            }
    }
    x += hspd;
    y += vspd;   
break;
}
[/gml]
[/spoiler]
51
Estoy trasteando con shaders,  me parecen increibles pero la mayoria de documentacion esta en ingles asi que lo poco que tengo son shaders de la pagina shaderToy convertidos a shaders  Game Maker 2 uno de estos cambia la tonalidad de la imagen por tiempo y el otro es un shader tipo waves ondas
la duda que tengo es como combinar ambos efectos,  trate de hacer un solo shader con ambos efectos pero siempre me arrojaban errores y ni idea de como solucionarlo
PROYECTO:
https://drive.google.com/file/d/1v31QgyNM6fKaxZmWWslwiFNOWyrP9P3-/view?usp=sharing

SHADER DISCO:
[spoiler]
[gml]
//shDisco
/*
//EVENT CREATE OBJECT:
sh_res  = shader_get_uniform(shDisco,"iResolution");
sh_time = shader_get_uniform(shDisco,"iGlobalTime");


//DRAW_EVENT OBJECT:
shader_set(shDisco)
shader_set_uniform_f(sh_res,512,512,0);
shader_set_uniform_f(sh_time,current_time/1000);
draw_self();
shader_reset()

*/

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float iGlobalTime;
uniform vec3 iResolution;

void main( void )
{
    //Inputs
    float gridRows = 1.0;
    float gridCols = 1.0;
    float satFactor = 0.5;
    float movingSpeed = 2.0;
   
   
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = 1.0/iResolution.xy;
   
    //We find out in which grid the pixel is
    int pixCol = int(uv.x*gridCols);
    int pixRow = int(uv.y*gridRows);
   
    // Time varying pixel color
    vec3 col = satFactor + satFactor*cos(iGlobalTime*movingSpeed+vec3(pixCol,pixRow,pixCol)+vec3(0,2,4));

    // Output to screen
    gl_FragColor = vec4(col,1.0)* texture2D(gm_BaseTexture, v_vTexcoord );
}
[/gml]
[/spoiler]

SOLUCION PROBLEMA :
al dibujar el backgroundWaves con el shader waves activado, se dibujaba la pagina de textura completa en lugar de solo el background
la solucion fue simple dibujar el backgroundWave en una surface y pasar lo dibujado en dicha surface al shader quedando nuestro evento de dibujo de esta manera
[spoiler]
[gml]
//evento draw
    //SHADER WAVES-----------------------------------------------
    //CREATE WAVES SURFACE:
    if(!surface_exists(surfWaves)){
       surfWaves = surface_create(room_width, room_height);
       }
       //draw wave sprite to waves surface:
       surface_set_target(surfWaves);
       draw_background_tiled_ext(backgroundWav,0,0,1,1,c_white,1);
       surface_reset_target();
       
       //DRAW SHADER SURFACE TO SCREEN
       shader_set(shWave);
       shader_set_uniform_f(sh_wtime,current_time/1000);
       shader_set_uniform_f(sh_wscale,mouse_x,5);
       shader_set_uniform_f(sh_wfactor,0.05,0.1);
       draw_surface(surfWaves,0,0);
       shader_reset();
[/gml]
[/spoiler]

SHADER WAVES:
[spoiler]
[gml]
//shWave
/*
//EVENT CREATE
sh_wtime =  shader_get_uniform(shWave,"time");
sh_wscale = shader_get_uniform(shWave,"Scale");
sh_wfactor = shader_get_uniform(shWave,"Factor");

//EVENT DRAW
shader_set(shWave)
shader_set_uniform_f(sh_wtime,current_time/1000);
shader_set_uniform_f(sh_wscale,10,5);
shader_set_uniform_f(sh_wfactor,0.05,0.1);
shader_reset();
*/

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float time;
uniform vec2 Scale;   // 10,5
uniform vec2 Factor; // 0.05, 0.1

void main() {
     
     vec2 texCoord = v_vTexcoord;
     texCoord.x = texCoord.x+cos(texCoord.y*Scale.x+time*Factor.x)*Factor.y;
     texCoord.y = texCoord.y+sin(texCoord.x*Scale.y+time*Factor.x)*Factor.y;
     
     gl_FragColor = texture2D(gm_BaseTexture, texCoord);
}
[/gml]
[/spoiler]



52
Gracias por la aclaracion eso explica por que al dibujar un background estatico en un objeto que sigue  a la view,
este se dibuja con un ligero desplazamiento, pero al poner x = view_xview[0];  en un evento EndStep se elimina dicho desplazamiento
53
tal vez esto le podria servir esta testeado en Game Maker 1.4

[gml]
//creo que me excedi con los comentarios asi que aqui  esta solo el codigo
//CREATE EVENT:
state = "IDLE";
runspd = 5;
walkspd = 2;
mainspd = walkspd;
hasStamina = 1;
staminaMax = 30;
staminaCount = staminaMax;

//STEP EVENT:
var keyRight = keyboard_check(vk_right);
var keyLeft  = keyboard_check(vk_left);
var keyUp    = keyboard_check(vk_up);
var keyDown  = keyboard_check(vk_down);
var keyRun   = keyboard_check(ord("E"));

    staminaCount = clamp(staminaCount,0,staminaMax);
    var moveX  = keyRight-keyLeft;
    var moveY  = keyDown-keyUp;
    var moving = point_direction(0,0,moveX,moveY);
   
    //ESTADO QUIETO
    if(state=="IDLE"){
       mainspd = 0;
       if(moveX!=0 && moveY!=0)
       ||(moveX!=0)||(moveY!=0){
          state = "MOVING";
          }
       }
    //ESTADO MOVIENDOSE
    if(state=="MOVING"){
       if(moveX!=0 && moveY!=0)
       ||(moveX!=0)||(moveY!=0){
          //CAMINAR
          mainspd = walkspd;
          //CORRER
          if(hasStamina && staminaCount>0 && keyRun){
             staminaCount -= 0.5;
             mainspd = runspd;
             }   
          }else{
                 state = "IDLE";
               }
       }
    //SI TIENE STAMINA
    if(hasStamina){
       //REGENERAR STAMINA SI EL JUGADOR PERMANECE QUIETO
       if(state=="IDLE" && staminaCount<staminaMax){
          staminaCount += 0.1;
          }
       //NO TENENMOS STAMINA
       if(staminaCount<=0){
          hasStamina = 0;
          }
    }
    //SI NO TIENE STAMINA
    if(!hasStamina){
       //REGENERAMOS NUESTRA STAMINA
       if(staminaCount<staminaMax){
          staminaCount += 0.1;
          }else{
                staminaCount = staminaMax;
                hasStamina = 1;
               }
       }
       
    direction = moving;
    speed = mainspd;

//DRAW EVENT o DRAW_GUI EVENT-----------------------------------------------------------------------------------------------------------------------------------------
//DIBUJAR MEDIDOR DE STAMINA
   draw_circular_bar(96,96,staminaCount,staminaMax,c_red,32,0.8,12);
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//CREAMOS UN SCRIPT PARA DIBUJAR NUESTRO MEDIDOR DE STAMINA CIRCULAR..COPIAR Y PEGAR EN UN SCRIPT
///draw_circular_bar(x ,y ,valor_actual, valor_maximo, color, radio, transparencia, ancho)
if (argument2 > 0) { // no point even running if there is nothing to display (also stops /0
    var i, len, tx, ty, val;
   
    var numberofsections = 60 // there is no draw_get_circle_precision() else I would use that here
    var sizeofsection = 360/numberofsections
   
    val = (argument2/argument3) * numberofsections
   
    if (val > 1) { // HTML5 version doesnt like triangle with only 2 sides
   
        piesurface = surface_create(argument5*2,argument5*2)
           
        draw_set_colour(argument4);
        draw_set_alpha(argument6);
       
        surface_set_target(piesurface)
       
        draw_clear_alpha(c_blue,0.7)
        draw_clear_alpha(c_black,0)
       
        draw_primitive_begin(pr_trianglefan);
        draw_vertex(argument5, argument5);
       
        for(i=0; i<=val; i++) {
            len = (i*sizeofsection)+90; // the 90 here is the starting angle
            tx = lengthdir_x(argument5, len);
            ty = lengthdir_y(argument5, len);
            draw_vertex(argument5+tx, argument5+ty);
        }
       
        draw_primitive_end();
       
        draw_set_alpha(1);
       
        draw_set_blend_mode(bm_subtract)
        draw_set_colour(c_black)
        draw_circle(argument5-1, argument5-1,argument5-argument7,false)
        draw_set_blend_mode(bm_normal)

        surface_reset_target()
     
        draw_surface(piesurface,argument0-argument5, argument1-argument5)
       
        surface_free(piesurface)
       
    }
   
}

[/gml]


54
es la primera vez que intento agregar dos jugadores , ya tengo casi todo listo, pero surgio una duda como controlar la camara   
SOLUCION : usar la funcion mean
[gml]
          //DOS JUGADORES UNA CAMARA...
           view_xview = ((mean(P1.x,P2.x)-view_wview/2)+view_xview*5)/6;
           view_yview = ((mean(P1.y,P2.y)-view_hview/2)+view_yview*5)/6;

[/gml]
plataformas 2 jugadores :  https://drive.google.com/file/d/1zkOHIF5ZABHBGiZIvm5_42D04HwYHNkh/view?usp=sharing
55
Cuales son las diferencias entre estos eventos  tal vez el evento step es el que tengo mas claro de todos esots, pero el resto de ellos jamas los he usado mucho menos sabria en que tipo de circunstancias seria mas  util usar uno u otro
56
estaba jugando algunos shoot em up para insipirarme, no plagio 100% inspiracion y  me tope con algunos efectos interesantes que mucha gente suele confundir con el modo7 de la super nintendo, en realidad son solo pseudo efectos 3d cualquier codificador experto de la epoca los podia crear y navegando por ahi me tope con una demo tecnica de la PC-Engine corriendo ese pseudo efecto 3d que todo mundo suele confundir con el modo7  de la snes,  para ser mas preciso estoy hablando de  una demo del Axelay....y bueno si la PC-Engine puede con ese tipo de efectos supongo que  Game Maker tambien seria capaz, sin mas rodeos estas son mis preguntas,  como podria dibujar ese tipo de backgrounds con Game Maker , es mejor usar shaders? , algun tutorial , por cierto ya intente usar las herramientas de dibujo 3d de Game Maker como d3d_draw_floor() pero los resultados no fueron muy buenos  les dejo el proyecto de prueba por si quiere echarle un vistazo

PC-Engine demos fake mode7 F-ZERO & AXELAY: https://www.chrismcovell.com/creations.html

game maker backgrounds 3d ejemplo : https://drive.google.com/file/d/1vqksrwXiYTTSoVA9rJkIBmWaBFm--IFJ/view?usp=sharing

He solucionado dos problemas  uno era que no se estaba creando la surface3D y el segundo es que  los backgrounds no se estaban dibujando correctamente al parecer si no se activa la casilla de uso para 3d las funciones de dibujado en 3d no se ejecutan correctamente, me alegra saberlo ya que en el manual no especifican nada,  pero bueno  hay otro problema y es como controlar la transparencia de los backgrounds 3d o el alpha  de la surface....
la idea es muy simple la nave navega dentro de las nubes,agua,lava hasta desaparecer dentro de estas  diminuyendo la depth de la camara y despues aumentamos la direcionz para simular un efecto zoom, para finalizar reduciriamos la transparencia de los backgrounds 3d  simulando un efecto pseudo3d muy simple pero algo es mejor que nada creo yo,  la cuestion es como se controla el alpha de una surface?
debo aclarar que  en mi mente se veia mas bonito verda de dios iwata  tal vez con un background mas grande y dibujando mas sprites se puede mejorar
tal vez hace falta jugar un poco con las variables y ver como queda mejor
57
Preguntas y respuestas / Re: Empezar de Cero
Enero 16, 2022, 08:44:33 PM
bueno eso depende de que juego quiera crear aqui le dejo mis experiencias con Game Maker:

1. fijarse un solo objetivo a la vez ....si usted quiere desarrollar un plataformas un shooter o cualquier tipo de juego necesita ir paso por paso y no avanzar hasta que
    dicho  objetivo se cumpla por ejemplo un objetivo seria crear todos los enemigos del juego o crear un personaje jugable 100% funcional no bugs. a mi me pasaba
    regularmente al no fijarme objetivos comenzaba un proyecto y lo abandonaba a la semana y comenzaba otro tipo de juego o me ponia  a ver tutoriales  al final perdia
    mi tiempo y no  aprendia nada.

2. los tutoriales estan bien para empezar pero tambien son un arma de doble filo, tenga en cuenta que la mayoria de ellos, solo abarcan un pequeño porciento de lo que
    implica desarrollar un juego, asi que,  solo debe de acudir a ellos cuando tenga alguna  duda de lo contrario perdera su tiempo y se alejara de su objetivo principal.
    como yo,  perdi un año haciendo  tutoriales y realmente aprendi muy poco.

3. escriba codigo para entender lo que esta haciendo,  puede buscar engines editables de juegos ya terminados  hay muchas por internet re-escribalas para  enteder la
    logica de  dicho codigo una vez entienda lo que hace el codigo re-interpretelas a su estilo o mejore el codigo si es posible , recuerde el inicio siempre es dificil y estara
   lleno de  pura  ​prueba y  error aun asi la mejor practica es escribir codigo aunque este no sea suyo, la practica hace al maestro si es constante en un año estara estara 
   escribiendo 2000000 lineas por segundo sera el proximo  jhon carmack.

4. y por ultimo si su juego no es divertido entonces esta haciendo algo mal, esto me paso con algunos juegos bueno niveles que cree , asi que pruebe sus juegos
   una y otra vez , si puede suba un demo para que la gente lo pruebe y asi reciba feedback, bueno aunque nadie los prueba mejor use a sus amigos como beta testers.
   
para finalizar aqui le dejo algunos editables con los que he aprendido mucho la verdad
shooter gradius engine: https://github.com/mysterypaint/Game-Maker-Studio-Shmup-Engine
mario : https://github.com/GateteVerde/Super-Mario-Bros-Engine
tohou : https://github.com/tyrz939/GMDE
mega hombre : https://github.com/rafaelcp/Super-Mega-Engine

mis proyectos test
estos son editables que uso para probar cosas como enemigos collisiones mecanicas al no tener tanta informacion pueden ser mas amigables para que practique y entienda lo que estaba tratando de hacer  al ser solo proyectos de prueba puede que encuentre muchos bugs y codigo basura
contra style game : https://drive.google.com/file/d/1fKNyJ3iKRho6NtjU3DdwUbySQkOdQ5zZ/view?usp=sharing
shoter vertical : https://drive.google.com/file/d/1rB6IaLmGn__ApLcYIS_IzXErFB4AcQF5/view?usp=sharing
megaman zero style game : https://drive.google.com/file/d/1fm8OBcp3cFUMGOSE3zz_PQiFMXoJq9h5/view?usp=sharing

este es el prototipo del juego en el que estoy trabajando no se cuantas veces e tenido que empezar de nuevo ya que siempre hay algo que se puede  mejorar o simplificar
contiene un nivel  y batalla con jefe100% terminado pero igualmente al ser un prototipo tiene muchas cosas por corregir
soldier blade fan game prototipo : https://drive.google.com/file/d/1fVBV4cgqa3_h0Vcwxn3u4m1-hdXr13x8/view?usp=sharing


espero que esto  sea de ayuda
58
estoy diseñando los niveles de mi juego con un programa externo llamado Ogmo editor pero solo maneja el formato json
como podria importarlo a Game Maker o existe algun editor que exporte mapas en formato .gmx........
lo unico que encontre fue este script que lee y almacena la data en ds_grids pero mejor usare Tiled otro editor  que  exporta tus mapas directamente a room.gmx
[gml]
///loadLevel
if(objMain.extFiles==true){
        dir = program_directory + "maps\";
        background_replace(tileset0, program_directory + "/maps/tileset_test.png",0,0);
        }
        else{
             dir = working_directory + "maps\";
        }

     var str  = "";
     var file = "";
     var hey  = "";
     var lineCount = 0;
     var tilemapWidthCountFlag = false;
     global.mapWidth = 0;

     if(ds_exists(objMain.levelData,ds_type_grid)){
        ds_grid_destroy(objMain.levelData);
     }
     
     if(ds_exists(objMain.levelDataLayer2,ds_type_grid)){
        ds_grid_destroy(objMain.levelDataLayer2);
     }
     
     file = file_text_open_read(dir+argument[0]);
     var mapHeader = file_text_readln(file);
     
     for(k=1; k<=string_length(mapHeader); k++)
     {
         if(string_char_at(string(mapHeader),k)=='"')
         { 
            var j = "";
                k++;
            while(string_char_at(string(mapHeader),k)!='"'){
                  j += string_char_at(string(mapHeader),k);
                  k++;
            }
            if(global.mapWidth<=0){
               global.mapWidth=real(j)/16;
            }
            else{
                 global.mapHeight=real(j)/16;
            }
          j = "";
         }   
    }

    global.tileWidth  = 16;
    global.tileHeight = 16;
    objMain.levelData = ds_grid_create(global.mapWidth, global.mapHeight);
    objMain.levelDataLayer2 = ds_grid_create(global.mapWidth, global.mapHeight);
    global.tilesetIndex = 0;

    for(var i=1; i<=global.mapHeight ;i++;)
    {
        for(var j=1; j<=global.mapWidth ;j++;)
        {
            var hey =  file_text_readln(file);
            var commaCount = 0;
            var tileBuffer = "";
            var tileID = "";
            for(var k=1; k <= string_length(hey); k++)
            {
                if(global.tilesetIndex==0)
                { 
                   var q="";
                   if(string_char_at(string(hey),k)==' ')
                   {
                      k+=23;
                      while(string_char_at(string(hey),k)!='"' && k<57){
                            q += (string_char_at(string(hey),k));
                            k++;
                      }
                      global.tilesetIndex = background_get_name(asset_get_index(q));//argument[1];
                      k+=19;
                   }
                   if(k==string_length(hey)){
                      i++; j--;
                   }         
                }
                tileBuffer = tileBuffer+string_char_at(string(hey),k);
                if(string_char_at(string(hey),k)==',')
                {   
                   tileID = string_delete(tileBuffer,string_length(tileBuffer),1);
                if(tileID="-1"){
                   tileID=0;
                   }
                   ds_grid_set(objMain.levelData, j-1, i-1, tileID);
                   tileBuffer = "";         
                   j++;
                }
                else if(j>=global.mapWidth){
                        tileID="";
                  while(string_char_at(string(hey),k)!='<') && (k<string_length(hey)){
                        tileID += string_char_at(string(hey),k);
                        k++;
                  }
                  if(tileID="-1"){
                     tileID=0;
                  }
                  ds_grid_set(objMain.levelData, j-1, i-1, tileID);
                  break;
                }
            } 
        }
    }

/*
//overlay tileset
global.overlayTilesetIndex=0;

for(var i=1; i<=global.mapHeight ;i++;)
{
for (var j=1; j<=global.mapWidth ;j++;)
{
var hey =  file_text_readln(file);
var commaCount = 0;
var tileBuffer = "";
var tileID = "";
for (var k=1; k <= string_length(hey); k++)
   {
   
      if global.overlayTilesetIndex==0
      {
        var q="";
          if (string_char_at(string(hey),k)==' ')
          {
          k+=20;
         
          while (string_char_at(string(hey),k)!='"' && k<57)
          {
          q += (string_char_at(string(hey),k));
          k++;
          }
         
          global.overlayTilesetIndex=background_get_name(asset_get_index(q));//argument[1];
         
          k+=19;
          }
      if k==string_length(hey)-1 {i++;j--;}   
         
      }
     
      if j>=string_length(hey)-1 {i++;break;}   
     
       tileBuffer = tileBuffer + string_char_at(string(hey),k);

       if (string_char_at(string(hey),k)==',')
       {

       tileID = string_delete(tileBuffer,string_length(tileBuffer),1);
       
       if (tileID="-1"){tileID=0;}
       //tileID is the tile we want to store here. Let's store it into the ds_grid.
       ds_grid_set(objMain.levelDataLayer2, j-1, i-1, tileID);
       
       tileBuffer = "";
       j++;
       }
       else if(j>=global.mapWidth)
       {
       tileID="";
       while (string_char_at(string(hey),k)!='<') && (k<string_length(hey))
       {
       tileID += string_char_at(string(hey),k);
       k++;
       }
       
       
       if (tileID="-1"){tileID=0;}
       ds_grid_set(objMain.levelDataLayer2, j-1, i-1, tileID);
       
       break;
       }
       
   } 
     
}
}
*/
/*

hey =  file_text_readln(file); //<entities>
hey =  file_text_readln(file); //first sprite

//entities layer
if(ds_exists(objMain.levelDataSprites,ds_type_grid)){
   ds_map_destroy(objMain.levelDataSprites);
   }
   objMain.levelDataSprites = ds_map_create();
   var q = 0;
while(string_char_at(string(hey),5)=="<")
{
   //loop through every sprite and draw them properly
   var dataPart = 0;
   var spriteIndex = "";
   for(var k=6; k<=string_length(hey); k++)
  {
    valueBuffer="";
    while(string_char_at(string(hey),k)!=' ') && (spriteIndex=="")
    {
       valueBuffer+=string_char_at(string(hey),k);
       k++;
    }
    if(spriteIndex==""){
       spriteIndex = valueBuffer;
       }
       valueBuffer = "";
    if(string_char_at(string(hey),k)=='"'){
       k++
       while(string_char_at(string(hey),k)!='"')
       {
         valueBuffer+=string_char_at(string(hey),k);
         k++;
       }
       switch(dataPart)
       {
        case 0: spriteID   = real(valueBuffer); break;
        case 1: spriteXPos = real(valueBuffer); break;
        case 2: spriteYPos = real(valueBuffer); break;
        default: break;
       }
       dataPart++;
    }
  }
  var b = string(q);
  ds_map_add(objMain.levelDataSprites, "spriteIndex" + b, spriteIndex);
  ds_map_add(objMain.levelDataSprites, "spriteID"    + b, spriteID);
  ds_map_add(objMain.levelDataSprites, "spriteXPos"  + b, spriteXPos);
  ds_map_add(objMain.levelDataSprites, "spriteYPos"  + b, spriteYPos);
  q++;
  hey =  file_text_readln(file);
}
spawnSprites();
*/
//Close the text document to avoid memory leaks
file_text_close(file);
global.tilesetWidth   = 16;
global.tilesetHeight  = 16;
global.currentMap     = argument[0]; //Let the game know which map is currently loaded
objMain.switchingMaps = false;
[/gml]
59
al parecer el evento draw  dibuja por capas lo que se dibuja primero queda al fondo, asi que la solucion fue cambiar el orden de dibujado
estos pequeños detalles son los que se olvidan facilmente y despues resultan  en un dolor de cabeza
[gml]
//DRAW EVENT
for(i=0; i<laserLength/32; i++){
    draw_sprite(sprite5,frame,x,y-i*32);  //cuerpo del laser
}   draw_sprite(sprite4,frame,x,y-laserLength);  //cabeza del lasaer
    draw_sprite_ext(sprite4,frame,x,y,1,-1,0,c_white,1);  //colita del laser


[/gml]
60
Estaba replicando algunos lasers de mis shoot em up favoritos , todo marchaba bien , hasta que intente replicar el laser  beam tipo consolador del juego Dogyuun,  el laser funciona adecuadamente, el unico problema fue que al colisionar el laser contra enemigos la punta del laser terminaba desapareciendo asi que decidi dibujar todo manual mente paso por paso osea con un monton de if,  aqui les dejo el codigo del laser y el projecto por si quieren echarle un vistazo  tal vez usted  encuentre la solucion
laser animado projecto:
https://drive.google.com/file/d/1rB6IaLmGn__ApLcYIS_IzXErFB4AcQF5/view?usp=sharing

[gml]
//LASER STEP EVENT
///STANDARD LASER TEST
var laserTrim = keyboard_check_pressed(ord("W"));

      frame += 0.3;
     
   if(laserTrim){
      laserEnd = 1;
      laserLength = maxLength/choose(1,2,3);
      }
   //INIT LASER BEAM
   if(image_xscale>0.1) && (!laserEnd)
   {  x = pShip.x;
      y = pShip.y;
      depth += 0.05;
      image_xscale -= 0.0125;   
     if(maxLength<512){maxLength +=32;}
     for(i=0; i<maxLength; i++)
     {   xEnd = x+lengthdir_x(i,90);
         yEnd = y+lengthdir_y(i,90);
         laserLength = i;
      if(collision_point(xEnd,yEnd,parEn,0,0)) && (parEn.canStopLaser){
         break;
         }
     }
   }
   //LASER END
   if(image_xscale<=0.1) || (laserEnd){
      speed = laserSpeed;
      image_xscale -= 0.0025;
   }
   //ENEMIES TAKE DAMAGE
   if(instance_exists(parEn))
   {var hitting = ds_list_create();
        hitting = collisionLineList(x,y,xEnd,yEnd,parEn,1,0);     
     if(hitting>0)
     {for(var i=0; i<ds_list_size(hitting); i++;)
       {var inst = ds_list_find_value(hitting,i);
         if(inst.hitPoints!=0){
            with(inst){
                 hitPoints--;
                 crashFX++;
                 }
            }
       }
       ds_list_destroy(hitting);
     }
   }
   //DESTROY LASER INSTANCE
   if(image_xscale<=0){
      instance_destroy();
      }
   if(y<=view_yview-sprite_height){
      instance_destroy();
      }
//DRAW EVENT
for(i=0; i<laserLength/32; i++){
    draw_sprite(sprite5,frame,x,y-i*32);  //cuerpo del laser
}   draw_sprite(sprite4,frame,x,y-laserLength);  //cabeza del lasaer
    draw_sprite_ext(sprite4,frame,x,y,1,-1,0,c_white,1);  //colita del laser

[/gml]