SchultzGames
Para tirar dúvidas, crie um tópico especifico na área "Dúvidas em Geral" e aguarde ser respondido. Evite comentar em tópicos não relacionados a sua dúvida :D
TÓPICOS RECENTES:
Tópico:
Postado em:
Postado por:
[RESOLVIDO] Ausencia da funçao NavMesh na Unity 2022.2.12
Interação com elementos UI
[_____IMPORTANTE_____] ALTERAÇÕES NA POLÍTICA DE COBRANÇA DA UNITY - 2
Roll Up Um jogo de aventura e desáfios
Terminologia da Unity em outras engines
Como criar a iluminação do Sol no Sistema Solar?
Unity - SceneManager.LoadScene abre scene com objeto "vazio"
Conexão de lobby pelo OnConnectedToMaster
Problema na exportção de projeto unity
[RESOLVIDO] Unity - Áudios estão emitindo som só Depois do Botão ser solto
Unity - Banco de Dados Online junto ao Jogo
Player virar para o inimigo(Prefab)
[_____IMPORTANTE_____] ALTERAÇÕES NA POLÍTICA DE COBRANÇA DA UNITY
[TUTORIAL] Sistema De Save Game Ao Sair Da Fase
Problema de Sincronização de um objeto de um jogo multiplayer usa q Photon
Unity - Compartilhar meu Jogo
Alguém que manja do Google ADmob?
Unity - Avaliar meu Jogo
[RESOLVIDO] Destruir inimigo com o player.
Salvar e carregar dados na Unity de objetos prefabs sem sobrescrever os dad
Unity - Salvar os Dados do Jogador Online
Input.GetAxis() obedercer a orientação de um objeto.
ajuda com o sistema de drag and drop com controle no invetario
Como executar outros blocos fora do bloco static void Main()
Usando a biblioteca UnityEngine fora da Unity
Mixamo - Character Gratuito?
Touch mobile
Erro NullReferenceException Não consigo resolver
Criador de Sites Freelancer DISPONIVEL!!!
Unity - Não deixar o Jogador alterar o Jogo pelo regedit do pc?
Tiro com Botao UI (ME AJUDEM)
[Projeto em Andamento] Draug, um jogo de hordas
Vagas de programadores e modeladores para startup
Consigo herdar/ copiar parâmetros do animator da unity?
O que seriam os códigos-fonte?
[RESOLVIDO] Unity Vulkan - Out of memory! (allocating memory for image)
Unity Problema de Vírus
[TUTORIAL] Como fazer uma gota de água na Unity
Mirror ou Photon Pun 2 ??? para Mobile
Character Player Modular
Icones não aparecem na Interface da Unity
Verificar se player está posado em blogo
Logica para criar (Player, Inventario, Arma) - Mobile
Sistema de pegar passageiros
Trailer Final de O Labirinto II
Meu jogo não conecta no google play games
ALGUEM ME AJUDA PFV
Problema tentando inserir "Sprite"
Oferto Serviço Programação para Jogos
FAZER AÇÂO AO ENTRAR NO CAMPO DA CAMERA
[RESOLVIDO] QUEBRA DE LINHA NO PLACEHOLDER. Nao lembro como que faz
Unity - Qual o Limite Máximo de Linhas em um Script para q ele fique Leve?
movimento 2d
Alguém que ja publicou na steam pode me ajudar com isso?
Animação Unity toda bugada
UDaySurvival - Jogo de sobrevivência de mundo aberto para mobile!https://yo
Trailer do meu jogo O Labirinto II
Jogo Atisk (Trailer)
Adicionem meu jogo na lista de desejos
Discord!
Como executar a void de um outro scrypt
Shader não funciona no Unity URP
Jogo Mobile - Ultimate Flight Simulator - Real World SDK
Unity - FPS e CPU ???
Usar microfone na Unity
Jogo ficando escuro quando faço a Build pela cena menu
Dúvida sobre movimentação do personagem
[RESOLVIDO] ACESSAR SCRIPT DE OUTRO GAMEOBJECT
Para eu ter shader em meu projeto eu tenho que usar o hdrp ou o 3d padrao?
Rotate Camera Mobile
Sou modelador 3d (!!! Arquitetonico!!!) Disponivel !!!!!!
Preciso de alguém que saiba programação e Raycast
Servidor/cliente usando sockets
Assets carregados com addressables causando erro na versão "buildada"
Jogo multiplayer com salas - não vai para o lobby
Texto - Não escreve no 'play'. Clica mais não digita.
Câmera Não esta renderizando na segunda janela.
Movimento da Câmera No Android
[RESOLVIDO] - Unity não está mais funcionando o "Build and Run"
Precisa de modelador com ou sem experiência
Duvida com "mesclagem" de animação
Missoes Aparecerem aleatoriamente do nada
Dúvida pafra IOS
botoes não esta funcionando corretamente nem a fisica?
Duvida com NavMeshAgent
COMO AUMENTAR E DIMINUÍ A SENSIBILIDADE DO TOQUE POR CÓDICO (MOBILE)
A Licença da Unity só funciona se eu tiver Internet
Problema com OnTriggerEnter
Transparência ao colidir
bool para evitar de salvar frames repetido
Unity - Transições no AnimatorController rodando errado
problemas com "wall Jump" , atribuir força ao eixo X
Meu Jogo ja Esta Pronto! EXPERIMENTEM!!
JOSTICK NAO SE MOVE
botoes para mobile
ERRO NO SCRIPT FOME E SEDE ETC
CORTAR ARVORES E DROPAR
Configurar sistema
Unity - Sugestões da Loja
Hoje à(s) 2:10 pm
Hoje à(s) 12:32 pm
Ontem à(s) 9:01 pm
Qui Set 21, 2023 11:04 am
Qua Set 20, 2023 4:40 pm
Qua Set 20, 2023 9:15 am
Dom Set 17, 2023 7:12 pm
Dom Set 17, 2023 12:17 pm
Sex Set 15, 2023 7:24 pm
Sex Set 15, 2023 5:41 pm
Sex Set 15, 2023 4:28 pm
Sex Set 15, 2023 10:56 am
Sex Set 15, 2023 10:22 am
Sex Set 15, 2023 10:15 am
Seg Set 11, 2023 11:43 am
Seg Set 11, 2023 11:31 am
Sáb Set 09, 2023 4:53 pm
Sáb Set 09, 2023 1:44 pm
Ter Set 05, 2023 11:12 pm
Ter Set 05, 2023 3:12 pm
Seg Set 04, 2023 11:53 pm
Seg Set 04, 2023 7:39 pm
Dom Set 03, 2023 9:47 pm
Sáb Set 02, 2023 11:53 am
Sex Set 01, 2023 2:21 pm
Qui Ago 31, 2023 8:19 pm
Qui Ago 31, 2023 6:15 pm
Qua Ago 30, 2023 11:21 am
Ter Ago 29, 2023 8:43 pm
Seg Ago 28, 2023 7:18 pm
Sáb Ago 26, 2023 4:49 pm
Sáb Ago 26, 2023 4:38 pm
Qui Ago 17, 2023 1:56 am
Qua Ago 16, 2023 10:21 pm
Seg Ago 14, 2023 12:28 pm
Dom Ago 06, 2023 5:24 pm
Dom Ago 06, 2023 10:58 am
Qui Ago 03, 2023 9:38 am
Qua Ago 02, 2023 8:20 am
Ter Ago 01, 2023 6:07 pm
Dom Jul 30, 2023 5:43 pm
Sáb Jul 29, 2023 7:24 pm
Qui Jul 27, 2023 9:27 am
Seg Jul 24, 2023 11:12 am
Seg Jul 24, 2023 12:44 am
Seg Jul 24, 2023 12:37 am
Seg Jul 24, 2023 12:17 am
Seg Jul 24, 2023 12:10 am
Qua Jul 19, 2023 11:37 am
Ter Jul 18, 2023 7:12 pm
Qua Jul 12, 2023 9:49 am
Ter Jul 11, 2023 8:58 am
Ter Jul 11, 2023 1:03 am
Seg Jul 10, 2023 9:10 pm
Sex Jul 07, 2023 4:14 pm
Ter Jul 04, 2023 12:11 am
Sex Jun 30, 2023 8:10 pm
Qui Jun 29, 2023 5:19 pm
Qui Jun 29, 2023 3:40 pm
Ter Jun 27, 2023 1:45 am
Seg Jun 19, 2023 11:03 am
Dom Jun 18, 2023 6:11 pm
Dom Jun 04, 2023 2:41 pm
Ter maio 30, 2023 7:28 pm
Ter maio 30, 2023 6:04 am
Seg maio 29, 2023 7:53 pm
Sáb maio 27, 2023 3:11 pm
Sex maio 26, 2023 4:59 pm
Sex maio 26, 2023 11:27 am
Qui maio 25, 2023 10:33 am
Sáb maio 20, 2023 12:25 pm
Ter maio 16, 2023 5:43 pm
Ter maio 16, 2023 5:42 pm
Ter maio 09, 2023 7:42 pm
Seg maio 08, 2023 7:13 am
Seg maio 08, 2023 6:38 am
Sáb maio 06, 2023 11:44 pm
Sáb maio 06, 2023 6:42 pm
Sáb maio 06, 2023 1:35 am
Qua maio 03, 2023 12:32 pm
Seg maio 01, 2023 8:51 pm
Dom Abr 30, 2023 8:49 pm
Dom Abr 30, 2023 5:06 pm
Sáb Abr 29, 2023 4:05 pm
Qui Abr 27, 2023 4:39 pm
Qui Abr 27, 2023 12:40 am
Ter Abr 25, 2023 5:33 pm
Ter Abr 25, 2023 10:23 am
Dom Abr 23, 2023 12:11 am
Sáb Abr 22, 2023 4:27 am
Sex Abr 21, 2023 11:38 pm
Sex Abr 21, 2023 10:21 pm
Qui Abr 20, 2023 4:57 pm
Qui Abr 20, 2023 12:28 pm
Qua Abr 19, 2023 3:03 pm
Qua Abr 19, 2023 1:52 pm
Qua Abr 19, 2023 11:59 am
Qua Abr 19, 2023 11:54 am
Sáb Abr 15, 2023 8:13 pm



































































































