/* ----------------------------------------------
 * Game Title: Mado Paf!
 * By: davidgd72k, Twitter: david de 72k (@davidgd72k)
 * Powered by: Gemix Studio 7.5 BETA Legacy
 * For: Dream Diary Jam
 ---------------------------------------------- */

//los nombres de las variables estan escritas siguiendo el modelo CamelCase
//y los nombres de los procesos y funciones propio estan escritas como si fuesen los nombres de comandos propios del lenguaje 

compiler_options _case_sensitive; //se diferencian las mayusculas de las minusculas
compiler_options _extended_conditions; //permite asignaciones en las condiciones

program Mado_Paf;
const
	velocidadMovimientoJugador = 7;
	
	//fuerza de la gravedad que modifica las demas fuerzas
	//cuanto menor sea, los objetos 'flotaran' mas (mas
	//tardaran en caer)
	gravedad = 2;
	
	//fuerza del impulso que se aplica al cuadrado en Y cualdo salta
	fuerza_y = 25;
	fuerzaCaida = 5;
	
	//punto de contacto con el suelo
	sueloBola = 380;
global
	string palabraNombreJuego = "Mado Paf!";
	string palabraNombreJuego2 = " by davidgd72k";
		
	int fpgGraficosPrincipales;
	int fpgMadotsuki;  //FPG, contiene los graficos de la prota
	
	int fntGeneral; //font for game texts
	int fntGeneral2;
	int fntTitleScreen; //font for game title screen
	
	int sfxExplota;
	int sfxDisparo;
	int musica;
	
	int canalMusica;
	int sonando = false;
	
	int tituloAparecido;
	
	int vidas; //lifes
	int puntos; //score
	int totalBolas; //total of ball per level
	int nivelJuego; //actual level
	
	int record = 100; //establezco el record por defecto
	
	int archivo;
	
	int disparosDisponibles; //indica los disparos que tienes disponibles para disparar
	int puntoXDisparo;
	int puntoYDisparo;
local
	int tiempoFrame = 0; //para emular el uso de FRAME(%) en caso de que lo use
private
	
begin
	mode_set(640,480,32); //set the video mode
	set_fps(30,0); //obviously set Frames Per Second
	
	window_set_title(palabraNombreJuego + palabraNombreJuego2); //muestra el nombre del juego
	
	carga_recursos(); //carga los recursos del juego
	
	//parte para cargar el fichero de guardado del record
	archivo = fopen("record.sav", "r");
	if (archivo)
		fclose(archivo);
		load("record.sav", offset record);
	end
	
	presentando_juego(); //inicia el juego mostrando información del mismo
end

// ----------------------------------------------

/* ----------------------------------------------
 * Proceso presentando juego
 * Se encarga de iniciar el juego, presentando la información de este.
 * Sin parametros
 ---------------------------------------------- */
 
process presentando_juego()

private
	contador = 0;
begin
	screen_fade_out();
	let_me_alone();
	controlador_de_ventana();
	tiempoFrame = 100;
	screen_set_color(40,40,40);
	screen_fade_in();
	
	write(fntGeneral,320,240-20,4,"Mado Paf!");
	write(fntGeneral,320,240,4,"By: davidgd72k");
	write(fntGeneral,320,240+20,4,"For: Dream Diary Jam");	
	
	while (contador < tiempoFrame)
		contador++;
		frame;
	end	
	
	inicio_juego();
	
end

// ----------------------------------------------

process inicio_juego()
private
	int tiempoEsperaTeclas = 0;
