En
la sección "Juegos" de JavaRush encontrará interesantes proyectos para escribir juegos de computadora populares. ¿Quieres crear tu propia versión de los populares juegos “2048”, “Sapper”, “Snake” y otros? Es sencillo. Hemos convertido la escritura de juegos en un proceso paso a paso.
Para probarse a sí mismo como desarrollador de juegos, no es necesario ser un programador avanzado, pero aún se requiere un cierto conjunto de conocimientos de Java. Aquí encontrarás
información que te será útil a la hora de escribir juegos .
1. Herencia
Trabajar con el motor de juego JavaRush implica utilizar la herencia. ¿Pero qué pasa si no sabes qué es? Por un lado, es necesario comprender este tema: se estudia en el
nivel 11 . Por otro lado, el motor fue diseñado deliberadamente para ser muy simple, por lo que puedes arreglártelas con un conocimiento superficial de la herencia. Entonces, ¿qué es la herencia? En pocas palabras, la herencia es la relación entre dos clases. Uno de ellos se convierte en padre y el segundo en hijo (clase sucesora). En este caso, es posible que la clase principal ni siquiera sepa que tiene clases descendientes. Aquellos. no recibe ningún beneficio particular de la presencia de clases herederas. Pero la herencia proporciona muchas ventajas a una clase descendiente. Y la principal es que todas las variables y métodos de la clase principal aparecen en la clase secundaria, como si el código de la clase principal se hubiera copiado en la clase secundaria. Esto no es del todo cierto, pero para una comprensión simplificada de la herencia servirá. A continuación se muestran algunos ejemplos para comprender mejor la herencia.
Ejemplo 1: la herencia más simple.
public class Родитель {
}
|
La clase Child hereda de la clase Parent usando la palabra clave extends . |
public class Потомок extends Родитель {
}
|
Ejemplo 2: uso de variables de clase principal.
public class Родитель {
public int age;
public String name;
}
|
La clase Child puede usar las variables de edad y nombre de la clase Parent como si estuvieran declaradas en ella. |
public class Потомок extends Родитель {
public void printInfo() {
System.out.println(name+" "+age);
}
}
|
Ejemplo 3: uso de métodos de clase principal.
public class Родитель {
public int age;
public String name;
public getName() {
return name;
}
}
|
La clase Child puede utilizar las variables y métodos de la clase Parent como si estuvieran declarados en ella. En este ejemplo estamos utilizando el método getName (). |
public class Потомок extends Родитель {
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
|
Así es como se ve la clase
Dedescendiente desde el punto de vista del compilador:
public class Потомок extends Родитель {
public int age;
public String name;
public getName() {
return name;
}
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
2. Anulación del método
A veces hay situaciones en las que heredamos nuestra clase Dedescendiente de alguna clase Padre muy útil, junto con todas las variables y métodos, pero algunos métodos no funcionan exactamente como queremos. O nada en la forma que no queremos. ¿Qué hacer en esta situación? Podemos anular un método que no nos guste. Esto se hace de manera muy simple: en nuestra clase Dedescendiente simplemente declaramos un método con la misma firma (encabezado) que el método de la clase Padre y escribimos nuestro código en él.
Ejemplo 1: anulación de método.
public class Родитель {
public String name;
public void setName (String nameNew) {
name = nameNew;
}
public getName() {
return name;
}
}
|
El método printInfo() imprimirá la frase "¡¡¡Luke, no!!!" |
public class Потомок extends Родитель {
public void setName (String nameNew) {
name = nameNew + ",No!!!";
}
public void printInfo() {
setName("Luke");
System.out.println( getName());
}
}
|
Así es como se ve la clase
Dedescendiente desde el punto de vista del compilador:
public Потомок extends Родитель {
public String name;
public void setName (String nameNew) {
name = nameNew + ", No!!!";
}
public getName() {
return name;
}
public void printInfo() {
setName("Luke");
System.out.println(getName());
}
}
Ejemplo 2: un poco de magia de herencia (y anulación de métodos).
public class Родитель {
public getName() {
return "Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
|
public class Потомок extends Родитель {
public getName() {
return "I'm your father, Luke";
}
}
|
En este ejemplo: si un método
printInfo
(de la clase Padre) no se anula en la clase Descendente, cuando se llama a este método en un objeto de la clase Descendente, se llamará a su método
getName()
, y no
getName()
a la clase Padre.
Родитель parent = new Родитель ();
parent.printnInfo();
|
Este código muestra la inscripción "Luke" en la pantalla . |
Потомок child = new Потомок ();
child.printnInfo();
|
Este código muestra la inscripción "Soy tu padre, Luke"; . |
Así es como se ve la clase
Dedescendiente desde el punto de vista del compilador:
public class Потомок extends Родитель {
public getName() {
return "I'm your father, Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
3. Listas
Si aún no te han presentado las Listas, aquí tienes una introducción rápida. Podrás encontrar información completa en
los niveles 6-7 del curso JavaRush .
Las listas tienen mucho en común con las matrices:
- puede almacenar una gran cantidad de datos de cierto tipo;
- le permite recuperar elementos por su índice/número;
- Los índices de los elementos comienzan en 0.
Ventajas de las listas: a diferencia de las matrices, las listas pueden cambiar de tamaño dinámicamente. Inmediatamente después de su creación, la lista tiene un tamaño de 0. A medida que agrega elementos a la lista, su tamaño aumenta. Ejemplo de creación de una lista:
ArrayList<String> myList = new ArrayList<String>();
El valor entre paréntesis angulares es el tipo de datos que la lista puede almacenar. A continuación se muestran algunos métodos para trabajar con una lista:
Código |
Breve descripción de lo que hace el código. |
ArrayList<String> list = new ArrayList<String>(); |
Creando una nueva lista de cadenas |
list.add("name"); |
Agregar un elemento al final de la lista |
list.add(0, "name"); |
Añadir un elemento al principio de la lista. |
String name = list.get(5); |
Obtener un elemento por su índice |
list.set(5, "new name"); |
Cambiar elemento por su índice |
int count = list.size(); |
Obtener el número de elementos de una lista |
list.remove(4); |
Eliminar un elemento de una lista |
Puede obtener más información sobre las listas en estos artículos:
- clase ArrayList
- ArrayList de trabajo en imágenes
- Eliminar un elemento de una ArrayList
4. matrices
¿Qué es una matriz? Una matriz no es más que una tabla rectangular que se puede llenar con datos. En otras palabras, es una matriz bidimensional. Como probablemente sepas, las matrices en Java son objetos. Un tipo de matriz unidimensional estándar
int
se ve así:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Imaginemos esto visualmente:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
32 |
43 |
54 |
15 |
36 |
67 |
28 |
La línea superior indica las direcciones de las celdas. Es decir, para obtener el número 67, es necesario acceder al elemento de la matriz con índice 6:
int number = array[6];
Aquí todo es muy sencillo. Una matriz bidimensional es una matriz de matrices unidimensionales. Si es la primera vez que escuchas sobre esto, detente e imagínalo en tu cabeza. Una matriz bidimensional se parece a esto:
0 |
Matriz unidimensional |
Matriz unidimensional |
1 |
Matriz unidimensional |
2 |
Matriz unidimensional |
3 |
Matriz unidimensional |
4 |
Matriz unidimensional |
5 |
Matriz unidimensional |
6 |
Matriz unidimensional |
7 |
Matriz unidimensional |
En el código:
int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78},
{76, 15, 76, 91, 66, 90, 15, 77},
{65, 96, 17, 25, 36, 75, 54, 78},
{59, 45, 68, 14, 57, 1, 9, 63},
{81, 74, 47, 52, 42, 785, 56, 96},
{66, 74, 58, 16, 98, 140, 55, 77},
{120, 99, 13, 90, 78, 98, 14, 78},
{20, 18, 74, 91, 96, 104, 105, 77}
}
0 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
sesenta y cinco |
99 |
87 |
90 |
156 |
75 |
98 |
78 |
1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
76 |
15 |
76 |
91 |
66 |
90 |
15 |
77 |
2 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
sesenta y cinco |
96 |
17 |
25 |
36 |
75 |
54 |
78 |
3 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
59 |
45 |
68 |
14 |
57 |
1 |
9 |
63 |
4 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
81 |
74 |
47 |
52 |
42 |
785 |
56 |
96 |
5 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
66 |
74 |
58 |
dieciséis |
98 |
140 |
55 |
77 |
6 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
120 |
99 |
13 |
90 |
78 |
98 |
14 |
78 |
7 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
18 |
74 |
91 |
96 |
104 |
105 |
77 |
Para obtener el valor 47, debe acceder al elemento de la matriz en [4][2].
int number = matrix[4][2];
Si observa, las coordenadas de la matriz son diferentes del sistema de coordenadas rectangular clásico (sistema de coordenadas cartesiano).
Al acceder a una matriz, se especifica y primero y luego x , mientras que en matemáticas es común especificar x(x, y) primero. Quizás te preguntes: “¿Por qué no invertir la matriz en tu imaginación y acceder a los elementos de la forma habitual a través de (x, y)? Esto no cambiará el contenido de la matriz”. Sí, nada cambiará. Pero en el mundo de la programación, es habitual referirse a matrices en la forma "primero y, luego x". Esto debe darse por sentado. Ahora hablemos de proyectar la matriz en nuestro motor (clase
Game
). Como sabes, el motor tiene muchos métodos que cambian las celdas del campo de juego en unas coordenadas determinadas. Por ejemplo, el
setCellValue(int x, int y, String value)
. Establece una determinada celda con coordenadas (x, y) al valor
value
. Como habrás notado, este método primero toma exactamente x, como en el sistema de coordenadas clásico. El resto de métodos del motor funcionan de forma similar. Al desarrollar juegos, a menudo será necesario reproducir el estado de la matriz en la pantalla. ¿Como hacer esto? Primero, en un bucle debes recorrer todos los elementos de la matriz. En segundo lugar, para cada uno de ellos, llame a un método para mostrar con coordenadas INVERTIDAS. Ejemplo:
private void drawScene() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
setCellValue(j, i, String.valueOf(matrix[i][j]));
}
}
}
Naturalmente, la inversión funciona en dos direcciones.
setCellValue
Puedes pasar (i, j) al método , pero al mismo tiempo tomar el elemento [j][i] de la matriz. La inversión puede parecer un poco difícil, pero es algo a tener en cuenta. Y siempre, si surge algún problema, conviene coger un papel con un bolígrafo, dibujar una matriz y reproducir los procesos que le están sucediendo.
5. Números aleatorios
¿Cómo trabajar con un generador de números aleatorios? La clase
Game
define un método
getRandomNumber(int)
. En el fondo, utiliza una clase
Random
del paquete java.util, pero esto no cambia el principio de trabajar con un generador de números aleatorios.
getRandomNumber(int)
Toma un número entero como argumento . Este número será el límite superior que el generador puede devolver. El límite inferior es 0.
¡Importante! El generador NUNCA devolverá un número de límite superior. Por ejemplo, si se llama
getRandomNumber(3)
aleatoriamente, puede devolver 0, 1, 2. Como puede ver, no puede devolver 3. Este uso de un generador es bastante sencillo, pero muy eficaz en muchos casos.
Necesita obtener un número aleatorio dentro de algunos límites: imagine que necesita un número de tres dígitos (100..999). Como ya sabes, el número mínimo devuelto es 0. Por lo tanto, deberás agregarle 100. Pero en este caso, debes tener cuidado de no exceder el límite superior. Para obtener 999 como valor aleatorio máximo, debe llamar al método
getRandomNumber(int)
con un argumento de 1000. Pero recordemos la adición posterior de 100: esto significa que el límite superior debe reducirse en 100. Es decir, el código para obtener un Un número aleatorio de tres dígitos se vería así:
int number = 100 + getRandomNumber(900);
Pero para simplificar dicho procedimiento, el motor proporciona un método
getRandomNumber(int, int)
que toma el número mínimo a devolver como primer argumento. Usando este método, el ejemplo anterior se puede reescribir:
int number = getRandomNumber(100, 1000);
Se pueden utilizar números aleatorios para obtener un elemento de matriz aleatorio:
String [] names = {"andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Desencadenar ciertos eventos con una cierta probabilidad. La mañana de una persona comienza según posibles escenarios: Dormido – 50%; Se levantó a tiempo – 40%; Se levantó una hora antes de lo esperado: 10%. Imagina que estás escribiendo un emulador matutino humano. Necesita desencadenar eventos con cierta probabilidad. Para hacer esto, nuevamente, necesitas usar un generador de números aleatorios. Las implementaciones pueden ser diferentes, pero la más sencilla debería seguir el siguiente algoritmo:
- establecemos los límites dentro de los cuales necesitamos generar el número;
- generar un número aleatorio;
- Procesamos el número resultante.
Entonces, en este caso, el límite será 10. Llamemos al método
getRandomNumber(10)
y analicemos qué nos puede devolver. Puede devolver 10 dígitos (del 0 al 9) y cada uno con la misma probabilidad: 10%. Ahora necesitamos combinar todos los resultados posibles y relacionarlos con nuestros posibles eventos. Puede haber muchas combinaciones, dependiendo de tu imaginación, pero la más obvia suena: “Si un número aleatorio se encuentra dentro de [0..4], llama al evento “Dormimiento”, si el número está dentro de [5..8] ] - “Me desperté a tiempo”, y solo si el número es 9, entonces “Me levanté una hora antes de lo esperado”. Todo es muy simple: dentro de [0..4] hay 5 números, cada uno de los cuales puede regresar con una probabilidad del 10%, que en total será el 50%; dentro de [5..8] hay 4 números, y el 9 es el único número que aparece con una probabilidad del 10%. En código, todo este diseño inteligente parece aún más simple:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
System.out.println("Проспал ");
} else if (randomNumber < 9) {
System.out.println("Встал вовремя ");
} else {
System.out.println("Встал на час раньше положенного ");
}
En general, puede haber muchas opciones para utilizar números aleatorios. Todo depende sólo de tu imaginación. Pero se utilizan con mayor eficacia si necesita obtener algún resultado repetidamente. Entonces este resultado será diferente al anterior. Con cierta probabilidad, claro. ¡Eso es todo! Si desea obtener más información sobre la sección Juegos, aquí tiene documentación útil que puede ayudar:
GO TO FULL VERSION