CodeGym /Blogue Java /Random-PT /Seção de jogos no CodeGym: teoria útil
John Squirrels
Nível 41
San Francisco

Seção de jogos no CodeGym: teoria útil

Publicado no grupo Random-PT
Na seção "Jogos" do CodeGym, você encontrará projetos empolgantes que envolvem escrever jogos de computador populares. Quer criar sua própria versão dos populares jogos 2048, Minesweeper, Snake e outros jogos? É simples. Transformamos a escrita de jogos em um processo passo a passo. Seção "Jogos" no CodeGym: teoria útil - 1Para testar suas habilidades como desenvolvedor de jogos, você não precisa ser um programador avançado, mas é necessário um conjunto específico de conhecimentos de Java. Aqui você encontrará informações que serão úteis na escrita do jogo .

1. Herança

Trabalhar com o mecanismo de jogo CodeGym envolve o uso de herança. Mas e se você não souber o que é isso? Por um lado, você precisa entender este tópico: é estudado no nível 11. Por outro lado, o mecanismo foi especialmente projetado para ser muito simples, para que você possa se safar com conhecimento superficial de herança. Então, o que é herança? Simplificando, a herança é um relacionamento entre duas classes. Um deles se torna o pai e o outro se torna filho (descendente). Além disso, a classe pai pode nem saber que tem descendentes. Em outras palavras, não ganha nenhuma vantagem particular por ter descendentes. Mas a herança dá ao descendente muitas vantagens. E o mais importante é que todas as variáveis ​​e métodos da classe pai apareçam no descendente como se o código da classe pai fosse copiado para a classe descendente. Esta não é uma descrição totalmente precisa, mas será suficiente para uma compreensão simplificada da herança. Exemplo 1: A herança mais simples.

public class Parent {

}
A classe Child herda a classe Parent usando a palavra-chave extends .

public class Child extends Parent {

}
Exemplo 2: Usando as variáveis ​​da classe pai.

public class Parent {

   public int age;
   public String name;
}
A classe Child pode usar as variáveis ​​age e name da classe Parent como se fossem declaradas na classe Parent .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
Exemplo 3: Usando os métodos da classe pai.

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
A classe Child pode usar as variáveis ​​e métodos da classe Parent como se fossem declarados na classe Child. Neste exemplo, usamos o método getName() .

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
Esta é a aparência da classe Child para o compilador:

public class Child extends Parent{

   public int age;  // Inherited variable
   public String name;  // Inherited variable

   public getName() {  // Inherited method.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. Substituindo métodos

Às vezes, há situações em que fazemos nossa classe Child herdar alguma classe Parent muito útil, junto com todas as suas variáveis ​​e métodos, mas alguns dos métodos não funcionam exatamente como queremos. Ou não como queremos. O que podemos fazer nesta situação? Podemos substituir o método que não gostamos. Isso é muito fácil de fazer: em nossa classe Child, simplesmente declaramos um método com a mesma assinatura do método na classe Parent e, em seguida, escrevemos nosso próprio código nele. Exemplo 1: Substituindo um método.

public class Parent {

   public String name;

   public void setName(String nameNew) {
       name = nameNew;
  }

   public getName() {
      return name;
  }
}
O método printInfo() exibirá "Luke, No!!!"

public class Child extends Parent{

   public void setName(String nameNew) {
       name = nameNew + ", No!!!";
  }

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
Esta é a aparência da classe Child para o compilador:

public Child extends Parent {

   public String name;  // Inherited variable

   public void setName(String nameNew)  // Overridden method instead of the inherited method {

       name = nameNew + ", No!!!";
   }
   public getName() {  // Inherited method.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println( getName());
   }
}
Exemplo 2: Alguma mágica de herança (e substituição de método).

public class Parent {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
  }
}
Neste exemplo, se o printInfométodo (da classe Parent) não for substituído na classe Child, quando este método for chamado em um objeto Child, seu getName()método será chamado em vez do getName()método da classe Parent.

Parent parent = new Parent ();
parent.printnInfo();
Este código exibe "Luke" na tela.

Child child = new Child ();
child.printnInfo();
Este código exibe "Luke, eu sou seu pai" na tela.
Esta é a aparência da classe Child para o compilador:

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
   }
   public void printInfo() {

     System.out.println(getName());
   }
}

