{"id":"asteroids-shapes","slug":"shapes","title":"The sea and the submarine","text":"The MOOC's section 14.3 builds a larger program step by step: a game in the style of Asteroids, where a ship turns, speeds up, shoots and dodges rocks. This module builds the same kind of game in a theme of its own: a small **yellow submarine** in a dark sea. It steers with the arrow keys, dodges **jellyfish** and fires **bubbles** at them. Each step adds one idea, and by step 8 it's a whole game with points and a game over.\n\n### How a game runs on this page\n\nAs with the windows, charts and drawings before (module 48 explained it), Java Arena's JavaFX is a practice version written for this site, and the page draws the game from what your program told JavaFX: every shape with its corners, its place, its turn and its color, approximately. The game **doesn't run live** here. Your program runs from its start to its end each time: you choose which keys are held and how many frames to run, the program runs those frames, and the page plays them back as an animation. The shapes, the turning, `Point2D` and the collision test of the practice version were compared with real JavaFX 21. Each model solution's game was also run on real JavaFX 21 frame by frame, with the same keys, and left the same shapes in the same places, turned the same way, after every step of each test. On your own computer, the same code runs live with the real JavaFX (step 8 says how).\n\n### A pane of a fixed size\n\nThe layouts of part 13 placed their children by themselves: a VBox one under the other, a GridPane in cells. A game places everything itself, so it uses the plainest layout, **Pane**, which leaves each child where the child says. Without one, a Pane is only as big as its children's own shapes, and moving a shape with translate doesn't count, so a game always gives it a size with `setPrefSize(width, height)`: its **preferred** size. A Scene made from that pane, without a size, takes the pane's.\n\nThen come the **shapes**, from the package `javafx.scene.shape`. They are nodes, like labels and canvases, so they go into the pane's children:\n\n```java\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Circle;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n\n        Rectangle water = new Rectangle(360, 240, Color.MIDNIGHTBLUE);\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(180);\n        sub.setTranslateY(120);\n        Circle bubble = new Circle(4, Color.LIGHTCYAN);\n        bubble.setTranslateX(215);\n        bubble.setTranslateY(110);\n\n        pane.getChildren().addAll(water, sub, bubble);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Deep dive\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Deep dive\",\"scene\":{\"width\":360,\"height\":240,\"root\":{\"n\":1,\"type\":\"Pane\",\"prefWidth\":360,\"prefHeight\":240,\"children\":[{\"n\":2,\"type\":\"Rectangle\",\"x\":0,\"y\":0,\"width\":360,\"height\":240,\"fill\":\"#191970\"},{\"n\":3,\"type\":\"Polygon\",\"translateX\":180,\"translateY\":120,\"points\":[-15,-6,9,-6,15,0,9,6,-15,6],\"fill\":\"#ffd700\"},{\"n\":4,\"type\":\"Circle\",\"translateX\":215,\"translateY\":110,\"centerX\":0,\"centerY\":0,\"radius\":4,\"fill\":\"#e0ffff\"}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Deep dive\\\"\\n  Pane 360 x 240\\n    Rectangle 360 x 240 at (0, 0), fill #191970\\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (180, 120), fill #ffd700\\n    Circle radius 4 at (0, 0), translate (215, 110), fill #e0ffff\"}\n```\n\n- `new Rectangle(360, 240, Color.MIDNIGHTBLUE)` is a filled rectangle 360 wide and 240 high, with its top left corner at (0, 0): the water.\n- `new Polygon(...)` is a shape with corners, given as numbers in pairs: x, then y, for each corner in turn. The submarine has five corners: (-15, -6), (9, -6), (15, 0), (9, 6) and (-15, 6). Its nose, (15, 0), points to the right. A polygon is closed: the last corner joins the first.\n- `new Circle(4, Color.LIGHTCYAN)` is a filled circle with a radius of 4 and its center at (0, 0).\n- `setFill` gives a shape its color. A new shape is black, as JavaFX makes it.\n- `pane.getChildren().addAll(water, sub, bubble)` puts the shapes into the pane. Later children are drawn over earlier ones, so the water goes first.\n\nCoordinates work as on module 52's canvas: (0, 0) is the top left corner of the pane, x grows to the right and y grows **down**.\n\n### Moving a shape: translate\n\nThe submarine's corners are around (0, 0), the pane's top left corner. `setTranslateX(180)` and `setTranslateY(120)` move the whole shape: what was at (0, 0) is drawn at (180, 120), the middle of the pane, and every corner moves with it. The corners themselves don't change: `getPoints()` gives them back as one list of numbers (x, y, x, y and so on), so `sub.getPoints().size()` is twice the number of corners, and it's the same list after a move. That is how the game will move things: it never changes a shape's corners, only its translate, frame after frame. The bubble is moved the same way, to (215, 110).\n\n### Turning a shape: rotate\n\n`setRotate(degrees)` turns a shape. A positive angle turns it **clockwise** on the screen (y grows down, so that's the direction of growing angles here), a negative one counterclockwise, and the shape turns about the **center of its own corners**: the middle of the box around its corners before it's moved. The submarine's corners go from -15 to 15 across and from -6 to 6 down, so that center is (0, 0), the point that translate moves, and the submarine turns on the spot. That's why the game's shapes are drawn around (0, 0).\n\nThree submarines, turned 0, 45 and -90 degrees:\n\n```java\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n        pane.getChildren().add(new Rectangle(360, 240, Color.MIDNIGHTBLUE));\n\n        int[] turns = {0, 45, -90};\n        for (int i = 0; i < turns.length; i++) {\n            Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n            sub.setFill(Color.GOLD);\n            sub.setTranslateX(70 + 110 * i);\n            sub.setTranslateY(120);\n            sub.setRotate(turns[i]);\n            pane.getChildren().add(sub);\n        }\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Turning\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Turning\",\"scene\":{\"width\":360,\"height\":240,\"root\":{\"n\":1,\"type\":\"Pane\",\"prefWidth\":360,\"prefHeight\":240,\"children\":[{\"n\":2,\"type\":\"Rectangle\",\"x\":0,\"y\":0,\"width\":360,\"height\":240,\"fill\":\"#191970\"},{\"n\":3,\"type\":\"Polygon\",\"translateX\":70,\"translateY\":120,\"points\":[-15,-6,9,-6,15,0,9,6,-15,6],\"fill\":\"#ffd700\"},{\"n\":4,\"type\":\"Polygon\",\"translateX\":180,\"translateY\":120,\"rotate\":45,\"points\":[-15,-6,9,-6,15,0,9,6,-15,6],\"fill\":\"#ffd700\"},{\"n\":5,\"type\":\"Polygon\",\"translateX\":290,\"translateY\":120,\"rotate\":-90,\"points\":[-15,-6,9,-6,15,0,9,6,-15,6],\"fill\":\"#ffd700\"}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Turning\\\"\\n  Pane 360 x 240\\n    Rectangle 360 x 240 at (0, 0), fill #191970\\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (70, 120), fill #ffd700\\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (180, 120), rotate 45, fill #ffd700\\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (290, 120), rotate -90, fill #ffd700\"}\n```\n\nThe first points right, the second down and to the right (45 degrees clockwise), the third straight up (90 degrees counterclockwise). Each loop round makes a **new** Polygon: a node can be in a pane only once, so three submarines need three shapes.\n\n### The window as text\n\n\"The window as text\" under each drawing lists the shapes, and it's what the challenges compare:\n\n```text\nWindow \"Turning\"\n  Pane 360 x 240\n    Rectangle 360 x 240 at (0, 0), fill #191970\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (70, 120), fill #ffd700\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (180, 120), rotate 45, fill #ffd700\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (290, 120), rotate -90, fill #ffd700\n```\n\n`Pane 360 x 240` is the pane's preferred size. A polygon's line has its corners as given, then `at` and its translate, then its rotate (when it isn't 0) and its fill. A rectangle's `at` is its own corner, and a circle's `at` is its center; a circle that is moved adds `translate (215, 110)`. The numbers are compared exactly, so a task always says where each shape goes, how far it's turned and in which color.\n","task":"The submarine at (90, 60), pointing down. Fill in the blanks: the pane gets the preferred size 360 x 240, and the submarine is moved to (90, 60) and turned so that its nose points straight down.\n","kind":"fill","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.[[setPrefSize]](360, 240);\n\n        Rectangle water = new Rectangle(360, 240, Color.MIDNIGHTBLUE);\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.[[setTranslateX]](90);\n        sub.setTranslateY([[60]]);\n        sub.[[setRotate]]([[90]]);\n\n        pane.getChildren().addAll(water, sub);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Deep dive\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n\n        Rectangle water = new Rectangle(360, 240, Color.MIDNIGHTBLUE);\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(90);\n        sub.setTranslateY(60);\n        sub.setRotate(90);\n\n        pane.getChildren().addAll(water, sub);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Deep dive\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["A pane's preferred size is set with `setPrefSize(width, height)`, and a shape is moved with `setTranslateX` and `setTranslateY`.","The nose points right at 0 degrees. Turning clockwise (a positive angle) by a quarter turn points it down: `setRotate(90)`."],"tests":[{"name":"Window","stdin":"","expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Deep dive","scene":{"width":360,"height":240,"root":{"n":1,"type":"Pane","prefWidth":360,"prefHeight":240,"children":[{"n":2,"type":"Rectangle","x":0,"y":0,"width":360,"height":240,"fill":"#191970"},{"n":3,"type":"Polygon","translateX":90,"translateY":60,"rotate":90,"points":[-15,-6,9,-6,15,0,9,6,-15,6],"fill":"#ffd700"}]}}}],"problems":[]},"outline":"Window \"Deep dive\"\n  Pane 360 x 240\n    Rectangle 360 x 240 at (0, 0), fill #191970\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (90, 60), rotate 90, fill #ffd700"}],"require":[],"forbid":[],"more":[{"task":"Add a jellyfish and a bubble to the sea. The starter code has the pane, the water and the submarine. After the submarine, add to the pane's children, in this order:\n\n1. a jellyfish: `new Polygon(-10, 0, -6, -8, 0, -10, 6, -8, 10, 0, 7, 10, 3, 2, 0, 10, -3, 2, -7, 10)` (a round top and three tentacles), filled with `Color.ORCHID`, moved to (270, 70) and turned 15 degrees\n2. a bubble: `new Circle(5, Color.LIGHTCYAN)`, moved with `setTranslateX` and `setTranslateY` to (60, 180)\n\nThe window it should show is drawn below.\n","kind":"code","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Circle;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n\n        Rectangle water = new Rectangle(360, 240, Color.MIDNIGHTBLUE);\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(180);\n        sub.setTranslateY(120);\n        pane.getChildren().addAll(water, sub);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Deep dive\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Circle;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n\n        Rectangle water = new Rectangle(360, 240, Color.MIDNIGHTBLUE);\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(180);\n        sub.setTranslateY(120);\n        pane.getChildren().addAll(water, sub);\n\n        Polygon jellyfish = new Polygon(-10, 0, -6, -8, 0, -10, 6, -8, 10, 0, 7, 10, 3, 2, 0, 10, -3, 2, -7, 10);\n        jellyfish.setFill(Color.ORCHID);\n        jellyfish.setTranslateX(270);\n        jellyfish.setTranslateY(70);\n        jellyfish.setRotate(15);\n        pane.getChildren().add(jellyfish);\n\n        Circle bubble = new Circle(5, Color.LIGHTCYAN);\n        bubble.setTranslateX(60);\n        bubble.setTranslateY(180);\n        pane.getChildren().add(bubble);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Deep dive\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["Make the jellyfish as the submarine is made: `new Polygon(...)` with the corners of the task, then `setFill`, `setTranslateX`, `setTranslateY` and `setRotate(15)`.","Add the shapes with `pane.getChildren().add(jellyfish);` and then `pane.getChildren().add(bubble);`, after the line that adds the water and the submarine."],"tests":[{"name":"Window","stdin":"","expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Deep dive","scene":{"width":360,"height":240,"root":{"n":1,"type":"Pane","prefWidth":360,"prefHeight":240,"children":[{"n":2,"type":"Rectangle","x":0,"y":0,"width":360,"height":240,"fill":"#191970"},{"n":3,"type":"Polygon","translateX":180,"translateY":120,"points":[-15,-6,9,-6,15,0,9,6,-15,6],"fill":"#ffd700"},{"n":4,"type":"Polygon","translateX":270,"translateY":70,"rotate":15,"points":[-10,0,-6,-8,0,-10,6,-8,10,0,7,10,3,2,0,10,-3,2,-7,10],"fill":"#da70d6"},{"n":5,"type":"Circle","translateX":60,"translateY":180,"centerX":0,"centerY":0,"radius":5,"fill":"#e0ffff"}]}}}],"problems":[]},"outline":"Window \"Deep dive\"\n  Pane 360 x 240\n    Rectangle 360 x 240 at (0, 0), fill #191970\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (180, 120), fill #ffd700\n    Polygon (-10, 0) (-6, -8) (0, -10) (6, -8) (10, 0) (7, 10) (3, 2) (0, 10) (-3, 2) (-7, 10), at (270, 70), rotate 15, fill #da70d6\n    Circle radius 5 at (0, 0), translate (60, 180), fill #e0ffff"}],"require":[],"forbid":[]},{"task":"A swarm of jellyfish in a row. Using a loop, add four jellyfish to the pane, after the water: jellyfish `i` (counting from 0) is a new `Polygon(-10, 0, -6, -8, 0, -10, 6, -8, 10, 0, 7, 10, 3, 2, 0, 10, -3, 2, -7, 10)` filled with `Color.ORCHID`, moved to x `60 + 80 * i` and y 50, and turned `30 * i` degrees. After the loop, the starter code adds the submarine, at (180, 180) and pointing up.\n\nThe window it should show is drawn below.\n","kind":"code","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n        pane.getChildren().add(new Rectangle(360, 240, Color.MIDNIGHTBLUE));\n\n        // the jellyfish\n\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(180);\n        sub.setTranslateY(180);\n        sub.setRotate(-90);\n        pane.getChildren().add(sub);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Swarm\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.layout.Pane;\nimport javafx.scene.paint.Color;\nimport javafx.scene.shape.Polygon;\nimport javafx.scene.shape.Rectangle;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        Pane pane = new Pane();\n        pane.setPrefSize(360, 240);\n        pane.getChildren().add(new Rectangle(360, 240, Color.MIDNIGHTBLUE));\n\n        for (int i = 0; i < 4; i++) {\n            Polygon jellyfish = new Polygon(-10, 0, -6, -8, 0, -10, 6, -8, 10, 0, 7, 10, 3, 2, 0, 10, -3, 2, -7, 10);\n            jellyfish.setFill(Color.ORCHID);\n            jellyfish.setTranslateX(60 + 80 * i);\n            jellyfish.setTranslateY(50);\n            jellyfish.setRotate(30 * i);\n            pane.getChildren().add(jellyfish);\n        }\n\n        Polygon sub = new Polygon(-15, -6, 9, -6, 15, 0, 9, 6, -15, 6);\n        sub.setFill(Color.GOLD);\n        sub.setTranslateX(180);\n        sub.setTranslateY(180);\n        sub.setRotate(-90);\n        pane.getChildren().add(sub);\n\n        stage.setScene(new Scene(pane));\n        stage.setTitle(\"Swarm\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["Make the polygon inside the loop, so each round has a new one: a node can be in a pane only once.","In the loop: `jellyfish.setTranslateX(60 + 80 * i);`, `jellyfish.setTranslateY(50);` and `jellyfish.setRotate(30 * i);`, then `pane.getChildren().add(jellyfish);`."],"tests":[{"name":"Window","stdin":"","expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Swarm","scene":{"width":360,"height":240,"root":{"n":1,"type":"Pane","prefWidth":360,"prefHeight":240,"children":[{"n":2,"type":"Rectangle","x":0,"y":0,"width":360,"height":240,"fill":"#191970"},{"n":3,"type":"Polygon","translateX":60,"translateY":50,"points":[-10,0,-6,-8,0,-10,6,-8,10,0,7,10,3,2,0,10,-3,2,-7,10],"fill":"#da70d6"},{"n":4,"type":"Polygon","translateX":140,"translateY":50,"rotate":30,"points":[-10,0,-6,-8,0,-10,6,-8,10,0,7,10,3,2,0,10,-3,2,-7,10],"fill":"#da70d6"},{"n":5,"type":"Polygon","translateX":220,"translateY":50,"rotate":60,"points":[-10,0,-6,-8,0,-10,6,-8,10,0,7,10,3,2,0,10,-3,2,-7,10],"fill":"#da70d6"},{"n":6,"type":"Polygon","translateX":300,"translateY":50,"rotate":90,"points":[-10,0,-6,-8,0,-10,6,-8,10,0,7,10,3,2,0,10,-3,2,-7,10],"fill":"#da70d6"},{"n":7,"type":"Polygon","translateX":180,"translateY":180,"rotate":-90,"points":[-15,-6,9,-6,15,0,9,6,-15,6],"fill":"#ffd700"}]}}}],"problems":[]},"outline":"Window \"Swarm\"\n  Pane 360 x 240\n    Rectangle 360 x 240 at (0, 0), fill #191970\n    Polygon (-10, 0) (-6, -8) (0, -10) (6, -8) (10, 0) (7, 10) (3, 2) (0, 10) (-3, 2) (-7, 10), at (60, 50), fill #da70d6\n    Polygon (-10, 0) (-6, -8) (0, -10) (6, -8) (10, 0) (7, 10) (3, 2) (0, 10) (-3, 2) (-7, 10), at (140, 50), rotate 30, fill #da70d6\n    Polygon (-10, 0) (-6, -8) (0, -10) (6, -8) (10, 0) (7, 10) (3, 2) (0, 10) (-3, 2) (-7, 10), at (220, 50), rotate 60, fill #da70d6\n    Polygon (-10, 0) (-6, -8) (0, -10) (6, -8) (10, 0) (7, 10) (3, 2) (0, 10) (-3, 2) (-7, 10), at (300, 50), rotate 90, fill #da70d6\n    Polygon (-15, -6) (9, -6) (15, 0) (9, 6) (-15, 6), at (180, 180), rotate -90, fill #ffd700"}],"require":[{"pattern":"for\\s*\\(","message":"Make the jellyfish in a for loop."},{"pattern":"new\\s+Polygon\\s*\\(\\s*-10","min":1,"max":1,"message":"Write `new Polygon(...)` for the jellyfish only once, inside the loop."}],"forbid":[]}]}