begin
	screen_fade(0,0,0,64); //screen off
	let_me_alone();
	text_delete(all_text);
	
	if (sonando == true)
		soundchannel_stop(canalMusica);
		sonando = false;
	end
	
	screen_clear();
	controlador_de_ventana();
	screen_set_color(40,40,40);	
	
	vidas = 5; //set lifes for player
	puntos = 0; //set score
	nivelJuego = 0; //set start level
	disparosDisponibles = 0; //set number of shoot's
	screen_fade(100,100,100,4); // screen on
	
	rotulo_juego();
	
	while(tituloAparecido == false)
		frame;
	end
	
	write(fntGeneral,320,467,4,"By: davidgd72k");
	
	loop //permite poder pulsar las teclas
		tiempoEsperaTeclas++;
		
		if (tiempoEsperaTeclas == 30)
			pulsar_boton_inicio(); //sale texto parpadeante de Press ENTER
		end
		
		if (tiempoEsperaTeclas > 32) //ya puedes pulsar ENTER para jugar al juego
			if (keydown(_enter))
				juego();
			end
			
			if (keydown(_esc))
				exit("Game for Dream Diary Jam, 2017",0);
			end
		end
		
		//no tiene porque poner esto, es totalmente prescindible
		if (tiempoEsperaTeclas > 50)
			tiempoEsperaTeclas = 50;
		end
		frame;
	end
end

// ----------------------------------------------

process rotulo_juego()
private
	tiempoAlpha = 0;
begin
	source.graph = write_in_map(fntTitleScreen,"Mado Paf!", 4);
	
	//set position of title screen
	position.x = 320;
	position.y = 210;
	
	fx.alpha = 0;
	
	tituloAparecido = false;
	
	while (fx.alpha < 255)
		fx.alpha += 2;
		frame;
	end
	
	fx.alpha = 255; //por si el canal alpha no se completa del todo
	
	tituloAparecido = true;
	
	loop
		frame;
	end
end

// ----------------------------------------------

process pulsar_boton_inicio()
private
	int textoIniciar = 0;
	string textoDeIniciar = "Press ENTER to start";
	int contador = 0;
	//int visibleTexto = 0;
begin
	tiempoFrame = 50;
	
	loop		
		textoIniciar = write(fntGeneral,320,445,4,textoDeIniciar);
		
		while (contador < tiempoFrame)
			contador++;
			frame;
		end
		contador = 0;
		
		text_delete(textoIniciar);
		
		while (contador < tiempoFrame)
			contador++;
			frame;
		end
		contador = 0;
				
		frame;
	end
end 
			
// ----------------------------------------------

process juego()
private
	int textoNivel = 0;
	int contador = 0;
begin
	screen_fade(0,0,0,4);
	let_me_alone();
	text_delete(all_text);
	screen_clear();
	controlador_de_ventana();
	
	//llamo al marcador del jugador
	foto_grafico(fpgGraficosPrincipales, 1, 320, 437, 10, 100, 100, 0, 255);
	foto_grafico(fpgGraficosPrincipales, 3, 320, 397, 11, 100, 100, 0, 255);
	
	//tiempoFrame = 200;
	screen_fade(100,100,100,5);
	
	while(fading)
		frame;
	end
	
	write(fntGeneral2,100,437,4,&vidas); //Muestra el numero de vidas del jugador
	write(fntGeneral,320,436,4,&puntos); //Muestra los puntos que tiene ahora mismo el jugador
	write(fntGeneral,480,436,4,&record); //Muestra el record (highscore) del jugador
	
	ground_put(fpgGraficosPrincipales, 2); //pone un grafico de fondo
	
	madotsuki();
	if (sonando == false)
		canalMusica = sound_play(musica);
		sonando = true;	
	end
	
	switch (nivelJuego)
		case 0:
			totalBolas = 14;
			
			bola(fpgGraficosPrincipales,20,190,120,100,100, 0, 1, 1);
			bola(fpgGraficosPrincipales,21,380,120,100,100, 0, 2, 1);
			
			signal(type bola, s_freeze);
			textoNivel = write(fntGeneral2,320,120,4,"Readying Level");
			
			tiempoFrame = 80;
			while (contador < tiempoFrame)
				contador++;
				frame;
			end	
			contador = 0;
			
			signal(type bola, s_wakeup);
			text_delete(textoNivel);
		end
		case 1:
			textoNivel = write(fntGeneral2,320,120,4,"You are ready for Infinite Level");
			
			
			tiempoFrame = 60;
			while (contador < tiempoFrame)
				contador++;
				frame;
			end	
			contador = 0;
			
			text_delete(textoNivel);
			
			textoNivel = write(fntGeneral2,320,120,4,"Infinite Level");
			
			tiempoFrame = 40;
			while (contador < tiempoFrame)
				contador++;
				frame;
			end	
			contador = 0;			
			
			text_delete(textoNivel);
						
			totalBolas = -1;
			controlador_de_bolas();
		end
	end
	loop
		if (puntos>record) 
			record=puntos;
		end
		if (totalBolas==0)
			nivelJuego += 1;
			while (contador < tiempoFrame)
				contador++;
				frame;
			end	
			contador = 0;
			
			juego(); 
			break;
		end
		if (keydown(_esc))
			inicio_juego();
		end
		
		frame;
	end
