Advertisement
  1. Code
  2. Games

Construye un juego de serpientes clásico en AS3

Scroll to top
Read Time: 34 min

Spanish (Español) translation by Juliana Carvajal (you can also view the original English article)

En este tutorial me gustaría mostrarte lo fácil que es crear un juego clásico de "Serpiente" en Flash. ¡Intentaré explicarte todo fácilmente, paso a paso, para que puedas desarrollar el juego según tus necesidades! El juego se desarrollará en AS3 y usaré el IDE de FlashDevelop.


Introducción

El juego no será complejo. Siempre que golpeemos una pared, se reiniciará el juego. Después de comer una manzana, la serpiente crecerá y aparecerá una "nueva" manzana. (En realidad, será la misma manzana, pero lo explicaré más adelante).

Uno de los aspectos más importantes del juego es la reacción del código a los eventos KEY_DOWN. La serpiente solo cambiará su dirección después de que haya pasado una marca, no inmediatamente después de presionar una tecla. Esto significa que, si la serpiente va hacia la derecha y tu presionas hacia abajo y hacia la izquierda muy rápido, la serpiente bajará, no bajará Y se irá a la izquierda. Sin esta 'característica', la serpiente nos permitiría ir a la izquierda mientras vamos a la derecha, lo que significaría que se golpea a sí misma.


¡Veamos ya el Juego!

Echemos un vistazo al resultado final hacia el que trabajaremos:


Paso 1: Creación del Proyecto

En FlashDevelop, crea un nuevo proyecto y, dentro de la carpeta 'src', crea una carpeta 'com'. En la carpeta 'com' crea una nueva clase y llámala 'Element.as'.

Establece las dimensiones del proyecto en 600x600px.

The FlashDevelop project structure

Paso 2: Espera ... ¿Qué es un Elemento?

La serpiente está formada por cuadrados azules, a los que llamo elementos. Crearemos un Element Class, que dibuja el elemento. La manzana roja también será un elemento, así que ampliaremos el código con algunas líneas más.

Por lo tanto, no crearemos una nueva clase para la manzana. (Pero si realmente lo deseas, puede hacerlo).


Paso 3: Escribir el Element Class

El Element class crea un cuadrado. No lo dibuja en el escenario, simplemente lo crea. El punto de registro del elemento, la posición a la que se refieren sus -coordenadas x y y-, está en la parte superior izquierda.

Después de abrir Element.as, verás algo como esto:

1
package com 
2
{
3
	/**

4
	 * ...

5
	 * @author Fuszenecker Zsombor

6
	 */
7
	public class Element 
8
	{
9
		
10
		public function Element() 
11
		{
12
			
13
		}
14
		
15
	}
16
}

Primero, necesitamos esto para extender la clase Shape, por lo que podemos usar el objeto graphics para dibujar el cuadrado. Después de esto, crea dos variables: una para la dirección (si es parte de la serpiente) y otra para el valor de puntuación (si es una manzana), y luego cambia los parámetros de la función constructora:

1
package com 
2
{
3
	import flash.display.Shape;
4
	
5
	public class Element extends Shape
6
	{
7
		protected var _direction:String;
8
		//IF IT IS AN APPLE ->

9
		protected var _catchValue:Number;
10
		
11
		//color,alpha,width,height

12
		public function Element(_c:uint,_a:Number,_w:Number,_h:Number) 
13
		{
14
15
		}
16
	}
17
}

Ahora completa la función con algo de código:

1
package com 
2
{
3
	import flash.display.Shape;
4
	
5
	public class Element extends Shape
6
	{
7
		protected var _direction:String;
8
		//IF IT IS AN APPLE ->

9
		protected var _catchValue:Number;
10
		
11
		//color,alpha,width,height

12
		public function Element(_c:uint,_a:Number,_w:Number,_h:Number) 
13
		{
14
			graphics.lineStyle(0, _c, _a);
15
			graphics.beginFill(_c, _a);
16
			graphics.drawRect(0, 0, _w, _h);
17
			graphics.endFill();
18
			
19
			_catchValue = 0;
20
		}
21
	}
22
}

Ahora, cada vez que creamos un elemento, dibujará un rectángulo y establecerá el valor de puntuación del elemento en 0 de forma predeterminada. (No pondrá el rectángulo en el escenario, solo lo dibujará dentro de sí mismo. Observa que no hemos llamado a la función addChild ()).

Terminemos esta clase y luego finalmente podemos probar cuánto hemos hecho ya:

1
package com 
2
{
3
	import flash.display.Shape;
4
	
5
	public class Element extends Shape
6
	{
7
		protected var _direction:String;
8
		//IF IT IS AN APPLE ->

9
		protected var _catchValue:Number;
10
		
11
		//color,alpha,width,height

12
		public function Element(_c:uint,_a:Number,_w:Number,_h:Number) 
13
		{
14
			graphics.lineStyle(0, _c, _a);
15
			graphics.beginFill(_c, _a);
16
			graphics.drawRect(0, 0, _w, _h);
17
			graphics.endFill();
18
			
19
			_catchValue = 0;
20
		}
21
		
22
		//ONLY USED IN CASE OF A PART OF THE SNAKE

23
		public function set direction(value:String):void
24
		{
25
			_direction = value;
26
		}
27
		public function get direction():String
28
		{
29
			return _direction;
30
		}
31
		
32
		//ONLY USED IN CASE OF AN APPLE

33
		public function set catchValue(value:Number):void
34
		{
35
			_catchValue = value;
36
		}
37
		public function get catchValue():Number
38
		{
39
			return _catchValue;
40
		}
41
	}
42
43
}

Creamos cuatro funciones para cambiar las direcciones y el valor de la manzana. Lo logramos usando setters y getters. ¡Más sobre Setters/Getters en este artículo!


Paso 4: Probar el Element Class

Abra Main.as ahora.

Importe la clase com.Element y crea un elemento en la función init ():

1
package  
2
{
3
	import flash.display.Sprite;
4
	import flash.events.Event;
5
	import com.Element;
6
		
7
	public class Main extends Sprite
8
	{
9
		public function Main() 
10
		{
11
			if(stage)
12
				addEventListener(Event.ADDED_TO_STAGE, init);
13
			else
14
				init();
15
		}
16
		
17
		private function init(e:Event = null):void
18
		{
19
			var testElement:Element = new Element(0x00AAFF, 1, 10, 10);
20
			testElement.x = 50;
21
			testElement.y = 50;
22
			this.addChild(testElement);
23
			
24
		}
25
		
26
	}
27
}

