在 #PMBH Coding 挑战倡议(?) 中,我提出了一个倡议:不使用 AI 挑战赛!#PMBH 代表 Proudly Made By Human。PMBH 的宗旨是:创造的目的是创造本身,而不是完成任务。所以完全可以让 AI 去工作,但是人类要把创造的能力留住。
但是说实话,也没啥反响,我觉得还是要亲自来示范一下。
[!Note] 所以今天带来的是:在浏览器地址栏里就能玩的游戏!
游玩方法:在当前页面或随便哪一个页面上打开控制台(option+command+i 或 f12),复制下面的 JS 代码到控制台中,回车。游戏会立刻开始。在页面上>代表玩家控制的角色,按↑控制角色跳跃(跳跃时角色变为^),躲开|代表的障碍物。
游戏结束时,按spacebar重开。
注意:游玩时,需要聚焦在页面上。如果此时聚焦的是控制台,将无法正常操控。
(function() {
const WIDTH = 50; // 设定游戏画面的字符宽度
const PLAYER_X = 6; // 玩家初始位置
// 代表玩家的符号
const SYMBOL_PLAYER = {
normal: '>',
jump: '^'
}
const SYMBOL_GROUND = '_' // 代表地面的符号
const SYMBOL_OBSTACLE = '|' // 代表障碍物的符号
const INIT_SPEED = 130; // 佬友们知道吗,init = initial,就像 util = utility
let ground, score, frame, jumpTimer, gameOver, loop; // 游戏状态
// 初始化
function init() {
ground = Array(WIDTH).fill(SYMBOL_GROUND); // 生成相当于游戏画面宽度的数组,填充为地面`_`
score = 0; // 初始化分数
frame = 0; // 记录帧数
jumpTimer = 0; // 记录跳跃状态的时间
speed = INIT_SPEED; // 不妨请佬友猜一下速度变快应该改大还是改小这个数
gameOver = false;
// 生成第一屏游戏画面的障碍物,免得 WIDTH 个字符全都是`_`让佬友硬的太容易
for (let i = 16; i < WIDTH; i += 8 + Math.floor(Math.random() * 6)) {
ground[i] = SYMBOL_OBSTACLE;
}
// 回收!释放!还你内存!
// 注意:内存并非立刻归还,垃圾也并非立刻清理
if (loop) clearInterval(loop);
loop = setInterval(update, speed);
render();
}
// 渲染到地址栏
function render() {
const scene = [...ground];
scene[PLAYER_X] = jumpTimer > 0 ? SYMBOL_PLAYER.jump : SYMBOL_PLAYER.normal;
const display = scene.join('') + '_得分:' + score;
history.replaceState(null, null, '#' + display);
}
// 主循环
function update() {
if (gameOver) return;
frame++;
if (jumpTimer > 0) jumpTimer--;
// 世界左滚
ground.shift();
// 生成新地形
let next = SYMBOL_GROUND;
// 生成新的地形时,考虑得分因素
// 使游戏越难,游戏就越难
const obstacleRate = 0.03 + Math.min(score * 0.0004, 0.28);
// 随机生成障碍物
if (Math.random() < obstacleRate) next = SYMBOL_OBSTACLE;
// 简单的方法避免必死连续障碍。我又不刷 leetcode 干嘛要回溯?
if (ground[ground.length - 1] === SYMBOL_OBSTACLE && next === SYMBOL_OBSTACLE) next = SYMBOL_GROUND;
ground.push(next);
// 碰撞检测
if (jumpTimer === 0 && ground[PLAYER_X] === SYMBOL_OBSTACLE) {
// 如果玩家没在跳跃,又恰好与 SMYBOL_OBSTACLE 处于同一位置,那就是撞了
// 此时结束游戏
gameOver = true;
// 改变地址栏现实的额内容
history.replaceState(null, null, '#GAME_OVER!_佬友的最终得分:' + score + '_按下SPACE再来');
// 释放(指计时器)!爽了!
clearInterval(loop);
return;
}
// zi yao 是你没死就能一直得分
score++;
// 加速
if (frame % 40 === 0 && speed > 30) {
// 如果又经过了 40 帧,并且还没到最高难度
clearInterval(loop);
// 继续加速!
speed -= 4;
loop = setInterval(update, speed);
}
render();
}
// 键盘控制
document.addEventListener('keydown', function(e) {
if (e.code === 'ArrowUp' && jumpTimer === 0 && !gameOver) {
jumpTimer = 5;
// 接管`↑`按键
e.preventDefault();
}
if (e.code === 'Space' && gameOver) {
// 接管 `Space` 按键
e.preventDefault();
init(); // 重置状态,原地重启
}
});
init();
})();
随手玩了一下的得分,不代表本人最高水平!!

这下没人看得出来你在玩游戏了
如果有想要创造一下但又选择困难或不知道方向的佬友,我本次提供的参考主题是:「拥挤/crowded」。期待能看到更多 Proudly Made By Human 的作品~