Caterpillar
Your caterpiller can grow by nibbling leaves for nourishment. Guide the caterpiller’s movement toward a leaf. Be careful though, if it touches the side of the screen it won’t live to be a butterfly.
const NEXT_SECTION_KEY = "__child_node";
namespace SpriteKind {
export const Tail = SpriteKind.create();
}
enum Direction {
Up,
Down,
Left,
Right
}
const size = 8;
const caterpillarHead = sprites.create(img`
. . 3 3 3 3 . .
. 3 2 2 2 2 3 .
3 2 f 2 2 f 2 3
3 2 f 2 2 f 2 3
3 2 2 2 2 2 2 3
3 2 2 2 2 2 2 3
. 3 2 2 2 2 3 .
. . 3 3 3 3 . .
`, SpriteKind.Player);
caterpillarHead.left = 4 * size;
caterpillarHead.top = 12 * size;
caterpillarHead.data = {};
let currentLeaf: Sprite;
tiles.setTilemap(tilemap`level`);
const leafImage = img`
. . . . . f f 7
. . . f f f 6 f
. . f 6 7 f f f
. f 6 7 f 7 7 f
f f 7 f 7 7 7 f
f 6 f 7 7 7 f .
f 6 7 7 f f . .
f f f f f . . .
`;
const shinyLeafImage = img`
. . 1 . . f f 7
. 1 . f f f 6 f
1 . f 6 7 f f f
. f 6 7 f 7 7 f
f f 7 f 7 7 7 f
f 6 f 7 7 7 f .
f 6 7 7 f f . 1
f f f f f . 1 .
`;
placeFruit();
info.setScore(0);
let direction = Direction.Up;
let addSection = true;
let enqueued = false;
let lastIteration = 0;
let timeout = 500;
forever(function () {
if (caterpillarHead.left < 0 || caterpillarHead.right > screen.width
|| caterpillarHead.top < 0 || caterpillarHead.bottom > screen.height) {
game.over(false);
}
if (!enqueued && game.runtime() - lastIteration < timeout) {
return;
}
if (addSection) {
addToBody();
} else {
move(caterpillarHead);
}
switch (direction) {
case Direction.Up:
caterpillarHead.y -= size;
break;
case Direction.Down:
caterpillarHead.y += size;
break;
case Direction.Left:
caterpillarHead.x -= size;
break;
case Direction.Right:
caterpillarHead.x += size;
break;
}
enqueued = false;
lastIteration = game.runtime();
function addToBody() {
const newSection = sprites.create(img`
. . f f f f . .
. f 1 1 1 1 f .
f 1 1 1 1 1 1 f
f 1 1 1 1 1 1 f
f 1 1 1 1 1 1 f
f 1 1 1 1 1 1 f
. f 1 1 1 1 f .
. . f f f f . .
`, SpriteKind.Tail);
newSection.data = {};
let newColor: number;
do {
newColor = randint(0x1, 0xE);
} while (newColor === 0x6);
newSection.image.replace(0x1, newColor);
do {
newColor = randint(0x1, 0xE);
} while (newColor === 0x6);
newSection.image.replace(0xF, newColor);
newSection.x = caterpillarHead.x;
newSection.y = caterpillarHead.y;
newSection.data[NEXT_SECTION_KEY] = caterpillarHead.data[NEXT_SECTION_KEY];
caterpillarHead.data[NEXT_SECTION_KEY] = newSection;
addSection = false;
}
function move(piece: Sprite) {
const next = piece.data[NEXT_SECTION_KEY];
if (next) {
move(next);
next.x = piece.x;
next.y = piece.y;
}
}
});
sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite: Sprite, otherSprite: Sprite) {
info.changeScoreBy(1);
otherSprite.destroy(effects.disintegrate);
music.baDing.play();
timeout = Math.max(150, timeout - 50);
addSection = true;
placeFruit();
});
sprites.onOverlap(SpriteKind.Player, SpriteKind.Tail, function (sprite: Sprite, otherSprite: Sprite) {
game.over(false);
});
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
setDirection(Direction.Up, Direction.Down, img`
. . 3 3 3 3 . .
. 3 2 2 2 2 3 .
3 2 f 2 2 f 2 3
3 2 f 2 2 f 2 3
3 2 2 2 2 2 2 3
3 2 2 2 2 2 2 3
. 3 2 2 2 2 3 .
. . 3 3 3 3 . .
`);
});
controller.down.onEvent(ControllerButtonEvent.Pressed, function () {
setDirection(Direction.Down, Direction.Up, img`
. . 3 3 3 3 . .
. 3 2 2 2 2 3 .
3 2 2 2 2 2 2 3
3 2 2 2 2 2 2 3
3 2 f 2 2 f 2 3
3 2 f 2 2 f 2 3
. 3 2 2 2 2 3 .
. . 3 3 3 3 . .
`);
});
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
setDirection(Direction.Left, Direction.Right, img`
. . 3 3 3 3 . .
. 3 2 2 2 2 3 .
3 2 f f 2 2 2 3
3 2 2 2 2 2 2 3
3 2 2 2 2 2 2 3
3 2 f f 2 2 2 3
. 3 2 2 2 2 3 .
. . 3 3 3 3 . .
`);
});
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
setDirection(Direction.Right, Direction.Left, img`
. . 3 3 3 3 . .
. 3 2 2 2 2 3 .
3 2 2 2 f f 2 3
3 2 2 2 2 2 2 3
3 2 2 2 2 2 2 3
3 2 2 2 f f 2 3
. 3 2 2 2 2 3 .
. . 3 3 3 3 . .
`);
});
function setDirection(targetDir: Direction, oppositeDir: Direction, im: Image) {
if (!enqueued && direction !== targetDir && direction !== oppositeDir) {
caterpillarHead.setImage(im);
direction = targetDir;
enqueued = true;
}
}
function placeFruit() {
currentLeaf = sprites.create(leafImage, SpriteKind.Food);
do {
currentLeaf.left = randint(0, 19) * size;
currentLeaf.top = randint(0, 14) * size;
} while (
(currentLeaf.top === 0 && currentLeaf.right === screen.width)
|| sprites
.allOfKind(SpriteKind.Tail)
.some(s => s.overlapsWith(currentLeaf))
);
}
game.onUpdateInterval(500, function () {
if (currentLeaf.image === leafImage) {
currentLeaf.setImage(shinyLeafImage);
} else {
currentLeaf.setImage(leafImage);
}
});
{
"transparency16": {
"data": "hwQQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"mimeType": "image/x-mkcd-f4",
"tilemapTile": true
},
"tile1": {
"data": "hwQQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"mimeType": "image/x-mkcd-f4",
"tilemapTile": true
},
"level": {
"id": "level",
"mimeType": "application/mkcd-tilemap",
"data": "MTAxMDAwMTAwMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA==",
"tileset": [
"myTiles.transparency16",
"sprites.castle.tileDarkGrass1"
]
},
"*": {
"mimeType": "image/x-mkcd-f4",
"dataEncoding": "base64",
"namespace": "myTiles"
}
}