Primero creamos la variable testElement que contiene nuestro elemento. Creamos un nuevo elemento y lo asignamos a nuestra variable testElement. Ten en cuenta los argumentos que te pasamos: primero le damos un color, luego el alpha, el ancho y el alto. Si observas la función Element en el Element class, puedes ver cómo usa estos datos para dibujar el rectángulo.

Después de crear el elemento, lo posicionamos y lo colocamos en el escenario!


Paso 5: Configurar las Variables

Mira el siguiente código. Escribí las funciones de las variables junto a ellas (observa que también importamos las clases necesarias):

1
package  
2
{
3
	import flash.display.Sprite;
4
	import flash.text.TextField;
5
	import flash.utils.Timer;
6
	import flash.events.TimerEvent;
7
	import flash.ui.Keyboard;
8
	import flash.events.KeyboardEvent;
9
	import flash.events.MouseEvent;
10
	import flash.events.Event;
11
	
12
	import com.Element;
13
		
14
	public class Main extends Sprite
15
	{
16
		
17
		//DO NOT GIVE THESE VARS A VALUE HERE! 

18
		//Give them their values in the init() function.

19
		private var snake_vector:Vector.<Element>; //the snake's parts are held in here

20
		private var markers_vector:Vector.<Object>; //the markers are held in here

21
		private var timer:Timer;
22
		private var dead:Boolean;
23
		private var min_elements:int; //holds how many parts the snake should have at the beginning

24
		private var apple:Element; //Our apple

25
		private var space_value:Number; //space between the snake's parts

26
		private var last_button_down:uint; //the keyCode of the last button pressed

27
		private var flag:Boolean; //is it allowed to change direction?

28
		private var score:Number;
29
		private var score_tf:TextField; //the Textfield showing the score

30
		
31
		public function Main() 
32
		{
33
			if(stage)
34
				addEventListener(Event.ADDED_TO_STAGE, init);
35
			else
36
				init();
37
		}
38
		
39
		private function init(e:Event = null):void
40
		{
41
			snake_vector = new Vector.<Element>;
42
			markers_vector = new Vector.<Object>;
43
			space_value = 2; //There will be 2px space between every Element

44
			timer = new Timer(50); //Every 50th millisecond, the moveIt() function will be fired! This will set the SPEED of the snake

45
			dead = false;
46
			min_elements = 10; //We will begin with 10 elements.

47
			apple = new Element(0xFF0000, 1, 10, 10); //red, not transparent, width:10, height: 10;

48
			apple.catchValue = 0; //pretty obvious - the score of the apple

49
			last_button_down = Keyboard.RIGHT; //The first direction of the snake is set in this variable

50
			score = 0;
51
			score_tf = new TextField(); //this is the TextField which shows our score.

52
			this.addChild(score_tf);
53
		}	
54
	}
55
}

La variable más importante es snake_vector. Pondremos cada Elemento de la serpiente en este Vector.

Luego está el markers_vector. Usaremos marcadores para establecer la dirección de las partes de la serpiente. Cada objeto de este Vector tendrá una posición y un tipo. El tipo nos dirá si la serpiente debe ir a la derecha, izquierda, arriba o abajo después de "golpear" el objeto. (No chocarán, solo se comprobará la posición de los marcadores y las partes de la serpiente).

Como ejemplo, si presionamos ABAJO, se creará un objeto. La x y y de este objeto serán las coordenadas x y y de la cabeza de la serpiente, y el tipo será "Down". Siempre que la posición de uno de los elementos de la serpiente sea la misma que la de este objeto, la dirección de los elementos de la serpiente se establecerá en "Down".

¡Lee los comentarios junto a las variables para comprender qué hacen las otras variables!


Paso 6: Escribir la Función attachElement ()

La función attachElement() tomará cuatro parámetros: el nuevo elemento serpiente, las coordenadas x y y, y la dirección de la última parte de la serpiente.

1
private function attachElement(who:Element,lastXPos:Number = 0,lastYPos:Number = 0,dirOfLast:String = "R"):void
2
{
3
4
}

Antes de poner el elemento en el escenario debemos colocarlo. Pero para esto necesitamos la dirección del último elemento de la serpiente, para saber si el nuevo elemento tiene que estar encima, debajo o al lado de este.

Después de verificar la dirección y establecer la posición, podemos agregarlo al escenario.

1
private function attachElement(who:Element,lastXPos:Number = 0,lastYPos:Number = 0,dirOfLast:String = "R"):void
2
{
3
	if (dirOfLast == "R")
4
	{
5
		who.x = lastXPos - snake_vector[0].width - space_value;
6
		who.y = lastYPos;
7
	}
8
	else if(dirOfLast == "L")
9
	{
10
		who.x = lastXPos + snake_vector[0].width + space_value;
11
		who.y = lastYPos;
12
	}
13
	else if(dirOfLast == "U")
14
	{
15
		who.x = lastXPos;
16
		who.y = lastYPos + snake_vector[0].height + space_value;
17
	}
18
	else if(dirOfLast == "D")
19
	{
20
		who.x = lastXPos;
21
		who.y = lastYPos - snake_vector[0].height - space_value;
22
	}
23
	this.addChild(who);
24
}

Ahora podemos usar esta función en la función init():

1
for(var i:int=0;i<min_elements;++i)
2
{
3
	snake_vector[i] = new Element(0x00AAFF,1,10,10);
4
	snake_vector[i].direction = "R"; //The starting direction of the snake

5
	if (i == 0)//first snake element

6
	{
7
		//you have to place the first element on a GRID. (now: 0,0) 

8
		//[possible x positions: (snake_vector[0].width+space_value)*<UINT> ]

9
		attachElement(snake_vector[i],0,0,snake_vector[i].direction) 
10
		snake_vector[0].alpha = 0.7;
11
	}
12
	else
13
	{
14
		attachElement(snake_vector[i], snake_vector[i - 1].x, snake_vector[i - 1].y, snake_vector[i - 1].direction);
15
	}
16
}

Creamos los primeros 10 elementos y establecemos la dirección de ellos en 'R' (derecha). Si es el primer elemento, llamamos attachElement() y cambiamos un poco su alpha (por lo que la "cabeza" es de un color ligeramente más claro).

Si deseas establecer la posición en otro lugar, ten en cuenta lo siguiente: la serpiente debe colocarse en una cuadrícula, de lo contrario se vería mal y no funcionaría. Si deseas cambiar la posición x y y puedes hacerlo de la siguiente manera:

Estableciendo la posición x(snake_vector[0].width+space_value)*[UINT], donde debes reemplazar [UINT] con un número entero positivo.

Estableciendo la posición y:  (snake_vector[0].height+space_value)*[UINT], donde debes reemplazar [UINT] con un número entero positivo.