[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

5 participantes

Ir para baixo

TUTORIAL [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por MayLeone Ter Jan 15, 2019 7:36 pm

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Jigsaw-Puzzle-PNG


Olá pessoal! No tutorial de hoje nós vamos desenvolver um jogo de quebra-cabeças (aqueles clássicos de encaixar as peças para formar uma imagem) na engine Unity.
Em nosso tutorial, será possível escolher qualquer imagem de qualquer tamanho para montar o quebra-cabeças, também será possível decidir o nível de dificuldade do mesmo, onde podemos ter quantidade de peças diferentes dependendo da grade selecionada, por exemplo, uma grade 4x4 terá ao todo 16 peças para serem montadas.
Em nosso jogo, teremos uma grade que irá orientar o jogador da onde cada peça deverá se encaixar, então em nosso tutorial iremos programar também a criação dessa grade proporcional à quantidade de peças, iremos criar o sistema de clique com o mouse, verificação de vitória, recorte da imagem e muito mais.
O resultado final será exatamente esse aqui:



Recortando a imagem:
Uma das primeiras coisas que faremos em nosso tutorial será "cortar" em vários pedacinhos a imagem que será usada como quebra-cabeças.
Antes de iniciarmos de fato a programação de tal sistema no Unity, vamos entender como faríamos esse tipo de "recorte", irei usar como exemplo a imagem abaixo:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Image

Essa imagem foi reduzida para se adequar ao tamanho do site corretamente, porém ela possui originalmente as dimensões 900x800 (largura e altura).
Supondo que desejamos cortar essa imagem em exatos 4 pedaços, isso significa que teremos uma grade 2x2 ou seja, teremos 2 pedaços a serem cortados horizontalmente e mais 2 pedaços na vertical, totalizando 4 peças.
Então tudo certo, sabemos a quantidade de peças e a grade (quantas imagens iremos ter nas linhas e colunas), mas a grande pergunta é... Qual o tamanho(dimensão) de cada pedaço, para que sejam cortados com exatidão sem sobrar partes da imagem?
O cálculo é mais simples do que pensa, para saber a largura do pedaço, basta dividir a largura total da imagem pelo valor da grade (no caso aqui, 2) e o mesmo com a altura, divida a altura da imagem pela dimensão da grade (2).
Por fim, iremos concluir que cada pedaço terá 450x400 de dimensão (900/2) e (800/2), isso significa que teremos 4 imagens de 450x400 de dimensão numa grade 2x2, ou seja, 2 imagens para as colunas e 2 para as linhas, dessa forma:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B2

O padrão se repete caso queria ter mais peças.
Por exemplo, no caso de querer 9 peças, teremos uma grade 3x3, ou seja, teremos 3 imagens para as linhas e 3 para as colunas.
Cada pedaço terá 300x266 pixels de altura e largura (caso a imagem possua 900x800 de dimensão).

Dessa forma, podemos então descobrir o tamanho de cada retângulo (parte da imagem/peça) quando formos cortar as peças através de código.

Script para recortar as peças:
Agora que está entendido como iremos "cortar" a imagem, abra um novo projeto 2D na engine com o nome "Puzzle Game" e importe a imagem que desejá cortar, também crie um prefab de um sprite 2D com o nome de "Piece", a única coisa que ele terá por enquanto será um box collider 2D.
Esse prefab será responsável por "ser a peça", onde exibirá seu sprite como sendo uma parte da imagem.

Para cortar uma imagem devemos utilizar uma Texture2D para representá-la, porém, para poder manipular as textures importadas do projeto devemos permitir que elas sejam passíveis à leitura e escrita, portanto, clique na imagem importada e através do inspector vá à opção "Texture Type >> Advanced" e marque a caixa "Read/Write Enabled" e dê apply:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B1


Dessa forma poderemos ter acesso à textura via código.

Agora crie um script chamado "CropTextures" para que possamos recortar as imagens.

Vamos agora criar algumas variáveis públicas para esse script: Um enumerador que irá definir o tamanho da grade do jogo, variando entre as grades 2x2 até 9x9 (você pode colocar mais, se desejar), uma variável do tipo do nosso enumerador para receber a resolução da grade, uma variável do tipo Texture2D chamada "sourceTexture" para recebermos a imagem que será cortada e uma variável do tipo "GameObject" para armazenar o prefab da peça a ser instanciada.
Também criaremos duas variáveis privadas, uma do tipo "int" chamada "amoutPieces" que representará a quantidade de peças e um Vector2 chamado "resolutionPieces" para armazenar a resolução de cada parte da imagem (aquele retângulo que vimos no exemplo anterior):


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B3



Vamos agora criar um método chamado "StartComponents" para inicializarmos alguns valores.
Por enquanto os únicos valores a serem iniciados serão a quantidade de peças que deve representar o índice do enum "Options", e a resolução das peças que deve ser calculada de acordo com o cálculo que eu mostrei a vocês, ou seja, resolutionPieces.x deve ser a largura da texture dividida pela grade na horizontal, e resolutionPieces.y deve ser a altura da texture dividida pela grade na vertical:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B4


Chame esse método dentro do Start do script.

Agora vamos criar o método que de fato cortará a textura em vários pedaços, para criá-lo deixe-o retornar uma Texture2D, chame-o de "CropTexture" e defina dois parâmetros do tipo inteiro, um chamado "row" para representar a coluna que ele deve cortar a imagem e outro chamado "line" para representar a linha.
Agora crie duas variáveis locais (chamadas resolutionX e resolutionY) para que elas recebam os valores da resolução das peças arredondadas (utilize o Mathf.RoundToInt para isso):

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B5

Então agora utilizaremos uma função da classe "Texture2D" que se chama "GetPixels".
Essa função irá retornar os pixels de uma textura/imagem de acordo com a posição e tamanho que serão passados como argumento em formato de um retângulo, deverá ser passado a posição na imagem onde os pixels serão obtidos e a resolução dessa área. A função retorna os pixels da área desejada em forma de um vetor do tipo "Color".

Vamos então criar uma variável local chamada "pixels" do tipo array Color e fazer com que receba a função "GetPixels" sendo chamada através da textura que será anexada ao inspector que ficará armazenada na variável "sourceTexture":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B6

Agora devemos passar o retângulo (área que deve-se obter os pixels da imagem) como argumento da função.
Esse argumento é um retângulo como já dito, que vai pedir a posição X da onde ele vai obter os pixels e a posição Y, então multiplique o valor da coluna (row) pela resolução em X da peça (row*resolutionX) e multiplique a linha pela resolução em Y (line*resolutionY).
Para saber o tamanho da área a ser obtida, basta passar o valor da resolução em X e em Y, respetivamente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B7

Como iremos criar um laço de repetição que irá percorrer a imagem completa de acordo com as dimensões da mesma, a função "CropTexture" irá ser chamada toda vez que uma parte da imagem for percorrida, representada pelos parâmetros "row" e "line" para sabermos em qual coluna e linha o laço está, dessa forma, a nossa função irá retornar um pedaço da textura num local específico da imagem toda vez que for chamada.

Agora vamos criar uma nova Texture2D para ser retornada da função com a parte da imagem que foi recortada através da função "GetPixels"
Para isso, basta criar uma variável local chamada "tex" e dentro do seu construtor passar a resolução dessa nova textura a ser criada, no caso, resolutionX e resolutionY.
Após fazer isso, preencha essa nova textura com os pixels obtidos anteriormente e que estão armazenados no array "pixels", através da função "SetPixels". Aplique essa atualização através da função "Apply" e retorne da função a variável "tex":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B8

Criando as posições para as peças:
Nessa altura do tutorial nós temos como retornar cada parte da imagem de acordo com sua resolução, mas ainda não temos onde colocar essas imagens das peças.
Nós iremos representar a imagem de cada peça a partir daquele prefab já citado anteriormente que é apenas um sprite2D com um collider.
Antes de instanciarmos o prefab com a imagem cortada em seu sprite, vamos definir as possíveis posições onde esses prefabs serão sorteados.
Para que o jogo fique mais interesse, vamos sortear os pedacinhos em locais aleatórios da cena e toda vez que o jogo ser iniciado novamente, os pedacinhos irão trocar de posições.

Vamos criar mais algumas variáveis do tipo "Vector2": uma chamada "position" que irá guardar a posição da peça que será instanciada, outra chamada "distancePieces" que irá guardar a resolução do tamanho das peças para que possamos instanciá-las uma do lado da outra, e duas listas do tipo "Vector2" uma chamada "positions" para guardar todas as posições possíveis que as peças ficarão, e outra chamada "sortedPieces" que irá armazenadas as peças já sorteadas, para que não se repita um local e alguma peça fique sobre a outra:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B9

Criaremos agora um método sem retorno chamado "CreatePositions" que vai ser responsável por de fato, criar as possíveis posições para que as peças possam ser instanciadas.
Vamos calcular primeiramente a distância de cada peça, que deve ser em "x" a resolução da peça em X divida por 100 (se a resolução da peça for 300, por exemplo, a distância entre essas peças na Unity será de 3 pixels, já que estamos utilizando 100 pixels per unit para o tamanho da imagem) e para Y será o mesmo princípio.
Depois disso, crie um laço de repetição que tem como contador um inteiro chamado "x" e que vai ser incrementado até que o mesmo seja menor que a quantidade de peças, e dentro desse laço defina outro laço com o contador chamado "y" que irá ser incrementado até que seu valor seja menor que a quantidade de peças.
Agora adicione dentro da lista "positions" um novo Vector2 em x tendo a distância das peças multiplicado pelo contador "x" e em "y" a distância das peças multiplicado pelo contador "y":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B10

Então se por exemplo temos uma peça com resolução de 400 pixels(de largura e altura) e uma grade 2x2, as posições serão:

0 e 0,
0 e 4,
4 e 0,
4 e 4.

Ou seja, teremos duas peças nas posições 0;0 e 0;4 (primeira linha) e duas peças nas posições 4;0 e 4;4 (segunda linha), ou seja, uma grade 2x2 com duas linhas e duas colunas.
A distância entre cada peça é de 4 pixels tanto em x quanto em y, pois dividimos a resolução da peça por 100, fazendo com que quando as peças forem instanciadas em alguma dessas quatro posições, elas fiquem exatamente uma do lado da outra, formando então uma grade 2x2 com 4 peças.

Chame esse método "CreatePositions" dentro do Start do script.

Randomizando posições:
Agora que temos dentro da lista "positions" todas as possíveis posições para as peças, vamos randomizá-las, sorteando aleatoriamente sempre uma nova posição para a peça que está sendo instanciada.
Para tal, crie um método chamado "RandomPosition" que retorna um Vector2.
Dentro desse método crie uma variável local chamada "sorted" para definirmos se alguma posição válida foi sorteada, então inicie essa variável como sendo "false".
Crie uma outra variável local chamada "pos" que irá conter as posições sorteadas e a inicialize como um Vector zero.
Agora crie um laço "while" que irá ficar sendo executado enquanto "sorted" for false.
Dentro do laço faça com que a variável "pos" receba um valor aleatório dentro da lista "positions" através do método Random.Range.
Após isso, nós iremos armazenar dentro da variável "sorted" se essa posição sorteada aleatoriamente já foi sorteada antes, para isso, basta verificar se dentro da lista "sortedPositions" o valor de "pos" não está contido nela.
Caso "sorted" seja true (ou seja, o valor ainda não foi sorteado) armazene dentro da variável "sortedPositions" o valor de "pos", já que é uma posição que ainda não foi sorteada. Após o laço, apenas retorne "pos":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B11

Pronto! Agora temos um método que irá randomizar as posições das peças de acordo com as possíveis posições na cena.

Instanciando as peças:
Vamos então finalmente instanciar as peças na cena que irão representar as partes da textura recortada.
Crie um método sem retorno com o nome "CreatePiece" e o chame dentro do Start do script.
Agora vamos instanciar os prefabs de acordo com a quantidade de peças.
Para isso, vamos criar dois laços de repetições aninhados (igual fizemos com o CreatePositions), assim, nós iremos percorrer as linhas e colunas da textura como um todo.
Vamos representar o primeiro laço pela obtenção das linhas da imagem(esse contador será chamado de 'i') e o segundo laço, as colunas da imagem (contador com o nome de 'j'), para representarmos uma matriz ixj.
Se começarmos o laço 'i' do zero, ele vai começar da última linha da imagem, ou seja, a primeira parte da imagem vai ser obtida a partir da última linha da mesma, então se quisermos que a primeira parte da imagem seja obtida a partir da sua primeira linha, devemos iniciar esse laço de trás pra frente, assim a imagem será recortada de cima para baixo da esquerda para a direita.
Então crie uma variável local chamada "start" e nela armazene "amoutPieces" -1.
Agora crie o laço "i" iniciando de start, e tendo seu delimitador até que "i" seja maior ou igual a 0, recebendo um decremento de um em um.
Já dentro do laço 'i' com o laço 'j', sua definição é mais simples: basta o iniciar a partir do 0, e se delimitar até que seu valor seja menor que "amoutPieces", recebendo o incremento de um em um:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B12

Vamos finalmente criar o prefab contendo a parte da textura cortada, crie uma variável local chamada "texture" e a faça receber a chamada da nossa função "CropTexture", passando como argumento j e i, respectivamente.
Faça com que a variável "position" receba a chamada da nossa função "RandomPosition" para que seja sorteada uma posição para esse prefab, e por fim, faça com que uma variável local chamada "quad" receba a instância do prefab "piecePrefab", na posição "position".

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B13

Agora faremos com que esse prefab tenha como imagem (sprite) o pedaço da peça cortada que está armazenada na variável "texture":
Através da variável "quad" pegue o componente "SpriteRenderer" do objeto e acesse sua propriedade "sprite". Através do comando "Sprite.Create" crie um novo sprite para esse prefab, passando como argumento a textura que irá ser criada (no caso, a variável "texture" que contém a parte cortada da imagem), e um novo retângulo que irá definir a dimensão desse sprite, ou seja, 0 e 0 para a imagem ser obtida a partir do canto inferior esquerdo, com as dimensões de "texture" para a largura e altura, e após definir o retângulo, defina o pivot dessa imagem, recomendo que seja central, sendo um novo Vector2 com os valores 0.5 e 0.5 (centro da imagem):

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B14

Vamos então ajustar o colisor do sprite para que fique do tamanho da textura cortada, para isso, através da variável "quad" obtenha o componente "BoxCollider2D"e faça acesso à propriedade "size", dentro dela armazene um novo Vector2 com "X" sendo o valor de "distancePieces.x" e "Y" sendo "distancePieces.y":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B15


Salve o script.
Agora crie um novo objeto vazio em cena com o nome de "GameManager" e nele adicione o script "CropTexture".
Através do inspector selecione um tamanho qualquer para a grade, anexe a imagem que deseja ser recortada para o quebra-cabeças e o prefab da peça:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B16

Teste o jogo e em tempo de execução ajuste a posição e campo de visão da câmera. 
Perceba que as peças são instanciadas de acordo com a grade selecionada, em diversos pedaços, um do lado do outro:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B17
Exemplo de grade 4x4 com 16 peças.

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B18
Exemplo de grade 2x2 com 4 peças.

Criando a grade:
Com a instanciação das peças, vamos então criar a instância da grade, para que cada parte da imagem seja encaixada corretamente.
Para tal, crie através de um editor de imagens de sua preferência um quadrado com a resolução 150x150(por exemplo), transparente e com uma borda interna cinza com 2 pixels de espessura. Salve a imagem em formato .png com o nome de "quad", a imagem será mais ou menos assim:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Quad
Importe a imagem para o projeto.
Agora crie um novo Sprite na cena com o nome de "Grid", contendo apenas um BoxCollider2D com a opção "Is Trigger" marcada, tendo como "sprite" a imagem que acabara de importar. Faça com que esse objeto se torne um prefab.

Vamos então voltar para o script "CropTexture" e criar a variável "gridPrefab" como pública:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B19

Após ter feito isso, crie um método sem retorno chamado "CreateGrid" que vai receber três parâmetros: dois inteiros chamados "j" e "i" e um GameObject chamado "quad".

Crie uma variável local chamada "grid" e a faça receber o Instantiate contendo o prefab "gridPrefab", um novo Vector2 recebendo em "x" a variável 'j' multiplicando a distância das peças em X e subtraindo esse valor por 10 (fazendo com que a grade seja instanciada com 10 pixels de distância das peças), e em "y" a variável 'i' multiplicando a distância das peças em Y.
Vamos também criar uma variável local chamada "newScale" para determinar a nova escala desse sprite de acordo com a grade das peças, fazendo com que essa variável receba um novo Vector2 em "x" sendo a resolução da peça em x dividida pela largura do sprite "quad" (que no caso é 150) e em "y" a resolução da peça em y também dividida por 150.
Agora é só aplicar "newScale" em x e y para "localScale" de "grid":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B21

Agora chame o método "CreateGrid" dentro do método "CreatePiece" após criar a peça passando como argumento as variáveis "j" e "i" e também "quad":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B22

Salve o script e através do inspector anexe o prefab "grid" na variável "gridPrefab" no GameManager. Teste o jogo:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B23

Exemplo de uma grade criada a partir de 9 peças (grade 3x3).

Script da peça:
Temos agora as peças e grade em cena, mas elas não possuem nenhuma interação com o usuário.
Vamos então criar o script responsável por "controlarmos" as peças, crie um novo c# script com o nome de "PieceScript".
Vamos então criar nossas variáveis públicas (que serão acessadas a partir de outra classe), portanto terão como atributo "HiddenInInspector": duas variáveis do tipo Vector2 uma chamada "startPosition" e outra com o nome de "endPosition", e duas variáveis do tipo bool, uma chamada "canMove" que vai verificar se essa peça pode se mover e outra "cancelPiece" que vai verificar se essa peça parou de ser manipulada.
Como variáveis privadas nós teremos a variável do tipo SpriteRenderer com o nome de "sprite" e uma outra do tipo float chamada "timeToLerp" para criarmos um efeito "Lerp" ao soltar a peça, essa variável irá iniciar com o valor 20.
Dentro do Start do script inicie a variável ''sprite'' com a obtenção do componente "SpriteRenderer" do objeto:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B24

A variável "startPosition" vai ser responsável por informar ao programa qual é a posição em que a peça foi instanciada, portanto, salve esse script e volte ao script "CropTexture" e antes de criar a grade dentro do método "CreatePiece", através da variável "quad" obtenha o script "PieceScript" e faça acesso à variável "StartPosition" definindo a variável "position":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B25

Já a variável "EndPosition" é responsável por informar ao programa qual é a parte da grade correta para que a peça seja posicionada, então é crucial que você vá ao método "CreateGrid" e através do parâmetro "quad" faça acesso ao script "PieceScript" e à propriedade "endPosition" da peça, fazendo com que receba a posição (transform.position) da grade que acabou de ser criada:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B27


Salve o script.
Vamos agora criar um script chamado "GameManager" que vai conter a score atual do jogador, o score que ele deve obter e a peça atual que está sendo manipulada.
Crie esse script com três variáveis públicas e estáticas, uma do tipo GameObject chamada "currentPiece" e duas do tipo int uma chamada "currentScore" e "scoreTotal". Salve o script:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B28

Volte para o script "CropTexture" e no método "StartComponents" faça com que "currentScore" inicie em zero e com que "scoreTotal" receba a quantidade de peças vezes ela mesma:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B29

Salve esse script e volte para o script "PieceScript".

Clicando na peça:
Após fazer esses pequenos ajustes, vamos fazer de fato a peça ser "levada" pelo mouse, ao clicar na mesma.
Defina o evento "OnMouseOver" no script "PieceScript" para ser disparado quando o ponteiro do mouse estiver sob o objeto da peça. Dentro do método crie uma condição que vai verificar o lado do mouse que foi pressionado, caso for o esquerdo(0) e cancelPiece for false e currentPiece for null (não há no momento nenhuma outra peça sendo manipulada pelo mouse), faremos com que currentPiece receba esse gameObject(essa peça) e que canMove fique true.
Caso o lado do mouse direito for pressionado (1), cancelPiece for false e canMove for true, iremos fazer com que cancelPiece receba true, pois com o lado direito do mouse nós iremos "soltar" a peça:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B30

Agora dentro do Update do script nós vamos criar uma validação se "canMove" for true, e caso for, a peça poderá seguir o ponteiro do mouse.
Primeiro faça com que a sortingOrder do sprite fique igual a 1 (para ficar sobre todas as outras peças), e então crie uma variável local chamada mouseP para receber a posição do mouse de acordo com o mousePosition.
vamos ajustar o eixo 'z' da posição do mouse para as definições da tela do jogo(Mundo do Unity) e não com relação à tela do computador, para isso, basta fazer com que mouseP.z receba a posição "z" da peça menos a posição "z" da câmera.
Então finalmente faça com que o transform.position do objeto(peça) receba a posição do mouse (mouseP) com relação ao mundo dentro do Unity:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B31

Através desses comandos, é possível que o sprite do objeto siga o ponteiro do mouse pela tela.

Faremos agora a função de cancelamento da peça, caso o jogador queira "largá-la".
Crie um método sem retorno chamado "CancelPiece" e dentro dele faça com que currentPiece receba 'null' (pois não estamos mais manipulando nenhuma peça), e faça com que a posição da peça volte para sua posição inicial com uma certa suavização utilizando o método "MoveTowards", saindo da posição atual onde o objeto se encontra, tendo como destino o Vector "startPosition" num tempo de acordo com a variável "TimeToLerp" multiplicado por time.DeltaTime.
Faça também com que a variável "canMove" fique false e depois uma validação se a posição do objeto é igual à posição "startPosition", caso for, faça com que o sortingOrder volte a ser 0 e que cancelPiece volte a ficar false:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B32

Dentro do Update faça com que CancelPiece seja chamado se "cancelPiece" for verdadeiro:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B33

Salve o script e o adicione ao prefab "Piece". Agora ao testar o jogo, você percebe que pode fazer com que a peça siga o mouse ao clicar na mesma, e se clicar com o lado direito, a peça se 'solta' e volta para seu ponto de origem suavemente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B34

Clicando na grade:
Agora que podemos transitar com a peça pela tela através do mouse, vamos criar o script da grade que irá verificar se a peça que estamos manipulando faz parte daquele pedaço da grade.
Crie um novo C# script com o nome de "GridScript".
Dentro do Update desse script, vamos verificar se o mouse está sob o colisor desse objeto (grade) , então crie uma validação através do BoxCollider2D do objeto, e do método "OverlapPoint, passando como argumento a posição do mouse de acordo com o mundo dentro do Unity.
Caso o mouse esteja sob esse collider, chame o método "Check" que iremos definir a seguir.

O método "Check" deve ser sem retorno, e dentro dele vamos verificar se o botão esquerdo o mouse foi pressionado (0) e se currentPiece não é nulo, ou seja, temos alguma peça sendo manipulada no momento.
Caso ambas sentenças forem verdadeiras, iremos criar uma segunda condição que verifica se "endPosition" de "currentPiece" é igual a posição dessa parte da grade, caso sim, iremos posicionar a peça exatamente na mesma posição que esse pedaço da grade, faremos com que o sortingOrder de "currentPiece" volte a ser 0, destruiremos o script "PieceScript" do "currentPiece" para que não possamos mais clicar na peça e movimentá-la, faremos com que currentPiece volte a ser nulo, incrementamos o score do jogador e por fim, destruímos o objeto da grade (Para evitar de clicar nela novamente e melhorar a performance do jogo, já que não iremos mais usar esse script).

Caso a peça corrente não tenha como 'destino' essa parte da grade, apenas faça com que ela "volte" para seu local de origem fazendo com que "cancelPiece" fique true.
O script deve estar assim:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B36


Salve o script e adicione-o no prefab "Grid". Teste o jogo e veja que agora é possível encaixar as peças:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B37

Verificando final de jogo:
Para verificar o final do jogo é bem simples: Primeiro crie um Canvas com um text ancorado e devidamente dimensionado com o texto "Congratulations":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B38

E por padrão deixe-o desativado.
Agora vá para o script "GameManager" e crie uma variável pública do tipo "Text" chamada "text" (referencie a biblioteca "UI" dentro do script!)
Agora dentro do Update crie uma validação se currentScore for igual a totalScore, o gameObject de "text" irá ser ativado:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B39

Agora anexe esse script no objeto "GameManager" e faça com que o text do canvas seja armazenado na variável "text" desse script.
Teste o jogo e tente montar o quebra-cabeças: Perceba que quando você o completa o jogo "se encerra" e a mensagem de congratulações aparece na tela:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B40

Mostrando imagem original:
Outro sistema que podemos fazer é o de mostrar a imagem como ela é quando montada, ao clicar num botão.
É muito fácil criar esse sistema, basta criar uma imagem dentro do Canvas e a posicionar, ancorar e redimensionar da forma que achar melhor:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B41

Desativa a imagem também.
Agora vá para o script "CropTextures" crie uma variável pública do tipo Image chamada "img" (referencie a biblioteca UI) e no método "StartComponents" faça com que ela receba a textura da imagem do quebra-cabeças de acordo com sourceTexture, igual já fizemos anteriormente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B43

Salve o script e anexe a imagem na variável "img"do script do GameManager.
Crie agora um Button dentro do Canvas com o Texto "View Image" e o ancore e posicione da forma que achar melhor.
Crie um novo C# script chamado "ButtonScript" e crie uma variável pública do tipo "Image" chamada "img" e uma variável private booleana chamada "isEnabled" iniciando em "false".
Agora defina um método público sem retorno chamado "ClickViewImage" e faça com que a variável "isEnabled" receba seu oposto. Após isso, faça com que a "img" seja ativada se isEnabled for true e desativada se isEnabled for false:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B44

Salve o script e o adicione no botão dentro do Canvas, anexando a imagem desativada dentro da variável "img". Dentro do evento "OnClick" clique no sinal de mais (+)  e em "None" adicione o próprio objeto do botão, e após isso em "No Function" vá em "ButtonScript >> ClickViewImage" para esse método seja disparado quando clicarmos no botão.
Teste o jogo e clique no button: Perceba que quando faz isso, a imagem original do quebra-cabeças aparece no canto da tela, e ao clicar novamente no button, ela é desativada:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B46

Isso pode auxiliar o jogador a ver como a imagem é de fato para poder montar o quebra-cabeças.

Final:
E chegamos (ufa) a mais um final de tutorial por aqui! A sugestão que eu ainda tenho para melhorar o jogo é criar um menu que possibilite o jogador a escolher com qual imagem ele quer jogar(uma gama de opções de imagens, ao invés de uma) e a dificuldade através da escolha da grade.
Esse tutorial foi muito trabalhoso de fazer (acho que foi o mais de todos) portanto, se gostou e se te ajudou em algo (mesmo se não for com relação ao desenvolvimento de um quebra-cabeças, mas ao aprender sobre algum comando que você não sabia) deixe o seu feedback, isso é muito importante para me motivar a continuar postando tutoriais e aulas aqui.
Por fim, caso queira, aqui está o link do código fonte no gitHub: https://github.com/mayleone1994/PuzzleGame

Até mais!
MayLeone
MayLeone
Instrutor

Feminino PONTOS : 3371
REPUTAÇÃO : 591
Áreas de atuação : Unity & C#
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

http://compilemosfacil.blogspot.com.br

Ir para o topo Ir para baixo

TUTORIAL Re: [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por dstaroski Ter Jan 15, 2019 7:48 pm

Nossa! Parabéns ai! Show!
dstaroski
dstaroski
Instrutor

Masculino PONTOS : 5875
REPUTAÇÃO : 1123
Idade : 34
Áreas de atuação : Teologia, Unity 3D, C#, HTML, CSS, Dart, Flutter.

Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

http://diegodeoliveira.gamejolt.io/defeattheilluminatis

Ir para o topo Ir para baixo

TUTORIAL Re: [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por MarcosSchultz Ter Jan 15, 2019 10:57 pm

Que tutorial topppp.

@MayLeone, você já pensou em vender cursos na Udemy? A qualidade dos seus tutoriais é bem alta, e o principal, é bastaante detalhado.

Meio que direto aparece gente pedindo se eu tenho cursos pra vender na Udemy, ou seja, tem público. Qualidade alta em tutoriais pode ser bem explorada em sites de vendas de tutoriais, e gera um money extra significativo as vezes.
MarcosSchultz
MarcosSchultz
Administrador

Masculino PONTOS : 64547
REPUTAÇÃO : 2647
Idade : 27
Áreas de atuação : Administrador do fórum
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

https://www.schultzgames.com

Ir para o topo Ir para baixo

TUTORIAL Re: [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por MayLeone Qua Jan 16, 2019 11:35 am

Vlw Marcos!
Eu realmente queria começar um curso de criação de jogos para iniciantes com Unity lá na Udemy, massssss me falta o essencial, um equipamento descente (máquina boa + microfone), sem dizer que minha casa é bem barulhenta, então quase sempre eu me estresso gravado vídeos, por isso prefiro escrever, apesar de que dá muito mais trabalho.
Mas eu pretendo normalizar essa situação e levar a sério a ideia desses cursos e etc.
Obrigada pelo feeback, é bem importante pra eu saber se estou no caminho certo.

Vlw vc também, dstaroski!
MayLeone
MayLeone
Instrutor

Feminino PONTOS : 3371
REPUTAÇÃO : 591
Áreas de atuação : Unity & C#
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

http://compilemosfacil.blogspot.com.br

Ir para o topo Ir para baixo

TUTORIAL Re: [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por fabricadegame Ter maio 28, 2019 9:31 am

MayLeone escreveu:Vlw Marcos!
Eu realmente queria começar um curso de criação de jogos para iniciantes com Unity lá na Udemy, massssss me falta o essencial, um equipamento descente (máquina boa + microfone), sem dizer que minha casa é bem barulhenta, então quase sempre eu me estresso gravado vídeos, por isso prefiro escrever, apesar de que dá muito mais trabalho.
Mas eu pretendo normalizar essa situação e levar a sério a ideia desses cursos e etc.
Obrigada pelo feeback, é bem importante pra eu saber se estou no caminho certo.

Vlw vc também, dstaroski!

Ou MayLeone, você escreve bem e de uma forma bastante didática. Existem poucos livros em português da Unity ou talvez nenhum. Ainda existem alguns cursos regulares, técnicos e superiores que estão demandando esse tipo de conteúdo.
O que acha de começar um projeto de um livro? Eu acho que vc teria um bom conteúdo final,l viu.

fabricadegame
Membro
Membro

PONTOS : 1789
REPUTAÇÃO : 11
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças WvDYdlf

Ir para o topo Ir para baixo

TUTORIAL Re: [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças

Mensagem por Diego Felix Ter Jun 18, 2019 9:46 am

MayLeone escreveu:
[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Jigsaw-Puzzle-PNG


Olá pessoal! No tutorial de hoje nós vamos desenvolver um jogo de quebra-cabeças (aqueles clássicos de encaixar as peças para formar uma imagem) na engine Unity.
Em nosso tutorial, será possível escolher qualquer imagem de qualquer tamanho para montar o quebra-cabeças, também será possível decidir o nível de dificuldade do mesmo, onde podemos ter quantidade de peças diferentes dependendo da grade selecionada, por exemplo, uma grade 4x4 terá ao todo 16 peças para serem montadas.
Em nosso jogo, teremos uma grade que irá orientar o jogador da onde cada peça deverá se encaixar, então em nosso tutorial iremos programar também a criação dessa grade proporcional à quantidade de peças, iremos criar o sistema de clique com o mouse, verificação de vitória, recorte da imagem e muito mais.
O resultado final será exatamente esse aqui:



Recortando a imagem:
Uma das primeiras coisas que faremos em nosso tutorial será "cortar" em vários pedacinhos a imagem que será usada como quebra-cabeças.
Antes de iniciarmos de fato a programação de tal sistema no Unity, vamos entender como faríamos esse tipo de "recorte", irei usar como exemplo a imagem abaixo:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Image

Essa imagem foi reduzida para se adequar ao tamanho do site corretamente, porém ela possui originalmente as dimensões 900x800 (largura e altura).
Supondo que desejamos cortar essa imagem em exatos 4 pedaços, isso significa que teremos uma grade 2x2 ou seja, teremos 2 pedaços a serem cortados horizontalmente e mais 2 pedaços na vertical, totalizando 4 peças.
Então tudo certo, sabemos a quantidade de peças e a grade (quantas imagens iremos ter nas linhas e colunas), mas a grande pergunta é... Qual o tamanho(dimensão) de cada pedaço, para que sejam cortados com exatidão sem sobrar partes da imagem?
O cálculo é mais simples do que pensa, para saber a largura do pedaço, basta dividir a largura total da imagem pelo valor da grade (no caso aqui, 2) e o mesmo com a altura, divida a altura da imagem pela dimensão da grade (2).
Por fim, iremos concluir que cada pedaço terá 450x400 de dimensão (900/2) e (800/2), isso significa que teremos 4 imagens de 450x400 de dimensão numa grade 2x2, ou seja, 2 imagens para as colunas e 2 para as linhas, dessa forma:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B2

O padrão se repete caso queria ter mais peças.
Por exemplo, no caso de querer 9 peças, teremos uma grade 3x3, ou seja, teremos 3 imagens para as linhas e 3 para as colunas.
Cada pedaço terá 300x266 pixels de altura e largura (caso a imagem possua 900x800 de dimensão).

Dessa forma, podemos então descobrir o tamanho de cada retângulo (parte da imagem/peça) quando formos cortar as peças através de código.

Script para recortar as peças:
Agora que está entendido como iremos "cortar" a imagem, abra um novo projeto 2D na engine com o nome "Puzzle Game" e importe a imagem que desejá cortar, também crie um prefab de um sprite 2D com o nome de "Piece", a única coisa que ele terá por enquanto será um box collider 2D.
Esse prefab será responsável por "ser a peça", onde exibirá seu sprite como sendo uma parte da imagem.

Para cortar uma imagem devemos utilizar uma Texture2D para representá-la, porém, para poder manipular as textures importadas do projeto devemos permitir que elas sejam passíveis à leitura e escrita, portanto, clique na imagem importada e através do inspector vá à opção "Texture Type >> Advanced" e marque a caixa "Read/Write Enabled" e dê apply:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B1


Dessa forma poderemos ter acesso à textura via código.

Agora crie um script chamado "CropTextures" para que possamos recortar as imagens.

Vamos agora criar algumas variáveis públicas para esse script: Um enumerador que irá definir o tamanho da grade do jogo, variando entre as grades 2x2 até 9x9 (você pode colocar mais, se desejar), uma variável do tipo do nosso enumerador para receber a resolução da grade, uma variável do tipo Texture2D chamada "sourceTexture" para recebermos a imagem que será cortada e uma variável do tipo "GameObject" para armazenar o prefab da peça a ser instanciada.
Também criaremos duas variáveis privadas, uma do tipo "int" chamada "amoutPieces" que representará a quantidade de peças e um Vector2 chamado "resolutionPieces" para armazenar a resolução de cada parte da imagem (aquele retângulo que vimos no exemplo anterior):


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B3



Vamos agora criar um método chamado "StartComponents" para inicializarmos alguns valores.
Por enquanto os únicos valores a serem iniciados serão a quantidade de peças que deve representar o índice do enum "Options", e a resolução das peças que deve ser calculada de acordo com o cálculo que eu mostrei a vocês, ou seja, resolutionPieces.x deve ser a largura da texture dividida pela grade na horizontal, e resolutionPieces.y deve ser a altura da texture dividida pela grade na vertical:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B4


Chame esse método dentro do Start do script.

Agora vamos criar o método que de fato cortará a textura em vários pedaços, para criá-lo deixe-o retornar uma Texture2D, chame-o de "CropTexture" e defina dois parâmetros do tipo inteiro, um chamado "row" para representar a coluna que ele deve cortar a imagem e outro chamado "line" para representar a linha.
Agora crie duas variáveis locais (chamadas resolutionX e resolutionY) para que elas recebam os valores da resolução das peças arredondadas (utilize o Mathf.RoundToInt para isso):

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B5

Então agora utilizaremos uma função da classe "Texture2D" que se chama "GetPixels".
Essa função irá retornar os pixels de uma textura/imagem de acordo com a posição e tamanho que serão passados como argumento em formato de um retângulo, deverá ser passado a posição na imagem onde os pixels serão obtidos e a resolução dessa área. A função retorna os pixels da área desejada em forma de um vetor do tipo "Color".

Vamos então criar uma variável local chamada "pixels" do tipo array Color e fazer com que receba a função "GetPixels" sendo chamada através da textura que será anexada ao inspector que ficará armazenada na variável "sourceTexture":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B6

Agora devemos passar o retângulo (área que deve-se obter os pixels da imagem) como argumento da função.
Esse argumento é um retângulo como já dito, que vai pedir a posição X da onde ele vai obter os pixels e a posição Y, então multiplique o valor da coluna (row) pela resolução em X da peça (row*resolutionX) e multiplique a linha pela resolução em Y (line*resolutionY).
Para saber o tamanho da área a ser obtida, basta passar o valor da resolução em X e em Y, respetivamente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B7

Como iremos criar um laço de repetição que irá percorrer a imagem completa de acordo com as dimensões da mesma, a função "CropTexture" irá ser chamada toda vez que uma parte da imagem for percorrida, representada pelos parâmetros "row" e "line" para sabermos em qual coluna e linha o laço está, dessa forma, a nossa função irá retornar um pedaço da textura num local específico da imagem toda vez que for chamada.

Agora vamos criar uma nova Texture2D para ser retornada da função com a parte da imagem que foi recortada através da função "GetPixels"
Para isso, basta criar uma variável local chamada "tex" e dentro do seu construtor passar a resolução dessa nova textura a ser criada, no caso, resolutionX e resolutionY.
Após fazer isso, preencha essa nova textura com os pixels obtidos anteriormente e que estão armazenados no array "pixels", através da função "SetPixels". Aplique essa atualização através da função "Apply" e retorne da função a variável "tex":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B8

Criando as posições para as peças:
Nessa altura do tutorial nós temos como retornar cada parte da imagem de acordo com sua resolução, mas ainda não temos onde colocar essas imagens das peças.
Nós iremos representar a imagem de cada peça a partir daquele prefab já citado anteriormente que é apenas um sprite2D com um collider.
Antes de instanciarmos o prefab com a imagem cortada em seu sprite, vamos definir as possíveis posições onde esses prefabs serão sorteados.
Para que o jogo fique mais interesse, vamos sortear os pedacinhos em locais aleatórios da cena e toda vez que o jogo ser iniciado novamente, os pedacinhos irão trocar de posições.

Vamos criar mais algumas variáveis do tipo "Vector2": uma chamada "position" que irá guardar a posição da peça que será instanciada, outra chamada "distancePieces" que irá guardar a resolução do tamanho das peças para que possamos instanciá-las uma do lado da outra, e duas listas do tipo "Vector2" uma chamada "positions" para guardar todas as posições possíveis que as peças ficarão, e outra chamada "sortedPieces" que irá armazenadas as peças já sorteadas, para que não se repita um local e alguma peça fique sobre a outra:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B9

Criaremos agora um método sem retorno chamado "CreatePositions" que vai ser responsável por de fato, criar as possíveis posições para que as peças possam ser instanciadas.
Vamos calcular primeiramente a distância de cada peça, que deve ser em "x" a resolução da peça em X divida por 100 (se a resolução da peça for 300, por exemplo, a distância entre essas peças na Unity será de 3 pixels, já que estamos utilizando 100 pixels per unit para o tamanho da imagem) e para Y será o mesmo princípio.
Depois disso, crie um laço de repetição que tem como contador um inteiro chamado "x" e que vai ser incrementado até que o mesmo seja menor que a quantidade de peças, e dentro desse laço defina outro laço com o contador chamado "y" que irá ser incrementado até que seu valor seja menor que a quantidade de peças.
Agora adicione dentro da lista "positions" um novo Vector2 em x tendo a distância das peças multiplicado pelo contador "x" e em "y" a distância das peças multiplicado pelo contador "y":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B10

Então se por exemplo temos uma peça com resolução de 400 pixels(de largura e altura) e uma grade 2x2, as posições serão:

0 e 0,
0 e 4,
4 e 0,
4 e 4.

Ou seja, teremos duas peças nas posições 0;0 e 0;4 (primeira linha) e duas peças nas posições 4;0 e 4;4 (segunda linha), ou seja, uma grade 2x2 com duas linhas e duas colunas.
A distância entre cada peça é de 4 pixels tanto em x quanto em y, pois dividimos a resolução da peça por 100, fazendo com que quando as peças forem instanciadas em alguma dessas quatro posições, elas fiquem exatamente uma do lado da outra, formando então uma grade 2x2 com 4 peças.

Chame esse método "CreatePositions" dentro do Start do script.

Randomizando posições:
Agora que temos dentro da lista "positions" todas as possíveis posições para as peças, vamos randomizá-las, sorteando aleatoriamente sempre uma nova posição para a peça que está sendo instanciada.
Para tal, crie um método chamado "RandomPosition" que retorna um Vector2.
Dentro desse método crie uma variável local chamada "sorted" para definirmos se alguma posição válida foi sorteada, então inicie essa variável como sendo "false".
Crie uma outra variável local chamada "pos" que irá conter as posições sorteadas e a inicialize como um Vector zero.
Agora crie um laço "while" que irá ficar sendo executado enquanto "sorted" for false.
Dentro do laço faça com que a variável "pos" receba um valor aleatório dentro da lista "positions" através do método Random.Range.
Após isso, nós iremos armazenar dentro da variável "sorted" se essa posição sorteada aleatoriamente já foi sorteada antes, para isso, basta verificar se dentro da lista "sortedPositions" o valor de "pos" não está contido nela.
Caso "sorted" seja true (ou seja, o valor ainda não foi sorteado) armazene dentro da variável "sortedPositions" o valor de "pos", já que é uma posição que ainda não foi sorteada. Após o laço, apenas retorne "pos":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B11

Pronto! Agora temos um método que irá randomizar as posições das peças de acordo com as possíveis posições na cena.

Instanciando as peças:
Vamos então finalmente instanciar as peças na cena que irão representar as partes da textura recortada.
Crie um método sem retorno com o nome "CreatePiece" e o chame dentro do Start do script.
Agora vamos instanciar os prefabs de acordo com a quantidade de peças.
Para isso, vamos criar dois laços de repetições aninhados (igual fizemos com o CreatePositions), assim, nós iremos percorrer as linhas e colunas da textura como um todo.
Vamos representar o primeiro laço pela obtenção das linhas da imagem(esse contador será chamado de 'i') e o segundo laço, as colunas da imagem (contador com o nome de 'j'), para representarmos uma matriz ixj.
Se começarmos o laço 'i' do zero, ele vai começar da última linha da imagem, ou seja, a primeira parte da imagem vai ser obtida a partir da última linha da mesma, então se quisermos que a primeira parte da imagem seja obtida a partir da sua primeira linha, devemos iniciar esse laço de trás pra frente, assim a imagem será recortada de cima para baixo da esquerda para a direita.
Então crie uma variável local chamada "start" e nela armazene "amoutPieces" -1.
Agora crie o laço "i" iniciando de start, e tendo seu delimitador até que "i" seja maior ou igual a 0, recebendo um decremento de um em um.
Já dentro do laço 'i' com o laço 'j', sua definição é mais simples: basta o iniciar a partir do 0, e se delimitar até que seu valor seja menor que "amoutPieces", recebendo o incremento de um em um:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B12

Vamos finalmente criar o prefab contendo a parte da textura cortada, crie uma variável local chamada "texture" e a faça receber a chamada da nossa função "CropTexture", passando como argumento j e i, respectivamente.
Faça com que a variável "position" receba a chamada da nossa função "RandomPosition" para que seja sorteada uma posição para esse prefab, e por fim, faça com que uma variável local chamada "quad" receba a instância do prefab "piecePrefab", na posição "position".

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B13

Agora faremos com que esse prefab tenha como imagem (sprite) o pedaço da peça cortada que está armazenada na variável "texture":
Através da variável "quad" pegue o componente "SpriteRenderer" do objeto e acesse sua propriedade "sprite". Através do comando "Sprite.Create" crie um novo sprite para esse prefab, passando como argumento a textura que irá ser criada (no caso, a variável "texture" que contém a parte cortada da imagem), e um novo retângulo que irá definir a dimensão desse sprite, ou seja, 0 e 0 para a imagem ser obtida a partir do canto inferior esquerdo, com as dimensões de "texture" para a largura e altura, e após definir o retângulo, defina o pivot dessa imagem, recomendo que seja central, sendo um novo Vector2 com os valores 0.5 e 0.5 (centro da imagem):

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B14

Vamos então ajustar o colisor do sprite para que fique do tamanho da textura cortada, para isso, através da variável "quad" obtenha o componente "BoxCollider2D"e faça acesso à propriedade "size", dentro dela armazene um novo Vector2 com "X" sendo o valor de "distancePieces.x" e "Y" sendo "distancePieces.y":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B15


Salve o script.
Agora crie um novo objeto vazio em cena com o nome de "GameManager" e nele adicione o script "CropTexture".
Através do inspector selecione um tamanho qualquer para a grade, anexe a imagem que deseja ser recortada para o quebra-cabeças e o prefab da peça:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B16

Teste o jogo e em tempo de execução ajuste a posição e campo de visão da câmera. 
Perceba que as peças são instanciadas de acordo com a grade selecionada, em diversos pedaços, um do lado do outro:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B17
Exemplo de grade 4x4 com 16 peças.

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B18
Exemplo de grade 2x2 com 4 peças.

Criando a grade:
Com a instanciação das peças, vamos então criar a instância da grade, para que cada parte da imagem seja encaixada corretamente.
Para tal, crie através de um editor de imagens de sua preferência um quadrado com a resolução 150x150(por exemplo), transparente e com uma borda interna cinza com 2 pixels de espessura. Salve a imagem em formato .png com o nome de "quad", a imagem será mais ou menos assim:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Quad
Importe a imagem para o projeto.
Agora crie um novo Sprite na cena com o nome de "Grid", contendo apenas um BoxCollider2D com a opção "Is Trigger" marcada, tendo como "sprite" a imagem que acabara de importar. Faça com que esse objeto se torne um prefab.

Vamos então voltar para o script "CropTexture" e criar a variável "gridPrefab" como pública:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B19

Após ter feito isso, crie um método sem retorno chamado "CreateGrid" que vai receber três parâmetros: dois inteiros chamados "j" e "i" e um GameObject chamado "quad".

Crie uma variável local chamada "grid" e a faça receber o Instantiate contendo o prefab "gridPrefab", um novo Vector2 recebendo em "x" a variável 'j' multiplicando a distância das peças em X e subtraindo esse valor por 10 (fazendo com que a grade seja instanciada com 10 pixels de distância das peças), e em "y" a variável 'i' multiplicando a distância das peças em Y.
Vamos também criar uma variável local chamada "newScale" para determinar a nova escala desse sprite de acordo com a grade das peças, fazendo com que essa variável receba um novo Vector2 em "x" sendo a resolução da peça em x dividida pela largura do sprite "quad" (que no caso é 150) e em "y" a resolução da peça em y também dividida por 150.
Agora é só aplicar "newScale" em x e y para "localScale" de "grid":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B21

Agora chame o método "CreateGrid" dentro do método "CreatePiece" após criar a peça passando como argumento as variáveis "j" e "i" e também "quad":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B22

Salve o script e através do inspector anexe o prefab "grid" na variável "gridPrefab" no GameManager. Teste o jogo:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B23

Exemplo de uma grade criada a partir de 9 peças (grade 3x3).

Script da peça:
Temos agora as peças e grade em cena, mas elas não possuem nenhuma interação com o usuário.
Vamos então criar o script responsável por "controlarmos" as peças, crie um novo c# script com o nome de "PieceScript".
Vamos então criar nossas variáveis públicas (que serão acessadas a partir de outra classe), portanto terão como atributo "HiddenInInspector": duas variáveis do tipo Vector2 uma chamada "startPosition" e outra com o nome de "endPosition", e duas variáveis do tipo bool, uma chamada "canMove" que vai verificar se essa peça pode se mover e outra "cancelPiece" que vai verificar se essa peça parou de ser manipulada.
Como variáveis privadas nós teremos a variável do tipo SpriteRenderer com o nome de "sprite" e uma outra do tipo float chamada "timeToLerp" para criarmos um efeito "Lerp" ao soltar a peça, essa variável irá iniciar com o valor 20.
Dentro do Start do script inicie a variável ''sprite'' com a obtenção do componente "SpriteRenderer" do objeto:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B24

A variável "startPosition" vai ser responsável por informar ao programa qual é a posição em que a peça foi instanciada, portanto, salve esse script e volte ao script "CropTexture" e antes de criar a grade dentro do método "CreatePiece", através da variável "quad" obtenha o script "PieceScript" e faça acesso à variável "StartPosition" definindo a variável "position":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B25

Já a variável "EndPosition" é responsável por informar ao programa qual é a parte da grade correta para que a peça seja posicionada, então é crucial que você vá ao método "CreateGrid" e através do parâmetro "quad" faça acesso ao script "PieceScript" e à propriedade "endPosition" da peça, fazendo com que receba a posição (transform.position) da grade que acabou de ser criada:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B27


Salve o script.
Vamos agora criar um script chamado "GameManager" que vai conter a score atual do jogador, o score que ele deve obter e a peça atual que está sendo manipulada.
Crie esse script com três variáveis públicas e estáticas, uma do tipo GameObject chamada "currentPiece" e duas do tipo int uma chamada "currentScore" e "scoreTotal". Salve o script:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B28

Volte para o script "CropTexture" e no método "StartComponents" faça com que "currentScore" inicie em zero e com que "scoreTotal" receba a quantidade de peças vezes ela mesma:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B29

Salve esse script e volte para o script "PieceScript".

Clicando na peça:
Após fazer esses pequenos ajustes, vamos fazer de fato a peça ser "levada" pelo mouse, ao clicar na mesma.
Defina o evento "OnMouseOver" no script "PieceScript" para ser disparado quando o ponteiro do mouse estiver sob o objeto da peça. Dentro do método crie uma condição que vai verificar o lado do mouse que foi pressionado, caso for o esquerdo(0) e cancelPiece for false e currentPiece for null (não há no momento nenhuma outra peça sendo manipulada pelo mouse), faremos com que currentPiece receba esse gameObject(essa peça) e que canMove fique true.
Caso o lado do mouse direito for pressionado (1), cancelPiece for false e canMove for true, iremos fazer com que cancelPiece receba true, pois com o lado direito do mouse nós iremos "soltar" a peça:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B30

Agora dentro do Update do script nós vamos criar uma validação se "canMove" for true, e caso for, a peça poderá seguir o ponteiro do mouse.
Primeiro faça com que a sortingOrder do sprite fique igual a 1 (para ficar sobre todas as outras peças), e então crie uma variável local chamada mouseP para receber a posição do mouse de acordo com o mousePosition.
vamos ajustar o eixo 'z' da posição do mouse para as definições da tela do jogo(Mundo do Unity) e não com relação à tela do computador, para isso, basta fazer com que mouseP.z receba a posição "z" da peça menos a posição "z" da câmera.
Então finalmente faça com que o transform.position do objeto(peça) receba a posição do mouse (mouseP) com relação ao mundo dentro do Unity:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B31

Através desses comandos, é possível que o sprite do objeto siga o ponteiro do mouse pela tela.

Faremos agora a função de cancelamento da peça, caso o jogador queira "largá-la".
Crie um método sem retorno chamado "CancelPiece" e dentro dele faça com que currentPiece receba 'null' (pois não estamos mais manipulando nenhuma peça), e faça com que a posição da peça volte para sua posição inicial com uma certa suavização utilizando o método "MoveTowards", saindo da posição atual onde o objeto se encontra, tendo como destino o Vector "startPosition" num tempo de acordo com a variável "TimeToLerp" multiplicado por time.DeltaTime.
Faça também com que a variável "canMove" fique false e depois uma validação se a posição do objeto é igual à posição "startPosition", caso for, faça com que o sortingOrder volte a ser 0 e que cancelPiece volte a ficar false:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B32

Dentro do Update faça com que CancelPiece seja chamado se "cancelPiece" for verdadeiro:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B33

Salve o script e o adicione ao prefab "Piece". Agora ao testar o jogo, você percebe que pode fazer com que a peça siga o mouse ao clicar na mesma, e se clicar com o lado direito, a peça se 'solta' e volta para seu ponto de origem suavemente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B34

Clicando na grade:
Agora que podemos transitar com a peça pela tela através do mouse, vamos criar o script da grade que irá verificar se a peça que estamos manipulando faz parte daquele pedaço da grade.
Crie um novo C# script com o nome de "GridScript".
Dentro do Update desse script, vamos verificar se o mouse está sob o colisor desse objeto (grade) , então crie uma validação através do BoxCollider2D do objeto, e do método "OverlapPoint, passando como argumento a posição do mouse de acordo com o mundo dentro do Unity.
Caso o mouse esteja sob esse collider, chame o método "Check" que iremos definir a seguir.

O método "Check" deve ser sem retorno, e dentro dele vamos verificar se o botão esquerdo o mouse foi pressionado (0) e se currentPiece não é nulo, ou seja, temos alguma peça sendo manipulada no momento.
Caso ambas sentenças forem verdadeiras, iremos criar uma segunda condição que verifica se "endPosition" de "currentPiece" é igual a posição dessa parte da grade, caso sim, iremos posicionar a peça exatamente na mesma posição que esse pedaço da grade, faremos com que o sortingOrder de "currentPiece" volte a ser 0, destruiremos o script "PieceScript" do "currentPiece" para que não possamos mais clicar na peça e movimentá-la, faremos com que currentPiece volte a ser nulo, incrementamos o score do jogador e por fim, destruímos o objeto da grade (Para evitar de clicar nela novamente e melhorar a performance do jogo, já que não iremos mais usar esse script).

Caso a peça corrente não tenha como 'destino' essa parte da grade, apenas faça com que ela "volte" para seu local de origem fazendo com que "cancelPiece" fique true.
O script deve estar assim:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B36


Salve o script e adicione-o no prefab "Grid". Teste o jogo e veja que agora é possível encaixar as peças:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B37

Verificando final de jogo:
Para verificar o final do jogo é bem simples: Primeiro crie um Canvas com um text ancorado e devidamente dimensionado com o texto "Congratulations":

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B38

E por padrão deixe-o desativado.
Agora vá para o script "GameManager" e crie uma variável pública do tipo "Text" chamada "text" (referencie a biblioteca "UI" dentro do script!)
Agora dentro do Update crie uma validação se currentScore for igual a totalScore, o gameObject de "text" irá ser ativado:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B39

Agora anexe esse script no objeto "GameManager" e faça com que o text do canvas seja armazenado na variável "text" desse script.
Teste o jogo e tente montar o quebra-cabeças: Perceba que quando você o completa o jogo "se encerra" e a mensagem de congratulações aparece na tela:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B40

Mostrando imagem original:
Outro sistema que podemos fazer é o de mostrar a imagem como ela é quando montada, ao clicar num botão.
É muito fácil criar esse sistema, basta criar uma imagem dentro do Canvas e a posicionar, ancorar e redimensionar da forma que achar melhor:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B41

Desativa a imagem também.
Agora vá para o script "CropTextures" crie uma variável pública do tipo Image chamada "img" (referencie a biblioteca UI) e no método "StartComponents" faça com que ela receba a textura da imagem do quebra-cabeças de acordo com sourceTexture, igual já fizemos anteriormente:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B43

Salve o script e anexe a imagem na variável "img"do script do GameManager.
Crie agora um Button dentro do Canvas com o Texto "View Image" e o ancore e posicione da forma que achar melhor.
Crie um novo C# script chamado "ButtonScript" e crie uma variável pública do tipo "Image" chamada "img" e uma variável private booleana chamada "isEnabled" iniciando em "false".
Agora defina um método público sem retorno chamado "ClickViewImage" e faça com que a variável "isEnabled" receba seu oposto. Após isso, faça com que a "img" seja ativada se isEnabled for true e desativada se isEnabled for false:

[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B44

Salve o script e o adicione no botão dentro do Canvas, anexando a imagem desativada dentro da variável "img". Dentro do evento "OnClick" clique no sinal de mais (+)  e em "None" adicione o próprio objeto do botão, e após isso em "No Function" vá em "ButtonScript >> ClickViewImage" para esse método seja disparado quando clicarmos no botão.
Teste o jogo e clique no button: Perceba que quando faz isso, a imagem original do quebra-cabeças aparece no canto da tela, e ao clicar novamente no button, ela é desativada:


[TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Untitled%2B46

Isso pode auxiliar o jogador a ver como a imagem é de fato para poder montar o quebra-cabeças.

Final:
E chegamos (ufa) a mais um final de tutorial por aqui! A sugestão que eu ainda tenho para melhorar o jogo é criar um menu que possibilite o jogador a escolher com qual imagem ele quer jogar(uma gama de opções de imagens, ao invés de uma) e a dificuldade através da escolha da grade.
Esse tutorial foi muito trabalhoso de fazer (acho que foi o mais de todos) portanto, se gostou e se te ajudou em algo (mesmo se não for com relação ao desenvolvimento de um quebra-cabeças, mas ao aprender sobre algum comando que você não sabia) deixe o seu feedback, isso é muito importante para me motivar a continuar postando tutoriais e aulas aqui.
Por fim, caso queira, aqui está o link do código fonte no gitHub: https://github.com/mayleone1994/PuzzleGame

Até mais!
Muito bom MayLeone, eu estava procurando algo do tipo esses dias em vídeo e não encontrei nada, ao menos bem explicado não, e geralmente quando encontro é em inglês e as vezes dificulta um pouco, realmente seria uma boa pra você o que o Marcos disse logo acima, criar um curso e mandar pra udemy, talento e conhecimento para criar um conteúdo de qualidade você tem, bom é isso agradeço pelo tutorial já me deu mais uma ideia kkkk e sucesso aí, vlw!!!  Vitoria
Diego Felix
Diego Felix
Avançado
Avançado

Masculino PONTOS : 2815
REPUTAÇÃO : 84
Idade : 33
Áreas de atuação : Modelagem 3D, Roteirista.
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças WvDYdlf

https://www.blogger.com/blogger.g?blogID=2315682099830977662#ove

Ir para o topo Ir para baixo

Ir para o topo

- Tópicos semelhantes

 
Permissões neste sub-fórum
Não podes responder a tópicos