end

// ----------------------------------------------



// ----------------------------------------------

/* ----------------------------------------------
 * Proceso Madotsuki, la protagonista del juego
 * Personaje que controla el jugador
 * ???
 ---------------------------------------------- */

process madotsuki()

private
	//Tabla con la animación hacia la derecha (tambien vale hacia la izquierda usando FLAGS)
	int animRight[] = 2,2,2,2,1,1,1,1,3,3,3,3,1,1,1,1,0;
	int i = 0;
	
	int pulsando = 0; //indica si se esta pulsando una tecla o no
	int direccionMovimiento = 0; //dirección del movimiento del jugador
	int tiempoInmune = 0; //indica el tiempo de inmunidad del personaje jugador
begin
	source.file = fpgMadotsuki;
	source.graph = 4;
	set.flags = 0;
	
	position.x = 320;
	position.y = 354;
	position.z = 5;
	
	scale.x = 200;
	scale.y = 200;
	
	loop
		if (pulsando < 3)
			if (keydown(_left) and position.x > 15)
				position.x -= velocidadMovimientoJugador;
				set.flags = 1;
				pulsando = 2;
				
				if(animRight[i] != 0)
					graph = animRight[i];
					i++;
				else
				  graph = animRight[i-1];
				  i = 0;  //vuelve al comienzo de la animación.
				end
			end
			if (keydown(_right) and position.x < 625)
				position.x += velocidadMovimientoJugador;
				set.flags = 0;
				pulsando = 2;
				
				if(animRight[i] != 0)
					graph = animRight[i];
					i++;
				else
				  graph = animRight[i-1];
				  i = 0;  //vuelve al comienzo de la animación.
				end
			end
		end
		
		if (keydown(_x) and disparosDisponibles <= 0)
			pulsando = 5; 
			source.graph = 4;
		end
		
		pulsando--;
		
		if (pulsando == 3) 
			disparo();
			disparosDisponibles = 1;
		end
		 
		if(pulsando == 0)
			source.graph = 4; //el grafico normalmente estaria mirando hacia arriba para dar mas precision al disparar
			set.flags = 0; //establezco el espejado del grafico
		end
		
		tiempoInmune++;
		
		if (tiempoInmune < 80)
			fx.alpha = 128;
		end
		if (tiempoInmune => 80)
			fx.alpha = 255;
			if (collision(type bola))       //comprueba si te toca una bola
                vidas--; 
				tiempoInmune=0;     //si te ha tocado resta vidas-1 y pone inmune a 0, para volver al protagonista inmunerable por unos instantes
                if (vidas<=0)
					if (puntos>record) 
						record = puntos;
					end
					save("record.sav", offset record, sizeof(record));
					inicio_juego();
                end     //comprueba si vidas es menor o igual a 0, si es igual o menor a -1 quiere decir que te han quitado todas las vidas y volveras a inicio del programa con la llamada inicio()
            end
		end
		frame;
	end
end

// ----------------------------------------------

process disparo()
private
	int animShoot[] = 20,20,20,20,21,21,21,21,22,22,22,22,23,23,23,23,0;
	int i = 0;
	
	int tiempoCola = 0;