Vamos a cambiarlo a esto:

1
if (i == 0)//first snake element

2
{
3
	//you have to place the first element on a GRID. (now: 0,0) 

4
	//[possible x positions: (snake_vector[0].width+space_value)*<UINT>]

5
	attachElement(
6
		snake_vector[i],
7
		(snake_vector[0].width+space_value)*20,
8
		(snake_vector[0].height+space_value)*10,
9
		snake_vector[i].direction
10
	);
11
	snake_vector[0].alpha = 0.7;
12
}

Y el primer elemento de la serpiente se coloca en el espacio 20 en la cuadrícula x- y en el décimo espacio en la cuadrícula y.

Esto es lo que tenemos hasta ahora:

1
package  
2
{
3
	import flash.display.Sprite;
4
	import flash.text.TextField;
5
	import flash.utils.Timer;
6
	import flash.events.TimerEvent;
7
	import flash.ui.Keyboard;
8
	import flash.events.KeyboardEvent;
9
	import flash.events.MouseEvent;
10
	import flash.events.Event;
11
	
12
	import com.Element;
13
		
14
	public class Main extends Sprite
15
	{
16
		
17
		//DO NOT GIVE THEM A VALUE HERE! Give them a value in the init() function

18
		private var snake_vector:Vector.<Element>; //the snake's parts are held in here

19
		private var markers_vector:Vector.<Object>; //the markers are held in here

20
		private var timer:Timer; 
21
		private var dead:Boolean;
22
		private var min_elements:int; //holds how many parts should the snake have at the beginning

23
		private var apple:Element; //Our apple

24
		private var space_value:Number; //space between the snake parts

25
		private var last_button_down:uint; //the keyCode of the last button pressed

26
		private var flag:Boolean; //is it allowed to change direction?

27
		private var score:Number;
28
		private var score_tf:TextField; //the Textfield showing the score

29
		
30
		public function Main() 
31
		{
32
			if(stage)
33
				addEventListener(Event.ADDED_TO_STAGE, init);
34
			else
35
				init();
36
		}
37
		
38
		private function init(e:Event = null):void
39
		{
40
			snake_vector = new Vector.<Element>;
41
			markers_vector = new Vector.<Object>;
42
			space_value = 2;
43
			timer = new Timer(50); //Every 50th millisecond, the moveIt() function will be fired!

44
			dead = false;
45
			min_elements = 10; //We will begin with 10 elements.

46
			apple = new Element(0xFF0000, 1,10, 10); //red, not transparent, width:10, height: 10;

47
			apple.catchValue = 0; //pretty obvious

48
			last_button_down = Keyboard.RIGHT; //The first direction of the snake is set in this variable

49
			score = 0;
50
			score_tf = new TextField(); //this is the TextField which shows our score.

51
			this.addChild(score_tf);
52
			
53
			for(var i:int=0;i<min_elements;++i)
54
			{
55
				snake_vector[i] = new Element(0x00AAFF,1,10,10);
56
				snake_vector[i].direction = "R"; //The starting direction of the snake

57
				if (i == 0)//first snake element

58
				{
59
					//you have to place the first element on a GRID. (now: 0,0) [possible x positions: (snake_vector[0].width+space_value)*<UINT> ]

60
					attachElement(snake_vector[i], (snake_vector[0].width + space_value) * 20, (snake_vector[0].height + space_value) * 10, snake_vector[i].direction);
61
					snake_vector[0].alpha = 0.7;
62
				}
63
				else
64
				{
65
					attachElement(snake_vector[i], snake_vector[i - 1].x, snake_vector[i - 1].y, snake_vector[i - 1].direction);
66
				}
67
			}
68
		}	
69
		
70
		private function attachElement(who:Element,lastXPos:Number = 0,lastYPos:Number = 0,dirOfLast:String = "R"):void
71
		{
72
			if (dirOfLast == "R")
73
			{
74
				who.x = lastXPos - snake_vector[0].width - space_value;
75
				who.y = lastYPos;
76
			}
77
			else if(dirOfLast == "L")
78
			{
79
				who.x = lastXPos + snake_vector[0].width + space_value;
80
				who.y = lastYPos;
81
			}
82
			else if(dirOfLast == "U")
83
			{
84
				who.x = lastXPos;
85
				who.y = lastYPos + snake_vector[0].height + space_value;
86
			}
87
			else if(dirOfLast == "D")
88
			{
89
				who.x = lastXPos;
90
				who.y = lastYPos - snake_vector[0].height - space_value;
91
			}
92
			this.addChild(who);
93
		}
94
	}
95
}

Paso 7: Escribir la Función placeApple()

Esta función hace lo siguiente:

  1. Comprueba si la manzana fue atrapada. Para esto usaremos el parámetro caught y estableceremos su valor predeterminado en true, en caso de que no pasemos ningún valor como parámetros en el futuro. Si fue detectado, agrega 10 al valor de puntuación de la manzana (por lo que la siguiente manzana vale más).
  2. Después de esto, la manzana debe reposicionarse (no creamos manzanas nuevas) en una posición de cuadrícula aleatoria.
  3. Si se coloca sobre la serpiente, debemos colocarla en otro lugar.
  4. Si aún no está en el escenario, la colocamos allí.
1
private function placeApple(caught:Boolean = true):void
2
{
3
	if (caught)
4
		apple.catchValue += 10;
5
		
6
	var boundsX:int = (Math.floor(stage.stageWidth / (snake_vector[0].width + space_value)))-1;
7
	var randomX:Number = Math.floor(Math.random()*boundsX);
8
		
9
	var boundsY:int = (Math.floor(stage.stageHeight/(snake_vector[0].height + space_value)))-1;
10
	var randomY:Number = Math.floor(Math.random()*boundsY);
11
12
	apple.x = randomX * (apple.width + space_value);
13
	apple.y = randomY * (apple.height + space_value);
14
		
15
	for(var i:uint=0;i<snake_vector.length-1;i++)
16
	{
17
		if(snake_vector[i].x == apple.x && snake_vector[i].y == apple.y)
18
			placeApple(false);
19
	}
20
	if (!apple.stage)
21
		this.addChild(apple);
22
}

Habrá algunas matemáticas aquí, pero si lo piensas bien, debes entender por qué es así. Simplemente dibújalo en un papel si es necesario.

  • boundsX contendrá cuántos elementos se pueden dibujar en una fila.
  • randomX toma este boundsX, lo multiplica por un Número entre cero y uno, y lo reduce. Si boundsX es 12 y el número aleatorio es 0.356, entonces el floor(12*0.356) es 4, por lo que la manzana se colocará en el cuarto lugar de la cuadrícula x.
  • boundsY contendrá cuántos elementos se pueden dibujar en una columna.
  • randomY toma este boundsY, lo multiplica por un Número entre cero y uno, y lo reduce.
  • Luego establecemos la posición x y y en estos números.

