Component Design Recall: Problem with Subclassing

Component Design Recall: Problem with Subclassing

<p>the </p><p>gamedesigninitiative </p><p>at cornell university </p><p>Lecture 8 </p><p>Component Design </p><p><strong>Recall</strong>: Problem with Subclassing </p><p>—ꢀ Games have <em>lots </em>of classes </p><p>—ꢀ Each game entity is different </p><p>NPC </p><p>—ꢀ Needs its own functionality <br>(e.g. object methods) </p><p></p><ul style="display: flex;"><li style="flex:1">Human </li><li style="flex:1">Orc </li></ul><p></p><p>—ꢀ Want to avoid <strong>redundancies </strong></p><p>—ꢀ Makes code hard to change —ꢀ Common source of bugs </p><p>Human Warrior <br>Human Archer </p><ul style="display: flex;"><li style="flex:1">Orc </li><li style="flex:1">Orc </li></ul><p></p><ul style="display: flex;"><li style="flex:1">Archer </li><li style="flex:1">Warrior </li></ul><p></p><p>—ꢀ Might be tempted to <strong>subclass </strong></p><p>—ꢀ Common behavior in parents —ꢀ Specific behavior in children </p><p>Redundant Behavior </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>2</p><p>at cornell university </p><p><strong>Recall</strong>: Problem with Subclassing </p><p>—ꢀ Games have <em>lots </em>of classes </p><p>—ꢀ Each game entity is different </p><p>NPC </p><p>—ꢀ Needs its own functionality <br>(e.g. object methods) </p><p></p><ul style="display: flex;"><li style="flex:1">Warrior </li><li style="flex:1">Archer </li></ul><p></p><p>—ꢀ Want to avoid <strong>redundancies </strong></p><p>—ꢀ Makes code hard to change —ꢀ Common source of bugs </p><p>Human Warrior </p><ul style="display: flex;"><li style="flex:1">Orc </li><li style="flex:1">Human </li></ul><p>Archer <br>Orc </p><ul style="display: flex;"><li style="flex:1">Warrior </li><li style="flex:1">Archer </li></ul><p></p><p>—ꢀ Might be tempted to <strong>subclass </strong></p><p>—ꢀ Common behavior in parents —ꢀ Specific behavior in children </p><p>Redundant Behavior </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>3</p><p>at cornell university </p><p><strong>Alternative</strong>: Decorator Pattern </p><p>New <br>Functionality </p><p>Original Object </p><p>Reference to Original </p><p>base object <br>Functionality </p><p>Decorator <br>Object </p><p>Request </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>4</p><p>at cornell university </p><p><strong>Alternate</strong>: Delegation Pattern </p><p>Original Object </p><p>Reference to </p><p>Delegate </p><p>Request delegate </p><p>Object </p><p>Forward Request </p><p><em>Inversion </em>of the Decorator Pattern </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>5</p><p>at cornell university </p><p>Issues with Static Typing </p><p>Method in original class <br>Original </p><p>object class </p><p>obj.request(arg<sub style="top: 0.6667em;">1</sub>,…, arg<sub style="top: 0.6667em;">n</sub>)ꢀ </p><p>Original Object </p><p>Reference to delegate </p><p>Delegate <br>Object </p><p>Request <br>Forward Request </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>6</p><p>at cornell university </p><p>The Subclass Problem Revisited </p><p>Delegates? </p><p>NPC <br>Orc </p><p>Slot Slot Slot </p><p>Human </p><ul style="display: flex;"><li style="flex:1">Human </li><li style="flex:1">Orc </li></ul><p>NPC </p><p>Warrior </p><p>Archer <br>Human Warrior <br>Human Archer </p><ul style="display: flex;"><li style="flex:1">Orc </li><li style="flex:1">Orc </li></ul><p></p><ul style="display: flex;"><li style="flex:1">Archer </li><li style="flex:1">Warrior </li></ul><p></p><p>Redundant Behavior </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>7</p><p>at cornell university </p><p>Component-Based Programming </p><p>Delegates </p><p>—ꢀ <strong>Role</strong>: Set of capabilities </p><p>Role 1 </p><p>—ꢀ Class with very little data —ꢀ A collection of methods </p><p>Slot </p><p>Role 2 </p><p>—ꢀ Add it to object as <em>delegate </em></p><p>Slot </p><p>Entity </p><p>—ꢀ Object gains those methods </p><p>Role 3 Role 4 </p><p>Slot </p><p>—ꢀ Acts as a “function pointer” </p><p>—ꢀ <em>Can-it</em>: search object roles </p><p>—ꢀ Check class of each role —ꢀ Better than duck typing —ꢀ Possible at compile time? </p><p>Field storing a single delegate or </p><p>a <strong>set of delegates </strong></p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>8</p><p>at cornell university </p><p>Aside: Objective-C </p><p>—ꢀDelegates are emphasized in <strong>Objective-C </strong></p><p>—ꢀ ObjC <em>protocols </em>function like Java interfaces —ꢀ But implement with a delegate, not a subclass </p><p>—ꢀOften leverages <strong>message passing </strong></p><p>—ꢀ Method call is considered a message —ꢀ Can call <em>any </em>method on <em>any </em>object —ꢀ Will get runtime error if method not supported —ꢀ Heavily optimized in latest Apple compilers </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>9</p><p>at cornell university </p><p>Aside: Objective-C </p><p>—ꢀDelegates are emphasized in <strong>Objective-C </strong></p><p>—ꢀ ObjC <em>protocols </em>function like Java interfaces —ꢀ But implement with a delegate, not a subclass </p><p>—ꢀOften leverages <strong>message passing </strong></p><p>—ꢀ Method call is considered a message —ꢀ Can call <em>any </em>method on <em>any </em>object —ꢀ Will get runtime error if method not supported —ꢀ Heavily optimized in latest Apple compilers </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>10 </p><p>at cornell university </p><p>Working With Static Typing </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Uniform Method </strong></li><li style="flex:1"><strong>Direct Access </strong></li></ul><p></p><p>ꢀ</p><p>if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ </p><p>extract role from oꢀ role.doSomething(info)ꢀ </p><p>}ꢀ </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>11 </p><p>at cornell university </p><p>Working With Static Typing </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Uniform Method </strong></li><li style="flex:1"><strong>Direct Access </strong></li></ul><p></p><p>ꢀ</p><p>if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ </p><p>extract role from oꢀ role.doSomething(info)ꢀ </p><p>}ꢀ </p><p><strong>Problem</strong>: </p><p>Multiple capabilities </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>12 </p><p>at cornell university </p><p>Working With Static Typing </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Uniform Method </strong></li><li style="flex:1"><strong>Direct Access </strong></li></ul><p></p><p>ꢀ</p><p>if (o has role) {ꢀ o.doSomething(kitchenSink)ꢀ </p><p>extract role from oꢀ role.doSomething(info)ꢀ </p><p>}ꢀ </p><p><strong>Problem</strong>: </p><p><strong>Problem</strong>: </p><p>Big switch statements <br>Multiple capabilities </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>13 </p><p>at cornell university </p><p>Entities Need Both Is-a and Can-it ꢀ </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Table </strong></li><li style="flex:1"><strong>Chair </strong></li></ul><p></p><p>Objects share same capabilities <em>in theory</em>. But certain actions are <strong>preferred </strong>on each. </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>14 </p><p>at cornell university </p><p>Solving the Problem </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Can-It </strong></li><li style="flex:1"><strong>Is-A </strong></li></ul><p></p><p>—ꢀ Indicated by object <strong>roles </strong></p><p>—ꢀ Component indicates role —ꢀ Check type of each role —ꢀ So again a typing solution </p><p>—ꢀ Indicated by object <strong>class </strong></p><p>—ꢀ But could do more than that </p><p>—ꢀ Keep a bag of types </p><p>—ꢀ Contains of the descriptions that apply to this object </p><p>—ꢀ “Formal duck typing” </p><p>—ꢀ <strong>Example</strong>: table, heirloom </p><p>—ꢀ Not limited to method name —ꢀ Role type indicates action </p><p>—ꢀ Why would we do this? </p><p>name, not a noun </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>15 </p><p>at cornell university </p><p>Fast Can-It Testing: Bit Vectors </p><p>—ꢀGive each object a bit-vector to cover types </p><p>—ꢀ Each role is a position in the bit vector </p><p>—ꢀ <strong>Example</strong>: </p><p>0100101ꢀ </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>16 </p><p>at cornell university </p><p>Fast Can-It Testing: Bit Vectors </p><p>—ꢀGive each object a bit-vector to cover types </p><p>—ꢀ Each role is a position in the bit vector </p><p>—ꢀ <strong>Example</strong>: </p><p>0100101ꢀ </p><p>Can Build </p><ul style="display: flex;"><li style="flex:1">Can Fight </li><li style="flex:1">Can Heal </li></ul><p></p><p>—ꢀ Use array if more than 32/64 roles </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>17 </p><p>at cornell university </p><p>Fast Can-It Testing: Bit Vectors </p><p>—ꢀGive each object a bit-vector to cover types </p><p>—ꢀ Each role is a position in the bit vector </p><p>—ꢀ <strong>Example</strong>: </p><p>0100101ꢀ </p><p>Can Build </p><ul style="display: flex;"><li style="flex:1">Can Fight </li><li style="flex:1">Can Heal </li></ul><p></p><p>—ꢀ Use array if more than 32/64 roles </p><p>—ꢀTest is quick logical operation. </p><p>—ꢀ <strong>Example</strong>: vector &amp; CAN_FIGHTꢀ </p><p>—ꢀ Faster than dynamic typing (why?) </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>18 </p><p>at cornell university </p><p>Model-Controller Separation Revisited </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Model </strong></li><li style="flex:1"><strong>Controller </strong></li></ul><p></p><p>—ꢀ Store/retrieve <strong>object data&nbsp;</strong>—ꢀ Process <strong>interactions </strong></p><p>—ꢀ Preserve any invariants —ꢀ Data may include delegates —ꢀ Determines is-a properties <br>—ꢀ Look at current game state —ꢀ Look for “triggering” event —ꢀ Apply interaction outcome </p><p><strong>Components </strong></p><p></p><ul style="display: flex;"><li style="flex:1">?</li><li style="flex:1">?</li></ul><p></p><p>—ꢀ Process <strong>game actions </strong></p><p>—ꢀ Attached to a entity (model) —ꢀ Uses the model as context —ꢀ Deter<sub style="top: 0.7792em;">A</sub>m<sub style="top: 0.7792em;">rc</sub>i<sub style="top: 0.7792em;">h</sub>n<sub style="top: 0.7792em;">ite</sub>e<sub style="top: 0.7792em;">c</sub>s<sub style="top: 0.7792em;">tur</sub>c<sub style="top: 0.7792em;">e</sub>a<sub style="top: 0.7792em;">P</sub>n<sub style="top: 0.7792em;">at</sub>-<sub style="top: 0.7792em;">t</sub>i<sub style="top: 0.7792em;">e</sub>t<sub style="top: 0.7792em;">rn</sub>p<sub style="top: 0.7792em;">s </sub>roperties </p><p>the </p><p>gamedesigninitiative </p><p>19 </p><p>at cornell university </p><p>Model-Controller Separation Revisited </p><p></p><ul style="display: flex;"><li style="flex:1"><strong>Model </strong></li><li style="flex:1"><strong>Controller </strong></li></ul><p></p><p>—ꢀ Store/retrieve <strong>object data&nbsp;</strong>—ꢀ Process <strong>interactions </strong></p><p>—ꢀ Preserve any invariants —ꢀ Data may include delegates —ꢀ Determines is-a properties <br>—ꢀ Look at current game state —ꢀ Look for “triggering” event —ꢀ Apply interaction outcome </p><p><strong>Components </strong></p><p>Is this always the best idea? </p><p></p><ul style="display: flex;"><li style="flex:1">?</li><li style="flex:1">?</li></ul><p></p><p>—ꢀ Process <strong>game actions </strong></p><p>—ꢀ Attached to a entity (model) —ꢀ Uses the model as context —ꢀ Deter<sub style="top: 0.7792em;">A</sub>m<sub style="top: 0.7792em;">rc</sub>i<sub style="top: 0.7792em;">h</sub>n<sub style="top: 0.7792em;">ite</sub>e<sub style="top: 0.7792em;">c</sub>s<sub style="top: 0.7792em;">tur</sub>c<sub style="top: 0.7792em;">e</sub>a<sub style="top: 0.7792em;">P</sub>n<sub style="top: 0.7792em;">at</sub>-<sub style="top: 0.7792em;">t</sub>i<sub style="top: 0.7792em;">e</sub>t<sub style="top: 0.7792em;">rn</sub>p<sub style="top: 0.7792em;">s </sub>roperties </p><p>the </p><p>gamedesigninitiative </p><p>20 </p><p>at cornell university </p><p><strong>Recall</strong>: Lab 3 in CS 3152 </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>21 </p><p>at cornell university </p><p>Processing Actions in Lab 3 </p><p>GameplayController.cs <br>Ship.cs </p><p></p><ul style="display: flex;"><li style="flex:1">—ꢀ Decides whether to shoot </li><li style="flex:1">—ꢀ Waits until objects commit </li></ul><p>—ꢀ Checks intent in Ship object —ꢀ Performs action for intent <br>—ꢀ Stores intent in the object </p><p>—ꢀ But <strong>DOES NOT </strong>shoot </p><p>the </p><p>gamedesigninitiative </p><p>Game Architecture </p><p>22 </p><p>at cornell university </p><p>Processing Actions in Lab 3 </p><p>GameplayController.cs </p><p>Attach components to controller? </p><p>Ship.cs </p><p></p><ul style="display: flex;"><li style="flex:1">—ꢀ Decides whether to shoot </li><li style="flex:1">—ꢀ Waits until objects commit </li></ul><p>—ꢀ Checks intent in Ship object —ꢀ Performs action for intent <br>—ꢀ Stores intent in the object </p><p>—ꢀ But <strong>DOES NOT </strong>shoot </p><p>the </p><p>gamedesigninitiative </p><p>Game Architecture </p><p>23 </p><p>at cornell university </p><p><strong>Related</strong>: Handling the View </p><p>—ꢀ Way too much to draw </p><p>—ꢀ Backgrounds —ꢀ UI elements </p><p>Update Draw </p><p>—ꢀ Individual NPCs —ꢀ Other moveable objects </p><p>—ꢀ Cannot cram all in Draw —ꢀ Put it in game object? </p><p>—ꢀ But objects are models </p><p>—ꢀ Violates MVC <strong>again </strong></p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>24 </p><p>at cornell university </p><p>First Attempt: A Drawing Canvas </p><p>—ꢀ Treat display as a <strong>container </strong></p><p>—ꢀ Often called a canvas —ꢀ Cleared at start of frame —ꢀ Objects added to container —ꢀ Draw contents at frame end </p><p>Passed as reference </p><p>—ꢀ Canvas abstracts <em>rendering </em></p><p>—ꢀ Hides animation details </p><p>void draw(Canvas c) {ꢀ </p><p>// Specify perspectiveꢀ // Add to canvas </p><p>}ꢀ </p><p>—ꢀ Like working with widget </p><p>—ꢀ Implement draw(c) in model </p><p>—ꢀ Classic heavyweight model —ꢀ No problems with extension </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>25 </p><p>at cornell university </p><p><strong>Problem</strong>: Canvas Methods </p><p>Ideal </p><p><strong>Model1 </strong></p><p>draw(canvas)ꢀ </p><p><strong>Canvas </strong></p><p>drawShape(…)ꢀ </p><p><strong>Model2 </strong></p><p>draw(canvas)ꢀ </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>26 </p><p>at cornell university </p><p><strong>Problem</strong>: Canvas Methods </p><p>In Practice </p><p><strong>Model1 </strong></p><p>draw(canvas)ꢀ </p><p><strong>Canvas </strong></p><p>drawShape1(…)ꢀ drawShape2(…)ꢀ </p><p><strong>Model2 </strong></p><p>draw(canvas)ꢀ </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>27 </p><p>at cornell university </p><p>Views and Components </p><p>Slot </p><p><strong>Component1ꢀ </strong></p><p>drawShape1(…)ꢀ </p><p>Slot Slot </p><p><strong>Model1 Model2 </strong></p><p><strong>Canvas </strong></p><p>drawPrimitive(…)ꢀ </p><p>Slot Slot Slot </p><p><strong>Component1ꢀ </strong></p><p>drawShape1(…)ꢀ </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>28 </p><p>at cornell university </p><p>Views and Components </p><p>Primitive effects </p><p>Slot </p><p><strong>Component1ꢀ </strong></p><p>Slot </p><p><strong>Model1 </strong></p><p>drawShape1(…)ꢀ </p><p>Slot </p><p>Complex, <br>Shape-specific rendering </p><p>Slot </p><p><strong>Canvas </strong></p><p>drawPrimitive(…)ꢀ </p><p><strong>Component1ꢀ </strong></p><p>drawShape1(…)ꢀ </p><p>Slot </p><p><strong>Model2 </strong></p><p>Slot </p><p>the </p><p>gamedesigninitiative </p><p>Architecture Patterns </p><p>29 </p><p>at cornell university </p><p>Components and AI </p><p><strong>Alert! </strong></p><p>—ꢀ NPCs use sense-think-act cycle </p><p>—ꢀ <strong>Sense</strong>: perceive&nbsp;the world —ꢀ <strong>Think</strong>: choose&nbsp;an action —ꢀ <strong>Act</strong>: update&nbsp;the game state </p><p>—ꢀ <strong>Act </strong>is stored in components </p><p>—ꢀ Capabilities given by roles </p><p>—ꢀ Where are <strong>sense </strong>and <strong>think</strong>? </p><p>Yes </p><p>—ꢀ In the component/role? </p><p>This is hard </p><p>—ꢀ How do roles interact? </p><p>the </p><p>gamedesigninitiative </p><p>Game Architecture </p><p>30 </p><p>at cornell university </p>

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    40 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us