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:
Animação de abrir/fechar porta mais complexa
duvida sobre essa Ui e raycast
Duvida Tamanho do Mapa unity
[____TÓPICO LIVRE____] FALE O QUE QUISER (Parte 2)
[Formação de Equipe] - City Driving
Nitro para Carro
Graficos bugados no android Unity 5
[ASSET] Script Arma Completo Incluso Recuo. Incluso outros Scripts
Clicar em um Sprite e realizar uma ação
[TUTORIAL] FPSController nadar e mergulhar, junto com efeito submerso
cliente/servidor
Ajuda com Colisões
mudar objeto ao clicar nele
Ajuda com um script(SmoothCamera)
Duvida em Desenhar UI -- HELP
Finalização Calculadora, fazer com que o jogador tente novamente
Como colocar musicas em um app?
[Duvida] Sobre Reference Resolution -> (Canvas)
Firebase (Login com facebook)
Como criar navegador próprio em app?
[RESOLVIDO] Duvida sobre Edição de texto em imagem
Da pra criar Apps na Unity?
BUG MT CHATO. USANDO O PlayerPrefs. ME AJUDAAAAAAA PF
[RESOLVIDO] Camera não colide com parede
Há algum segredo em criações de I.A?
[RESOLVIDO] salvar as configurações para aparecer no game certo que o jogador configurou
Dica de estudos
[RESOLVIDO] Duvida Sobre C#
Script parando de funcionar quando maximizo a tela do game
Fazer uma seleção de personagens e seguir para o jogo com o personagem escolhido
Como faço para colocar unity em rede
personagem
Criar animações
Detectar movimento Joystick
tem como abrir arquivos de jogos já compilado?
Como criar rede neural para AI
[____ADMINISTRAÇÃO____] Gostaria da opinião de vocês...
[____ADMINISTRAÇÃO____] Alterações IMPORTANTES no fórum.
Navegador reiniciando no mobile dos IOS [WEBGL]
[RESOLVIDO] Dúvida Script OnTriggerEnter
Gerar APK
[TUTORIAL] Salvar dados com playerprefs facilmente.
É possível reproduzir som durante logo de abertura do jogo?
[TUTORIAL] Criação de Skins Realistas em 3D!
Command 888
Sistema de Yu-Gi-Oh - C O M P L E T O - Download 13/08
[RESOLVIDO] Como fazer uma calculadora recebendo o resultado do jogador? UNITY
Construção de um save das configurações e ir pro jogo com as config certas
Podem me ajudar com esse problema
Contagem de tempo em classes abstratas
[TUTORIAL] Controle 3ª pessoa com animações mecânicas (root motion)
[RESOLVIDO] Como mostrar o valor atual de uma variável do tipo Int em um text
Como se faz um dash?
Como permitir que o usuário escolha uma imagem para ser usada em um jogo?
[Projeto em Andamento] Favela Combat - Multiplayer online (Android & iOS)
[TUTORIAL] Sistema Pdv, Mercado, Padaria, Conveniência, Lojas Em Geral - C# VISUAL STUDIO
Diferenciar execução (mobile / desktop) WEBGL
Como mudar de camera assim que o player entrar no Trigger
WEBGL
Como faço para mover um objeto?
[TUTORIAL] Unity 5 - Sistema Completo de PORTAS E CHAVES
Ajuda em bug da Unity!
como mudar o material de um mesh que tem mas de 1 material por Script ?
[Duvida] Como funciona a coleta de dados e como é feito?
Teclado na Unity
Formação de equipe -- ASSALTO A BANCO--
Câmera estar limitada ao tamanho da tela
ESCOLA DE DESENVOLVIMENTO DE GAMES.
Mudar uma animação já existente com o clique em um botão UI
Cam
[RESOLVIDO] Minha imagem só aparece na scene
COMO EXPORTAR PARA IOS COM WINDOWS
Criei uma Grama com Shader Graph
[TUTORIAL] Mover personagem com Touch, no estilo SUBWAY SURFERS
Joystick
Limite Máximo de tamanho de mapa na Unity?
Jogo Mobile (Leia)
Entender um script
[RESOLVIDO] Como Ativar Objeto Apenas na Frente Dele?
POR QUE O TOUCH MOBILE TRAVA COM ADMOB?
Qual o Tempo Máximo que vocês Jogaram um Jogo ?
Tocar audio
Todos os veiculos mudando de cor no multplayer, como resolver ?
[Projeto em Andamento] Brazil Combat
Background com bug
[Projeto] Omega Racers
[RESOLVIDO] Clones morrendo ao mesmo tempo?
Alguém pode me dizer o que esse script está fazendo?
HELP inimigo perseguir personagens
Html 5
1 exception was raised by workers: see the console for detail HELP
Acessar teclado nativo dispositivo, para inputFiled [WEBGL]
Como fazer uma animação parar em determinado frame?
Meu Jogo inspirado em resident evil 2 remake
Posso limitar o "Instantiate" para instanciar até uma quantidade X?
Grama
Player desliza nas subidas - Unity 2D
[RESOLVIDO] Como Detectar o idioma do dispositivo?
[TUTORIAL] FPS Controller com corpo completo!
Hoje à(s) 3:59 am
Hoje à(s) 3:47 am
Ontem à(s) 11:29 pm
Ontem à(s) 10:14 pm
Ontem à(s) 9:40 pm
Ontem à(s) 7:08 pm
Ontem à(s) 7:08 pm
Ontem à(s) 5:33 pm
Ontem à(s) 3:16 pm
Sab Ago 17, 2019 11:23 pm
Sab Ago 17, 2019 9:05 am
Sab Ago 17, 2019 3:16 am
Sex Ago 16, 2019 11:27 pm
Sex Ago 16, 2019 8:50 pm
Sex Ago 16, 2019 12:19 pm
Sex Ago 16, 2019 12:07 pm
Sex Ago 16, 2019 10:58 am
Sex Ago 16, 2019 6:33 am
Qui Ago 15, 2019 9:46 pm
Qui Ago 15, 2019 6:42 pm
Qui Ago 15, 2019 4:02 pm
Qui Ago 15, 2019 12:10 pm
Qui Ago 15, 2019 11:57 am
Qua Ago 14, 2019 7:13 pm
Qua Ago 14, 2019 6:07 pm
Qua Ago 14, 2019 5:48 pm
Qua Ago 14, 2019 5:18 pm
Qua Ago 14, 2019 5:05 pm
Qua Ago 14, 2019 5:00 pm
Qua Ago 14, 2019 4:56 pm
Qua Ago 14, 2019 4:53 pm
Qua Ago 14, 2019 4:52 pm
Qua Ago 14, 2019 4:49 pm
Qua Ago 14, 2019 4:47 pm
Qua Ago 14, 2019 4:45 pm
Qua Ago 14, 2019 4:44 pm
Qua Ago 14, 2019 4:35 pm
Qua Ago 14, 2019 4:32 pm
Qua Ago 14, 2019 4:31 pm
Qua Ago 14, 2019 4:10 pm
Qua Ago 14, 2019 12:39 am
Ter Ago 13, 2019 10:23 pm
Ter Ago 13, 2019 10:03 pm
Ter Ago 13, 2019 7:53 pm
Ter Ago 13, 2019 6:33 pm
Ter Ago 13, 2019 4:26 pm
Ter Ago 13, 2019 4:10 pm
Seg Ago 12, 2019 11:25 pm
Seg Ago 12, 2019 8:31 pm
Seg Ago 12, 2019 6:17 pm
Seg Ago 12, 2019 12:51 pm
Dom Ago 11, 2019 7:54 pm
Dom Ago 11, 2019 10:17 am
Sab Ago 10, 2019 10:32 pm
Sab Ago 10, 2019 2:34 pm
Sex Ago 09, 2019 10:43 pm
Sex Ago 09, 2019 5:56 pm
Qui Ago 08, 2019 7:48 pm
Qui Ago 08, 2019 5:21 pm
Qui Ago 08, 2019 12:32 pm
Qui Ago 08, 2019 2:53 am
Qua Ago 07, 2019 10:57 pm
Qua Ago 07, 2019 8:10 pm
Qua Ago 07, 2019 7:16 pm
Qua Ago 07, 2019 4:29 pm
Qua Ago 07, 2019 2:51 pm
Seg Ago 05, 2019 11:24 pm
Seg Ago 05, 2019 9:51 pm
Seg Ago 05, 2019 8:48 pm
Seg Ago 05, 2019 8:33 pm
Seg Ago 05, 2019 7:36 pm
Seg Ago 05, 2019 6:23 pm
Seg Ago 05, 2019 5:31 pm
Seg Ago 05, 2019 5:27 pm
Seg Ago 05, 2019 2:35 am
Seg Ago 05, 2019 2:27 am
Dom Ago 04, 2019 7:37 pm
Dom Ago 04, 2019 4:25 pm
Dom Ago 04, 2019 3:58 pm
Dom Ago 04, 2019 3:44 pm
Dom Ago 04, 2019 4:50 am
Dom Ago 04, 2019 4:39 am
Dom Ago 04, 2019 4:37 am
Sab Ago 03, 2019 9:43 pm
Sab Ago 03, 2019 9:13 pm
Sex Ago 02, 2019 8:47 pm
Sex Ago 02, 2019 11:55 am
Sex Ago 02, 2019 2:48 am
Sex Ago 02, 2019 2:41 am
Sex Ago 02, 2019 2:36 am
Qui Ago 01, 2019 11:00 pm
Qui Ago 01, 2019 10:50 pm
Qui Ago 01, 2019 10:47 pm
Qui Ago 01, 2019 8:23 pm
Qua Jul 31, 2019 11:00 pm
Qua Jul 31, 2019 10:58 pm
Qua Jul 31, 2019 10:19 pm
Ter Jul 30, 2019 10:58 pm
Ter Jul 30, 2019 9:19 am
MayLeone
clarckquente
MarcosSchultz
MarcosSchultz
artplayer
MarcosSchultz
MarcosSchultz
Jhonyzin
MayLeone
Callyde Jr
artplayer
MarcosSchultz
MayLeone
rafaelllsd
SteveRogers
lucaspoiob
Daniel Dória
nibirou
artplayer
Daniel Dória
nibirou
Daniel Dória
daniel123163
SergioDB
Projeto Residentes Evil
lucaspoiob
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
Dionilson
guimaraf
rafaelllsd
artplayer
Diguinho
Callyde Jr
MayLeone
lucaspoiob
Unidade3d5
MayLeone
MayLeone
dstaroski
RodriGO3477
SteveRogers
artplayer
dkrazor
Chilinger
numb123
Matrirxp
MarcosSchultz
Lonx SpellArtsStudio
MarcosSchultz
SteveRogers
ffabim
poyser
artplayer
artplayer
joffersoju
rafaelllsd
RodriGO3477
MarcosSchultz
Hamassfall
gtcmcsgo
MarcosSchultz
MarcosSchultz
MarcosSchultz
MarcosSchultz
iToddy
MayLeone
LardosJogos
artplayer
MarcosSchultz
MarcosSchultz
MarcosSchultz
dkrazor
abraao36
zZAndersonZz
speedluk
MarcosSchultz
MarcosSchultz
MarcosSchultz
Magnatah
Magnatah
Magnatah
iToddy
RodriGO3477
bugador
Evandro Mateus
dkrazor
LúcioHenrique098

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