En el ciclo for, verificamos si las nuevas posiciones x y y de la manzana son idénticas a cualquiera de los elementos snake_vectors. Si es así, volvemos a llamar a la función placeApple() (función recursiva) y establecemos el parámetro en false. (Lo que significa que la manzana no fue atrapada, solo necesitamos reposicionarla)

(apple.stage) devuelve verdadero si la manzana está en el escenario. Usamos el '!' operador para invertir ese valor, por lo que si NO está en el escenario, lo colocamos allí.

Lo último que debemos hacer es llamar a la función placeApple() al final de la función init().

1
private function init(e:Event = null):void
2
{
3
    /*   

4
	.

5
	.

6
	.

7
	*/
8
	
9
	placeApple(false);
10
}

Observe que pasamos false como parámetro. Es lógico, porque todavía no capturamos la manzana en la función init(). Solo lo capturaremos en la función moveIt().

Ahora solo quedan tres funciones más para escribir: las funciones directionChanged(), moveIt() y gameOver().


Paso 8: Iniciar la función moveIt()

La función moveIt() es responsable de todo el movimiento. Esta función comprobará los límites y comprobará si hay un objeto en la posición x y y de la cabeza de la serpiente. También buscará la manzana en esta posición.

Para todo esto, usaremos nuestra variable de temporizador.

Agrega dos líneas más al final de la función init():

1
timer.addEventListener(TimerEvent.TIMER,moveIt);
2
timer.start();

Mira los comentarios en el código fuente para ver qué bloque de código hace qué.

1
		private function moveIt(e:TimerEvent):void
2
		{
3
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
4
			{
5
				//This code runs if the snakes heads position and the apples position are the same

6
			}
7
			
8
			if (snake_vector[0].x > stage.stageWidth-snake_vector[0].width || snake_vector[0].x < 0 || snake_vector[0].y > stage.stageHeight-snake_vector[0].height || snake_vector[0].y < 0)
9
			{
10
				//This block runs if the snakes head is out of the stage (hitting the walls)

11
			}
12
			
13
			
14
			for (var i:int = 0; i < snake_vector.length; i++)
15
			{
16
				/*

17
					START OF FOR BLOCK

18
					This whole 'for' block will run as many times, as many elements the snake has.

19
					If there are four snake parts, this whole for cycle will run four times. 

20
				*/
21
				
22
				if (snake_vector[i] != snake_vector[0] && (snake_vector[0].x == snake_vector[i].x && snake_vector[0].y == snake_vector[i].y))
23
				{
24
					//If the snakes heads position is the same as any of the snake parts, this block will run (Checking the collision with itself).

25
				}
26
			
27
				if (markers_vector.length > 0)
28
				{
29
					//if there are direction markers, this code runs

30
				}
31
			
32
				
33
				var DIRECTION:String = snake_vector[i].direction; //getting the direction of the current snake element.

34
				switch (DIRECTION)
35
				{
36
					//Sets the new position of the snakes part

37
				}
38
				
39
				/*

40
					END OF FOR BLOCK

41
				*/
42
			}
43
			
44
		}

Ahora necesitamos codificar el movimiento. Para esto, saltamos al bloque de switch, que se ejecutará en cada parte de la serpiente, debido al ciclo for.

Primero necesitamos verificar la dirección del elemento actual.

1
				switch (DIRECTION)
2
				{
3
					case "R" :
4
						//Here we need to set the new x position for the current part

5
						break;
6
					case "L" :
7
						//Here we need to set the new x position for the current part

8
						break;
9
					case "D" :
10
						//Here we need to set the new y position for the current part

11
						break;
12
					case "U" :
13
						//Here we need to set the new y position for the current part

14
						break;
15
				}

Cuando la dirección de la parte se establece en "R", por ejemplo, necesitamos agregar algo a su posición X actual (el space_value más el ancho de la parte de la serpiente).

Con esto en mente, podemos completarlo:

1
				switch (DIRECTION)
2
				{
3
					case "R" :
4
						snake_vector[i].x += snake_vector[i].width + space_value;
5
						break;
6
					case "L" :
7
						snake_vector[i].x -= snake_vector[i].width + space_value;
8
						break;
9
					case "D" :
10
						snake_vector[i].y += snake_vector[i].height + space_value;
11
						break;
12
					case "U" :
13
						snake_vector[i].y -= snake_vector[i].width + space_value;
14
						break;
15
				}

Después de probar el código, deberías ver que la serpiente se mueve, sale del escenario y nunca se detiene. (Es posible que debas actualizar la página, o simplemente hagas clic aquí para cargarla en una nueva ventana).

Entonces tenemos que detener a la serpiente


Paso 9: Escribir la Función gameOver()

Esta función será la más corta. Simplemente limpiamos el escenario y lo reiniciamos:

1
private function gameOver():void 
2
{
3
	dead = true;
4
	timer.stop();
5
	while (this.numChildren)
6
		this.removeChildAt(0);
7
	timer.removeEventListener(TimerEvent.TIMER,moveIt);
8
	init();
9
}

Eso es. Establecemos la variable dead en verdadera, detenemos el movimiento con el temporizador, eliminamos todos los elementos secundarios de la clase y llamamos a la función init(), como si recién comenzáramos el juego.

Ahora, volvamos a la función moveIt().


Paso 10: Continuación de la función moveIt()

Usaremos la función gameOver() en dos lugares. La primera es cuando comprobamos si la cabeza está fuera de límites, y la segunda es cuando la serpiente se golpea a sí misma:

1
		private function moveIt(e:TimerEvent):void
