Pravidla Ucet
Nepřihlášen

Článek

Menu

Zeď s více texturami (Tiles, GML)
Napsal: D-Sheep
Přidáno: 11.09. 2011

Chcete z objektů vytvořit zeď, která by používala jinou texturu k kloubech a spojeních? Zde je návod na optimalizaci vašich kódů a obrázků

Trochu lepší zdi

V mém dalším článku se vám pokusím popsat, jak se dá vyrobit hezky vypadající zeď z objektů s použitím více textur. Často vidím, že lidé používají pro zdi pouze jeden obrázek (nejčastěji cihlovou texturu, nebo prázdný čtverec)... Vždyť zdi mohou vypadat mnohem lépe! V každém kloubu a propojení může být jiný obrázek, na okrajích třeba jiná barva a to dělá dojem krásně celistvé zdi.

Pro plnou funkčnost budeme potřebovat vytvořit jedno od každého: sprite, objekt, pozadí a skript.

Sprite

Vytvoříme sprite s názvem spr_wall a takovou velikostí, jako každý kus zdi (nejčastěji čtverec 32×32, nebo 16×16). Origin necháme na (0, 0). Jeho účel je zajistit snadné vkládání do místností, ale hlavně obstarání collision masky.

Objekt

Tento objekt budeme vkládat do místnosi pro každý segment zdi, pojmenujeme ho obj_wall. Jako sprite zvolíme spr_wall, vlastnost Visible odškrtneme - nechceme, aby se zobrazoval.

Pozadí

Pozadí pojmenujeme back_wall, uděláme ho čtyřikrát větší, než sprite spr_wall. Zaškrtneme možnost Use as tile set, tile width a tile height nastavíme stejnou jako velikost spritu. Nyní na pozadí musíme určitým systémem nakreslit obrázek pro každý úsek zdi. Zde je schéma:

V každém čtverci je napsáno, kde objekt sousedí s další zdí (vlevo, vpravo, nahoře, dole) a tam by měl být příslušný obrázek pro danou situaci. Nula znamená, že objekt nemá žádné sousedy.

Skript

Nazveme ho třeba RefreshWalls a vložíme do něj následující kód:

with obj_wall
{
  var l, p, n, d, w, h, t, b;
  l = 0;
  p = 0;
  n = 0;
  d = 0;
  w = sprite_width;
  h = sprite_height;
  t = tile_layer_find(depth, x, y);
  b = back_wall;
  if tile_exists(t)
   tile_delete(t);
  if place_meeting(x - w, y, obj_wall)
   l = 1; //Má souseda vlevo
  if place_meeting(x + w, y, obj_wall)
   p = 10; //Má souseda vpravo
  if place_meeting(x, y - h, obj_wall)
   n = 100; //Má souseda nahoÅ™e
  if place_meeting(x, y + h, obj_wall)
   d = 1000; //Má souseda dole
  switch (l + p + n + d)
  {
   case 0: tile_add(b, 0, 0, w, h, x, y, depth); break; //0
   case 1: tile_add(b, w, 0, w, w, x, y, depth); break; //L
   case 10: tile_add(b, 2 * w, 0, w, h, x, y, depth); break; //P
   case 11: tile_add(b, 3 * w, 0, w, h, x, y, depth); break; //LP
   case 100: tile_add(b, 0, h, w, h, x, y, depth); break; //N
   case 101: tile_add(b, w, h, w, h, x, y, depth); break; //LN
   case 110: tile_add(b, 2 * w, h, w, h, x, y, depth); break; //PN
   case 111: tile_add(b, 3 * w, h, w, h, x, y, depth); break; //LPN
   case 1000: tile_add(b, 0, 2 * h, w, h, x, y, depth); break; //D
   case 1001: tile_add(b, w, 2 * h, w, h, x, y, depth); break; //LD
   case 1010: tile_add(b, 2 * w, 2 * h, w, h, x, y, depth); break; //PD
   case 1011: tile_add(b, 3 * w, 2 * h, w, h, x, y, depth); break; //LPD
   case 1100: tile_add(b, 0, 3 * h, w, h, x, y, depth); break; //ND
   case 1101: tile_add(b, w, 3 * h, w, h, x, y, depth); break; //LND
   case 1110: tile_add(b, 2 * w, 3 * h, w, h, x, y, depth); break; //PND
   case 1111: tile_add(b, 3 * w, 3 * h, w, h, x, y, depth); break; //LPND
   default: break;
  }
}

Možná to vypadá šíleně a nesrozumitelně, ale princip je jednoduchý: Nad každým objektem obj_wall se vykresluje jedna tile. Ta se na pokyn smaže, zjistí se, kde jsou sousedící objekty a podle toho se vybere nová, vyhovující tile. Skript je plně automatický a měl by se použít vždy po přidávání a mazání zdí a na začátku každé místnosti. Použití je jednoduché: stačí do kódu napsat RefreshWalls().

Podrobný popis skriptu

Proměnnné l, p, n a d v sobě uchovávají informace o sousedících objektech - pokud je vlevo soused, zapíše se do proměnné l hodnota 1. Do každé další proměnné se zapisuje hodnota o jeden řád vyšší tzn. 10, 100 a 1000. Zjistil jsem, že je pak velmi jednoduché pracovat s každou kombinací těchto proměnných (jejich součtem). V cyklu switch můžete vidět, že tyto kombinace vypadají jako binární soustava. Díky tomuto způsobu zápisu hodnot se nemůže stát že by se omylem vykonal stejný příkaz pro jinou kombinaci. Postupujeme dále v kódu: proměnná t dostane přiřazenou id hodnotu tile, která se nachází přesně na místě daného objektu nebo kusu zdi, chcete-li. Tile se dalším příkazem smaže. 4 podmínky if dále zjistí, jestli je v každém směru nějaký další objekt. A nyní už jen switch pomocí součtu 4 proměnných zvolí příslušnou novou tile, která se pomocí celkem divných (ale fungujících) argumentů vyhledá na určeném pozadí. Doufám, že chápete :)

20.2.2013 - nová, kratší verze skriptu:
with obj_wall
{
  var s, w, h, t;
  w = sprite_width;
  h = sprite_height;
  s = place_meeting(x - w, y, obj_wall); //Má souseda vlevo
  s += place_meeting(x + w, y, obj_wall) << 1; //Má souseda vpravo
  s += place_meeting(x, y - h, obj_wall) << 2; //Má souseda nahoÅ™e
  s += place_meeting(x, y + h, obj_wall) << 3; //Má souseda dole
  t = tile_layer_find(depth, x, y);
  if tile_exists(t)
   tile_delete(t);
  tile_add(back_wall, (s mod 4) * w, (s div 4) * h, w, h, x, y, depth);
}

Klíčová slova: zdi zeď textury tiles D-Sheep
 

Komentáře:

Napsal: akxe
Přidáno: 06.10. 2011

S timhle sem delal třeba i koleje

Trvalý odkaz

Napsal: D-Sheep
Přidáno: 13.09. 2011

Hotovo :3

Trvalý odkaz

Napsal: DDL Blue
Přidáno: 12.09. 2011

Bezva, jen bych ještě bejt tebou víc vysvětlil jednotlivý části kódu ;).

Trvalý odkaz

Velkej Chytrák
Copyright (c) 2001-2010