begin
	source.file = fpgMadotsuki;
	
	position.x = father.x +12;
	position.y = father.y -10;
	
	puntoXDisparo = position.x;
	puntoYDisparo = position.y -10;
	
	sound_play(sfxDisparo);
	
	loop
		position.y -= 10;
		
		if(animShoot[i] != 0)
			graph = animShoot[i];
			i++;
		else
			graph = animShoot[i-1];
			i = 0;  //vuelve al comienzo de la animación.
		end
		
		if (position.y < -20)
			disparosDisponibles = 0;
			signal(type cola_disparo, s_kill);
			break;
		end
		
		//-----------------------------------------------------------
		// * Añade al disparo la función de crear una cuerda que sigue a la flecha principal
		tiempoCola++; //ve sumando el tiempo del disparo
		
		if (tiempoCola>=3) //si tiempo_cola es igual o mayor que un cierto valor ...
			cola_disparo(); //crea un trozo de cola
			tiempoCola = 0; //reinicia el tiempo del disparo de la cola
		end
		//-----------------------------------------------------------
		
		frame;
	end
end

// ----------------------------------------------

process cola_disparo()
begin
	source.file = fpgMadotsuki;
	source.graph = 30; 
	position.z = 2; //profundidad del grafico (que esta detras del prota)
	set.flags = 0;
	
	position.x = puntoXDisparo;
	position.y = puntoYDisparo;
	
	loop
		position.y-=10;
		
		//set.flags++;
		
		/*if (set.flags>1) 
			set.flags=0;
		end*/
		
		frame;
	end
end

// ----------------------------------------------
// bola(file,graph,x,y,size_x,size_y, flags, yendoX, yendoY)
process bola( source.file, source.graph, position.x, position.y, scale.x, scale.y, set.flags, yendoX, yendoY)
private
	int idDisp;        //variable para identificar si colisiona con el disparo del prota
	int idColaDisp;   //variable para identificar si colisiona con la cola del disparo del prota
	int velocidadBola = 4;
	int velocidadCaidaBola = 0;
	int f_y = 0;
	int cayendoInicial;
	int botando;
	