2
		{
3
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
4
			{
5
				//This code runs if the snakes heads position and the apples position are the same

6
			}
7
			
8
			if (snake_vector[0].x > stage.stageWidth-snake_vector[0].width || snake_vector[0].x < 0 || snake_vector[0].y > stage.stageHeight-snake_vector[0].height || snake_vector[0].y < 0)
9
			{
10
				gameOver();
11
			}
12
			
13
			
14
			for (var i:int = 0; i < snake_vector.length; i++)
15
			{
16
				/*

17
					START OF FOR BLOCK

18
					This whole 'for' block will run as many times, as many elements the snake has.

19
					If there are four snake parts, this whole for cycle will run four times. 

20
				*/
21
				
22
				if (snake_vector[i] != snake_vector[0] && (snake_vector[0].x == snake_vector[i].x && snake_vector[0].y == snake_vector[i].y))
23
				{
24
					//If the snakes heads position is the same as any of the snake parts, this block will run

25
					gameOver();
26
				}
27
			
28
				if (markers_vector.length > 0)
29
				{
30
					//if there are direction markers, this code runs

31
				}
32
			
33
				
34
				var DIRECTION:String = snake_vector[i].direction; //getting the direction of the current snake element.

35
				switch (DIRECTION)
36
				{
37
					case "R" :
38
						snake_vector[i].x += snake_vector[i].width + space_value;
39
						break;
40
					case "L" :
41
						snake_vector[i].x -= snake_vector[i].width + space_value;
42
						break;
43
					case "D" :
44
						snake_vector[i].y += snake_vector[i].height + space_value;
45
						break;
46
					case "U" :
47
						snake_vector[i].y -= snake_vector[i].width + space_value;
48
						break;
49
				}
50
				
51
				/*

52
					END OF FOR BLOCK

53
				*/
54
			}
55
			
56
		}

Este es el código que tenemos ahora:

1
package  
2
{
3
	import flash.display.Sprite;
4
	import flash.text.TextField;
5
	import flash.utils.Timer;
6
	import flash.events.TimerEvent;
7
	import flash.ui.Keyboard;
8
	import flash.events.KeyboardEvent;
9
	import flash.events.MouseEvent;
10
	import flash.events.Event;
11
	
12
	import com.Element;
13
		
14
	public class Main extends Sprite
15
	{
16
		
17
		//DO NOT GIVE THEM A VALUE HERE! Give them a value in the init() function

18
		private var snake_vector:Vector.<Element>; //the snake's parts are held in here

19
		private var markers_vector:Vector.<Object>; //the markers are held in here

20
		private var timer:Timer; 
21
		private var dead:Boolean;
22
		private var min_elements:int; //holds how many parts should the snake have at the beginning

23
		private var apple:Element; //Our apple

24
		private var space_value:Number; //space between the snake parts

25
		private var last_button_down:uint; //the keyCode of the last button pressed

26
		private var flag:Boolean; //is it allowed to change direction?

27
		private var score:Number;
28
		private var score_tf:TextField; //the Textfield showing the score

29
		
30
		public function Main() 
31
		{
32
			if(stage)
33
				addEventListener(Event.ADDED_TO_STAGE, init);
34
			else
35
				init();
36
		}
37
		
38
		private function init(e:Event = null):void
39
		{
40
			snake_vector = new Vector.<Element>;
41
			markers_vector = new Vector.<Object>;
42
			space_value = 2;
43
			timer = new Timer(50); //Every 50th millisecond, the moveIt() function will be fired!

44
			dead = false;
45
			min_elements = 10; //We will begin with 10 elements.

46
			apple = new Element(0xFF0000, 1,10, 10); //red, not transparent, width:10, height: 10;

47
			apple.catchValue = 0; //pretty obvious

48
			last_button_down = Keyboard.RIGHT; //The first direction of the snake is set in this variable

49
			score = 0;
50
			score_tf = new TextField(); //this is the TextField which shows our score.

51
			this.addChild(score_tf);
52
			
53
			for(var i:int=0;i<min_elements;++i)
54
			{
55
				snake_vector[i] = new Element(0x00AAFF,1,10,10);
56
				snake_vector[i].direction = "R"; //The starting direction of the snake

57
				if (i == 0)//first snake element

58
				{
59
					//you have to place the first element on a GRID. (now: 0,0) [possible x positions: (snake_vector[0].width+space_value)*<UINT> ]

60
					attachElement(snake_vector[i], (snake_vector[0].width + space_value) * 20, (snake_vector[0].height + space_value) * 10, snake_vector[i].direction);
61
					snake_vector[0].alpha = 0.7;
62
				}
63
				else
64
				{
65
					attachElement(snake_vector[i], snake_vector[i - 1].x, snake_vector[i - 1].y, snake_vector[i - 1].direction);
66
				}
67
			}
68
			
69
			placeApple(false);
70
			timer.addEventListener(TimerEvent.TIMER, moveIt);
71
			timer.start();
72
		}	
73
		
74
		private function attachElement(who:Element,lastXPos:Number = 0,lastYPos:Number = 0,dirOfLast:String = "R"):void
75
		{
76
			if (dirOfLast == "R")
77
			{
78
				who.x = lastXPos - snake_vector[0].width - space_value;
79
				who.y = lastYPos;
80
			}
81
			else if(dirOfLast == "L")
82
			{
83
				who.x = lastXPos + snake_vector[0].width + space_value;
84
				who.y = lastYPos;
85
			}
86
			else if(dirOfLast == "U")
87
			{
88
				who.x = lastXPos;
89
				who.y = lastYPos + snake_vector[0].height + space_value;
90
			}
91
			else if(dirOfLast == "D")
92
			{
93
				who.x = lastXPos;
94
				who.y = lastYPos - snake_vector[0].height - space_value;
95
			}
96
			this.addChild(who);
97
		}
98
		
99
		private function placeApple(caught:Boolean = true):void
100
		{
101
			if (caught)
102
				apple.catchValue += 10;
103
			
104
			var boundsX:int = (Math.floor(stage.stageWidth / (snake_vector[0].width + space_value)))-1;
105
			var randomX:Number = Math.floor(Math.random()*boundsX);
106
			
107
			var boundsY:int = (Math.floor(stage.stageHeight/(snake_vector[0].height + space_value)))-1;
108
			var randomY:Number = Math.floor(Math.random()*boundsY);
109
110
			apple.x = randomX * (apple.width + space_value);
111
			apple.y = randomY * (apple.height + space_value);
112
			
113
			for(var i:uint=0;i<snake_vector.length-1;i++)
114
			{
115
				if(snake_vector[i].x == apple.x && snake_vector[i].y == apple.y)
116
					placeApple(false);
117
			}
118
			if (!apple.stage)
119
				this.addChild(apple);
120
		}		
121
		
122
		private function moveIt(e:TimerEvent):void
123
		{
124
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
125
			{
126
				//This code runs if the snakes heads position and the apples position are the same

127
			}
128
			
129
			if (snake_vector[0].x > stage.stageWidth-snake_vector[0].width || snake_vector[0].x < 0 || snake_vector[0].y > stage.stageHeight-snake_vector[0].height || snake_vector[0].y < 0)
130
			{
131
				gameOver();
132
			}
133
			
134
			
135
			for (var i:int = 0; i < snake_vector.length; i++)
136
			{
137
				/*

138
					START OF FOR BLOCK

139
					This whole 'for' block will run as many times, as many elements the snake has.

140
					If there are four snake parts, this whole for cycle will run four times. 

141
				*/
142
				
143
				if (snake_vector[i] != snake_vector[0] && (snake_vector[0].x == snake_vector[i].x && snake_vector[0].y == snake_vector[i].y))
144
				{
145
					//If the snakes heads position is the same as any of the snake parts, this block will run

146
					gameOver();
147
				}
148
			
149
				if (markers_vector.length > 0)
150
				{
151
					//if there are direction markers, this code runs

152
				}
153
			
154
				
155
				var DIRECTION:String = snake_vector[i].direction; //getting the direction of the current snake element.

156
				switch (DIRECTION)
157
				{
158
					case "R" :
159
						snake_vector[i].x += snake_vector[i].width + space_value;
160
						break;
161
					case "L" :
162
						snake_vector[i].x -= snake_vector[i].width + space_value;
163
						break;
164
					case "D" :
165
						snake_vector[i].y += snake_vector[i].height + space_value;
166
						break;
167
					case "U" :
168
						snake_vector[i].y -= snake_vector[i].width + space_value;
169
						break;
170
				}
171
				
172
				/*

173
					END OF FOR BLOCK

174
				*/
175
			}
176
			
177
		}
178
		
179
		private function gameOver():void 
180
		{
181
			dead = true;
182
			timer.stop();
183
			while (this.numChildren)
184
				this.removeChildAt(0);
185
			timer.removeEventListener(TimerEvent.TIMER,moveIt);
186
			//stage.removeEventListener(KeyboardEvent.KEY_DOWN,directionChanged);

187
			init();
188
		}
189
		
190
	}
191
}

