| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958 |
- <html xmlns:MSHelp="http://msdn.microsoft.com/mshelp" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xanx="http://schemas.microsoft.com/developer/xanx/2005"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="save" content="history" /><title>2D Collision Tutorial 2: Per-Pixel</title>
- <style><!--
- /***********************************************************
- * SCRIPT-SUPPORTING STYLES
- ***********************************************************/
- /* Defines the userData cache persistence mechanism. */
- .userDataStyle
- {
- behavior: url(#default#userData);
- }
- /* Used to save the scroll bar position when navigating away from a page. */
- div.saveHistory
- {
- behavior: url(#default#saveHistory);
- }
- /* Formats the expand/collapse images for all collapsible regions. */
- img.toggle
- {
- border: 0;
- margin-right: 5;
- }
- /* Formats the Language filter drop-down image. */
- img#languageFilterImage
- {
- border: 0;
- margin-left: 0;
- vertical-align: middle;
- }
- /* Formats the Members Options filter drop-down image. */
- img#membersOptionsFilterImage
- {
- border: 0;
- margin-left: 0;
- vertical-align: middle;
- }
- /* Formats the Collapse All/Expand All images. */
- img#toggleAllImage
- {
- margin-left: 0;
- vertical-align: middle;
- }
- /* Supports XLinks */
- MSHelp\:link
- {
- text-decoration: underline;
- color: #0000ff;
- hoverColor: #3366ff;
- filterString: ;
- }
- body
- {
- background: #FFFFFF;
- color: #000000;
- font-family: Verdana;
- font-size: medium;
- font-style: normal;
- font-weight: normal;
- margin-top: 0;
- margin-bottom: 0;
- margin-left: 0;
- margin-right: 0;
- width: 100%;
- /*font-size: 110%;*/
- }
- div.section
- {
- margin-left: 15px;
- }
- div.hxnx5
- {
- margin-left: 1.5em;
- }
- /* Font for all headings */
- h1, h2, h3, h4, h5, h6
- {
- font-family: Verdana, Arial, Helvetica, sans-serif;
- margin-top: 18;
- margin-bottom: 8;
- font-weight: bold;
- }
- h1
- {
- font-size: 130%;
- color: #003399;
- }
- div#scrollyes h1 /* Changes font size for full-scrolling topic */
- {
- font-size: 150%;
- }
- h2
- {
- font-size: 122%;
- }
- h3
- {
- font-size: 115%;
- margin-top: 9;
- margin-bottom: 4;
- }
- h4
- {
- font-size: 115%;
- margin-top: 9;
- margin-bottom: 4;
- }
- h5
- {
- font-size: 100%;
- margin-top: 9;
- margin-bottom: 4;
- }
- h6
- {
- font-size: 100%;
- margin-top: 9;
- margin-bottom: 4;
- }
- ul p, ol p, dl p
- {
- margin-left: 0em;
- }
- p
- {
- margin-top: .6em;
- margin-bottom: .6em;
- }
-
- td p
- {
- margin-top: 0.0em;
- margin-bottom: 0.6em;
- }
- dd p
- {
- margin-top: 0.0em;
- margin-bottom: 0.6em;
- }
- .image
- {
- text-align: center;
- }
- dl
- {
- margin-top: 0em;
- margin-bottom: 1.3em;
- }
- dd
- {
- margin-bottom: 0em;
- margin-left: 1.5em;
- }
- dl.glossary dd
- {
- margin-bottom: 0em;
- margin-left: 1.5em;
- }
- dt
- {
- margin-top: .6em;
- margin-bottom: 1;
- }
- ul, ol
- {
- margin-top: 0.6em;
- margin-bottom: 0.6em;
- }
-
- ol
- {
- margin-left: 2.5em;
- }
-
- ul
- {
- list-style-type: disc;
- margin-left: 1.9em;
- }
- li
- {
- margin-bottom: 0.4em;
- }
- ul ol, ol ol
- {
- list-style-type: lower-alpha;
- }
- pre
- {
- margin-top: .6em;
- margin-bottom: .6em;
- font: 105% Lucida, mono;
- color: #000066;
- }
- code
- {
- font-family: Monospace, Courier New, Courier;
- font-size: 105%;
- color: #000066;
- }
- table.userdata td
- {
- background: #ffffff;
- background-color: #F5F5F5;
- border-color: #ffffff;
- border: none;
- }
- table.clsWarning
- {
- background: #ffffff;
- padding: 0px;
- margin: 0px;
- border: none;
- }
- table.clsWarning td
- {
- padding: 0px;
- margin: 0px;
- background: #ffffff;
- vertical-align: middle;
- font-size: 70%;
- }
- div#mainSection table
- {
- width: 95%;
- background: #ffffff;
- margin-top: 5px;
- margin-bottom: 5px;
- }
- div#mainSection table th
- {
- padding: 5px 6px;
- background: #EFEFF7;
- text-align: left;
- font-size: 70%;
- vertical-align: bottom;
- border-bottom: 1px solid #C8CDDE;
- }
- div#mainSection table td
- {
- padding: 5px 5px;
- background: #F7F7FF;
- vertical-align: top;
- font-size: 70%;
- border-bottom: 1px solid #D5D5D3;
- }
- div#syntaxCodeBlocks table th
- {
- padding: 1px 6px;
- color: #000066;
- }
- div#syntaxCodeBlocks table td
- {
- padding: 1px 5px;
- }
- /* Applies to the running header text in the first row of the upper table in the
- non-scrolling header region. */
- span#runningHeaderText
- {
- color: #003399;
- font-size: 90%;
- padding-left: 13;
- }
- /* Applies to the topic title in the second row of the upper table in the
- non-scrolling header region. */
- span#nsrTitle
- {
- color: #003399;
- font-size: 120%;
- font-weight: 600;
- padding-left: 13;
- }
- /* Applies to everything below the non-scrolling header region. */
- div#mainSection
- {
- font-size: 70%;
- width: 100%;
- }
- /* Applies to everything below the non-scrolling header region, minus the footer. */
- div#mainBody
- {
- font-size: 90%;
- margin-left: 15;
- margin-top: 10;
- padding-bottom: 20;
- }
- /* Adds right padding for all blocks in mainBody */
- div#mainBody p, div#mainBody ol, div#mainBody ul, div#mainBody dl
- {
- padding-right: 5;
- }
- div#mainBody div.alert, div#mainBody div.code, div#mainBody div.tableSection
- {
- width:98.9%;
- }
- div.alert p, div.code p
- {
- margin-top:5;
- margin-bottom:8;
- }
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- div#mainSection div.alert table
- {
- border: 0;
- }
- div#mainSection div.alert table th
- {
- padding-top: 0;
- padding-bottom: 0;
- padding-left: 5;
- padding-right: 5;
- }
- div#mainSection div.alert table td
- {
- padding-left: 5;
- padding-right: 5;
- }
- img.note
- {
- border: 0;
- margin-left: 0;
- margin-right: 3;
- }
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - End Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Non-scrolling Header Region Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
- /* Applies to the entire non-scrolling header region. */
- div#header
- {
- background-color: #D4DFFF;
- padding-top: 0;
- padding-bottom: 0;
- padding-left: 0;
- padding-right: 0;
- width: 100%;
- }
- /* Applies to both tables in the non-scrolling header region. */
- div#header table
- {
- margin-top: 0;
- margin-bottom: 0;
- border-bottom-color: #C8CDDE;
- border-bottom-style: solid;
- border-bottom-width: 1;
- background: #D4DFFF;
- width: 100%;
- }
- /* Applies to cells in both tables in the non-scrolling header region. */
- div#header table td
- {
- color: #0000FF;
- font-size: 70%;
- padding-right: 20;
- padding-top: 1;
- padding-bottom: 1;
- border: none;
- background: #D4DFFF;
- }
- /* Applies to the last row in the upper table of the non-scrolling header region. Text
- in this row includes See Also, Constructors, Methods, and Properties. */
- div#header table tr#headerTableRow3 td
- {
- padding-bottom: 2;
- padding-top: 5;
- padding-left: 15;
- }
- /* Applies to the lower table in the non-scrolling header region. Text in this table
- includes Collapse All/Expand All, Language Filter, and Members Options. */
- div#header table#bottomTable
- {
- border-top-color: #FFFFFF;
- border-top-style: solid;
- border-top-width: 1;
- text-align: left;
- padding-left: 15;
- }
- blockquote
- {
- margin-left: 3.8em;
- margin-right: 3.8em;
- margin-top: .6em;
- margin-bottom: .6em;
- }
- sup
- {
- text-decoration: none;
- font-size: smaller;
- }
- a:link
- {
- color: #0000FF;
- /* font-weight: bold */
- }
-
- a:visited
- {
- color: #0000AA;
- /* font-weight: bold */
- }
-
- a:hover
- {
- color: #3366FF;
- /* font-weight: bold */
- }
-
- .label
- {
- font-weight: bold;
- margin-top: 1em;
- margin-left: -26px;
- }
-
- .tl
- {
- margin-bottom: .75em;
- }
-
- .atl
- {
- padding-left: 1.5em;
- padding-bottom: .75em;
- }
-
- .cfe
- {
- font-weight: bold;
- }
-
- .mini
- {
- font-size: smaller;
- }
-
- .dt
- {
- margin-bottom: -.6em;
- }
-
- .indent
- {
- margin-left: 1.9em;
- margin-right: 1.9em;
- }
- .product
- {
- text-align: right;
- color: #333333;
- font-size: smaller;
- font-style: italic;
- }
- .buttonbarshade
- {
- position: relative;
- margin: 0;
- left: 0px;
- top: 2;
- width: 50%;
- height: 40px;
- }
- .buttonbartable
- {
- position: absolute;
- margin: 0;
- padding:0;
- border:0;
- left:0px;
- top: 2;
- width: 100%;
- height: 40px;
- }
- /* background color, font for header */
- table.buttonbartable td, table.buttonbarshade td
- {
- background: #ffffff; /*#5177B8; #80C615;*/
- border-left: 0px solid #80C615;
- margin: 0;
- padding: 0px 0px 0px 0px;
- font-family: Impact, sans-serif;
- font-size: 14pt;
- }
- table.buttonbartable td.button1
- {
- background: #5177B8; /*#80C615;*/;
- padding: 0;
- font-weight: bold;
- text-align: center;
- cursor: hand;
- }
- table.buttonbartable td.button2
- {
- background: #5177B8; /*#80C615;*/;
- font-weight: bold;
- text-align: center;
- }
- table.buttonbartable td.button3
- {
- background: #5177B8; /*#80C615;*/;
- font-weight: bold;
- text-align: center;
- }
- table.buttonbartable td.runninghead
- {
- padding-left: 0px;
- font-style: italic;
- text-align: left;
- }
- .version
- {
- text-align: left;
- color: #000000;
- margin-top: 3em;
- margin-left: -26px;
- font-size: smaller;
- font-style: italic;
- }
- .lang, .ilang
- {
- color: #0000ff;
- font: normal 7pt Arial, Helvetica, sans-serif;
- }
- div.langMenu
- {
- position: absolute;
- z-index: 1;
- width: 96pt;
- padding: 8pt;
- visibility: hidden;
- border: 1px solid #000000;
- background: #ffffd0;
- }
- div.langMenu ul
- {
- padding-left: 2em;
- margin-left: 0;
- }
- div.filtered
- {
- margin: 4pt 0 8pt -26px;
- padding: 4px 4px 8px 26px;
- width: 100%;
- border: 2px solid #aaaacc;
- background: #ffffff;
- }
- div.filtered2
- {
- margin: 4pt 0 8pt -26px;
- padding: 4px 4px 8px 26px;
- width: 100%;
- border: none;
- background: #ffffff;
- }
- div.filtered h1, div.filtered h2, div.filtered h3, div.filtered h4
- {
- margin-left: -22px;
- }
- div.filtered span.lang
- {
- position: relative;
- left: -22px;
- }
- div.reftip
- {
- position: absolute;
- z-index: 1;
- padding: 8pt;
- visibility: hidden;
- border: 1px solid #000000;
- background: #ffffd0;
- }
- a.synParam
- {
- color: #0000FF;
- /*color: #3F7800;*/
- /*color: #8DC54F;*/
- text-decoration: none;
- font-weight: normal;
- }
- a.synParam:hover
- {
- text-decoration: underline;
- font-weight: normal;
- }
- div.sapop
- {
- position: absolute;
- z-index: 1;
- left: 26px;
- width: 100%;
- padding: 10px 10px 10px 36px;
- visibility: hidden;
- border: 1px solid #000000;
- background: #ffffd0;
- }
- div.footer
- {
- width: 100%;
- border: none;
- background: #ffffff;
- margin-top: 18pt;
- padding-bottom: 12pt;
- color: #0000FF;
- /*color: #228B22; */
- text-align: center;
- font-size: 76%;
- }
- div.preliminary
- {
- margin-top: 8pt;
- padding-bottom: 12pt;
- color: #A0A0A0;
- }
- /* A procedure section. eg. 'To create a file', 'To add a value' */
- div.proc
- {
- margin-left: 0.5em;
- }
-
- /* The title of a 'procedure' section. */
- div.proc h3
- {
- font-family: Verdana, Arial, Helvetica, sans-serif;
- font-weight: bold;
- font-size: 115%;
- margin-top: 1em;
- margin-bottom: 0.4em;
- margin-left: -0.5em;
- color: #003399;
- }
- div.proc ul
- {
- margin-left: 1.5em;
- }
- div.proc ol
- {
- margin-left: 2.0em;
- }
-
- .note
- {
- margin-left: 14pt;
- margin-right: 12pt;
- }
- .indent1
- {
- margin-left: 12pt;
- }
- .indent2
- {
- margin-left: 24pt;
- }
- .indent3
- {
- margin-left: 36pt;
- }
- p.proch
- {
- padding-left: 16px;
- }
- p.proch img
- {
- position: relative;
- vertical-align: top;
- left: -18px;
- margin-right: -14px;
- margin-bottom: -18px;
- }
-
- div.clsPlatSpec
- {
- background-color:#FFF8DC;
- border-style:solid;
- border-width:1pt 0pt 0pt 1pt;
- border-color:#ffE4C4;
- margin-top:0.6em;
- width:100%;
- }
- /* Applies to the language labels in the Language Filter drop-down list. */
- .languageFilter
- {
- color: #0000FF;
- cursor:hand;
- text-decoration:underline;
- padding-bottom:4;
- }
- /* Dropdown areas */
- #languageSpan {
- position: absolute;
- visibility: hidden;
- border-style: solid;
- border-width: 1px;
- border-color: #C8CDDE;
- background: #d4dfff;
- padding: 4px;
- font-size: 70%;
- }
- #membersOptionsSpan {
- position: absolute;
- visibility: hidden;
- border-style: solid;
- border-width: 1px;
- border-color: #C8CDDE;
- background: #d4dfff;
- padding: 4px;
- font-size: 70%;
- }
- --></style>
- <xml>
- <MSHelp:TOCTitle Title="2D Collision Tutorial 2: Per-Pixel" />
- <MSHelp:RLTitle Title="2D Collision Tutorial 2: Per-Pixel" />
- <MSHelp:Keyword Index="A" Term="O:Microsoft.Xna.PerPixelCollision" />
- <MSHelp:Keyword Index="A" Term="d665c74c-f0ef-eb45-488a-16d71787cc4d" />
- <MSHelp:Keyword Index="K" Term="2D Collision Tutorial 2: Per-Pixel" />
- <MSHelp:Attr Name="AssetID" Value="d665c74c-f0ef-eb45-488a-16d71787cc4d" />
- <MSHelp:Attr Name="Locale" Value="en-us" />
- <MSHelp:Attr Name="CommunityContent" Value="1" />
- <MSHelp:Attr Name="TopicType" Value="kbOrient" />
- </xml>
- </head><body><div id="mainSection"><div id="mainBody">
-
- <h1>2D Collision Tutorial 2: Per-Pixel</h1>
-
- This article explains how to perform per-pixel collision detection.
- <div class="alert"><table cellspacing="0" cellpadding="0"><tr><th>Note </th></tr><tr><td>This tutorial builds on code you have written during the previous tutorial, 2D Collision Tutorial 1: Rectangle. Follow the steps in the previous tutorial before starting this one.</td></tr></table></div>
- <a id="ID2EM" name="ID2EM"> </a><h1 class="heading">Introduction</h1><div id="ID2EM" class="hxnx1">
-
- <p>In Tutorial 1 you created a simple object-avoidance game using rectangle collision detection. The rectangles used were only an approximation of the blocks and person drawn into the textures. You may have noticed the exclusive use of rectangles resulted in imprecise behavior for nonrectangular objects.</p>
- <p>
- The current behavior is a red background, which indicates that the block is colliding with the person. That is clearly not the case in this image; therefore, this behavior is undesirable. The sprite rectangles overlap, but the rectangular collision detection is not smart enough to realize that the shapes within these sprites, in fact, are not touching.</p>
- <img src="redblock.png" />
-
- <p>
- The desired behavior in this instance is a blue background. This indicates the block is colliding with the person.</p>
- <img src="blueblock.png" />
-
- <p>In order to achieve the desired behavior, the code must examine every overlapping pixel to determine if there is a collision. This is called per-pixel collision.</p>
- </div>
- <a id="ID2E6" name="ID2E6"> </a><h1 class="heading">Step 1: Get Texture Data</h1><div id="ID2E6" class="hxnx1">
-
- <p>Per-pixel collision requires examining individual pixels of a given texture. To access the individual pixels, you must call <b>Texture2D.GetData</b>. This method copies the pixels into an array you specify. The default texture processor will have pixel data of type <b>Color</b>.</p>
- <ol>
- <li>
- <p>
- Declare a <b>Color</b> array for each texture at the top of your game class.
- </p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>// The color data for the images; used for per-pixel collision
- Color[] personTextureData;
- Color[] blockTextureData; </pre></pre></td></tr></table></span></div></li>
- <li>
- <p>
- Use <b>Texture2D.GetData</b> to retrieve a copy of the pixel data from our textures. This must be done after the textures are loaded.
- </p>
- </li>
- <li>
- <p>Modify the <b>LoadContent</b> method by adding the lines of code in bold.</p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>
- // Load textures
- blockTexture = Content.Load<Texture2D>("Block");
- personTexture = Content.Load<Texture2D>("Person");
- <b>
- // Extract collision data
- blockTextureData =
- new Color[blockTexture.Width * blockTexture.Height];
- blockTexture.GetData(blockTextureData);
- personTextureData =
- new Color[personTexture.Width * personTexture.Height];
- personTexture.GetData(personTextureData);
- </b>
- </pre></pre></td></tr></table></span></div>
- <p>
- For both textures, you allocate a color array first. The color array is linear, which means that there is only one row of pixels that will contain all of the texture's rows attached end to end. Once the color array is allocated, <b>GetData</b> is called to fill the array with the pixels from the texture.
- </p>
- </li>
- </ol>
- </div>
-
- <a id="ID2EZC" name="ID2EZC"> </a><h1 class="heading">Step 2: Write Per-Pixel Collision Method</h1><div id="ID2EZC" class="hxnx1">
- <p>Now that you are equipped with all of the necessary data, you need to write a method to perform the per-pixel collision test. This method will accept a pair of sprite bounding rectangles and their necessary color data.</p>
- <ol>
- <li>
- <p>Add a method with the following signature to your code.</p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>static bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
- Rectangle rectangleB, Color[] dataB) </pre></pre></td></tr></table></span></div>
- <p>This method will have two key parts. First, it will identify the intersecting region of both rectangles. The intersection will be another rectangle or will not exist. Second, the method will iterate over every pixel in the intersection region and test for collision. If a collision is found, the method will terminate immediately with a return value of <b>true</b>. If after walking through each potentially colliding pixel, no collision is found, the method will return <b>false</b>.</p></li>
- <li><p>Add the following code to the beginning of the <b>IntersectPixels</b> method.</p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>// Find the bounds of the rectangle intersection
- int top = Math.Max(rectangleA.Top, rectangleB.Top);
- int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
- int left = Math.Max(rectangleA.Left, rectangleB.Left);
- int right = Math.Min(rectangleA.Right, rectangleB.Right); </pre></pre></td></tr></table></span></div>
- <p>These four variables represent the intersection rectangle of the two input rectangles. If no intersection exists, right minus left or bottom minus top, or both, will be negative. The nested <b>for</b> loops used in the following section automatically account for the non-intersecting bounding rectangles case.</p></li>
- <li><p>Append the following code to the end of the <b>IntersectPixels</b> method:</p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>// Check every point within the intersection bounds
- for (int y = top; y < bottom; y++)
- {
- for (int x = left; x < right; x++)
- {
- // Get the color of both pixels at this point
- Color colorA = dataA[(x - rectangleA.Left) +
- (y - rectangleA.Top) * rectangleA.Width];
- Color colorB = dataB[(x - rectangleB.Left) +
- (y - rectangleB.Top) * rectangleB.Width];
- // If both pixels are not completely transparent,
- if (colorA.A != 0 && colorB.A != 0)
- {
- // then an intersection has been found
- return true;
- }
- }
- }
- // No intersection found
- return false;</pre></pre></td></tr></table></span></div></li></ol>
- <p>The <b>for</b> loops iterate over the overlapping rectangle one pixel at a time in reading order (left to right, top to bottom). For each pixel coordinate in global space, the coordinate is converted into each rectangles local space by subtracting the upper-left corner of the rectangle. The local coordinate is made linear by multiplying the y-coordinate by the texture width. The linear coordinate is then indexed into the color data. Given both colors, an intersection occurs when both are not completely transparent (alpha of 0).</p>
- <div class="alert"><table cellspacing="0" cellpadding="0"><tr><th>Note </th></tr><tr><td>Recall from Tutorial 1 that the default texture processor performs color keying, which converts the magenta background to be zero alpha.</td></tr></table></div>
- </div>
-
- <a id="ID2ESE" name="ID2ESE"> </a><h1 class="heading">Step 3: Invoke the Per-pixel Collision Test</h1><div id="ID2ESE" class="hxnx1">
- <p>Now that you have a method to perform per-pixel collision, you need to invoke it in place of the existing rectangle collision test.</p>
- <ol>
- <li>
- <p>In your game's <b>Update</b> method, modify the block update loop to match the following code. The changed lines are bold.</p>
- <div class="code"><span codeLanguage=""><table><tr><th> </th></tr><tr><td><pre><pre>// Update each block
- personHit = false;
- for (int i = 0; i < blockPositions.Count; i++)
- {
- // Animate this block falling
- blockPositions[i] =
- new Vector2(blockPositions[i].X,
- blockPositions[i].Y + BlockFallSpeed);
- // Get the bounding rectangle of this block
- Rectangle blockRectangle =
- new Rectangle((int)blockPositions[i].X, (int)blockPositions[i].Y,
- blockTexture.Width, blockTexture.Height);
- <b>// Check collision with person
- if (IntersectPixels(personRectangle, personTextureData,
- blockRectangle, blockTextureData))
- {
- personHit = true;
- }</b>
- // Remove this block if it has fallen off the screen
- if (blockPositions[i].Y > Window.ClientBounds.Height)
- {
- blockPositions.RemoveAt(i);
- // When removing a block, the next block will have the same index
- // as the current block. Decrement i to prevent skipping a block.
- i--;
- }
- } </pre></pre></td></tr></table></span></div></li>
- <li>
- <p>That's it! Compile and run the game.</p>
- </li>
- </ol>
- </div>
-
- <a id="ID2EQF" name="ID2EQF"> </a><h1 class="heading">Congratulations!</h1><div id="ID2EQF" class="hxnx1">
- <p>You should now have working per-pixel collision detection.</p>
- <a id="ID2EVF" name="ID2EVF"> </a><h2 class="subHeading">Ideas to Expand</h2><div id="ID2EVF" class="hxnx2">
- <p>Haven't had enough per-pixel collisions? Try these ideas.</p>
- <ul>
- <li>Create several shapes and sizes of blocks, and then randomly pick a shape each time a block is spawned</li>
- <li>Add the ability to activate a round bubble shield</li>
- <li>Add falling items, which you need to collect to boost your score</li>
- </ul>
- </div>
- </div>
- </div><div class="footer" id="footer"><p>© 2010 Microsoft Corporation. All rights reserved.<br />Send feedback to <a href="mailto:[email protected]?subject=Documentation Feedback: 2D Collision Tutorial 2: Per-Pixel">[email protected]</a>.</p></div></div></body></html>
|