diff --git a/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.jsx b/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.jsx
index cd9c97dd676..ede808e24aa 100644
--- a/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.jsx
+++ b/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.jsx
@@ -1,8 +1,392 @@
// Deck definitions for the blockBasics/blockGames tutorial categories
-// (Phase 3, issue #680). Stub — populated by #680 so
-// that category can be developed without touching index.jsx or the
-// other tutorial categories (issue #932).
+// (Phase 3, issue #680). This module holds the blockGames (第4章
+// シューティング) decks (issue #958).
+//
+// These decks are book-excerpt "試食" tutorials: each opens with the book's
+// bibliographic info and closes with a "続きは書籍で" purchase link. The
+// shared opening/closing steps and book constant live in book-promo.jsx
+// (issue #956). The excerpted programs come from
+// docs/tutorial/book-kirakira-ruby-source.md 第4章 (chapter 4), converted to
+// Ruby v2 syntax so they convert cleanly into blocks.
-const decks = {};
+import React from 'react';
+import {FormattedMessage} from 'react-intl';
+
+import {CATEGORIES} from '../../tutorial-tags';
+import GreenFlagIcon from '../green-flag-icon.jsx';
+import {bookOpeningStep, bookClosingStep, bookAdvancedClosingStep} from './book-promo.jsx';
+
+import libraryBlockShootingLv0 from '../thumbnails/block-shooting-lv0.jpg';
+import libraryBlockShootingLv2 from '../thumbnails/block-shooting-lv2.jpg';
+import libraryBlockShootingLv3 from '../thumbnails/block-shooting-lv3.jpg';
+import libraryBlockShootingAdvanced from '../thumbnails/block-shooting-advanced.jpg';
+
+// Chapter this series excerpts from (see book-kirakira-ruby-source.md).
+const CHAPTER = 4;
+
+// ネコ(スプライト1)を上下に動かすプログラム。Lv0/Lv2/Lv3 で共通の題材。
+const CAT_MOVE_CODE = `when_key_pressed("up arrow") do
+ self.y += 10
+end
+when_key_pressed("down arrow") do
+ self.y += -10
+end`;
+
+// タマ(Arrow1)を発射して右へ飛ばし、端で消すプログラム。
+const BULLET_CODE = `when_flag_clicked do
+ hide
+end
+when_key_pressed("space") do
+ go_to("スプライト1")
+ show
+ until touching?("_edge_")
+ self.x += 10
+ end
+ hide
+end`;
+
+// 発展:クローンでタマをたくさん出すプログラム(見せるだけ)。
+const CLONE_CODE = `when_flag_clicked do
+ hide
+end
+when_key_pressed("space") do
+ create_clone("_myself_")
+end
+when_start_as_a_clone do
+ go_to("スプライト1")
+ show
+ until touching?("_edge_")
+ self.x += 10
+ end
+ delete_this_clone
+end`;
+
+const decks = {
+ // ─── blockGames 第4章 Lv0:コードを挿入して動かしてみる ───
+ 'block-shooting-lv0': {
+ name: (
+
+ ),
+ tags: [],
+ category: CATEGORIES.blockGames,
+ img: libraryBlockShootingLv0,
+ nameMessageId: 'gui.howtos.block-shooting-lv0.name',
+ allowedBlocks: {
+ motion: ['motion_changeyby'],
+ looks: [],
+ sound: [],
+ event: ['event_whenkeypressed'],
+ control: [],
+ sensing: [],
+ operators: [],
+ },
+ steps: [
+ bookOpeningStep(CHAPTER, 'blockShootingOpening'),
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv0Intro',
+ startTutorial: true,
+ animationTarget: 'startTutorialButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv0Move',
+ code: CAT_MOVE_CODE,
+ codeType: 'blocks',
+ animationTarget: 'insertCodeButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingRun',
+ animationTarget: 'nextButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv0Customize',
+ animationTarget: 'nextButton',
+ },
+ bookClosingStep(CHAPTER, 'blockShootingClosing'),
+ ],
+ urlId: 'blockShootingLv0',
+ },
+
+ // ─── blockGames 第4章 Lv2:ブロックを自分で組み立てる ───
+ 'block-shooting-lv2': {
+ name: (
+
+ ),
+ tags: [],
+ category: CATEGORIES.blockGames,
+ img: libraryBlockShootingLv2,
+ nameMessageId: 'gui.howtos.block-shooting-lv2.name',
+ allowedBlocks: {
+ motion: ['motion_changeyby', 'motion_changexby', 'motion_goto'],
+ looks: ['looks_show', 'looks_hide'],
+ sound: [],
+ event: ['event_whenflagclicked', 'event_whenkeypressed'],
+ control: ['control_repeat_until'],
+ sensing: ['sensing_touchingobject'],
+ operators: [],
+ },
+ steps: [
+ bookOpeningStep(CHAPTER, 'blockShootingOpening'),
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv2Intro',
+ startTutorial: true,
+ animationTarget: 'startTutorialButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv2CatBlocks',
+ animationTarget: 'nextButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingAddArrow',
+ animationTarget: 'nextButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv2BulletBlocks',
+ animationTarget: 'nextButton',
+ },
+ {
+ title: (
+ }}
+ />
+ ),
+ image: 'blockShootingRun',
+ animationTarget: 'nextButton',
+ },
+ bookClosingStep(CHAPTER, 'blockShootingClosing'),
+ ],
+ urlId: 'blockShootingLv2',
+ },
+
+ // ─── blockGames 第4章 Lv3:Ruby で書く ───
+ 'block-shooting-lv3': {
+ name: (
+
+ ),
+ tags: ['ruby'],
+ category: CATEGORIES.blockGames,
+ img: libraryBlockShootingLv3,
+ nameMessageId: 'gui.howtos.block-shooting-lv3.name',
+ // Lv3 は Ruby タブ・Ruby モードで開く(improvement-plan.md 参照)。
+ setup: {
+ tab: 'ruby',
+ rubyMode: 'ruby',
+ },
+ allowedBlocks: {
+ motion: ['motion_changeyby', 'motion_changexby', 'motion_goto'],
+ looks: ['looks_show', 'looks_hide'],
+ sound: [],
+ event: ['event_whenflagclicked', 'event_whenkeypressed'],
+ control: ['control_repeat_until'],
+ sensing: ['sensing_touchingobject'],
+ operators: [],
+ },
+ steps: [
+ bookOpeningStep(CHAPTER, 'blockShootingOpening'),
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv3RubyTab',
+ startTutorial: true,
+ animationTarget: 'startTutorialButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv3CatCode',
+ code: CAT_MOVE_CODE,
+ animationTarget: 'insertCodeButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingAddArrow',
+ animationTarget: 'nextButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingLv3BulletCode',
+ code: BULLET_CODE,
+ animationTarget: 'insertCodeButton',
+ },
+ {
+ title: (
+ }}
+ />
+ ),
+ image: 'blockShootingRun',
+ animationTarget: 'nextButton',
+ },
+ bookClosingStep(CHAPTER, 'blockShootingClosing'),
+ ],
+ urlId: 'blockShootingLv3',
+ },
+
+ // ─── blockGames 第4章【発展】:クローンでタマを増やす(見せるだけ・Lv0) ───
+ 'block-shooting-advanced': {
+ name: (
+
+ ),
+ tags: [],
+ category: CATEGORIES.blockGames,
+ img: libraryBlockShootingAdvanced,
+ nameMessageId: 'gui.howtos.block-shooting-advanced.name',
+ allowedBlocks: {
+ motion: ['motion_changexby', 'motion_goto'],
+ looks: ['looks_show', 'looks_hide'],
+ sound: [],
+ event: ['event_whenflagclicked', 'event_whenkeypressed'],
+ control: [
+ 'control_create_clone_of',
+ 'control_start_as_clone',
+ 'control_delete_this_clone',
+ 'control_repeat_until',
+ ],
+ sensing: ['sensing_touchingobject'],
+ operators: [],
+ },
+ steps: [
+ bookOpeningStep(CHAPTER, 'blockShootingOpening'),
+ {
+ title: (
+
+ ),
+ image: 'blockShootingAdvIntro',
+ startTutorial: true,
+ animationTarget: 'startTutorialButton',
+ },
+ {
+ title: (
+
+ ),
+ image: 'blockShootingAdvClone',
+ code: CLONE_CODE,
+ codeType: 'blocks',
+ animationTarget: 'insertCodeButton',
+ },
+ {
+ title: (
+ }}
+ />
+ ),
+ image: 'blockShootingRun',
+ animationTarget: 'nextButton',
+ },
+ bookAdvancedClosingStep(CHAPTER, 'blockShootingAdvClosing'),
+ ],
+ urlId: 'blockShootingAdvanced',
+ },
+};
export default decks;
diff --git a/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.locale.js b/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.locale.js
index b46326f9dfc..3b7239f38fc 100644
--- a/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.locale.js
+++ b/packages/scratch-gui/src/lib/libraries/decks/categories/block-series.locale.js
@@ -44,14 +44,138 @@ const bookPromoEn = {
'gui.howtos.book-promo.purchase': '📖 Buy the book',
};
+// blockGames 第4章(シューティング)の deck 名・ステップ文言(issue #958)。
+const blockGames = {
+ 'gui.howtos.block-shooting-lv0.name': 'シューティングゲームを作ろう Lv0',
+ 'gui.howtos.block-shooting-lv0.step.intro':
+ 'この章ではネコが上下に動いてタマをうつシューティングゲームを作るよ。まずは動かしてみよう!',
+ 'gui.howtos.block-shooting-lv0.step.move':
+ '「コードを挿入」ボタンを押して、ネコを上下に動かすプログラムを入れてみよう',
+ 'gui.howtos.block-shooting-lv0.step.run': 'キーボードの上・下の矢印キーを押すと、ネコが上下に動くよ',
+ 'gui.howtos.block-shooting-lv0.step.customize':
+ '「10」の数を変えると、動く速さが変わるよ。好きな数に変えて試してみよう',
+ 'gui.howtos.block-shooting-lv2.name': 'シューティングゲームを作ろう Lv2',
+ 'gui.howtos.block-shooting-lv2.step.intro': '今度はブロックを自分で組み立ててみよう!',
+ 'gui.howtos.block-shooting-lv2.step.catBlocks':
+ 'ネコ:「上向き矢印キーが押されたとき」に「y座標を10ずつ変える」、下向きには「-10ずつ変える」を組み立てよう。y座標は上下の位置だよ',
+ 'gui.howtos.block-shooting-lv2.step.addArrow':
+ 'タマになるスプライト「Arrow1」を追加しよう(スプライト一覧の+ボタンから選べるよ)',
+ 'gui.howtos.block-shooting-lv2.step.bulletBlocks':
+ 'タマ:スペースキーで「スプライト1へ行く」「表示する」、そして「端に触れるまでx座標を10ずつ変える」を繰り返し、最後に「隠す」。' +
+ '『〜まで繰り返す』は条件が成り立つまで続けるブロックだよ',
+ 'gui.howtos.block-shooting-lv2.step.run':
+ '{greenFlag}を押して、矢印キーで動かしスペースキーでタマをうってみよう!',
+ 'gui.howtos.block-shooting-lv3.name': 'シューティングゲームを作ろう Lv3',
+ 'gui.howtos.block-shooting-lv3.step.intro':
+ '同じゲームを Ruby で書いてみよう。ルビータブが開いているのを確認してね',
+ 'gui.howtos.block-shooting-lv3.step.catCode':
+ 'ネコ:「コードを挿入」で上下移動のプログラムを入れよう。self.y は上下の位置だよ',
+ 'gui.howtos.block-shooting-lv3.step.addArrow':
+ 'タマになるスプライト「Arrow1」を追加して、そのスプライトを選ぼう',
+ 'gui.howtos.block-shooting-lv3.step.bulletCode':
+ 'タマ:スペースキーで発射して右へ飛ばすプログラムを入れよう。until は条件が成り立つまで繰り返すよ',
+ 'gui.howtos.block-shooting-lv3.step.run':
+ '{greenFlag}を押して、矢印キーとスペースキーで遊んでみよう!',
+ 'gui.howtos.block-shooting-advanced.name': 'シューティングゲーム【発展】クローンでタマを増やそう',
+ 'gui.howtos.block-shooting-advanced.step.intro':
+ 'タマを一度にたくさん出すには「クローン」を使うよ。まずは動くところを見てみよう!',
+ 'gui.howtos.block-shooting-advanced.step.clone':
+ 'タマ(Arrow1)を選んで「コードを挿入」しよう。スペースキーを押すたびに自分のクローンを作ってタマを増やすよ',
+ 'gui.howtos.block-shooting-advanced.step.run':
+ '{greenFlag}を押して、スペースキーを連打してみよう。タマがどんどん増えるよ!',
+};
+
+const blockGamesHira = {
+ 'gui.howtos.block-shooting-lv0.name': 'シューティングゲームをつくろう Lv0',
+ 'gui.howtos.block-shooting-lv0.step.intro':
+ 'このしょうではネコがじょうげにうごいてタマをうつシューティングゲームをつくるよ。まずはうごかしてみよう!',
+ 'gui.howtos.block-shooting-lv0.step.move':
+ '「コードをそうにゅう」ボタンをおして、ネコをじょうげにうごかすプログラムをいれてみよう',
+ 'gui.howtos.block-shooting-lv0.step.run':
+ 'キーボードのうえ・したのやじるしキーをおすと、ネコがじょうげにうごくよ',
+ 'gui.howtos.block-shooting-lv0.step.customize':
+ '「10」のかずをかえると、うごくはやさがかわるよ。すきなかずにかえてためしてみよう',
+ 'gui.howtos.block-shooting-lv2.name': 'シューティングゲームをつくろう Lv2',
+ 'gui.howtos.block-shooting-lv2.step.intro': 'こんどはブロックをじぶんでくみたててみよう!',
+ 'gui.howtos.block-shooting-lv2.step.catBlocks':
+ 'ネコ:「うわむきやじるしキーがおされたとき」に「yざひょうを10ずつかえる」、したむきには「-10ずつかえる」をくみたてよう。yざひょうはじょうげのいちだよ',
+ 'gui.howtos.block-shooting-lv2.step.addArrow':
+ 'タマになるスプライト「Arrow1」をついかしよう(スプライトいちらんの+ボタンからえらべるよ)',
+ 'gui.howtos.block-shooting-lv2.step.bulletBlocks':
+ 'タマ:スペースキーで「スプライト1へいく」「ひょうじする」、そして「はしにふれるまでxざひょうを10ずつかえる」をくりかえし、さいごに「かくす」。' +
+ '『〜までくりかえす』はじょうけんがなりたつまでつづけるブロックだよ',
+ 'gui.howtos.block-shooting-lv2.step.run':
+ '{greenFlag}をおして、やじるしキーでうごかしスペースキーでタマをうってみよう!',
+ 'gui.howtos.block-shooting-lv3.name': 'シューティングゲームをつくろう Lv3',
+ 'gui.howtos.block-shooting-lv3.step.intro':
+ 'おなじゲームを Ruby でかいてみよう。ルビータブがひらいているのをかくにんしてね',
+ 'gui.howtos.block-shooting-lv3.step.catCode':
+ 'ネコ:「コードをそうにゅう」でじょうげいどうのプログラムをいれよう。self.y はじょうげのいちだよ',
+ 'gui.howtos.block-shooting-lv3.step.addArrow':
+ 'タマになるスプライト「Arrow1」をついかして、そのスプライトをえらぼう',
+ 'gui.howtos.block-shooting-lv3.step.bulletCode':
+ 'タマ:スペースキーではっしゃしてみぎへとばすプログラムをいれよう。until はじょうけんがなりたつまでくりかえすよ',
+ 'gui.howtos.block-shooting-lv3.step.run':
+ '{greenFlag}をおして、やじるしキーとスペースキーであそんでみよう!',
+ 'gui.howtos.block-shooting-advanced.name': 'シューティングゲーム【はってん】クローンでタマをふやそう',
+ 'gui.howtos.block-shooting-advanced.step.intro':
+ 'タマをいちどにたくさんだすには「クローン」をつかうよ。まずはうごくところをみてみよう!',
+ 'gui.howtos.block-shooting-advanced.step.clone':
+ 'タマ(Arrow1)をえらんで「コードをそうにゅう」しよう。スペースキーをおすたびにじぶんのクローンをつくってタマをふやすよ',
+ 'gui.howtos.block-shooting-advanced.step.run':
+ '{greenFlag}をおして、スペースキーをれんだしてみよう。タマがどんどんふえるよ!',
+};
+
+const blockGamesEn = {
+ 'gui.howtos.block-shooting-lv0.name': 'Make a Shooting Game Lv0',
+ 'gui.howtos.block-shooting-lv0.step.intro':
+ 'In this chapter we make a shooting game where the cat moves up and down and shoots. First, try running it!',
+ 'gui.howtos.block-shooting-lv0.step.move':
+ 'Press "Insert code" to add the program that moves the cat up and down',
+ 'gui.howtos.block-shooting-lv0.step.run': 'Press the up/down arrow keys and the cat moves up and down',
+ 'gui.howtos.block-shooting-lv0.step.customize':
+ 'Changing the "10" changes how fast it moves. Try your own number!',
+ 'gui.howtos.block-shooting-lv2.name': 'Make a Shooting Game Lv2',
+ 'gui.howtos.block-shooting-lv2.step.intro': 'Now build the blocks yourself!',
+ 'gui.howtos.block-shooting-lv2.step.catBlocks':
+ 'Cat: on "when up arrow key pressed", "change y by 10"; for down, "change y by -10". y is the up/down position.',
+ 'gui.howtos.block-shooting-lv2.step.addArrow':
+ 'Add the sprite "Arrow1" for the bullet (pick it with the + button in the sprite list)',
+ 'gui.howtos.block-shooting-lv2.step.bulletBlocks':
+ 'Bullet: on space, "go to スプライト1", "show", then "repeat until touching edge: change x by 10", finally "hide". ' +
+ '"Repeat until" keeps going until the condition becomes true.',
+ 'gui.howtos.block-shooting-lv2.step.run':
+ 'Press {greenFlag}, move with the arrow keys and shoot with the space key!',
+ 'gui.howtos.block-shooting-lv3.name': 'Make a Shooting Game Lv3',
+ 'gui.howtos.block-shooting-lv3.step.intro':
+ "Let's write the same game in Ruby. Make sure the Ruby tab is open.",
+ 'gui.howtos.block-shooting-lv3.step.catCode':
+ 'Cat: use "Insert code" to add the up/down movement. self.y is the up/down position.',
+ 'gui.howtos.block-shooting-lv3.step.addArrow': 'Add the sprite "Arrow1" for the bullet and select it',
+ 'gui.howtos.block-shooting-lv3.step.bulletCode':
+ 'Bullet: add the program that fires on space and flies right. "until" repeats until the condition is true.',
+ 'gui.howtos.block-shooting-lv3.step.run':
+ 'Press {greenFlag} and play with the arrow keys and the space key!',
+ 'gui.howtos.block-shooting-advanced.name': 'Shooting Game (Advanced): Multiply bullets with clones',
+ 'gui.howtos.block-shooting-advanced.step.intro':
+ 'To fire many bullets at once, use "clones". First, watch it run!',
+ 'gui.howtos.block-shooting-advanced.step.clone':
+ 'Select the bullet (Arrow1) and "Insert code". Each space press makes a clone of itself to add bullets.',
+ 'gui.howtos.block-shooting-advanced.step.run':
+ 'Press {greenFlag} and mash the space key. The bullets keep multiplying!',
+};
+
export const ja = {
...bookPromo,
+ ...blockGames,
};
export const jaHira = {
...bookPromoHira,
+ ...blockGamesHira,
};
export const en = {
...bookPromoEn,
+ ...blockGamesEn,
};
diff --git a/packages/scratch-gui/src/lib/libraries/decks/en-steps.js b/packages/scratch-gui/src/lib/libraries/decks/en-steps.js
index e09179c26e7..74d251ecb95 100644
--- a/packages/scratch-gui/src/lib/libraries/decks/en-steps.js
+++ b/packages/scratch-gui/src/lib/libraries/decks/en-steps.js
@@ -115,6 +115,24 @@ import rubyBasics6Step5 from './steps/ruby-basics-6-5-modify.png';
// only the final step shows the TryRuby screenshot (see tutorial.md image reuse rule).
import rubyBasics7TryRuby from './thumbnails/ruby-basics-1-tryruby.png';
+// blockGames 第4章 シューティング (issue #958)
+import blockShootingOpening from './steps/blockShootingOpening.png';
+import blockShootingLv0Intro from './steps/blockShootingLv0Intro.png';
+import blockShootingLv0Move from './steps/blockShootingLv0Move.png';
+import blockShootingRun from './steps/blockShootingRun.png';
+import blockShootingLv0Customize from './steps/blockShootingLv0Customize.png';
+import blockShootingClosing from './steps/blockShootingClosing.png';
+import blockShootingLv2Intro from './steps/blockShootingLv2Intro.png';
+import blockShootingLv2CatBlocks from './steps/blockShootingLv2CatBlocks.png';
+import blockShootingAddArrow from './steps/blockShootingAddArrow.png';
+import blockShootingLv2BulletBlocks from './steps/blockShootingLv2BulletBlocks.png';
+import blockShootingLv3RubyTab from './steps/blockShootingLv3RubyTab.png';
+import blockShootingLv3CatCode from './steps/blockShootingLv3CatCode.png';
+import blockShootingLv3BulletCode from './steps/blockShootingLv3BulletCode.png';
+import blockShootingAdvIntro from './steps/blockShootingAdvIntro.png';
+import blockShootingAdvClone from './steps/blockShootingAdvClone.png';
+import blockShootingAdvClosing from './steps/blockShootingAdvClosing.png';
+
const enImages = {
// Getting Started
introRubyTab: introRubyTab,
@@ -214,7 +232,24 @@ const enImages = {
rubyBasics6Step4: rubyBasics6Step4,
rubyBasics6Step5: rubyBasics6Step5,
- rubyBasics7TryRuby: rubyBasics7TryRuby
+ rubyBasics7TryRuby: rubyBasics7TryRuby,
+ // blockGames 第4章 シューティング (issue #958)
+ blockShootingOpening: blockShootingOpening,
+ blockShootingLv0Intro: blockShootingLv0Intro,
+ blockShootingLv0Move: blockShootingLv0Move,
+ blockShootingRun: blockShootingRun,
+ blockShootingLv0Customize: blockShootingLv0Customize,
+ blockShootingClosing: blockShootingClosing,
+ blockShootingLv2Intro: blockShootingLv2Intro,
+ blockShootingLv2CatBlocks: blockShootingLv2CatBlocks,
+ blockShootingAddArrow: blockShootingAddArrow,
+ blockShootingLv2BulletBlocks: blockShootingLv2BulletBlocks,
+ blockShootingLv3RubyTab: blockShootingLv3RubyTab,
+ blockShootingLv3CatCode: blockShootingLv3CatCode,
+ blockShootingLv3BulletCode: blockShootingLv3BulletCode,
+ blockShootingAdvIntro: blockShootingAdvIntro,
+ blockShootingAdvClone: blockShootingAdvClone,
+ blockShootingAdvClosing: blockShootingAdvClosing
};
export {enImages};
diff --git a/packages/scratch-gui/src/lib/libraries/decks/ja-steps.js b/packages/scratch-gui/src/lib/libraries/decks/ja-steps.js
index 6f8c65d90fc..2d6a86f8461 100644
--- a/packages/scratch-gui/src/lib/libraries/decks/ja-steps.js
+++ b/packages/scratch-gui/src/lib/libraries/decks/ja-steps.js
@@ -116,6 +116,24 @@ import rubyBasics6Step5 from './steps/ruby-basics-6-5-modify.png';
// (docs/tutorial/improvement-plan.md Phase 2 / tutorial.md「画像の流用ルール」)。
import rubyBasics7TryRuby from './thumbnails/ruby-basics-1-tryruby.png';
+// blockGames 第4章 シューティング (issue #958)
+import blockShootingOpening from './steps/blockShootingOpening.png';
+import blockShootingLv0Intro from './steps/blockShootingLv0Intro.png';
+import blockShootingLv0Move from './steps/blockShootingLv0Move.png';
+import blockShootingRun from './steps/blockShootingRun.png';
+import blockShootingLv0Customize from './steps/blockShootingLv0Customize.png';
+import blockShootingClosing from './steps/blockShootingClosing.png';
+import blockShootingLv2Intro from './steps/blockShootingLv2Intro.png';
+import blockShootingLv2CatBlocks from './steps/blockShootingLv2CatBlocks.png';
+import blockShootingAddArrow from './steps/blockShootingAddArrow.png';
+import blockShootingLv2BulletBlocks from './steps/blockShootingLv2BulletBlocks.png';
+import blockShootingLv3RubyTab from './steps/blockShootingLv3RubyTab.png';
+import blockShootingLv3CatCode from './steps/blockShootingLv3CatCode.png';
+import blockShootingLv3BulletCode from './steps/blockShootingLv3BulletCode.png';
+import blockShootingAdvIntro from './steps/blockShootingAdvIntro.png';
+import blockShootingAdvClone from './steps/blockShootingAdvClone.png';
+import blockShootingAdvClosing from './steps/blockShootingAdvClosing.png';
+
const jaImages = {
// Getting Started
introRubyTab: introRubyTab,
@@ -215,7 +233,24 @@ const jaImages = {
rubyBasics6Step4: rubyBasics6Step4,
rubyBasics6Step5: rubyBasics6Step5,
- rubyBasics7TryRuby: rubyBasics7TryRuby
+ rubyBasics7TryRuby: rubyBasics7TryRuby,
+ // blockGames 第4章 シューティング (issue #958)
+ blockShootingOpening: blockShootingOpening,
+ blockShootingLv0Intro: blockShootingLv0Intro,
+ blockShootingLv0Move: blockShootingLv0Move,
+ blockShootingRun: blockShootingRun,
+ blockShootingLv0Customize: blockShootingLv0Customize,
+ blockShootingClosing: blockShootingClosing,
+ blockShootingLv2Intro: blockShootingLv2Intro,
+ blockShootingLv2CatBlocks: blockShootingLv2CatBlocks,
+ blockShootingAddArrow: blockShootingAddArrow,
+ blockShootingLv2BulletBlocks: blockShootingLv2BulletBlocks,
+ blockShootingLv3RubyTab: blockShootingLv3RubyTab,
+ blockShootingLv3CatCode: blockShootingLv3CatCode,
+ blockShootingLv3BulletCode: blockShootingLv3BulletCode,
+ blockShootingAdvIntro: blockShootingAdvIntro,
+ blockShootingAdvClone: blockShootingAdvClone,
+ blockShootingAdvClosing: blockShootingAdvClosing
};
export {jaImages};
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAddArrow.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAddArrow.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAddArrow.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClone.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClone.png
new file mode 100644
index 00000000000..9bd9aea3aa9
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClone.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClosing.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClosing.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvClosing.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvIntro.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvIntro.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingAdvIntro.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingClosing.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingClosing.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingClosing.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Customize.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Customize.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Customize.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Intro.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Intro.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Intro.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Move.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Move.png
new file mode 100644
index 00000000000..bd85cdb9efb
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv0Move.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2BulletBlocks.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2BulletBlocks.png
new file mode 100644
index 00000000000..ac44ace9418
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2BulletBlocks.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2CatBlocks.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2CatBlocks.png
new file mode 100644
index 00000000000..bd85cdb9efb
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2CatBlocks.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2Intro.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2Intro.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv2Intro.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3BulletCode.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3BulletCode.png
new file mode 100644
index 00000000000..e959de64de1
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3BulletCode.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3CatCode.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3CatCode.png
new file mode 100644
index 00000000000..881028bf0b7
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3CatCode.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3RubyTab.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3RubyTab.png
new file mode 100644
index 00000000000..881028bf0b7
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingLv3RubyTab.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingOpening.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingOpening.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingOpening.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingRun.png b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingRun.png
new file mode 100644
index 00000000000..187c483c366
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/steps/blockShootingRun.png differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-advanced.jpg b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-advanced.jpg
new file mode 100644
index 00000000000..9666c37bd30
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-advanced.jpg differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv0.jpg b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv0.jpg
new file mode 100644
index 00000000000..66b4575d027
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv0.jpg differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv2.jpg b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv2.jpg
new file mode 100644
index 00000000000..e854f33c27e
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv2.jpg differ
diff --git a/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv3.jpg b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv3.jpg
new file mode 100644
index 00000000000..4b7f9eda756
Binary files /dev/null and b/packages/scratch-gui/src/lib/libraries/decks/thumbnails/block-shooting-lv3.jpg differ
diff --git a/packages/scratch-gui/test/unit/lib/libraries/decks/tutorial-categories-refactor.test.js b/packages/scratch-gui/test/unit/lib/libraries/decks/tutorial-categories-refactor.test.js
index 1513ca0875d..b4cd8151cb6 100644
--- a/packages/scratch-gui/test/unit/lib/libraries/decks/tutorial-categories-refactor.test.js
+++ b/packages/scratch-gui/test/unit/lib/libraries/decks/tutorial-categories-refactor.test.js
@@ -1,8 +1,9 @@
/**
* Guards the decks/index.jsx + locale-file split into per-category modules
- * (issue #932): deck order/content must stay identical, and the Phase 3
- * (#680) / Phase 4 (#681) stub categories must be independent, empty, and
- * not collide with the existing categories.
+ * (issue #932): deck order/content must stay identical across the split.
+ * block-series has since been populated by Phase 4 (#681 / #958); dncl is
+ * still an empty stub for Phase 3 (#680). Each category module must remain
+ * independent and not collide with the others.
*/
import decks from '../../../../../src/lib/libraries/decks/index.jsx';
import gettingStartedDecks from '../../../../../src/lib/libraries/decks/categories/getting-started.jsx';
@@ -42,7 +43,19 @@ const EXPECTED_DECK_ID_ORDER = [
'ruby-basics-4-arrays',
'ruby-basics-5-blocks',
'ruby-basics-6-methods',
- 'ruby-basics-7-next'
+ 'ruby-basics-7-next',
+ // block-series decks (Phase 4 / #681, #958) — appended after ruby-basics
+ 'block-shooting-lv0',
+ 'block-shooting-lv2',
+ 'block-shooting-lv3',
+ 'block-shooting-advanced'
+];
+
+const BLOCK_SERIES_DECK_IDS = [
+ 'block-shooting-lv0',
+ 'block-shooting-lv2',
+ 'block-shooting-lv3',
+ 'block-shooting-advanced'
];
describe('Tutorial deck category split (issue #932)', () => {
@@ -50,7 +63,7 @@ describe('Tutorial deck category split (issue #932)', () => {
expect(Object.keys(decks)).toEqual(EXPECTED_DECK_ID_ORDER);
});
- test('getting-started and ruby-basics decks are composed from their category modules', () => {
+ test('getting-started, ruby-basics and block-series decks are composed from their category modules', () => {
expect(decks['intro-getting-started']).toBe(gettingStartedDecks['intro-getting-started']);
expect(decks['ruby-basics-1-numbers']).toBe(rubyBasicsDecks['ruby-basics-1-numbers']);
expect(decks['ruby-basics-2-strings']).toBe(rubyBasicsDecks['ruby-basics-2-strings']);
@@ -58,13 +71,15 @@ describe('Tutorial deck category split (issue #932)', () => {
expect(decks['ruby-basics-4-arrays']).toBe(rubyBasicsDecks['ruby-basics-4-arrays']);
expect(decks['ruby-basics-5-blocks']).toBe(rubyBasicsDecks['ruby-basics-5-blocks']);
expect(decks['ruby-basics-6-methods']).toBe(rubyBasicsDecks['ruby-basics-6-methods']);
+ BLOCK_SERIES_DECK_IDS.forEach(id => {
+ expect(decks[id]).toBe(blockSeriesDecks[id]);
+ });
});
- test('block-series and dncl are empty stub categories that add no deck ids', () => {
- expect(blockSeriesDecks).toEqual({});
+ test('block-series exposes exactly its Phase 4 decks; dncl is still an empty stub', () => {
+ expect(Object.keys(blockSeriesDecks)).toEqual(BLOCK_SERIES_DECK_IDS);
expect(dnclDecks).toEqual({});
EXPECTED_DECK_ID_ORDER.forEach(id => {
- expect(Object.prototype.hasOwnProperty.call(blockSeriesDecks, id)).toBe(false);
expect(Object.prototype.hasOwnProperty.call(dnclDecks, id)).toBe(false);
});
});
@@ -75,15 +90,23 @@ describe('Tutorial deck category split (issue #932)', () => {
expect(dnclLocale.en).toEqual({});
});
- test('block-series locale holds only the shared book-promo foundation (issue #956), no deck-id howtos', () => {
- // #956 populates the Block-axis common book-promotion strings; the
- // per-deck howto strings still come later (#680).
+ test('block-series locale holds the shared book-promo foundation (#956) plus Phase 4 deck howtos (#681)', () => {
+ // #956 added the Block-axis common book-promotion strings; #681/#958
+ // added the per-deck howto strings for the block-shooting decks.
[blockSeriesLocale.ja, blockSeriesLocale.jaHira, blockSeriesLocale.en].forEach(table => {
const keys = Object.keys(table);
expect(keys.length).toBeGreaterThan(0);
+ // every key is either the shared book-promo foundation or a
+ // block-shooting deck howto — no strays from other categories.
keys.forEach(id => {
- expect(id.startsWith('gui.howtos.book-promo.')).toBe(true);
+ const isBookPromo = id.startsWith('gui.howtos.book-promo.');
+ const isBlockShooting = BLOCK_SERIES_DECK_IDS.some(
+ deckId => id.startsWith(`gui.howtos.${deckId}.`)
+ );
+ expect(isBookPromo || isBlockShooting).toBe(true);
});
+ // the shared book-promo foundation must still be present.
+ expect(keys.some(id => id.startsWith('gui.howtos.book-promo.'))).toBe(true);
});
});