3. Listas

Se você ainda não conheceu as listas (List), aqui está uma breve visão geral. Você pode encontrar informações completas nos Níveis 6-7 do curso CodeGym . Listas têm muito em comum com arrays:
  • você pode armazenar muitos dados de um tipo específico;
  • eles permitem que você obtenha itens por seu índice;
  • índices de elementos começam em 0.
Benefícios das listas: Ao contrário dos arrays, as listas podem mudar de tamanho dinamicamente. Quando uma lista é criada, seu tamanho é 0. À medida que você adiciona itens a uma lista, seu tamanho aumenta. Aqui está um exemplo de criação de uma lista:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
O valor entre os colchetes indica o tipo de dados que a lista pode armazenar. Aqui estão alguns métodos para trabalhar com a lista:
Código Breve descrição do que o código faz
ArrayList<String> list = new ArrayList<String>(); Criar nova lista de strings
list.add("name"); Adicionar um elemento ao final da lista
list.add(0, "name"); Adicionar um elemento ao início da lista
String name = list.get(5); Obter um elemento por seu índice
list.set(5, "new name"); Alterar um elemento por seu índice
int count = list.size(); Obter o número de elementos na lista
list.remove(4); Excluir um elemento da lista
Você pode aprender mais sobre listas nos seguintes artigos:
  1. classe ArrayList
  2. ArrayList em imagens
  3. Excluindo um elemento de um ArrayList

4. Matrizes

O que é uma matriz? Uma matriz nada mais é do que uma tabela retangular que pode ser preenchida com dados. Em outras palavras, é uma matriz bidimensional. Como você provavelmente sabe, arrays em Java são objetos. Uma matriz unidimensional padrão intse parece com isso:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Podemos visualizar assim:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
A linha superior indica os endereços das células. Em outras palavras, para obter o número 67, você precisa acessar o elemento da matriz com índice 6:

int number = array[6];
É tudo muito simples. Uma matriz bidimensional é uma matriz de matrizes unidimensionais. Se você está ouvindo sobre isso pela primeira vez, pare e imagine isso em sua cabeça. Uma matriz bidimensional se parece com isso:
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
Em 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
65 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
65 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 16 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 obter o valor 47, você precisa consultar o elemento da matriz em [4][2].

int number = matrix[4][2];
Você deve ter notado que as coordenadas da matriz são diferentes do sistema clássico de coordenadas retangulares (sistema de coordenadas cartesianas). Ao acessar a matriz, você primeiro especifica a coordenada y e depois a coordenada x. Em matemática, costuma-se especificar primeiro a coordenada x, ou seja, (x, y). Você pode estar se perguntando: "Bem, por que não girar sua representação da matriz e então acessar os elementos da maneira usual usando (x, y)? Fazer isso não mudaria o conteúdo da matriz". Sim, nada mudaria. Mas no mundo da programação, a prática aceita é acessar matrizes "primeiro por y, depois por x". Você deve aceitar isso como a maneira correta. Agora vamos falar sobre como projetar a matriz para nosso mecanismo (Gameaula). Como você sabe, o mecanismo possui muitos métodos que alteram as células do campo de jogo em coordenadas específicas. Por exemplo, o setCellValue(int x, int y, String value)método. Define uma célula específica com coordenadas (x, y) iguais ao parâmetro de valor. Você deve ter notado que esse método leva x primeiro, assim como no sistema de coordenadas clássico. Os outros métodos do mecanismo funcionam de maneira semelhante. Ao desenvolver jogos, muitas vezes será necessário reproduzir o estado de uma matriz na tela. Como fazemos isso? Primeiro, você precisa percorrer todos os elementos da matriz em um loop. Em segundo lugar, chame o método de exibição para cada um deles, usando coordenadas REVERSED. Por exemplo:

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, a reversão funciona em ambas as direções. Você pode passar (i, j) para o setCellValuemétodo e simultaneamente pegar o elemento [j][i] da matriz. Inverter as coordenadas pode parecer um pouco difícil, mas você precisa se lembrar disso. E sempre, se você encontrar algum problema, você deve pegar um pedaço de papel e uma caneta, desenhar a matriz e reproduzir os processos que envolvem a matriz.

