我正在参加掘金社区游戏创意投稿大赛团队赛,详情请看:游戏创意投稿大赛
游戏在线体验地址:biao-code.github.io/magic-game/
游戏介绍
前几天看到的这个活动,就跟朋友一起报了名,由于最近快要考试,复习加上每天还要更文完成4月更文挑战,很难抽出时间来做这款游戏。今天放假一天,在逛掘金的时候,才发现活动明天就结束了,专门腾出一下午的时间来做这款游戏
这款游戏主要基于kaboomjs,它提供了大量的API和示例让我们挑选,节省了大量的时间来写代码,我只需要改人物的贴图和设计游戏的关卡,就可以玩这个游戏
这是一款网页版的闯关小游戏,你可以通过按键盘右下方的左右键和空格键来操作人物的移动。小人贴图我换成了掘金挖矿里的人物,小人没有生命值,但只要碰到陷阱和怪物就会死,无限条命,可以尽情的玩,但要注意的是:人物死后,不是在当前关重生,而是直接从第一关重生,我有好几次都快到终点了,因为碰到了陷阱,只能从头再来,就很烦。
游戏总共只有6关,数量虽然不多,但每一关的难度都不简单,如果有人能一条命就通关,那我只能称你为“最强王者”。每一关都有5个金币,想要百分百通过不只是要到终点,还需要将这些金币都拿到。
游戏
具体实现
游戏一共设计了6个关卡,在字符数组中绘制了地图,设计代码如下:
const LEVELS = [
[
" ",
" ==== $",
" $",
" $$ = $",
" % ==== = $",
" = $",
" = ",
" @ > ^^ =>>>>>>>> = @",
"===============================",
],
[
" $ ",
" = $ @",
" = = $ ",
" = = $ ",
" = = $ ",
" = = > > > > >=",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
"============================================",
],
[
" $ $ $ $ $",
" ",
" ",
" ",
" ",
" ",
" ",
"^^ >^^^^>^^^^>^^^^>^^^^^@",
"===========================",
],
[
" == == == $@ ",
" === === === === ",
" $ $ $ $ ",
" = = = = ",
" = = = = ",
" = = = = ",
" = = = = ",
"=> >=> >=> >=> >= ",
"===================================",
],
[
" $^^ ",
" === @",
" ^ $ ",
" = $ ",
" =%= = $ ",
" = $ ",
" = ",
" ^^ =^^>^^^^=^^^ > $=",
"===================================",
],
[
" = $ ^^^ =^ ",
" = = = ",
" $ = =@s ",
" = ^ = ",
" $ = ^ = ",
" = ^ = ^ ^",
" = ^ = $ ",
"= > ^^=^^^^^^^^>^ ^ >^>>=>^>^^",
"================= ==============",
],
]
上面每一个符号都代码一个地图对象,在下面定义了每个对象对应的内容。
// 定义每个符号在水平图中的含义
const levelConf = {
// 网格大小
width: 64,
height: 64,
// 将每个对象定义为组件列表
"=": () => [
sprite("grass"),
area(),
solid(),
origin("bot"),
],
"$": () => [
sprite("coin"),
area(),
pos(0, -9),
origin("bot"),
"coin",
],
"%": () => [
sprite("prize"),
area(),
solid(),
origin("bot"),
"prize",
],
"^": () => [
sprite("spike"),
area(),
solid(),
origin("bot"),
"danger",
],
"#": () => [
sprite("apple"),
area(),
origin("bot"),
body(),
"apple",
],
">": () => [
sprite("ghosty"),
area(),
origin("bot"),
body(),
patrol(),
"enemy",
],
"@": () => [
sprite("portal"),
area({ scale: 0.5, }),
origin("bot"),
pos(0, -12),
"portal",
],
}
游戏主要交互动作方法,包含按键绑定,玩家对象的主要操作方法。
scene("game", ({ levelId, coins } = { levelId: 0, coins: 0 }) => {
gravity(3200)
// 向场景添加关卡
const level = addLevel(LEVELS[levelId ?? 0], levelConf)
// 定义玩家对象
const player = add([
sprite("bean"),
pos(0, 0),
area(),
scale(1),
// 使重心下降并可跳跃
body(),
// 我们在上面定义的自定义组件
big(),
origin("bot"),
])
// action() 每帧运行一次
player.onUpdate(() => {
// 中央摄影机图层
camPos(player.pos)
// 制止坠落死亡
if (player.pos.y >= FALL_DEATH) {
go("lose")
}
})
// 如果玩家与任何带有“危险”标签的obj碰撞,则失败
player.onCollide("danger", () => {
go("lose")
play("hit")
})
player.onCollide("portal", () => {
play("portal")
if (levelId + 1 < LEVELS.length) {
go("game", {
levelId: levelId + 1,
coins: coins,
})
} else {
go("win")
}
})
player.onGround((l) => {
if (l.is("enemy")) {
player.jump(JUMP_FORCE * 1.5)
destroy(l)
addKaboom(player.pos)
play("powerup")
}
})
player.onCollide("enemy", (e, col) => {
// 如果不是从上面,那就去死吧
if (!col.isBottom()) {
go("lose")
play("hit")
}
})
let hasApple = false
player.onHeadbutt((obj) => {
if (obj.is("prize") && !hasApple) {
const apple = level.spawn("#", obj.gridPos.sub(0, 1))
apple.jump()
hasApple = true
play("blip")
}
})
// 玩家在与“苹果”obj的碰撞中变大
player.onCollide("apple", (a) => {
destroy(a)
// 正如我们在big()组件中定义的
player.biggify(3)
hasApple = false
play("powerup")
})
let coinPitch = 0
onUpdate(() => {
if (coinPitch > 0) {
coinPitch = Math.max(0, coinPitch - dt() * 100)
}
})
player.onCollide("coin", (c) => {
destroy(c)
play("coin", {
detune: coinPitch,
})
coinPitch += 100
coins += 1
coinsLabel.text = coins
})
const coinsLabel = add([
text(coins),
pos(24, 24),
fixed(),
])
// 空格键跳跃
onKeyPress("space", () => {
// 这两个函数由body()组件提供
if (player.isGrounded()) {
player.jump(JUMP_FORCE)
}
})
// 下面都是按键绑定
onKeyDown("left", () => {
player.move(-MOVE_SPEED, 0)
})
onKeyDown("right", () => {
player.move(MOVE_SPEED, 0)
})
onKeyPress("down", () => {
player.weight = 3
})
onKeyRelease("down", () => {
player.weight = 1
})
onKeyPress("f", () => {
fullscreen(!fullscreen())
})
onKeyPress("w", () => {
if (player.isGrounded()) {
player.jump(JUMP_FORCE)
}
})
onKeyDown("a", () => {
player.move(-MOVE_SPEED, 0)
})
onKeyDown("d", () => {
player.move(MOVE_SPEED, 0)
})
})