Ir em baixo

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

Mensagem por MayLeone em 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 : 1130
REPUTAÇÃO : 297
Áreas de atuação : Unity & C#
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

Ver perfil do usuário http://compilemosfacil.blogspot.com.br

Voltar ao Topo Ir em baixo

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

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

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

Masculino PONTOS : 4331
REPUTAÇÃO : 1096
Idade : 30
Áreas de atuação : Desenvolvedor .NET Jr. ,Téc. Hardware e Redes, Programação C#, Asp .NET, HTML, CSS, Unity 3D

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

Ver perfil do usuário http://diegodeoliveira.gamejolt.io/defeattheilluminatis

Voltar ao Topo Ir em baixo

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

Mensagem por MarcosSchultz em 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 : 62217
REPUTAÇÃO : 2328
Idade : 22
Áreas de atuação : Administrador do fórum
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

Ver perfil do usuário http://www.schultzgames.com

Voltar ao Topo Ir em baixo

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

Mensagem por MayLeone em 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 : 1130
REPUTAÇÃO : 297
Áreas de atuação : Unity & C#
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças Aad8pUi

Ver perfil do usuário http://compilemosfacil.blogspot.com.br

Voltar ao Topo Ir em baixo

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

Mensagem por fabricadegame em 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 : 266
REPUTAÇÃO : 9
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças WvDYdlf

Ver perfil do usuário

Voltar ao Topo Ir em baixo

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

Mensagem por Diego Felix em 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 : 1305
REPUTAÇÃO : 83
Idade : 29
Áreas de atuação : Modelagem 3D, Roteirista.
Respeito as regras : [TUTORIAL] Desenvolvendo um jogo de quebra-cabeças WvDYdlf

Ver perfil do usuário https://www.blogger.com/blogger.g?blogID=2315682099830977662#ove

Voltar ao Topo Ir em baixo

Voltar ao Topo


 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum