Técnicas Gráficas para Jogos • • • • • Eduardo Sampaio Rocha Pedro Henrique Macedo Börje Karlsson Geber Ramalho Vicente Vieira Filho 1 2 Representação da Cor nos Computadores Para cada pixel, um conjunto de bits é usado para representar a cor. Geralmente o sistema usado é o RGB. Pixel BBP 1 bit – 2 cores 8 bits – 256 cores (paleta) 16 bits – 65536 cores 24 bits – 16.7 milhões de cores 3 Paleta (8 bpp) Rápido Fácil de mudar as cores de toda a tela 12 5 29 250 Pixel values (0-255) 6 Índice Verme. Verde Azul 0 100 5 36 1 52 36 161 2 29 200 161 . . . 8 bits 6 255 0 255 100 100 . . . 100 100 8 bits 8 bits 8 bits 24 bits 4 16 bpp – High Color Alpha(transparência).5.5.5 A R4 R3 R2 R1 R0 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 X(don’t care).5.5.5 X R4 R3 R2 R1 R0 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 5.6.5 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 5 24/32 bpp 8.8.8 Vermelho Verde Azul R7-R0 G7-G0 B7-B0 Alpha (8).8.8.8 Alpha Vermelho Verde Azul A7-A0 R7-R0 G7-G0 B7-B0 Don’t care Vermelho Verde Azul xxxxxxxx R7-R0 G7-G0 B7-B0 X(8).8.8.8 6 Conceitos Básicos • Sprite • Tile e tilemap • Operações (blitting, flipping, clipping, blending, scrolling,...) 7 Imagem – Sprites & Background Sprite – imagem de tamanho arbitrário que é usado por agentes (se move na tela) ou por objetos fixos. Background – “Pano de Fundo” • Baseado em Cores • Baseado em textura • Tiles 8 Sprites - Animação 9 Sprites & Background Sprites 10 Sprites - Evolução Anos 80 ... Anos 90 ... Últimos 4 anos ... 11 Background - Textura 12 Background - Tiles Podem ser animados 13 TileMaps Uma estrutura contendo informações sobre como o mundo se parece, e sobre os objetos e agentes imersos no mundo. Ex: struct TILEMAPSQUARE { char BasicTerrain; //0=ocean;1=plains;2=forest; // 3=hills;4=mountains; uchar RoadFlags; //0=north;1=northeast; etc. uchar RiverFlags; //0=north;1=northeast; etc. UINT* Unit; } int iTileMap[WIDTH][HEIGHT]; 14 Tilemap 1 3 3 1 1 1 1 3 3 1 1 1 1 3 3 3 3 1 1 3 2 2 3 1 1 3 2 2 3 1 1 3 3 3 3 1 1 1 1 1 1 1 1 = pedra 2 = água 3 = pista Pode conter mais informação do que o tipo de tile • custo de atravessar, ... 15 Localização/movimentação de Sprites Sprites = objetos • coordenadas independentes do background • detecção de colisão entre objetos • problema: pode custar caro... Sprites amarrados ao mapa de tiles • movimentação • colisão testada no tilemap • problema: atualizar tilemap Híbrido: sprites = objetos e mundo = mapa de tiles • Mais usado • detecção de colisão entre objetos 16 Exibição via blitting Transferência de mapa de bits (blitting): operação de cópia (central!!) Da RAM (lenta e abundante) para VRAM (rápida e escassa) ou da VRAM para a própria VRAM 17 Page Flipping e double buffering Como é uma operação “cara” quando feita por software, utilizase page flipping Para evitar flickering, usa-se mais de um buffer (backbuffer ou double bufrer) 18 Raster Operations Ao transferir um bloco de bits, nós podemos : • Simplesmente jogar o bit de origem no destino • Compor o bit de origem com o já existente no destino usando as operações de AND, OR e XOR. 19 Transparência MÁSCARA FUNDO AND MÁSCARA F•AND•M XOR SPRITE 20 Transparência – Source Color Keying A idéia é usar uma cor que não é usada na figura e utilizá-la como “cor transparente”. if ( src != colorkey ) dst = src; else dst = background; 21 Blending alpha = sprite.alpha / MAX_ALPHA; beta = 1.0 - alpha; dst.red = (src.red * alpha) + (background.red * beta); dst.green = (src.green * alpha) + (background.green * beta); dst.blue = (src.blue * alpha) + (background.blue * beta); 22 Game Spaces Space • Um espaço bidimensional de tamanho e forma arbitrárias World Space (mundo) • Espaço composto de todos os objetos/sprites. View Space (janela visível) • Espaço geralmente do mesmo tamanho do screen space, mas com coordenada do ponto esquerdo superior igual a (0,0) Screen Space • Espaço na tela usado para renderizar a área do jogo (não inclui bordas, status panels, barra de menu, etc.) • coordenadas em relação à tela (haverá ajustes!) 23 Game Spaces (cont.) 24 Âncora Uma correlação entre um ponto de um espaço (geralmente (0,0)) e um outro espaço. Âncora (16,15) Screen Space View Space 25 Âncora Também usada para colocar um Sprite em um tile 26 Clipping O que cai fora da janela visível é cortado 27 Scrolling - Tiles Geralmente baseado na entrada do usuário. Deslocamento do view space em relação ao world space 28 Scrolling - Textura Fundo repetidamente desenhado. • janela com velocidade fixa • ou baseado na entrada do usuário 29 Scrolling A partir de quando fazer o scroll? • Centrado na “unidade” que está sendo controlada no momento -> região central • Janela visível De quanto faz o scroll? • O suficiente para recolocar “unidade”em área visível (ou região central) • Tela visivel inteira 30 Tilesets 31 Tilesets Um conjunto de tiles. Como é ineficiente colocar um tile em cada arquivo, nós simplesmente agrupamos um conjunto lógico de tiles e colocamos no mesmo arquivo gráfico. 32 Trabalhando com Tilesets Para trabalharmos com tilesets, nós precisamos disponibilizar mais algumas informações além da gráfica contida no arquivo. Por exemplo, o tamanho de cada tile. Estas informações podem ser obtidas: • Colocando-as junto com o código (hardcoded) • Disponibilizando um arquivo texto para cada tileset. • Colocando-as dentro do arquivo gráfico 33 Criando um Template para os Tilesets Para colocar informações no arquivo gráfico, vamos criar um padrão. A idéia é utilizar um frame para cada tile, e neste frame colocar as informações necessárias embutidas em cada pixel Algumas informações: • Comprimento e largura • Quina de cada tile cor de transparência • Âncora de cada tile 34 Template para Tilesets Informações Parâmetros 35 Informações Transparência e Quina Moldura Âncora Tamanho da Figura Âncora Interna Parâmetros Largura (Verde) Altura (Verde) Âncora Mais Tilesets 38 Gerenciando a Transição de Tiles Como tornar a transição entre os tiles mais suave? 39 Transição de Tiles – Solução 1 Criar tiles de transição entre os vários tipos. Criando 8 pontos de transição entre 2 tipos diferentes (ex. agua e terra), seriam necessários 28=256 tiles. Tendo 8 tipos de tiles, seriam 7x8x256 = 14336 tiles. Impossível !!!!!!!! 40 Transição de Tiles – Solução 2 Criar uma precedência, ou seja, quando dois tipos se encontram, o que tiver maior precedência, sobrepõe o outro. • Exemplo: selva, floresta, montanha, morro, mangue, deserto, campo e água Isto garante que podemos fazer um template para cada tipo e depois podemos compor usando a transparência do bitblt. 41 Transição de Tiles - Solução 2 Dividir os pontos de transição em 2 grupos: aresta e quina. Isto leva a 32 tiles: 42 Transição de Tiles - Solução 2 No total seriam 32 * (8-1) = 224 tiles 43 Zoo tycoon sem blending Tiles: blending de terreno 44 Zoo tycoon com blending Tiles: blending de terreno 45 Motores 2D - Java J2DA! http://j2da.sourceforge.net/index.php GOLDEN T GAME ENGINE http://www.goldenstudios.or.id/products/GTGE/inde x.php Planetation http://www.scottshaver2000.com/template/templat e.php?page=planetation_main GAGE - Genuine Advantage Gaming Engine http://java.dnsalias.com/ 46 Jogos Isométricos 47 Projeções Axonométricas Não possuem “ponto de fuga” Linhas que são paralelas no espaço 3D continuam paralelas na figura 2D Objetos distantes tem o mesmo tamanho que objetos próximos 48 Projeções Isométricas e Jogos São projeções axonométricas onde os eixos x,y e z possuem a mesma métrica • se projetarmos um cubo, todas as arestas terão o mesmo tamanho. Os jogos isométricos geralmente são baseados em tiles para poder compô-los formando mapas • projeção isométrica 1:2 (razão altura:comprimento). 49 Construindo os Tiles 50 Construindo os Tiles (cont.) 51 Construtindo um Mapa de Tiles (cont.) 52 Construindo um mapa de Tiles Necessidade de transparência 53 Tiles Isométricos – Blitting Order 1. Tiles “da frente” devem ser plotados depois 2. Se uma pequena porção da tela tiver que ser atualizada, nós devemos plotar os tiles que mudaram e todos os respectivos vizinhos obedecendo a regra 1. 54 Desenhando um Sprite em um Tile Isométrico O Sprite pode ser desenhado na região em vermelho 55 Tilemaps Isométricos X Retangulares Mapas retangulares e isométricos geralmente possuem uma estrutura bidimensional associada que guarda informações de cada tile – Tilemap. Nos mapas retangulares, incrementar x no tilemap significa se mover para o leste na tela, e aumentar y significa se mover para o sul E nos mapas isométricos ???? 56 Problemas dos Mapas Isométricos Tile Plotting • Dado uma posição no Tilemap [x][y], como encontrar a coordenada no mundo (em que ponto da tela fica) ? Mouse mapping • Dado um ponto na tela (ou no mundo), qual a posição no Tilemap? Tile Walking • Como mover um objeto de um ponto do mundo para o outro? 57 Tipos de Mapas Isométricos Slide Staggered Diamond 58 Slide Maps Fácil de • Plotar • Navegar • Interagir Ocupa muito espaço em tela Usado em scrolled action games • Zaxxon (1982) 59 Slide Maps – Sistema de Coordenadas X 0 Y 0 1 2 3 4 1 2 (0,0) (1,0) (0,1) 3 (2,0) (1,1) (0,2) (3,0) (2,1) (1,2) (0,3) (3,1) (2,2) (1,3) (0,4) (3,2) (2,3) (1,4) (3,3) (2,4) (3,4) X Y 60 Slide Maps - Tile Plotting Dada uma posição no tilemap, qual o pixel equivalente? (0,0) (1,0) (0,1) (1,1) Valor do Pixel Aumento de 1 em MapX Aumento de 1 em MapY Equação PixelX +TileWidth +Tilewidth/2 MapX*TileWidth + MapY*TileWidth/2 PixelY 0 +TileHeight/2 MapY*TileHeight/2 61 Slide Maps - Tile Plotting POINT SlideMap_TilePlotter( POINT ptMap, int iTileWidth, int iTileHeight) { POINT ptReturn; ptReturn.x = ptMap.x*iTileWidth + ptMap.y*iTileWidth/2; ptReturn.y = ptMap.y+iTileHeight/2; return (ptReturn); } 62 Slide Maps – Tile Walking Como mover de um objeto de um ponto do mundo para o outro? Direções Possíveis: N NO NE O L SE SO S 63 Slide Maps – Tile Walking X (0,0) (1,0) (0,1) (2,0) (1,1) (0,2) (2,1) (1,2) (0,3) Y (3,0) (3,1) (2,2) (1,3) (0,4) (3,2) (2,3) (1,4) (3,3) (2,4) Direção Variação no X (Tilemap) Variação no y (Tilemap) Leste +1 0 Sudeste 0 +1 Oeste -1 0 Noroeste 0 -1 (3,4) 64 Slide Maps – Tile Walking Norte e Sul X = 1(leste) + 0(noroeste) + 0(noroeste) y = 0(leste) - 1(noroeste) - 1(noroeste) X = -1(oeste) + 0(sudeste) + 0(sudeste) y = 0(oeste) - 1(sudeste) - 1(sudeste) 65 Slide Maps – Tile Walking Nordeste/Sudoeste X = 1(leste) + 0(noroeste) y = 0(leste) - 1(noroeste) X = -1(oeste) + 0(sudeste) y = 0(oeste) - 1(sudeste) 66 Slide Maps – Tile Walking Direção Variação no X (Tilemap) Variação no y (Tilemap) Leste +1 0 Sudeste 0 +1 Oeste -1 0 Noroeste 0 -1 Norte +1 -2 Sul -1 +2 Nordeste +1 -1 Sudoeste -1 +1 67 Slide Maps – Código POINT SlideMap_Tilewalker(POINT ptStart, IsoDirection dir) { switch (dir){ case ISO_NORTH: ptStart.x++; ptStart.y-=2; case ISO_NORTHEAST: ptStart.x++; ptStart.y--; case ISO_EAST: ptStart.x++; case ISO_SOUTHEAST: ptStart.y++; case ISO_SOUTH: ptStart.x--; ptStart.y+=2; case ISO_SOUTHWEST: ptStart.x--; ptStart.y++; case ISO_WEST: ptStart.x--; case ISO_NORTWEST: ptStart.y--; } return(ptStart); } 68 Slide Maps – Mouse mapping Dado um ponto na tela (ou no mundo), qual a posição no Tilemap? Como fazer esta conversão de forma rápida e eficiente ?? Subdividindo o mundo em Retângulos ! 69 Slide Maps – Mousemapping Sabendo em que ponto do retângulo o mouse foi clicado, basta obter a cor do pixel do ponto equivalente no template acima para obter o tile. 70 Slide Maps – Mousemapping Ou fazendo uma lookup table: 0000002222111111 0000222222221111 0022222222222200 2222222222222222 3322222222222244 3333222222224444 3333332222444444 71 Staggered Maps Muito usado em jogos de estratégia • Civilization II e III • Alpha Centauri • Pharao 72 Staggered Maps – Sistema de Coordenadas X 0 Y 0 1 2 3 1 (0,0) 2 (1,0) (0,1) (2,0) (1,1) (1,2) (0,2) (0,3) 3 (3,0) (2,1) (2,2) (1,3) (3,1) (3,2) (2,3) (3,3) X Y 73 Staggered Maps – Tileplotting (0,0) (1,0) (0,1) (2,0) (1,1) (1,2) (0,2) (0,3) (3,0) (2,1) (2,2) (1,3) (3,1) (3,2) (2,3) (3,3) Valor do Pixel Aumento de 1 em MapX Aumento de 1 em MapY Equação PixelX +TileWidth Se MapY é par, TileWidth/2 Se ímpar, - TileWidth/2 MapX*TileWidth + (MapY&1)*TileWidth /2 PixelY 0 +TileHeight/2 MapY*TileHeight/2 74 Staggered Maps – Tileplotting POINT StaggedMap_TilePlotter( POINT ptMap, int iTileWidth, int iTileHeight) { POINT ptReturn; ptReturn.x = ptMap.x*iTileWidth + (ptMap.y&1)*iTileWidth/2; ptReturn.y = ptMap.y+iTileHeight/2; return (ptReturn); } 75 Staggered Maps – Tilewalking (0,0) X (1,0) (0,1) (1,1) (1,2) (0,2) Y (2,0) (0,3) (3,0) (2,1) (2,2) (1,3) (3,1) (3,2) (2,3) Direção Y Par/Ímpar Mudança em X Mudança em Y Leste - 1 0 Oeste - -1 0 Sudeste Par 0 1 Sudoeste Ímpar 0 1 (3,3) 76 Staggered Maps – Tilewalking Y ímpar - Noroeste Y par - Sudeste (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y ímpar - Noroeste Se de um Y par para irmos para sudeste basta incrementar x de 0 e y de 1 (o que nos deixa em Y ímpar), então de Y ímpar para irmos para noroeste basta mover x de 0 y de -1 77 Staggered Maps – Tilewalking Y par - Nordeste Y ímpar - Sudoeste (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y par - Nodeste Se de um Y ímpar para irmos para sudoeste basta incrementar x de 0 e y de 1 (o que nos deixa em Y par), então de Y par para irmos para nordeste basta mover x de 0 y de -1 78 Staggered Maps – Tilewalking Direção +/-x (y par) +/-y (y par) +/-x (y ímpar) +/-y (y ímpar) Norte ??? ??? ??? ??? Nordeste 0 -1 ??? ??? Leste 1 0 1 0 Sudeste 0 1 ??? ??? Sul ??? ??? ??? ??? Sudoeste ??? ??? 0 1 Oeste -1 0 -1 0 Noroeste ??? ??? 0 -1 79 Staggered Maps – Tilewalking Y Par – Noroeste/Sudoeste X = 0(nordeste) –1(oeste) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) Y = -1(nordeste) +0(oeste) (1,5) X = 0(sudeste) –1(oeste) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y = +1(sudeste) +0(oeste) 80 Staggered Maps – Tilewalking Y Par – Norte/Sul X = 0(nordeste) –0(noroeste-ímpar) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) Y = -1(nordeste) -1(noroeste-ímpar) (1,5) X = 0(sudeste) –1(sudoeste-ímpar) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y = +1(sudeste) +1(sudoeste-ímpar) 81 Staggered Maps – Tilewalking Y Ímpar – Nordeste/Sudeste X = 0(noroeste) +1(leste) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) Y = -1(noroeste) +0(leste) (1,5) (1,1) (1,2) (0,3) X = 0(sudoeste) +1(leste) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y = +1(sudoeste) +0(leste) 82 Staggered Maps – Tilewalking Y Ímpar – Norte/Sul X = +1(nordeste) –1(noroeste-par) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) Y = -1(nordeste) -1(noroeste-par) (1,5) X = +1(sudeste) –1(sudoeste-par) (1,1) (1,2) (0,3) (2,2) (1,3) (1,4) (2,3) (2,4) (1,5) Y = +1(sudeste) +1(sudoeste-par) 83 Staggered Maps – Tilewalking Direção +/-x (y par) +/-y (y par) +/-x (y ímpar) +/-y (y ímpar) Norte 0 -2 0 -2 Nordeste 0 -1 1 -1 Leste 1 0 1 0 Sudeste 0 1 1 1 Sul 0 2 0 2 Sudoeste -1 1 0 1 Oeste -1 0 -1 0 Noroeste -1 -1 0 -1 84 Staggered Maps – Tilewalking Código POINT StaggeredMap_Tilewalker(POINT ptStart, IsoDirection dir) { switch (dir){ case ISO_NORTH: ptStart.y-=2; case ISO_NORTHEAST: ptStart.y--; ptStart.x +=(ptStart.y&1); case ISO_EAST: ptStart.x++; case ISO_SOUTHEAST: ptStart.y++; ptStart.x +=(ptStart.y&1); case ISO_SOUTH: ptStart.y+=2; case ISO_SOUTHWEST: ptStart.y++; ptStart.x+=(ptStart.y&1-1); case ISO_WEST: ptStart.x--; case ISO_NORTWEST: ptStart.y--; ptStart.x+=(ptStart.y&1-1); } return(ptStart); } 85 Staggered Maps Mapa sem “Dentes”/ Mapas Cilíndricos 86 Diamond Maps Muito usado em jogos de estratégia em tempo real: • Age of Empire • Sim City 2000/3000 • Roller Coaster Tycoon 87 Diamond Maps – Sistema de Coordenadas Y 7 y 5 6 4 3 2 1 0 0 1 X 2 3 4 5 6 7 x 88 Diamond Maps - Tileplotting (0,0) (0,1) (0,2) (1,0) (1,1) (2,0) (1,2) (2,1) (2,2) Valor do Pixel Aumento de 1 em MapX Aumento de 1 em MapY Equação PixelX TileWidth/2 -TileWidth/2 (MapX-MapY)*TileWidth/2 PixelY TileHeight/2 +TileHeight/2 (MapX+MapY)*TileHeight/2 89 Diamond Maps - Tileplotting POINT DiamondMap_TilePlotter( POINT ptMap, int iTileWidth, int iTileHeight) { POINT ptReturn; ptReturn.x=(ptMapX+ptMapY)*iTileWidth/2 ptReturn.y =(ptMapX+ptMapY)* iTileHeight/2; return (ptReturn); } 90 Diamond Maps - Tilewalking (0,0) (0,1) x y (0,2) (1,0) (1,1) (2,0) (1,2) (2,1) (2,2) Direção +/- X +- Y Sudeste 1 0 Sudoeste 0 1 Noroeste -1 0 Nordeste 0 -1 91 Diamond Maps – Tilewalking Norte/Sul (0,0) (0,1) (0,2) X = 0(nordeste) –1(noroeste) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) Y = -1(nordeste) +0(noroeste) (0,0) (0,1) (0,2) X = 1(sudeste) +0 (sudoeste) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) Y = 0(sudeste) +1(sudoeste) 92 Diamond Maps-Tilewalking Leste/Oeste (0,0) (0,1) (0,2) X = 1(sudeste) +0(nordeste) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) Y = 0(sudeste) -1(nordeste) (0,0) (0,1) (0,2) X = 0(sudoeste) +1 (noroeste) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2) Y = -1(sudoeste) +0(noroeste) 93 Diamond Maps – Tilewalking Direção +/- X +- Y Norte -1 -1 Nordeste 0 -1 Leste 1 -1 Sudeste 1 0 Sul 1 1 Sudoeste 0 1 Oeste -1 1 Noroeste -1 0 94 Diamond Maps – Tilewalking POINT StaggeredMap_Tilewalker(POINT ptStart, IsoDirection dir) { switch (dir){ case ISO_NORTH: ptStart.x--;ptStart.y--; case ISO_NORTHEAST: ptStart.y--; case ISO_EAST: ptStart.x++; ptStart.y--; case ISO_SOUTHEAST: ptStart.x++; case ISO_SOUTH: ptStart.x++;ptStart.y++ case ISO_SOUTHWEST: ptStart.y++; case ISO_WEST: ptStart.x--; ptStart.y++; case ISO_NORTWEST: ptStart.x--; } return(ptStart); } 95 Referências http://www.gamedev.net/reference/list.asp?categoryid=44 • Introduction To Isometric Engines; Smooth Scrolling a Tile Map; and Screen to Map Coordinates by Adams, J. • Axonometric Projections - A Technical Overview by Riemersma, T. • Isometric 'n' Hexagonal Maps Part I and Part II by Tanstaafl • Map file format by Gambone, D. • Tile Graphics Techniques 1.0 by McIntosh, J • Tile Based Games FAQ by Palmer, C. and Taylor, G. • Tile/Map-Based Game Techniques: Base Data Structures; and Tile/Map-Based Game Techniques: Handling Terrain Transitions Michael, D. • Tiling in DirectX: Part 1 and Part 2 Estevão, D. 96