Paso 11: La Función directionChanged()

Queremos escuchar el teclado para poder controlar a la serpiente. Para esto, necesitamos poner algo de código en la función init() y la función gameOver().

Pon esto al final de la función init() (configurando la función de escucha):

1
stage.addEventListener(KeyboardEvent.KEY_DOWN,directionChanged);

Y esto al final de la función gameOver():

1
stage.removeEventListener(KeyboardEvent.KEY_DOWN,directionChanged);

Ahora crea una nueva función:

1
private function directionChanged(e:KeyboardEvent):void 
2
{
3
	var m:Object = new Object(); //MARKER OBJECT 

4
	//this will be added to the markers_vector, and have the properties x,y, and type 

5
	//the type property will show us the direction. if it is set to right, whenever a snake's part hits it, 

6
	//the direction of that snake's part will be set to right also

7
	
8
	if (e.keyCode == Keyboard.LEFT && last_button_down != e.keyCode && last_button_down != Keyboard.RIGHT)
9
	{
10
		//If we pressed the LEFT arrow, 

11
		//and it was not the last key we pressed, 

12
		//and the last key pressed was not the RIGHT arrow either...

13
		//Then this block of code will run

14
	}
15
	markers_vector.push(m); //we push the object into a vector, so we can acces to it later (in the moveIt() function)

16
}

¿Qué entra en el bloque if?

  • La dirección de la cabeza debe reescribirse.
  • El objeto marker debe configurarse correctamente.
  • La variable last_button debe establecerse en el último botón presionado.
1
if (e.keyCode == Keyboard.LEFT && last_button_down != e.keyCode && last_button_down != Keyboard.RIGHT && flag)
2
{
3
	snake_vector[0].direction = "L";
4
	m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"L"};
5
	last_button_down = Keyboard.LEFT;
6
}

Repite esto tres veces más, y tendremos esto:

1
private function directionChanged(e:KeyboardEvent):void 
2
		{
3
			var m:Object = new Object(); //MARKER OBJECT

4
5
			if (e.keyCode == Keyboard.LEFT && last_button_down != e.keyCode && last_button_down != Keyboard.RIGHT)
6
			{
7
				snake_vector[0].direction = "L";
8
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"L"};
9
				last_button_down = Keyboard.LEFT;
10
			}
11
			else if (e.keyCode == Keyboard.RIGHT && last_button_down != e.keyCode && last_button_down != Keyboard.LEFT)
12
			{
13
				snake_vector[0].direction = "R";
14
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"R"};
15
				last_button_down = Keyboard.RIGHT;
16
			}
17
			else if (e.keyCode == Keyboard.UP && last_button_down != e.keyCode && last_button_down != Keyboard.DOWN)
18
			{
19
				snake_vector[0].direction = "U";
20
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"U"};
21
				last_button_down = Keyboard.UP;
22
			}
23
			else if (e.keyCode == Keyboard.DOWN && last_button_down != e.keyCode && last_button_down != Keyboard.UP)
24
			{
25
				snake_vector[0].direction = "D";
26
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"D"};
27
				last_button_down = Keyboard.DOWN;
28
			}
29
			markers_vector.push(m);
30
		}

Necesitamos una cosa más para probarlo. En la función moveIt() tenemos algo como esto:

1
				if (markers_vector.length > 0)
2
				{
3
					//if there are direction markers, this code runs

4
				}

Aquí necesitamos otro ciclo for, para verificar la parte de cada serpiente con cada marcador en el escenario y verificar si chocan. Si lo hacen, debemos establecer la dirección de la parte de la serpiente según el tipo de marcador. Si es la última parte de la serpiente que choca con el marcador, también debemos quitar el marcador del vector markers_vector, para que las partes de la serpiente no choquen más con él.

1
				if (markers_vector.length > 0)
2
				{
3
					for(var j:uint=0;j < markers_vector.length;j++)
4
					{
5
						if(snake_vector[i].x == markers_vector[j].x && snake_vector[i].y == markers_vector[j].y)
6
						{
7
							//setting the direction

8
							snake_vector[i].direction = markers_vector[j].type;
9
							if(i == snake_vector.length-1)
10
							{
11
								//if its the last snake_part

12
								markers_vector.splice(j, 1);
13
							}
14
						}
15
					}
16
				}

Ahora, si juegas con él, se ve bien, pero hay un error allí. ¿Recuerdas lo que dije al principio del tutorial?

Por ejemplo, si la serpiente va hacia la derecha y presionas el combo abajo-izquierda muy rápido, se golpeará a sí misma y reiniciará el juego.

¿Cómo corregimos esto? Bueno, es fácil. Tenemos nuestra variable de flag y la usaremos para esto. Solo podremos cambiar las direcciones de la serpiente cuando se establezca en verdadero (el valor predeterminado es falso, verifica la función init() para eso).

