Show HN:Sprigman——在有限瓦片式JavaScript引擎中重现的吃豆人游戏
Show HN: Sprigman – Pac-Man Recreated in a Limited Tile Based JavaScript Engine

原始链接: https://sprig.hackclub.com/share/X4EGvOFk1q8FroEPCj1G

Sprig 是 Hack Club 推出的一个基于 JavaScript 的游戏构建工具包,用于创建基于瓦片的益智游戏。 使用 `setLegend` 定义游戏元素,用单字符键作为标识符,并用 `bitmap` 字面量表示其视觉效果。 使用 `map` 字面量创建关卡,并用 `setMap` 加载它们。 使用 `setSolids` (碰撞)和 `setPushables` (可推动精灵)管理精灵交互。 使用 `onInput` 控制游戏逻辑,处理玩家输入 (w, a, s, d, i, j, k, l),并使用 `afterInput` 进行后续任务,例如胜利条件检查。 使用 `getTile`、`tilesWith`、`addSprite`、`clearTile`、`getAll` 和 `getFirst` 等函数与精灵交互。 你还可以操作精灵的属性,例如 `x`、`y` 和 `type`。 使用 `setBackground` 添加视觉效果,使用 `addText` 添加文本,并使用 `tune` 关键词和 `playTune` 添加音乐/音效。 Sprig 具有无限循环检测功能,以防止浏览器崩溃。

Hacker News用户kuberwastaken分享了他使用Hack Club的基于瓦片的Game Engine——Sprig——制作的吃豆人游戏复刻版。Sprig引擎设计上有所限制,使用位图精灵、类似MIDI的音序器和基础控制。kuberwastaken版本的吃豆人拥有随机生成的迷宫。其他用户指出了诸如硬币无法获取等问题。kuberwastaken更新了游戏,解决了这些问题,并加入了更智能的地图生成和拥有多种个性的幽灵。另一位用户tdy_err指出了由于控制器点击会缩放导致的移动端可用性问题,并建议使用CSS修复。kuberwastaken解释说,由于引擎的限制和目标硬件,移动端优化比较困难,游戏主要针对WASD和K键控制设计。

原文

Sprig is a tiny construction kit to build tile based games. The games are written in JavaScript. It was made by Hack Club, a global community of teen coders who believe people learn best by making things they care about and sharing them with others. You can watch this video for an introduction to Sprig website.

Run games by hitting the Run button or pressing Shift+Enter.

Getting Help

If this is your first time using Sprig, try playing through the tutorial. From there, we suggest hacking on any of the current games or starting from scratch.

If you ever need help, have ideas, or want to meet other game-makers, join the community in the #sprig channel on the Hack Club Slack. You can access this guide here.

Level Design

Sprig games are made up of grids of square tiles.

setLegend(bitmaps)

Tell Sprig what types of sprites are available in your game. Bitmap keys must be a single character. We recommend storing character keys in variables.

const player = "p"
const wall = "w"

setLegend(
  [ player, bitmap`...` ],
  [ wall, bitmap`...` ],
)

To create a new bitmap, type

bitmap`.`

Those are backticks! Click on the highlighted “bitmap” button to edit your drawing.

The order of sprite types in your legend also determines the z-order of drawing them. Sprite types that come first are drawn on top.

setBackground(bitmapKey)

Tiles a bitmap as the background of the game:

setBackground(spriteKey)

This only changes the visuals of the game.

setMap(level)

Designing a level is like drawing a bitmap:

map`...`

The characters in the map come from the order of your bitmap legend. Levels don’t have to be kept track of in a legend, you should store them in a variable yourself. You can call setMap to clear the game and load a new level:

const level = map`...`
setMap(level)

You might want to keep track of multiple levels using an array to switch between them mid-game:

const levels = [
  map`...`,
  map`...`,
  // etc.
]
setMap(levels[0])

// Later:
setMap(levels[1])

setSolids(bitmapKey)

Solid sprites can’t overlap with each other. This is useful for creating things like walls:

const player = "p"
const wall = "w"

setSolids([ player, wall ])

setPushables(pushMap)

Use setPushables to make sprites push other sprites around. The sprite on the left will be able to push all sprites listed on the right.

const player = "p"
const block = "b"

setPushables({ 
  [player]: [ block, player ] 
})

Watch out! Make sure everything you pass to setPushables is also marked as a solid or they won’t be pushed around.

width()

Get the width of the current map.

height()

Get the height of the current map.

User Input

Sprig has eight inputs w, a, s, d, i, j, k, l.

Typically w, a, s, d are used as directional controls.

onInput(type, callback)

Do something when the player presses a control:

onInput("d", () => {
  // Move the player one tile to the right
  getFirst(player).x += 1
})

afterInput(callback)

Runs after every input event has finished being handled. Useful for tasks like checking win states:

afterInput(() => {
  if (getAll(block).length > 0) {
    console.log("you win")
  }
})

Sprites and Tiles

Each tile can contain any number of sprites stacked on top of each other.

Sprites contain:

{
  type
  x
  y
}

You can move the sprite by setting x and y.

The bitmapKey can also be changed to update the rendered graphic and collision rules the sprite will follow.

sprite.y += 1
sprite.type = "p"

You can remove a sprite with sprite.remove().

getTile(x, y)

Returns a list of the sprites in the specified tile.

tilesWith(type, …)

Returns a list of the tiles that contain type.

tilesWith(block)

tilesWith accepts multiple sprite types.

tilesWith(block, player, ...)

addSprite(x, y, spriteType)

Creates a new sprite of the given type.

clearTile(x, y)

Removes all sprites from the specified tile.

getAll(type)

Returns all sprites of the given type. If no bitmap key is specified, it returns all the sprites in the game.

getFirst(type)

Returns the first sprite of a given type. Useful if you know there’s only one of a sprite, such as with a player character.

Shortcut for getAll(type)[0].

Text

addText(string, options = { x, y, color })

You can add text with optional x, y, and color.

In Sprig, each color is represented by a single character. Like bitmap and map, you can use the color keyword to pick a color for your text. A preview of your selected color will also show next to the character.

For example:

addText("hello", { 
  x: 10,
  y: 4,
  color: color`3`
})

clearText()

Clears all text on the screen.

Music and Sound Effects

Sprig comes bundled with a built-in sound engine and sequencer! You can use this to write background music, or with a high BPM to make sound effects.

You can create a tune with the tune keyword. As usual, click on the button to open an editor window.

// Create a tune:
const melody = tune`...`

// Play it:
playTune(melody)

// Play it 5 times:
playTune(melody, 5)

// Play it until the heat death of the universe:
const playback = playTune(melody, Infinity)

// Or make it shut up early:
playback.end()

Infinite loop detection

The Sprig editor will automatically insert a heuristic in your for, while and or do-while loops to detect potential infinite loops. Code looking like

while (condition) {
  // do stuff
}

will become

startTime = performance.now()
while (condition) {if (++_loopIt > 2000 && performance.now() - startTime > 1500) throw new RangeError("Potential infinite loop")
  // do stuff
}

Note that all original line numbers in your code will be preserved.

联系我们 contact @ memedata.com