begin
	position.z=30;
	
	cayendoInicial = true;
	botando = false;
	
	loop
		//bola normal
		if (source.graph == 20) 
			if (yendoX==0 and botando == false and cayendoInicial == true)      //si anima_x & anima_y es 0
                position.y++;      //saldra la bola en la parte superior de la pantalla bajando a 1
                if (y=>30)      //comprueba si y es mayor o igual de 30                    
					botando = false;
					cayendoInicial = true;
					yendoX=rand(1,2);
					set.flags=0;    //y hace un rand para que vaya saltado hacia la izquierda o hacia la derecha
                end
            end
			
			if (yendoX==1)
                position.x-=velocidadBola;
                if (position.x<10) 
					position.x=10;
					yendoX=2;
				end
            end
            
			if (yendoX==2)
                position.x+=velocidadBola;
                if (position.x>630) 
					position.x=630;
					yendoX=1;
				end
            end
			
			if (botando == false and cayendoInicial == true)				
				
				position.y += velocidadCaidaBola; 
				velocidadCaidaBola++;
				
                if (velocidadCaidaBola>16) 
					velocidadCaidaBola=16;
				end
				
                if (position.y > sueloBola)
					position.y = sueloBola;
					cayendoInicial = false;
				end
			end
			
			if (botando == true and cayendoInicial == false)
				f_y -= gravedad;
			else
				if (position.y >= sueloBola)
					botando = true;
					f_y = fuerza_y;
				end
			end
			
			position.y -= f_y;
			
			if (y >= sueloBola)
				position.y = sueloBola;
				botando = false;
			end
		end
		
		//bola cuadrada
		if (source.graph == 21)
			if (yendoX == 0 and yendoY == 0)      //si anima_x & anima_y es 0
                position.y++;      //saldra la bola en la parte superior de la pantalla bajando a 1
                if (y=>30)      //comprueba si y es mayor o igual de 30                    
					yendoX=rand(1,2);
					yendoY = 1;
					set.flags=0;    //y hace un rand para que vaya saltado hacia la izquierda o hacia la derecha
                end
            end
			if (yendoX==1)
                position.x -= 6;
                if (position.x<10) position.x=10;
					yendoX=2;
				end
            end
            if (yendoX==2)
                position.x+=6;
                if (position.x>630)
					position.x=630;
					yendoX=1;
				end
            end
            if (yendoY==1)
                position.y+=6;
                if (position.y>sueloBola) 
					position.y=sueloBola;
					yendoY=2;
				end
            end
            if (yendoY==2)
                position.y-=6;
                if (position.y<30) 
					position.y=30;
					yendoY=1;				
				end
            end
		end
		
		if (yendoX <> 0)
			if ((idDisp=collision(type disparo)))      //comprueba si la bola a colisionado con el proceso disparo
                signal(type disparo,s_kill);     //si ha colisionado con el disparo, borra el proceso disparo con un signal
                signal(type cola_disparo,s_kill); //borra la cola del disparo si colisiona con una bola con un signal
				//explota(graph+1,x,y,size+100,25);       //y hacemos que la bola llame al proceso explosion para que haga la explosion de la bola
				disparosDisponibles = 0;
                explota_bola( source.graph, position.x, position.y, 25, scale.x+100, scale.y+100);
				totalBolas--;
                if (scale.x ==100 and scale.y == 100)      //comprueba si la bola era de tama¤o normal
                    puntos += 25;       //si era del tama¤o normal te daran 25 puntos
                    bola(file,graph,x-10,y-10,50,50,0,1,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    bola(file,graph,x-10,y-10,50,50,0,2,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    break;          //eliminamos el proceso de la bola que ha explotao
                end
                if (scale.x ==50 and scale.y == 50)       //comprueba si la bola era la mitad del tama¤o normal
                    puntos += 50;       //si era la mitad del tama¤o te daran 50 puntos					
                    bola(file,graph,x-10,y-10,25,25,0,1,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    bola(file,graph,x+10,y-10,25,25,0,2,2);
                    break;          //eliminamos el proceso de la bola que ha explotao
                end
                if (scale.x ==25 and scale.y == 25)       //comprueba si el tama¤o de la bola era la mas peque¤a
                    puntos += 100;      //te incrementara 100 puntos
                    break;          //eliminamos el proceso de la bola que ha explotao, sin hacer mas llamadas
                end
            end
			if ((idColaDisp=collision(type cola_disparo))) 
				signal(type disparo,s_kill);     //si ha colisionado con el disparo, borra el proceso disparo con un signal
                signal(type cola_disparo,s_kill); //borra la cola del disparo si colisiona con una bola con un signal
				disparosDisponibles = 0;
				explota_bola( source.graph, position.x, position.y, 25, scale.x+100, scale.y+100);
                totalBolas--;
                if (scale.x ==100 and scale.y == 100)      //comprueba si la bola era de tama¤o normal
                    puntos += 25;       //si era del tama¤o normal te daran 25 puntos
                    bola(file,graph,x-10,y-10,50,50,0,1,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    bola(file,graph,x-10,y-10,50,50,0,2,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    break;          //eliminamos el proceso de la bola que ha explotao
                end
                if (scale.x ==50 and scale.y == 50)       //comprueba si la bola era la mitad del tama¤o normal
                    puntos += 50;       //si era la mitad del tama¤o te daran 50 puntos					
                    bola(file,graph,x-10,y-10,25,25,0,1,2);     //y hacemos dos llamadas para hacer que salten dos bolas a mitad de tama¤o
                    bola(file,graph,x+10,y-10,25,25,0,2,2);
                    break;          //eliminamos el proceso de la bola que ha explotao
                end
                if (scale.x == 25 and scale.y == 25)       //comprueba si el tama¤o de la bola era la mas peque¤a
                    puntos += 100;      //te incrementara 100 puntos
                    break;          //eliminamos el proceso de la bola que ha explotao, sin hacer mas llamadas
                end
            end
			
		end
		// bola(file,graph,x,y,size_x,size_y, flags, yendoX, yendoY)
		frame;
	end
end

// ----------------------------------------------

process controlador_de_bolas()
private;
	graficoBola=0;     //variable para hacer el rand del grafico de la bola
	posicionX=0;       //variable para la posicion x de la bola
	tamanyoBola=0;      //variable para hacer el rand del tama¤o de la bola
	contador = 0;
begin

	tiempoFrame = 60;
	while (contador < tiempoFrame)
		contador++;
		frame;
	end	
	contador = 0;
	
    loop
        graficoBola=rand(0,1);     //hacemos un rando para que saque uno de los cuantro graficos de la bola
        if (graficoBola==0) graficoBola=20;end
        if (graficoBola==1) graficoBola=21;end
 

        posicionX=rand(20,620);      //hacemos un rando para que la bola salga en la posicion x, cuando esta la bola arriba, aleatoria

        tamanyoBola=rand(0,2);      //otro random para los 3 tama¤os de la bola size=100, size=50 y size=25
        if (tamanyoBola==0) tamanyoBola=100;end
        if (tamanyoBola==1) tamanyoBola=50;end
        if (tamanyoBola==2) tamanyoBola=25;end

        bola(fpgGraficosPrincipales,graficoBola,posicionX,-22,tamanyoBola,tamanyoBola,0,0,0);

		tiempoFrame = 60;
		while (contador < tiempoFrame)
			contador++;
			frame;
		end	
		contador = 0;
		frame;
    end
end

// ----------------------------------------------

process explota_bola( source.graph, position.x, position.y, position.z, scale.x, scale.y)
private
	int velocidadExplota = 20;
begin
	source.file = fpgGraficosPrincipales;
	sound_play(sfxExplota);
	
	if (source.graph == 20)
		source.graph = 22;
	end
	if (source.graph == 21)
		source.graph = 23;
	end
	loop
		scale.x -= velocidadExplota;
		scale.y -= velocidadExplota;
		if ((scale.x < 10) and (scale.y < 10))
			break;
		end
		frame;
	end
end

// ----------------------------------------------
/* ----------------------------------------------
 * Proceso foto grafico 
 * Coloca un grafico con los parametros especificados
 * Uso: foto_grafico(fichero,grafico,x,y,z,tamaño x, tamaño y, flags, alpha);
 ------------------------------------------------ */
process foto_grafico(source.file, source.graph, position.x, position.y, position.z, transform.scale.x, transform.scale.y, set.flags, fx.alpha)
private
begin
	loop
		frame;
	end
end

// ----------------------------------------------

process controlador_de_ventana()

private
	int windowTime = 0;
	int fullScreen = false;
	
begin

	loop
		
		if (fullScreen == false and windowTime == 0)
			if (keydown(_f11))
				fullScreen = true;
				mode_change(mode_fullscreen);
				windowTime = 10;
			end
		end
		
		if (fullScreen == true and windowTime == 0)
			if (keydown(_f11))
				fullScreen = false;
				mode_change(mode_window);
				windowTime = 10;
			end
		end
		
		windowTime--;
		
		if (windowTime<0)
			windowTime=0;
		end
		
		frame;
	end
end

// ----------------------------------------------

function carga_recursos()

begin
	//graphics file
	fpgMadotsuki = fpg_load("data\graphics\Madotsuki.fpg");
	fpgGraficosPrincipales = fpg_load("data\graphics\Elementos_principales.fpg");	
	
	//FNT files
	fntGeneral = fnt_load("data\fonts\general_font.fnt");
	fntGeneral2 = fnt_load("data\fonts\mark_numbers.fnt");
	fntTitleScreen = fnt_load("data\fonts\title_screen.fnt");
	
	//sfx files
	sfxExplota = sound_load("data\sounds_and_music\FX061.mp3"); //sonido al romperse las bolas
	sfxDisparo = sound_load("data\sounds_and_music\disparo.wav");
	musica = sound_load("data\sounds_and_music\Mystic_Force.mp3",1);
	return(0);
end