5. Números aleatórios

Como você trabalha com um gerador de números aleatórios? A Gameclasse define o getRandomNumber(int)método. Nos bastidores, ele usa a Randomclasse do pacote java.util, mas a maneira como você trabalha com o gerador de números aleatórios não muda. getRandomNumber(int)recebe um inteiro como argumento. Este número será o limite superior do que o gerador pode retornar. O limite inferior é 0. Importante! O gerador NUNCA retornará o número limite superior. Por exemplo, se você chamar getRandomNumber(3), ele retornará aleatoriamente 0, 1 ou 2. Como você pode ver, ele não pode retornar 3. Usar o gerador dessa maneira é bastante simples, mas altamente eficaz em muitos casos. Suponha que você precise obter um número aleatório em algum intervalo: Imagine que você precisa de um número de três dígitos no intervalo [100..999]. Como você já sabe, o número mínimo retornado é 0. Portanto, você precisará somar 100. Mas, neste caso, é preciso tomar cuidado para não ultrapassar o limite superior. Para obter 999 como o valor aleatório máximo, chame ogetRandomNumber(int)método com o argumento 1000. Mas agora lembramos que estamos adicionando 100 ao resultado: isso significa que o limite superior deve ser reduzido em 100. Em outras palavras, o código para obter nosso número aleatório de três dígitos ficará assim :

int number = 100 + getRandomNumber(900);
Mas para simplificar esse procedimento, a engine disponibiliza o getRandomNumber(int, int)método cujo primeiro parâmetro é o número mínimo a ser retornado. Usando este método, o exemplo anterior pode ser reescrito da seguinte forma:

int number = getRandomNumber(100, 1000);
Números aleatórios podem ser usados ​​para obter um elemento aleatório da matriz:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
Gerando certos eventos com alguma probabilidade. Para os humanos, as manhãs começam com alguns cenários possíveis: Dormir demais – 50% de chance; Acordou na hora – 40% de chance; Acordei uma hora mais cedo – 10% de chance. Imagine que você está escrevendo um gerador de resultado matinal. Você precisa gerar eventos com uma certa probabilidade. Para fazer isso, você precisa novamente usar um gerador de números aleatórios. Diferentes implementações são possíveis, mas a mais simples deve ser baseada no seguinte algoritmo:
  1. definir os limites usados ​​para gerar um número;
  2. gerar um número aleatório;
  3. processar o número obtido.
Neste caso, o máximo será 10. Ligue para ogetRandomNumber(10)método e analisar que podemos retornar. Ele pode retornar 10 números (de 0 a 9), cada um com a mesma probabilidade — 10%. Agora precisamos combinar todos os resultados possíveis e mapeá-los para nossos possíveis eventos. Sua imaginação pode pensar em várias combinações possíveis, mas aqui está a mais óbvia: "Se o número aleatório estiver no intervalo [0..4], temos o evento "Overslept"; se o número estiver no intervalo [5 ..8], temos o evento "Acordei na hora"; e se o número for 9, então temos o evento "Acordei uma hora mais cedo". É tudo muito simples. São 5 números no intervalo [0 ..4], cada um dos quais pode ser retornado com uma probabilidade de 10%, para um total de 50%; são 4 números no intervalo [5..8], bem, e 9 é apenas um número que aparece com uma probabilidade de 10%.

int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Overslept");
} else if (randomNumber < 9) {
    System.out.println("Woke up on time");
} else {
    System.out.println("Woke up an hour early");
}
Em geral, existem inúmeras maneiras de usar números aleatórios. Você está limitado apenas pela sua imaginação. Mas eles são usados ​​​​com mais eficiência se você precisar obter algum resultado repetidamente. Então o novo resultado será diferente do anterior. Com alguma probabilidade, é claro. É tudo por agora! Se você quiser saber mais sobre a seção "Jogos", aqui está uma documentação útil que pode ajudar:
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION