aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/games/techniques/control_mechanisms
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/games/techniques/control_mechanisms
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/games/techniques/control_mechanisms')
-rw-r--r--files/zh-cn/games/techniques/control_mechanisms/index.html78
-rw-r--r--files/zh-cn/games/techniques/control_mechanisms/移动端触摸控制/index.html152
2 files changed, 230 insertions, 0 deletions
diff --git a/files/zh-cn/games/techniques/control_mechanisms/index.html b/files/zh-cn/games/techniques/control_mechanisms/index.html
new file mode 100644
index 0000000000..07b6e0b6e1
--- /dev/null
+++ b/files/zh-cn/games/techniques/control_mechanisms/index.html
@@ -0,0 +1,78 @@
+---
+title: Implementing game control mechanisms
+slug: Games/Techniques/Control_mechanisms
+tags:
+ - Controls
+ - Desktop
+ - Gamepad
+ - Games
+ - JavaScript
+ - Laptop
+ - Mobile
+ - NeedsTranslation
+ - TopicStub
+ - keyboard
+ - mouse
+ - touch
+translation_of: Games/Techniques/Control_mechanisms
+---
+<div>{{GamesSidebar}}</div><p class="summary">One of HTML5's main advantages as a game development platform is the ability to run on various platforms and devices. Streamlining cross device differences creates multiple challenges, not least when providing appropriate controls for different contexts. In this series of articles we will show you how you can approach building a game that can be played using touchscreen smartphones, mouse and keyboard, and also less common mechanisms such as gamepads.</p>
+
+<h2 id="Case_study">Case study</h2>
+
+<p>We'll be using the <a href="http://rogers2.enclavegames.com/demo/">Captain Rogers: Battle at Andromeda demo</a> as an example.</p>
+
+<p><img alt="Captain Rogers: Battle at Andromeda - cover of the game containing Enclave Games and Blackmoon Design logos, Roger's space ship and title of the game." src="https://mdn.mozillademos.org/files/13849/captainrogers2-cover.png" style="display: block; height: 325px; margin: 0px auto; width: 575px;"></p>
+
+<p>Captain Rogers was created using the <a href="http://phaser.io/">Phaser</a> framework, the most popular tool for simple 2D game development in JavaScript right now, but it should be fairly easy to reuse the knowledge contained within these articles when building games in pure JavaScript or any other framework. If you're looking for a good introduction to Phaser, then check the <a href="/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser">2D breakout game using Phaser</a> tutorial.</p>
+
+<p>In the following articles we will show how to implement various different control mechanisms for Captain Rogers to support different platforms — from touch on mobile, through keyboard/mouse/gamepad on desktop, to more unconventional ones like TV remote, shouting to or waving your hand in front of the laptop, or squeezing bananas.</p>
+
+<h2 id="Setting_up_the_environment">Setting up the environment</h2>
+
+<p>Let's start with a quick overview of the game's folder structure, JavaScript files and in-game states, so we know what's happening where. The game's folders look like this:</p>
+
+<p><img alt="Captain Rogers: Battle at Andromeda - folder structure of the games' project containing JavaScript sources, images and fonts." src="https://mdn.mozillademos.org/files/13851/captainrogers2-folderstructure.png" style="border-style: solid; border-width: 1px; display: block; height: 479px; margin: 0px auto; width: 575px;"></p>
+
+<p>As you can see there are folders for images, JavaScript files, fonts and sound effects. The <code>src</code> folder contains the JavaScript files split as a separate states — <code>Boot.js</code>, <code>Preloader.js</code>, <code>MainMenu.js</code> and <code>Game.js</code> — these are loaded into the index file in this exact order. The first one initializes Phaser, the second preloads all the assets, the third one controls the main menu welcoming the player, and the fourth controls the actual gameplay.</p>
+
+<p>Every state has its own default methods: <code>preload()</code>, <code>create()</code>, and <code>update()</code>. The first one is needed for preloading required assets, <code>create()</code> is executed once the state had started, and <code>update()</code> is executed on every frame.</p>
+
+<p>For example, you can define a button in the <code>create()</code> function:</p>
+
+<pre class="brush: js">create: function() {
+ // ...
+ var buttonEnclave = this.add.button(10, 10, 'logo-enclave', this.clickEnclave, this);
+ // ...
+}
+</pre>
+
+<p>It will be created once at the start of the game, and will execute <code>this.clickEnclave()</code> action assigned to it when clicked, but you can also use the mouse's pointer value in the <code>update()</code> function to make an action:</p>
+
+<pre class="brush: js">update: function() {
+ // ...
+ if(this.game.input.mousePointer.isDown) {
+ // do something
+ }
+ // ...
+}
+</pre>
+
+<p>This will be executed whenever the mouse button is pressed, and it will be checked against the input's <code>isDown</code> boolean variable on every frame of the game.</p>
+
+<p>That should give you some understanding of the project structure. We'll be playing mostly with the <code>MainMenu.js</code> and <code>Game.js</code> files, and we'll explain the code inside the <code>create()</code> and <code>update()</code> methods in much more detail in later articles.</p>
+
+<h2 id="Pure_JavaScript_demo">Pure JavaScript demo</h2>
+
+<p>There's also a <a href="https://end3r.github.io/JavaScript-Game-Controls/">small online demo</a> with full source code <a href="https://github.com/end3r/JavaScript-Game-Controls/">available on GitHub</a> where the basic support for the control mechanisms described in the articles is implemented in pure JavaScript. It will be explained in the given articles themselves below, but you can play with it already, and use the code however you want for learning purposes.</p>
+
+<h2 id="The_articles">The articles</h2>
+
+<p>JavaScript is the perfect choice for mobile gaming because of HTML5 being truly multiplatform; all of the following articles focus on the APIs provided for interfacing with different control mechanisms:</p>
+
+<ol>
+ <li><a href="/en-US/docs/Games/Techniques/Control_mechanisms/Mobile_touch">Mobile touch controls</a> — The first article will kick off with touch, as the mobile first approach is very popular.</li>
+ <li><a href="/en-US/docs/Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard">Desktop mouse and keyboard controls</a> — When playing on a desktop/laptop computer, providing keyboard and mouse controls is essential to provide an acceptable level of accessibility for the game.</li>
+ <li><a href="/en-US/docs/Games/Techniques/Control_mechanisms/Desktop_with_gamepad">Desktop gamepad controls</a> — The Gamepad API rather usefully allows gamepads to be used for controlling web apps on desktop/laptop, for that console feel.</li>
+ <li><a href="/en-US/docs/Games/Techniques/Control_mechanisms/Other">Unconventional controls</a> — The final article showcases some unconventional control mechanisms, from the experimental to the slightly crazy, which you might not believe could be used to play the game.</li>
+</ol>
diff --git a/files/zh-cn/games/techniques/control_mechanisms/移动端触摸控制/index.html b/files/zh-cn/games/techniques/control_mechanisms/移动端触摸控制/index.html
new file mode 100644
index 0000000000..e9a9abaf15
--- /dev/null
+++ b/files/zh-cn/games/techniques/control_mechanisms/移动端触摸控制/index.html
@@ -0,0 +1,152 @@
+---
+title: 移动端触摸控制
+slug: Games/Techniques/Control_mechanisms/移动端触摸控制
+translation_of: Games/Techniques/Control_mechanisms/Mobile_touch
+---
+<div>{{GamesSidebar}}</div>
+
+<p>{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}</p>
+
+<p class="summary">未来手游一定是Web的天下,许多开发在游戏开发过程中首先选择手游 — 既然如此,触摸控制是不可少的。我们将在本教程中了解怎样简单地在移动端H5游戏中实现触摸控制 ,只要移动端支持触摸,你就可以尽情的玩。</p>
+
+<p class="note"><strong>说明</strong>:游戏 <a class="external external-icon" href="http://rogers2.enclavegames.com/demo/">Captain Rogers: Battle at Andromeda</a> 是基于<a href="http://phaser.io/">Phaser</a> 和Phaser-based管理控制,但它也可以用纯JavaScript实现。使用Phaser的好处它提供了辅助变量和方法可以直接调用,有助于快速的开发游戏,这需要根据项目实际情况选择。</p>
+
+<h2 id="纯_JavaScript_方式实现">纯 JavaScript 方式实现</h2>
+
+<p>我们可以实现自己的触摸事件 — 给document添加事件监听,并传入自定义功能的方法,非常简单:</p>
+
+<pre class="brush: js">var el = document.getElementsByTagName("canvas")[0];
+el.addEventListener("touchstart", handleStart);
+el.addEventListener("touchmove", handleMove);
+el.addEventListener("touchend", handleEnd);
+el.addEventListener("touchcancel", handleCancel);</pre>
+
+<p>这样, 在移动设备上屏幕上触摸游戏的 {{htmlelement("canvas")}} 将触发这些事件,因为我们就可以随意操控游戏(如:移动太空船)。 事件如下所示:</p>
+
+<ul>
+ <li><a href="/en-US/docs/Web/API/GlobalEventHandlers/ontouchstart">touchstart</a> 当用户手指放在屏幕上触发。</li>
+ <li><a href="/en-US/docs/Web/API/GlobalEventHandlers/ontouchmove">touchmove</a> 当他们在屏幕上移动手指时触发。</li>
+ <li><a href="/en-US/docs/Web/API/GlobalEventHandlers/ontouchend">touchend</a> 当用户在屏幕上停止移动时触发。</li>
+ <li><a href="/en-US/docs/Web/API/GlobalEventHandlers/ontouchcancel">touchcancel</a> 触摸被取消是触发,例如当用户将他们的手指移动到屏幕之外时。</li>
+</ul>
+
+<div class="note">
+<p><strong>说明</strong>: 这篇 <a href="/en-US/docs/Web/API/Touch_events">touch events</a> 参考文章提供了更多的实例和介绍。</p>
+</div>
+
+<h3 id="纯JavaScript示例">纯JavaScript示例</h3>
+
+<p>这个实现了移动端触摸的<a href="https://github.com/end3r/JavaScript-Game-Controls/">little demo</a>代码已经放到了GibHub上,我们下载这个示例就可以实现在移动端屏幕上移动飞船。</p>
+
+<p>我们将两种事件:<code>touchstart </code>和<code>touchmove</code> 放到一个方法里处理. 为什么呢? <code>touchHandler</code> 方法定义的飞船位置变量适合下面两种情况下: 当玩家触摸时,但不移动它(<code>touchstart</code>)和当手指在屏幕上开始移动 (<code>touchmove</code>):</p>
+
+<pre class="brush: js">document.addEventListener("touchstart", touchHandler);
+document.addEventListener("touchmove", touchHandler);</pre>
+
+<p><code>touchHandler</code> 方法的代码如下:</p>
+
+<pre class="brush: js">function touchHandler(e) {
+ if(e.touches) {
+ playerX = e.touches[0].pageX - canvas.offsetLeft - playerWidth / 2;
+ playerY = e.touches[0].pageY - canvas.offsetTop - playerHeight / 2;
+ output.innerHTML = "Touch: "+ " x: " + playerX + ", y: " + playerY;
+ e.preventDefault();
+ }
+}</pre>
+
+<p>If the touch occurs (<code>touches</code> object is not empty), then we will have all the info we need in that object. We can get the first touch (<code>e.touches[0]</code>, our example is not multitouch-enabled), extract the <code>pageX</code> and <code>pageY</code> variables and set the player's ship position on the screen by subtracting the Canvas offset (distance from the Canvas and the edge of the screen) and half the player's width and height.</p>
+
+<p><img alt="Touch controls for the player's ship, with visible output of the x and y position." src="https://mdn.mozillademos.org/files/14201/controls-touch.png" style="border-style: solid; border-width: 1px; display: block; height: 436px; margin: 0px auto; width: 575px;"></p>
+
+<p>To see if it's working correctly we can output the <code>x</code> and <code>y</code> positions using the <code>output</code> element. The <code>preventDefault()</code> function is needed to prevent the browser from moving — without it you'd have the default behaviour, and the Canvas would be dragged around the page, which would show the browser scroll bars and look messy.</p>
+
+<h2 id="Touch_events_in_Phaser">Touch events in Phaser</h2>
+
+<p>We don't have to do this on our own; frameworks like Phaser offer systems for managing touch events for us — see <a href="http://phaser.io/docs/2.6.1/Phaser.Touch.html">managing the touch events</a>.</p>
+
+<h3 id="Pointer_theory">Pointer theory</h3>
+
+<p>A <a href="http://phaser.io/docs/2.6.1/Phaser.Pointer.html">pointer</a> represents a single finger on the touch screen. Phaser starts two pointers by default, so two fingers can perform an action at once. Captain Rogers is a simple game — it can be controlled by two fingers, the left one moving the ship and the right one controlling the ship's gun. There's no multitouch or gestures — everything is handled by single pointer inputs.</p>
+
+<p>You can add more pointers to the game by using; <code>this.game.input.addPointer</code> up to ten pointers can be managed simultaneously. The most recently used pointer is available in the <code>this.game.input.activePointer</code> object — the most recent finger active on the screen.</p>
+
+<p>If you need to access a specific pointer, they are all available at, <code>this.game.input.pointer1</code><code>this.game.input.pointer2</code>, etc. They are assigned dynamically, so if you put three fingers on the screen, then, <code>pointer1</code><code>pointer2</code>, and <code>pointer3</code> will be active. Removing the second finger, for example, won't affect the other two, and setting it back again will use the first available property, so <code>pointer2</code> will be used again.</p>
+
+<p>You can quickly get the coordinates of the most recently active pointer via the <code>this.game.input.x</code> and <code>this.game.input.y</code> variables.</p>
+
+<h3 id="Input_events">Input events</h3>
+
+<p>Instead of using the pointers directly it is also possible to listen for <code>this.game.input</code> events, like <code>onDown</code>, <code>onUp</code>, <code>onTap</code> and <code>onHold</code>:</p>
+
+<pre class="brush: js">this.game.input.onDown.add(itemTouched, this);
+
+function itemTouched(pointer) {
+ // do something
+}</pre>
+
+<p>The <code>itemTouched()</code> function will be executed when the <code>onDown</code> event is dispatched by touching the screen. The <code>pointer</code> variable will contain the information about the pointer that activated the event.</p>
+
+<p>This approach uses the generally available <code>this.game.input</code> object, but you can also detect the actions on any game objects like sprites or buttons by using <code>onInputOver</code>, <code>onInputOut</code>, <code>onInputDown</code>, <code>onInputUp</code>, <code>onDragStart</code>, or <code>onDragStop</code>:</p>
+
+<pre class="brush: js">this.button.events.onInputOver.add(itemTouched, this);
+
+function itemTouched(button, pointer) {
+ // do something
+}</pre>
+
+<p>That way you'll be able to attach an event to any object in the game, like the player's ship, and react to the actions performed by the user.</p>
+
+<p>An additional advantage of using Phaser is that the buttons you create will take any type of input, whether it's a touch on mobile or a click on desktop — the framework sorts this out in the background for you.</p>
+
+<h3 id="Implementation">Implementation</h3>
+
+<p>The easiest way to add an interactive object that will listen for user input is to create a button:</p>
+
+<pre class="brush: js">var buttonEnclave = this.add.button(10, 10, 'logo-enclave', this.clickEnclave, this);</pre>
+
+<p>This one is formed in the <code>MainMenu</code> state — it will be placed ten pixels from the top left corner of the screen, use the <code>logo-enclave</code> image, and execute the <code>clickEnclave()</code> function when it is touched. This will work on mobile and desktop out of the box. There are a few buttons in the main menu, including the one that will start the game.</p>
+
+<p>For the actual gameplay, instead of creating more buttons and covering the small mobile screen with them, we can use something a little bit different: we'll create invisible areas which respond to the given action. From a design point of view, it is better to make the field of activity bigger without covering half of the screen with button images. For example, tapping on the right side of the screen will fire the weapon:</p>
+
+<pre class="brush: js">this.buttonShoot = this.add.button(this.world.width*0.5, 0, 'button-alpha', null, this);
+this.buttonShoot.onInputDown.add(this.goShootPressed, this);
+this.buttonShoot.onInputUp.add(this.goShootReleased, this);</pre>
+
+<p>The code above will create a new button using a transparent image that covers the right half of the screen. You can assign functions on input down and input up separately if you'd like to perform more complicated actions, but in this game touching the right side of the screen will simply fire the bullets to the right — this is all we need in this case.</p>
+
+<p>Moving the player could be managed by creating the four directional buttons, but we can take the advantage of touch screens and drag the player's ship around:</p>
+
+<pre class="brush: js">var player = this.game.add.sprite(30, 30, 'ship');
+player.inputEnabled = true;
+player.input.enableDrag();
+player.events.onDragStart.add(onDragStart, this);
+player.events.onDragStop.add(onDragStop, this);
+
+function onDragStart(sprite, pointer) {
+ // do something when dragging
+}</pre>
+
+<p>We can pull the ship around and do something in the meantime, and react when the drag is stopped. Hauling in Phaser, if enabled, will work out of the box — you don't have to set the position of the sprite yourself manually, so you could leave the <code>onDragStart()</code> function empty, or place some debug output to see if it's working correctly. The <code>pointer</code> element contains the <code>x</code> and <code>y</code> variables storing the current position of the dragged element.</p>
+
+<h3 id="Dedicated_plugins">Dedicated plugins</h3>
+
+<p>You could go even further and use dedicated plugins like <a href="http://phaser.io/shop/plugins/virtualjoystick">Virtual Joystick</a> — this is a paid, official Phaser plugin, but you can find free and <a href="https://github.com/Gamegur-us/phaser-touch-control-plugin">open source alternatives</a>. The initialization of Virtual Joystick looks like this:</p>
+
+<pre class="brush: js">this.pad = this.game.plugins.add(Phaser.VirtualJoystick);
+this.stick = this.pad.addStick(30, 30, 80, 'generic');</pre>
+
+<p>In the <code>create()</code> function of the <code>Game</code> state we're creating a virtual pad and a generic stick that has four directional virtual buttons by default. This is placed 30 pixels from the top and left edges of the screen and is 80 pixels wide.</p>
+
+<p>The stick being pressed can be handled during the gameplay in the <code>update</code> function like so:</p>
+
+<pre class="brush: js">if(this.stick.isDown) {
+ // move the player
+}</pre>
+
+<p>We can adjust the player's velocity based on the current angle of the stick and move him appropriately.</p>
+
+<h2 id="摘要">摘要</h2>
+
+<p>这篇文章主要讲解如何在移动端实现触摸控制; 下一篇文章我们将看到怎样添加键盘和鼠标支持。</p>
+
+<p>{{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}</p>