Bookmark and Share

Svårighetsgrad
Svårighetsgrad
Betyg (9 röster)
BetygBetygBetygBetygBetyg
 

Kollisioner med pixlar

Inledning

Tidigare artiklar har tagit upp hur man detekterar kollisioner med hjälp av cirklar och rektanglar. Dessa metoder är relativt enkla och snabba men tyvärr inte så exakta. För perfekt kollisionsdetektering så får vi testa kollision på pixelnivå. För att göra metoden någorlunda effektiv så kombinerar vi kollision med rektanglar (eller cirklar) för att sedan gå vidare för att undersöka pixlarna.

bild

Bilderna ovan illustrerar problemet. I bilden till vänster hade indikerat en kollision om vi enbart använde oss av rektanglar. Bilden till höger visar ett exempel på riktigt en kollision. Vi vill veta om vi har en kollision då pixlar från båda föremålen överlappar varandra.

Dags att söka T4!


läs mer...

Ansökningen har börjat!
25 april till 15 maj!
ansök via skanegy.se

Är du intresserad av programmering, t.ex. spelutveckling, inbyggda system eller webbserverprogrammering?
Går du på Teknikprogrammet på gymnasiet och läser Programmering 1?
(eller har gått och är max 22 år)

Till höst startar jag ett nytt 4:e tekniskt år tillsammans med NTI i Lund för dig som vill bli Gymnasieingenjör. Målet är att du efter 4:e året kommer ut i arbete inom mjukvaruutveckling!

/MVH
Jonas Nilsson
skapare csharpskolan.se

Överlappande rektangel

Vi utgår från rektanglar för att avgöra om det kan tänkas ske en kollision. Så först beräknar vi den överlappande rektangeln (om det finns en sådan) med funktionen Intersection som beskrivs mer i artikeln "Kollision med rektanglar".

Om vi har en överlappande rektangel så måste denna ha en Width och en Height som båda är större än 0. Då vet vi att vi måste undersöka noggrannare.

Räkna ut pixelområden

Den överlappande rektanglen är ett område som delas av båda texturerna som kolliderar. Därför är det dessa texturer och pixlarna i dem som måste undersökas. Tittar vi bara på texturerna så har de ett eget koordinatsystem som börjar på (0,0) längst upp i vänstra hörnet. Rektangeln kollision (i exemplet ovan) har koordinater som stämmer överrens med skärmens koordinater. Första steget är att normalisera och räkna fram rektanglar som motsvarar områden i texturerna. Funktionen Normalize gör just detta.

Testa pixlarna!

När vi har två rektanglar som beskriver pixelområdet i de båda texturerna så kan vi fortsätta. Dessa områden är lika stora då de kommer från den överlappande rektangeln. Pixlarna kopieras ut som rådata med funktionen GetData och lägs i separata vektorer.

Därefter så loop'ar vi igenom vektorerna och jämför varje överlappande pixel. Villkoret är att det ska finnas en färg som inte är helt genomskinlig på samma plats i båda vektorerna för att det ska räknas som en träff!

Nu behövs det en kort introduktion till grafik. Det är kanske bekant att grafik byggs upp av RGB (röd, grön och blått) värden. Utöver detta så finns det också ett alpha värde som bestämmer hur genomskinlig färgen är. Effekten av alpha syns bästa när två föremål ritas ovanpå varandra. Ett konkret exempel är den röda rektangeln i bilden ovan. Den ritas ut med ett lågt alpha-värde för att indikera att den är aningen genomskinlig.

Allt som nämnts nu går att sätta ihop till en funktion som testar kollision, t.ex. TestCollision. Som inparametrar tar den två texturer och två rektanglar. Rektanglarna beskriver då vilka områden i respektive textur som ska jämföras. Funktionen returnerar då true om det är kollision, annars false.

Koden texture1Pixels[i] & 0xff000000 "klipper av" RGB informationen för pixeln så att bara alpha-värdet för varje pixel jämförs. Vidare läsning kring logiska operationer på bitnivå rekommenderas. Talet 0xff000000 är skrivet på hexadecimal form, därav 0x i början. Informationen är i följande ordning; alpha röd grön blå, där varje del är 8 bitar stor, dvs. två hexadecimala siffror. texture1Pixels[i] & 0xff000000 blir alltså att vi sparar alla alpha-information och klipper bort resten då den inte är intressant för oss.

DEMO

Allt finns såklart som en liten demonstration att ladda hem. För att illustrera grafiskt så har grafiken delats upp till följande för att kunna visa rektanglarna runt föremålen.

bild

bild

Bugg i XNA?

När denna artikel konstruerades så dök följande exception upp vid användning av GetData.

bild

Efter en del testande så framgick det att den textur som sist ritades ut i Draw kraschade då man i Update anropade GetData på samma textur. Bara genom att ändra ordningen i Draw fixade problemet. Dock kan det bli ett problem om det bara finns 2 texturer och båda ska användas i samband med GetData metoden. Tydligen så markeras inte den sist använda texturen som klar i uppritningen av XNA.

MYCKET märkligt men en varning till er andra om ni skulle råka ut för samma problem.

Viktiga begrepp

  • normalisera/eng. normalize
  • alpha

Kommentarer

8 inlägg