Entonces necesitamos cambiar un poco la función directionChanged(). Las cabezas de los bloques if deben cambiarse: agrega una cláusula de && flag al final de cada 'if'.

1
		private function directionChanged(e:KeyboardEvent):void 
2
		{
3
			var m:Object = new Object(); //MARKER OBJECT

4
5
			if (e.keyCode == Keyboard.LEFT && last_button_down != e.keyCode && last_button_down != Keyboard.RIGHT && flag)
6
			{
7
				snake_vector[0].direction = "L";
8
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"L"};
9
				last_button_down = Keyboard.LEFT;
10
				flag = false;
11
			}
12
			else if (e.keyCode == Keyboard.RIGHT && last_button_down != e.keyCode && last_button_down != Keyboard.LEFT && flag)
13
			{
14
				snake_vector[0].direction = "R";
15
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"R"};
16
				last_button_down = Keyboard.RIGHT;
17
				flag = false;
18
			}
19
			else if (e.keyCode == Keyboard.UP && last_button_down != e.keyCode && last_button_down != Keyboard.DOWN && flag)
20
			{
21
				snake_vector[0].direction = "U";
22
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"U"};
23
				last_button_down = Keyboard.UP;
24
				flag = false;
25
			}
26
			else if (e.keyCode == Keyboard.DOWN && last_button_down != e.keyCode && last_button_down != Keyboard.UP && flag)
27
			{
28
				snake_vector[0].direction = "D";
29
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"D"};
30
				last_button_down = Keyboard.DOWN;
31
				flag = false;
32
			}
33
			markers_vector.push(m);
34
		}

Si lo pruebas ahora, no funcionará porque la bandera siempre es falsa.

Entonces, ¿Cuándo debemos configurarlo como verdadero?

Después de un movimiento/marca, podemos permitir que los usuarios cambien de dirección, pero no queremos cambiarlo dos veces en una marca. Así que pon esto al final de la función moveIt():

1
flag = true;

Ahora pruébalo y ya no habrá ningún error.


Paso 12: Finalización del Juego

Ahora lo único que tenemos que hacer es el 'apple-check'

¿Recuerdas esto al principio de la función moveIt()?

1
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
2
			{
3
				//This code runs if the snake's head's position and the apple's position are the same

4
			}

Esto es lo que debemos hacer allí:

  • Llama la función placeApple(). (No establecemos el parámetro en falso; lo dejamos como está. El valor predeterminado es verdadero).
  • Mostrar la puntuación actual
  • Adjunta un nuevo elemento a la última parte de la serpiente.
1
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
2
			{
3
				//calling the placeApple() function

4
				placeApple();
5
				//show the current Score

6
				score += apple.catchValue;
7
				score_tf.text = "Score:" + String(score);
8
				//Attach a new snake Element

9
				snake_vector.push(new Element(0x00AAFF,1,10,10));
10
				snake_vector[snake_vector.length-1].direction = snake_vector[snake_vector.length-2].direction; //lastOneRichtung

11
				//attachElement(who,lastXPos,lastYPos,lastDirection)

12
				attachElement(snake_vector[snake_vector.length-1],
13
									  (snake_vector[snake_vector.length-2].x),
14
									  snake_vector[snake_vector.length-2].y,
15
									  snake_vector[snake_vector.length-2].direction);
16
			}

Ahora todo debería funcionar bien. Pruébalo:

Aquí está toda la clase principal nuevamente:

1
			package  
