{"$schema": "https://raw.githubusercontent.com/guitaripod/wwdc-sessions/master/schema/transcript.schema.json", "id": "wwdc2026-358", "language": "eng", "source": "https://developer.apple.com/videos/play/wwdc2026/358", "wordCount": 3094, "segments": [{"start": 7.0, "text": "Hi! I'm Keyi Yu from the Game Technology team."}, {"start": 11.0, "text": "Porting your game from Mac to iOS is incredibly straightforward,"}, {"start": 16.0, "text": "with help from the Game Porting Toolkit 4."}, {"start": 19.0, "text": "Players can already use a wide range of game controllers across Apple devices —"}, {"start": 24.0, "text": "Mac, iPad, and iPhone."}, {"start": 28.0, "text": "Players love taking their favorite games with them everywhere."}, {"start": 32.0, "text": "They'll pull out their iPhone and jump into your game anywhere, anytime."}, {"start": 37.0, "text": "But in those spontaneous moments,"}, {"start": 40.0, "text": "they may not always have a controller with them."}, {"start": 43.0, "text": "So how do you make sure they still get a fantastic, responsive experience?"}, {"start": 48.0, "text": "The answer is to give your game great touch controls."}, {"start": 53.0, "text": "Dredge, by Black Salt Games,"}, {"start": 55.0, "text": "is a perfect example of how touch controls"}, {"start": 58.0, "text": "can elevate an already engaging experience."}, {"start": 62.0, "text": "Players get a seamless blend of gameplay and platform interaction."}, {"start": 67.0, "text": "Everything feels natural and intuitive, letting players focus on the adventure."}, {"start": 74.0, "text": "I'll walk you through, step by step,"}, {"start": 77.0, "text": "how to design and implement great touch controls on iOS and iPadOS,"}, {"start": 82.0, "text": "using my game as an example."}, {"start": 86.0, "text": "Here's the plan: I'll set up touch controls for my game,"}, {"start": 91.0, "text": "create flexible layouts,"}, {"start": 94.0, "text": "design fluid interactions on screen,"}, {"start": 98.0, "text": "and provide rich feedback to the player."}, {"start": 102.0, "text": "The first step is to set up the touch controller."}, {"start": 106.0, "text": "If your game already has support for game controllers,"}, {"start": 109.0, "text": "or has keyboard and mouse support,"}, {"start": 112.0, "text": "chances are you're familiar with the Game Controller framework."}, {"start": 117.0, "text": "Building on top of that,"}, {"start": 118.0, "text": "the Touch Controller framework extends that support to touch input."}, {"start": 124.0, "text": "The core of the Game Controller framework is straightforward."}, {"start": 128.0, "text": "It reacts to notifications when GCController objects"}, {"start": 132.0, "text": "connect or disconnect,"}, {"start": 134.0, "text": "and then either polls active devices for their input state,"}, {"start": 138.0, "text": "or sets up value-changed handlers to be notified when input state changes."}, {"start": 144.0, "text": "And once you've implemented your game logic using GCController,"}, {"start": 149.0, "text": "you're ready to add touch controls on top of it,"}, {"start": 152.0, "text": "using the Touch Controller framework."}, {"start": 156.0, "text": "The Touch Controller framework includes a rich set of button types"}, {"start": 160.0, "text": "and behaviors to support the most common game inputs."}, {"start": 164.0, "text": "On top of that,"}, {"start": 165.0, "text": "each button's appearance can be customized to best fit your game."}, {"start": 171.0, "text": "And the API integrates directly with Metal"}, {"start": 173.0, "text": "to ensure the highest possible performance."}, {"start": 178.0, "text": "When Touch Controller is enabled in your game,"}, {"start": 181.0, "text": "it shows up as a GCController object."}, {"start": 185.0, "text": "So you can poll its state,"}, {"start": 187.0, "text": "or set up handlers to listen for input updates,"}, {"start": 191.0, "text": "just like any other controller."}, {"start": 194.0, "text": "Here's my game."}, {"start": 195.0, "text": "It already has game controller support, so now I'll add support for touch controls."}, {"start": 202.0, "text": "I'll start by creating"}, {"start": 203.0, "text": "a touch controller object from a descriptor."}, {"start": 207.0, "text": "Then, I'll enable the touch controller."}, {"start": 210.0, "text": "This automatically enables game controller logic."}, {"start": 214.0, "text": "With the touch controller enabled, I'll work on 2 things."}, {"start": 218.0, "text": "First, in UIView, I'll add a handler for touch input."}, {"start": 224.0, "text": "This notifies the touch controller when players start,"}, {"start": 227.0, "text": "end, and move the touch."}, {"start": 230.0, "text": "Second, in the Metal renderer, I render the touch controls on screen."}, {"start": 236.0, "text": "In the code, I'll use a descriptor to create a touch controller object."}, {"start": 242.0, "text": "I'll enable the touchController using the connect API."}, {"start": 247.0, "text": "Then, I'll render all the controls using the touchController's render API."}, {"start": 254.0, "text": "In UIKit, the touchesBegan function"}, {"start": 257.0, "text": "reports when one or more new touches occurred in a view or window."}, {"start": 262.0, "text": "I'll override that, and call handleTouchBegan instead."}, {"start": 266.0, "text": "You'll want to do that for touchesEnd and touchesMove also."}, {"start": 271.0, "text": "Finally, I'll set up the polling states and valueChangedHandler."}, {"start": 277.0, "text": "There's one more thing I still need to do:"}, {"start": 280.0, "text": "add all the controls to the touch controller object."}, {"start": 284.0, "text": "But where should I place them?"}, {"start": 286.0, "text": "And how can I do it in a way that gives players the best experience?"}, {"start": 292.0, "text": "The key is setting up a flexible layout."}, {"start": 296.0, "text": "A flexible layout means your game feels comfortable on any screen size."}, {"start": 301.0, "text": "With Apple's unified gaming platform,"}, {"start": 304.0, "text": "players can find your game across a wide variety of devices."}, {"start": 308.0, "text": "The key is to plan early,"}, {"start": 310.0, "text": "and design an adaptive game interface that scales gracefully across all of them."}, {"start": 316.0, "text": "The Touch Controller framework makes it easy to do that."}, {"start": 321.0, "text": "It provides nine anchor points for each layout."}, {"start": 324.0, "text": "After you assign the anchor for a control,"}, {"start": 328.0, "text": "you can place it with an offset which is relative to the anchor."}, {"start": 332.0, "text": "You can group related controls into a section"}, {"start": 336.0, "text": "and assign the same anchor point to every control in that section."}, {"start": 341.0, "text": "Then, as the device shape changes,"}, {"start": 343.0, "text": "each section stays at a consistent size and distance from its anchor point."}, {"start": 350.0, "text": "This keeps your controls at physically comfortable sizes for mobile players,"}, {"start": 355.0, "text": "while making the best use of available screen space"}, {"start": 358.0, "text": "across all devices."}, {"start": 361.0, "text": "You'll also want to make sure your controls are always visible."}, {"start": 366.0, "text": "The way to do that is to design for the fullscreen."}, {"start": 370.0, "text": "On iPad and iPhone,"}, {"start": 372.0, "text": "designing a fullscreen gaming experience means"}, {"start": 375.0, "text": "keeping the safe areas in mind."}, {"start": 378.0, "text": "Safe areas are regions of the display where you can safely put UI"}, {"start": 383.0, "text": "so that it doesn't overlap with hardware or software features."}, {"start": 388.0, "text": "On iPad and iPhone, safe areas help you avoid placing UI"}, {"start": 393.0, "text": "where the device's rounded corners could obscure it."}, {"start": 397.0, "text": "They also help you steer clear of the system home indicator"}, {"start": 401.0, "text": "and the Dynamic Island on iPhone,"}, {"start": 403.0, "text": "both of which can potentially overlap your controls' tap targets."}, {"start": 408.0, "text": "On iOS and iPadOS, you can read the safeAreaInsets"}, {"start": 413.0, "text": "from any UIView in UIKit."}, {"start": 416.0, "text": "Then you can add the safeAreaInsets"}, {"start": 419.0, "text": "to the offset of the controls you want to place on the screen."}, {"start": 423.0, "text": "Avoiding the safe areas is a start."}, {"start": 426.0, "text": "But I also need to place my controls carefully"}, {"start": 430.0, "text": "so they don't interfere with the game's play area."}, {"start": 435.0, "text": "I want to avoid placing controls where I expect movement"}, {"start": 438.0, "text": "or camera input to happen."}, {"start": 441.0, "text": "And of course, I don't want to cover my character,"}, {"start": 445.0, "text": "so no controls will go in the center of the display."}, {"start": 449.0, "text": "That leaves the regions near the thumbs,"}, {"start": 451.0, "text": "which are ideal for frequent or important actions,"}, {"start": 455.0, "text": "and the region at the top of the screen,"}, {"start": 457.0, "text": "which is a great place to put less frequently used controls"}, {"start": 461.0, "text": "like menu buttons."}, {"start": 463.0, "text": "With that, I know exactly where to place my touch controls."}, {"start": 468.0, "text": "Now, I'll implement these controls in my game"}, {"start": 471.0, "text": "using the touch controller I set up earlier."}, {"start": 475.0, "text": "The Touch Controller framework provides convenient APIs"}, {"start": 478.0, "text": "to create controls."}, {"start": 480.0, "text": "And they all follow a similar pattern."}, {"start": 483.0, "text": "Set up the relevant properties for the control using a descriptor."}, {"start": 488.0, "text": "Some controls have properties in common."}, {"start": 491.0, "text": "Some properties are unique to a specific type of control."}, {"start": 495.0, "text": "Then, using the descriptor, create a control."}, {"start": 500.0, "text": "Add it to the TCTouchController."}, {"start": 504.0, "text": "For my game, I'll need to implement these controls"}, {"start": 507.0, "text": "to match my controller support."}, {"start": 509.0, "text": "I'll start with creating button B."}, {"start": 513.0, "text": "Here I'll create a standard circular button B."}, {"start": 517.0, "text": "First, I initialize a TCButtonDescriptor."}, {"start": 522.0, "text": "I set its label to TCControlLabel.buttonB."}, {"start": 526.0, "text": "This maps it to the physical buttonB on a game controller."}, {"start": 531.0, "text": "Since my game was already handling the input from a physical controller,"}, {"start": 536.0, "text": "I don't have to write any more game logic here."}, {"start": 539.0, "text": "It's already handled!"}, {"start": 541.0, "text": "I just have to place the button on screen."}, {"start": 545.0, "text": "I anchor it in the bottomRight region, and set a fixed offset."}, {"start": 550.0, "text": "I also need to set the button's visual contents"}, {"start": 553.0, "text": "so it actually appears on screen."}, {"start": 556.0, "text": "Finally, I call addButton on the touchController"}, {"start": 560.0, "text": "and pass this descriptor."}, {"start": 563.0, "text": "And since my game is fullscreen,"}, {"start": 565.0, "text": "I'll adjust the offset using safeAreaInsets so nothing gets clipped."}, {"start": 572.0, "text": "Button B is showing up at the bottom right in a circular shape."}, {"start": 576.0, "text": "All the other controls follow a similar pattern."}, {"start": 580.0, "text": "After I add all the controls into the touch controller object,"}, {"start": 584.0, "text": "they are appearing in the game."}, {"start": 587.0, "text": "Because I applied safe areas to the offsets,"}, {"start": 591.0, "text": "the Dynamic Island doesn't overlap any of my controls."}, {"start": 595.0, "text": "The controls also don't cover the main character,"}, {"start": 598.0, "text": "keeping the game area clean."}, {"start": 601.0, "text": "But these controls don't feel quite right."}, {"start": 605.0, "text": "I've created a direct one-to-one mapping from a physical controller."}, {"start": 610.0, "text": "This makes the screen cluttered with controls that compete for space."}, {"start": 615.0, "text": "But I can improve on that."}, {"start": 617.0, "text": "In this section, I'll clean up the clutter"}, {"start": 620.0, "text": "and design controls that feel native to touch"}, {"start": 624.0, "text": "because when interactions feel fluid and natural,"}, {"start": 627.0, "text": "players feel immersed in the gaming experience."}, {"start": 632.0, "text": "There are a few choices you can make here that really make a difference."}, {"start": 637.0, "text": "I'll start with using dynamic controls."}, {"start": 641.0, "text": "Unlike a physical game controller button,"}, {"start": 643.0, "text": "you can easily change the appearance of on screen controls."}, {"start": 648.0, "text": "You can choose a glyph"}, {"start": 650.0, "text": "that actually represents what the control's function is."}, {"start": 653.0, "text": "Since I'm using system assets for my controls,"}, {"start": 657.0, "text": "I'll just change the name of the system assets from buttonB"}, {"start": 661.0, "text": "to instead display an icon showing the actual action."}, {"start": 666.0, "text": "Now, the button B displays the icon for the strike action."}, {"start": 673.0, "text": "After swapping out all the system assets"}, {"start": 676.0, "text": "the layout is much more intuitive."}, {"start": 679.0, "text": "Players immediately know what each control does"}, {"start": 682.0, "text": "without having to check the settings or read hints during gameplay."}, {"start": 687.0, "text": "And when a control's behavior changes based on context,"}, {"start": 691.0, "text": "you should update its icon to match."}, {"start": 695.0, "text": "In my game, besides the default strike power,"}, {"start": 698.0, "text": "the single button B can also represent the fireball or water power."}, {"start": 704.0, "text": "So the icon should update with the flame or water drop image"}, {"start": 708.0, "text": "when players select the power."}, {"start": 711.0, "text": "I'll create a helper function that updates the contents of button B."}, {"start": 717.0, "text": "Then, in the cyclePower function,"}, {"start": 719.0, "text": "I'll call it with the right symbolName for each power type."}, {"start": 724.0, "text": "This shows the players exactly what action they are playing with."}, {"start": 729.0, "text": "Now, once a player selects their power,"}, {"start": 732.0, "text": "button B on the bottom right automatically shows the correct icon"}, {"start": 737.0, "text": "for that power."}, {"start": 741.0, "text": "And importantly, when an action isn't available or relevant,"}, {"start": 746.0, "text": "remove it from the screen entirely."}, {"start": 749.0, "text": "Don't leave controls visible that players can not use."}, {"start": 753.0, "text": "In my game, here's how I apply this."}, {"start": 757.0, "text": "Thumbsticks are hidden when they're not being touched."}, {"start": 761.0, "text": "The pick-up button only appears when there's an item nearby to pick up."}, {"start": 767.0, "text": "And quick time event buttons are only shown"}, {"start": 770.0, "text": "when a quick time event is actually happening."}, {"start": 774.0, "text": "The aim and release power button should only appear"}, {"start": 777.0, "text": "when a specific power is selected."}, {"start": 781.0, "text": "Hiding thumbsticks when not in use is easy."}, {"start": 785.0, "text": "When you create the thumbstick, just set hidesWhenNotPressed to true."}, {"start": 792.0, "text": "For other controls like buttons, set isEnabled to false to hide them."}, {"start": 799.0, "text": "The pickup button is a little different."}, {"start": 802.0, "text": "It should appear right next to the item that needs picking up."}, {"start": 806.0, "text": "So I update its position every time I show it."}, {"start": 811.0, "text": "When it's time to dismiss it,"}, {"start": 813.0, "text": "I remove the button from the touchController entirely."}, {"start": 818.0, "text": "After hiding the thumbsticks, pickup button, and quick time event buttons"}, {"start": 823.0, "text": "when they're not needed, the screen is much cleaner."}, {"start": 829.0, "text": "One of the real advantages of touch controls is that"}, {"start": 832.0, "text": "they can serve as both input and output."}, {"start": 836.0, "text": "So instead of showing an overlay and cycling through actions,"}, {"start": 840.0, "text": "you can display those actions directly as touch controls."}, {"start": 845.0, "text": "In the buttonX press handler,"}, {"start": 847.0, "text": "I'll open the power wheel controls directly"}, {"start": 850.0, "text": "instead of showing the power wheel overlay."}, {"start": 854.0, "text": "In the openPowerWheel function,"}, {"start": 856.0, "text": "I add each power control to the touch controller"}, {"start": 860.0, "text": "based on what powers are currently available."}, {"start": 863.0, "text": "Then, I set a value-changed handler for each one."}, {"start": 868.0, "text": "And since these controls are not used all the time,"}, {"start": 872.0, "text": "I auto-dismiss them after three seconds if no selection is made."}, {"start": 878.0, "text": "Now players can select a power directly from the touch controls."}, {"start": 882.0, "text": "No overlay is needed!"}, {"start": 886.0, "text": "Smooth character and camera movement are essential for a great-feeling game."}, {"start": 892.0, "text": "So how do you adapt those from a physical controller to touch?"}, {"start": 897.0, "text": "I'll use the fullscreen for both character and camera movement."}, {"start": 902.0, "text": "For sprinting, I'll use a single left thumbstick"}, {"start": 905.0, "text": "without an extra button."}, {"start": 907.0, "text": "I'll also replace the right thumbstick with a touchpad."}, {"start": 912.0, "text": "Physical thumbsticks have a fixed size."}, {"start": 915.0, "text": "But on touch screen, you're not bound by those constraints at all."}, {"start": 921.0, "text": "And because players can't physically feel"}, {"start": 924.0, "text": "where their finger is relative to a visual control,"}, {"start": 928.0, "text": "it's important to expand the input area as much as possible."}, {"start": 934.0, "text": "I'll set the colliderShape to either leftSide or rightSide,"}, {"start": 939.0, "text": "which gives the thumbstick access to the entire half of the screen"}, {"start": 942.0, "text": "for touch detection."}, {"start": 945.0, "text": "Now, the entire left half of the screen responds to the player's touch."}, {"start": 952.0, "text": "Let's look at another issue I want to address:"}, {"start": 955.0, "text": "when the character is sprinting."}, {"start": 958.0, "text": "In my game, sprinting requires players to hold down the left thumbstick"}, {"start": 963.0, "text": "and move it at the same time."}, {"start": 965.0, "text": "On a physical controller that's fine,"}, {"start": 968.0, "text": "but on touch, it means using at least two fingers simultaneously."}, {"start": 974.0, "text": "This is really difficult to do."}, {"start": 976.0, "text": "To solve this, I'll embed the thumbstick button's functionality"}, {"start": 981.0, "text": "directly into the thumbstick itself."}, {"start": 984.0, "text": "And I'll use the tilt magnitude to determine sprint."}, {"start": 990.0, "text": "A small tilt means the character moves at a normal pace."}, {"start": 995.0, "text": "If it's a big tilt, the character will sprint."}, {"start": 999.0, "text": "In the pollInput() function, I read the leftThumbstick from GCController"}, {"start": 1005.0, "text": "and get the tilt value from it."}, {"start": 1009.0, "text": "Then I do a quick magnitude check"}, {"start": 1012.0, "text": "to decide whether the tilt is large enough to trigger sprinting."}, {"start": 1017.0, "text": "Now players can sprint using just the thumbstick."}, {"start": 1020.0, "text": "No second finger is required!"}, {"start": 1024.0, "text": "Another issue I want to solve is the camera control."}, {"start": 1029.0, "text": "Directly mapping the right thumbstick to camera movement on touch"}, {"start": 1033.0, "text": "can cause over-rotation, and can feel sluggish."}, {"start": 1037.0, "text": "A touchpad gives you both speed and precision."}, {"start": 1042.0, "text": "The camera moves immediately."}, {"start": 1044.0, "text": "The player doesn't have to wait for it to spin around."}, {"start": 1048.0, "text": "It moves exactly as far as their finger moves,"}, {"start": 1051.0, "text": "with no latency or drift at the start or end of a gesture."}, {"start": 1056.0, "text": "The Touch Controller framework provides TCTouchpad for this."}, {"start": 1060.0, "text": "I initialize the descriptor,"}, {"start": 1062.0, "text": "set its label to rightThumbstick"}, {"start": 1065.0, "text": "so it maps to the existing camera logic,"}, {"start": 1069.0, "text": "set colliderShape to rightSide so it covers the right half of the screen,"}, {"start": 1075.0, "text": "and set reportsRelativeValues to true"}, {"start": 1078.0, "text": "so it works no matter where on the screen the player touches."}, {"start": 1082.0, "text": "Then I add it to the touchController."}, {"start": 1086.0, "text": "Now, when players use the touchpad to control the camera,"}, {"start": 1090.0, "text": "there's no visible control to clutter the screen."}, {"start": 1094.0, "text": "This leaves more room for the game itself."}, {"start": 1097.0, "text": "And there's no over-rotation when they move their fingers."}, {"start": 1101.0, "text": "Most modern games have some complex control combinations"}, {"start": 1105.0, "text": "that are fine on a physical controller, but need rethinking for touch."}, {"start": 1112.0, "text": "It's important to approach those thoughtfully."}, {"start": 1117.0, "text": "In my game, there are two cases worth working through."}, {"start": 1121.0, "text": "A quick time event and an aim-to-release power."}, {"start": 1126.0, "text": "These events usually require using two or more fingers at once"}, {"start": 1131.0, "text": "on a physical controller, but on touch there are better ways."}, {"start": 1137.0, "text": "I'll start with the quick time event."}, {"start": 1140.0, "text": "One quick time event happens when the big boss freezes your character."}, {"start": 1145.0, "text": "Players need to hold L1 and R1 to break free,"}, {"start": 1149.0, "text": "while also using the left thumbstick to move away from the boss."}, {"start": 1154.0, "text": "That's a lot to manage with just two fingers!"}, {"start": 1158.0, "text": "Instead, consider collapsing those two buttons into a single quick time event button."}, {"start": 1165.0, "text": "And hide it entirely when the event isn't happening."}, {"start": 1170.0, "text": "In my game, I add this quick time event button once during setup."}, {"start": 1175.0, "text": "Unlike the pickup button, which appears at different positions,"}, {"start": 1180.0, "text": "the quick time event button always appears in the same spot."}, {"start": 1184.0, "text": "So I use isEnabled to show and hide the button"}, {"start": 1188.0, "text": "instead of adding and removing it each time."}, {"start": 1193.0, "text": "Now players can hold the quick time event button to escape"}, {"start": 1197.0, "text": "while moving with the left thumbstick at the same time."}, {"start": 1201.0, "text": "The other challenge is aiming to use a power."}, {"start": 1205.0, "text": "This is a common event in modern games."}, {"start": 1208.0, "text": "To throw a fireball, players need to use more than two fingers to aim,"}, {"start": 1213.0, "text": "move and release power at the same time."}, {"start": 1216.0, "text": "That's very challenging in a busy game."}, {"start": 1219.0, "text": "The fix is to combine the aim and release into a single action button."}, {"start": 1228.0, "text": "In code, I'll remove the aim and release buttons."}, {"start": 1232.0, "text": "Instead, in buttonB's valueChangedHandler,"}, {"start": 1235.0, "text": "I'll call the releasePower function based on this pressed state."}, {"start": 1240.0, "text": "To implement hold and drag,"}, {"start": 1242.0, "text": "capture the raw touch delta while button B is held."}, {"start": 1247.0, "text": "This has to happen in touchesMoved because it's tracked independently"}, {"start": 1251.0, "text": "from the button's pressed state itself."}, {"start": 1254.0, "text": "Now, if a player wants to throw a fireball,"}, {"start": 1257.0, "text": "they hold button B and drag to aim,"}, {"start": 1260.0, "text": "while still moving with the left thumbstick."}, {"start": 1263.0, "text": "When they release button B, the fireball fires."}, {"start": 1267.0, "text": "The interaction feels much smoother with this redesign."}, {"start": 1272.0, "text": "Now that players can touch anywhere on screen,"}, {"start": 1276.0, "text": "it's just as important to give them clear feedback about what they're touching."}, {"start": 1282.0, "text": "Every touch control you create should have a visible pressed state."}, {"start": 1286.0, "text": "And the Touch Controller framework handles this for you by default."}, {"start": 1290.0, "text": "Thumbsticks animate as they move and the buttons highlight when pressed."}, {"start": 1295.0, "text": "But in the context of a visually busy game,"}, {"start": 1298.0, "text": "you may want to go further with custom visual feedback."}, {"start": 1303.0, "text": "In my game, players don't get much feedback when they're sprinting."}, {"start": 1308.0, "text": "I'll fix that with a strong visual indicator."}, {"start": 1312.0, "text": "I'll add a glowing halo around the outer ring of the left thumbstick"}, {"start": 1316.0, "text": "when sprint is active."}, {"start": 1318.0, "text": "To do this, I create TCControlContents manually."}, {"start": 1323.0, "text": "First, I generate the halo ring TCControlImage from a halo Metal texture."}, {"start": 1330.0, "text": "It's sized slightly larger than the thumbstick background."}, {"start": 1334.0, "text": "TCControlContents is essentially an array of layers."}, {"start": 1339.0, "text": "I stack the halo control image on top of the standard background images."}, {"start": 1344.0, "text": "Then, I swap in the new TCControlContents with the halo when sprint is active,"}, {"start": 1350.0, "text": "and revert to the normal background when it's not."}, {"start": 1353.0, "text": "Now, when a player is sprinting,"}, {"start": 1356.0, "text": "the glowing halo around the thumbstick"}, {"start": 1358.0, "text": "makes it immediately clear the character is in sprint mode."}, {"start": 1364.0, "text": "Great!"}, {"start": 1365.0, "text": "So far, I've set up a touch controller,"}, {"start": 1368.0, "text": "redesigned my controls and implemented the design"}, {"start": 1372.0, "text": "with Touch Controller framework in my game."}, {"start": 1375.0, "text": "Let's check how it works in the game overall!"}, {"start": 1379.0, "text": "This is where I started."}, {"start": 1381.0, "text": "Every button from a physical controller mapped directly onto the screen,"}, {"start": 1386.0, "text": "cluttering the game."}, {"start": 1388.0, "text": "With all the improvements I went through in today's session,"}, {"start": 1392.0, "text": "the game view is clear and controls are straightforward to use."}, {"start": 1396.0, "text": "The left thumbstick appears when players touch the screen."}, {"start": 1400.0, "text": "The pickup button shows up when there's an item nearby to pick up."}, {"start": 1403.0, "text": "The right half screen is the touchpad for camera control without over rotation."}, {"start": 1409.0, "text": "Simply press the button to pick a power that players just picked up."}, {"start": 1413.0, "text": "Hold and drag one single action button to aim and release."}, {"start": 1419.0, "text": "The sprint indicator enhances the gameplay a lot!"}, {"start": 1424.0, "text": "Players can jump into my game with only two fingers anywhere, anytime."}, {"start": 1429.0, "text": "It's your turn to design touch controls."}, {"start": 1432.0, "text": "When done well, they can make your game feel brand new to players"}, {"start": 1436.0, "text": "who pick it up on their phone."}, {"start": 1439.0, "text": "And implement those great controls with the Touch Controller framework."}, {"start": 1444.0, "text": "For more, watch \"Design great interfaces for handheld games\""}, {"start": 1449.0, "text": "and \"Level up with Apple game technologies.\""}, {"start": 1452.0, "text": "Thanks so much for watching!"}]}