2
{
3
	import flash.display.Sprite;
4
	import flash.text.TextField;
5
	import flash.utils.Timer;
6
	import flash.events.TimerEvent;
7
	import flash.ui.Keyboard;
8
	import flash.events.KeyboardEvent;
9
	import flash.events.MouseEvent;
10
	import flash.events.Event;
11
	
12
	import com.Element;
13
		
14
	public class Main extends Sprite
15
	{
16
		//DO NOT GIVE THEM A VALUE HERE! Give them a value in the init() function

17
		private var snake_vector:Vector.<Element>; //the snake's parts are held in here

18
		private var markers_vector:Vector.<Object>; //the markers are held in here

19
		private var timer:Timer; 
20
		private var dead:Boolean;
21
		private var min_elements:int; //holds how many parts should the snake have at the beginning

22
		private var apple:Element; //Our apple

23
		private var space_value:Number; //space between the snake parts

24
		private var last_button_down:uint; //the keyCode of the last button pressed

25
		private var flag:Boolean; //is it allowed to change direction?

26
		private var score:Number;
27
		private var score_tf:TextField; //the Textfield showing the score

28
		
29
		public function Main() 
30
		{
31
			if(stage)
32
				addEventListener(Event.ADDED_TO_STAGE, init);
33
			else
34
				init();
35
		}
36
		
37
		private function init(e:Event = null):void
38
		{
39
			snake_vector = new Vector.<Element>;
40
			markers_vector = new Vector.<Object>;
41
			space_value = 2;
42
			timer = new Timer(50); //Every 50th millisecond, the moveIt() function will be fired!

43
			dead = false;
44
			min_elements = 1;
45
			apple = new Element(0xFF0000, 1,10, 10); //red, not transparent, width:10, height: 10;

46
			apple.catchValue = 0; //pretty obvious

47
			last_button_down = Keyboard.RIGHT; //The starting direction of the snake (only change it if you change the 'for cycle' too.)

48
			score = 0;
49
			score_tf = new TextField();
50
			this.addChild(score_tf);
51
52
			//Create the first <min_elements> Snake parts

53
			for(var i:int=0;i<min_elements;++i)
54
			{
55
				snake_vector[i] = new Element(0x00AAFF,1,10,10);
56
				snake_vector[i].direction = "R"; //The starting direction of the snake

57
				if (i == 0)
58
				{
59
					//you have to place the first element on a GRID. (now: 0,0) [possible x positions: (snake_vector[0].width+space_value)*<UINT> ]

60
					attachElement(snake_vector[i],0,0,snake_vector[i].direction) 
61
					snake_vector[0].alpha = 0.7;
62
				}
63
				else
64
				{
65
					attachElement(snake_vector[i], snake_vector[i - 1].x, snake_vector[i - 1].y, snake_vector[i - 1].direction);
66
				}
67
			}
68
			
69
			placeApple(false);
70
			timer.addEventListener(TimerEvent.TIMER,moveIt);
71
			stage.addEventListener(KeyboardEvent.KEY_DOWN,directionChanged);
72
			timer.start();
73
		}
74
		
75
		private function attachElement(who:Element,lastXPos:Number = 0,lastYPos:Number = 0,dirOfLast:String = "R"):void
76
		{
77
			if (dirOfLast == "R")
78
			{
79
				who.x = lastXPos - snake_vector[0].width - space_value;
80
				who.y = lastYPos;
81
			}
82
			else if(dirOfLast == "L")
83
			{
84
				who.x = lastXPos + snake_vector[0].width + space_value;
85
				who.y = lastYPos;
86
			}
87
			else if(dirOfLast == "U")
88
			{
89
				who.x = lastXPos;
90
				who.y = lastYPos + snake_vector[0].height + space_value;
91
			}
92
			else if(dirOfLast == "D")
93
			{
94
				who.x = lastXPos;
95
				who.y = lastYPos - snake_vector[0].height - space_value;
96
			}
97
			this.addChild(who);
98
		}
99
		
100
		private function placeApple(caught:Boolean = true):void
101
		{
102
			if (caught)
103
				apple.catchValue += 10;
104
			
105
			var boundsX:int = (Math.floor(stage.stageWidth / (snake_vector[0].width + space_value)))-1;
106
			var randomX:Number = Math.floor(Math.random()*boundsX);
107
			
108
			var boundsY:int = (Math.floor(stage.stageHeight/(snake_vector[0].height + space_value)))-1;
109
			var randomY:Number = Math.floor(Math.random()*boundsY);
110
111
			apple.x = randomX * (apple.width + space_value);
112
			apple.y = randomY * (apple.height + space_value);
113
			
114
			for(var i:uint=0;i<snake_vector.length-1;i++)
115
			{
116
				if(snake_vector[i].x == apple.x && snake_vector[i].y == apple.y)
117
					placeApple(false);
118
			}
119
			if (!apple.stage)
120
				this.addChild(apple);
121
		}
122
		
123
		private function moveIt(e:TimerEvent):void
124
		{
125
			if (snake_vector[0].x == apple.x && snake_vector[0].y == apple.y)
126
			{
127
				placeApple();
128
				//show the current Score

129
				score += apple.catchValue;
130
				score_tf.text = "Score:" + String(score);
131
				//Attach a new snake Element

132
				snake_vector.push(new Element(0x00AAFF,1,10,10));
133
				snake_vector[snake_vector.length-1].direction = snake_vector[snake_vector.length-2].direction; //lastOneRichtung

134
				attachElement(snake_vector[snake_vector.length-1],
135
									  (snake_vector[snake_vector.length-2].x),
136
									  snake_vector[snake_vector.length-2].y,
137
									  snake_vector[snake_vector.length-2].direction);
138
			}
139
			if (snake_vector[0].x > stage.stageWidth-snake_vector[0].width || snake_vector[0].x < 0 || snake_vector[0].y > stage.stageHeight-snake_vector[0].height || snake_vector[0].y < 0)
140
			{
141
				gameOver();
142
			}
143
			
144
			for (var i:int = 0; i < snake_vector.length; i++)
145
			{
146
				if (markers_vector.length > 0)
147
				{
148
					for(var j:uint=0;j < markers_vector.length;j++)
149
					{
150
						if(snake_vector[i].x == markers_vector[j].x && snake_vector[i].y == markers_vector[j].y)
151
						{
152
							snake_vector[i].direction = markers_vector[j].type;
153
							if(i == snake_vector.length-1)
154
							{
155
								markers_vector.splice(j, 1);
156
							}
157
						}
158
					}
159
				}
160
				if (snake_vector[i] != snake_vector[0] && (snake_vector[0].x == snake_vector[i].x && snake_vector[0].y == snake_vector[i].y))
161
				{
162
					gameOver();
163
				}
164
			
165
				//Move the boy

166
				var DIRECTION:String = snake_vector[i].direction;
167
				switch (DIRECTION)
168
				{
169
					case "R" :
170
						snake_vector[i].x += snake_vector[i].width + space_value;
171
						break;
172
					case "L" :
173
						snake_vector[i].x -= snake_vector[i].width + space_value;
174
						break;
175
					case "D" :
176
						snake_vector[i].y += snake_vector[i].height + space_value;
177
						break;
178
					case "U" :
179
						snake_vector[i].y -= snake_vector[i].width + space_value;
180
						break;
181
				}
182
				
183
			}
184
						
185
			flag = true;
186
		}
187
		
188
		private function gameOver():void 
189
		{
190
			dead = true;
191
			timer.stop();
192
			while (this.numChildren)
193
				this.removeChildAt(0);
194
			timer.removeEventListener(TimerEvent.TIMER,moveIt);
195
			stage.removeEventListener(KeyboardEvent.KEY_DOWN,directionChanged);
196
			init();
197
		}
198
	
199
		private function directionChanged(e:KeyboardEvent):void 
200
		{
201
			var m:Object = new Object(); //MARKER OBJECT

202
203
			if (e.keyCode == Keyboard.LEFT && last_button_down != e.keyCode && last_button_down != Keyboard.RIGHT && flag)
204
			{
205
				snake_vector[0].direction = "L";
206
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"L"};
207
				last_button_down = Keyboard.LEFT;
208
				flag = false;
209
			}
210
			else if (e.keyCode == Keyboard.RIGHT && last_button_down != e.keyCode && last_button_down != Keyboard.LEFT && flag)
211
			{
212
				snake_vector[0].direction = "R";
213
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"R"};
214
				last_button_down = Keyboard.RIGHT;
215
				flag = false;
216
			}
217
			else if (e.keyCode == Keyboard.UP && last_button_down != e.keyCode && last_button_down != Keyboard.DOWN && flag)
218
			{
219
				snake_vector[0].direction = "U";
220
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"U"};
221
				last_button_down = Keyboard.UP;
222
				flag = false;
223
			}
224
			else if (e.keyCode == Keyboard.DOWN && last_button_down != e.keyCode && last_button_down != Keyboard.UP && flag)
225
			{
226
				snake_vector[0].direction = "D";
227
				m = {x:snake_vector[0].x, y:snake_vector[0].y, type:"D"};
228
				last_button_down = Keyboard.DOWN;
229
				flag = false;
230
			}
231
			markers_vector.push(m);
232
		}
233
		
234
	}
235
236
}

Paso 13: Resumiendo Todo

¡Felicidades! Acabas de crear un buen juego. Ahora puedes desarrollarlo más y crear una súper manzana o algo así. Para eso recomiendo usar otra función llamada placeSuperApple() y una nueva clase llamada SuperApple. Siempre que atrapes una súper manzana, las partes de las serpientes podrían alargarse en tres elementos, tal vez. Esto podría establecerse con setters/getters en la clase SuperApple.

Si deseas hacer esto y te quedas atascado en algún lugar, déjame un comentario aquí.

¡Gracias por tu tiempo!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.