blessed-snake
Version:
Nokia3310
336 lines (286 loc) • 12.1 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
var _react = _interopRequireWildcard(require("react"));
var _blessed = _interopRequireDefault(require("blessed"));
var _reactBlessed = require("react-blessed");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var ARROWS = {
left: "left",
down: "down",
up: "up",
right: "right",
a: "left",
s: "down",
w: "up",
d: "right"
};
var DIFFICULTY = {
easy: 500,
normal: 250,
hard: 200,
insane: 100,
catreflex: 50
};
var initialSnake = [{
x: 1,
y: 1
}, {
x: 1,
y: 2
}, {
x: 1,
y: 3
}];
var nextHead = function nextHead(_ref, direction) {
var x = _ref.x,
y = _ref.y;
switch (direction) {
case ARROWS.left:
return {
x: x - 1,
y: y
};
case ARROWS.right:
return {
x: x + 1,
y: y
};
case ARROWS.up:
return {
x: x,
y: y - 1
};
case ARROWS.down:
return {
x: x,
y: y + 1
};
default:
return head;
}
};
var randomLocation = function randomLocation(n) {
var x = Math.floor(Math.random() * n);
var y = Math.floor(Math.random() * n);
return {
x: x,
y: y
};
};
var hasDied = function hasDied(snake, n) {
var head = snake[snake.length - 1];
var ateSelf = snake.some(function (_ref2, i) {
var x = _ref2.x,
y = _ref2.y;
return i !== snake.length - 1 && head.x === x && head.y === y;
});
var outOfBounds = head.x >= n || head.x < 0 || head.y >= n || head.y < 0;
return ateSelf || outOfBounds;
};
var App = function App(_ref3) {
var _ref3$difficulty = _ref3.difficulty,
difficulty = _ref3$difficulty === void 0 ? "hard" : _ref3$difficulty,
_ref3$size = _ref3.size,
size = _ref3$size === void 0 ? 20 : _ref3$size;
var _useState = (0, _react.useState)(false),
_useState2 = _slicedToArray(_useState, 2),
gameOver = _useState2[0],
setGameOver = _useState2[1];
var _useState3 = (0, _react.useState)(ARROWS.down),
_useState4 = _slicedToArray(_useState3, 2),
direction = _useState4[0],
setDirection = _useState4[1];
var _useState5 = (0, _react.useState)(0),
_useState6 = _slicedToArray(_useState5, 2),
score = _useState6[0],
setScore = _useState6[1];
var _useState7 = (0, _react.useState)(randomLocation(size)),
_useState8 = _slicedToArray(_useState7, 2),
fruit = _useState8[0],
setFruit = _useState8[1];
var _useState9 = (0, _react.useState)(initialSnake),
_useState10 = _slicedToArray(_useState9, 2),
snake = _useState10[0],
setSnake = _useState10[1];
var gameClock = (0, _react.useRef)(null);
var restart = function restart() {
setSnake(initialSnake);
setScore(0);
setDirection(ARROWS.down);
setGameOver(false);
setFruit(randomLocation(size));
};
var handleDeath = function handleDeath() {
setGameOver(true);
clearTimeout(gameClock.current);
};
var handleAteFruit = function handleAteFruit() {
setFruit(function () {
return randomLocation(size);
});
setScore(function (s) {
return s + 1;
});
};
var tick = function tick() {
setSnake(function (s) {
hasDied(s, size) && handleDeath();
var newSnake = _toConsumableArray(s);
var newHead = nextHead(s[s.length - 1], direction);
var ateFruit = newHead.x === fruit.x && newHead.y === fruit.y;
ateFruit ? handleAteFruit() : newSnake.shift();
newSnake.push(newHead);
return newSnake;
});
};
(0, _react.useEffect)(function () {
if (!gameOver) {
clearInterval(gameClock.current);
gameClock.current = setInterval(tick, 10 / size * (DIFFICULTY[difficulty] || DIFFICULTY["hard"]));
}
return function () {
return clearInterval(gameClock.current);
};
}, [direction, gameOver]);
var handleKeyPress = function handleKeyPress(_, _ref4) {
var name = _ref4.name;
return name === "enter" ? restart() : setDirection(function (direction) {
return ARROWS[name] || direction;
});
};
return /*#__PURE__*/_react["default"].createElement("element", {
keyable: true,
focused: true,
input: true,
width: "100%",
height: "100%",
onKeypress: handleKeyPress,
style: {
bg: "#2A223A",
fg: "#2A223A"
}
}, !gameOver ? /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("box", {
width: "80%",
top: "0",
left: "0"
}, "~~~ Snake Game ~~~"), /*#__PURE__*/_react["default"].createElement("box", {
width: "20%",
top: "0",
right: "0"
}, /*#__PURE__*/_react["default"].createElement("box", {
width: "50%",
top: "0",
right: "15"
}, "Score"), /*#__PURE__*/_react["default"].createElement("box", {
width: "50%",
top: "0",
right: "5"
}, score)), /*#__PURE__*/_react["default"].createElement("box", {
top: "center",
left: "center",
width: "90%",
height: "90%",
border: {
type: "line"
},
style: {
border: {
fg: "red"
}
}
}, /*#__PURE__*/_react["default"].createElement(Fruit, _extends({}, fruit, {
size: Math.floor(100 / size)
})), snake.map(function (part, i) {
return /*#__PURE__*/_react["default"].createElement(BodyPart, _extends({}, part, {
isHead: i === snake.length - 1,
key: i,
size: Math.floor(100 / size)
}));
}))) : /*#__PURE__*/_react["default"].createElement(GameOver, {
score: score,
restart: restart
}));
};
var getPositionProps = function getPositionProps(x, y, size) {
return {
top: "".concat(y * size, "%"),
left: "".concat(x * size, "%"),
width: "".concat(size, "%"),
height: "".concat(size, "%")
};
};
var BodyPart = function BodyPart(_ref5) {
var x = _ref5.x,
y = _ref5.y,
isHead = _ref5.isHead,
size = _ref5.size;
return /*#__PURE__*/_react["default"].createElement("box", _extends({}, getPositionProps(x, y, size), {
style: {
bg: isHead ? "#19EBFF" : "#F3EEE3"
}
}));
};
var Fruit = function Fruit(_ref6) {
var x = _ref6.x,
y = _ref6.y,
size = _ref6.size;
return /*#__PURE__*/_react["default"].createElement("box", _extends({}, getPositionProps(x, y, size), {
style: {
bg: "green"
}
}));
};
var GameOver = function GameOver(_ref7) {
var restart = _ref7.restart,
score = _ref7.score;
return /*#__PURE__*/_react["default"].createElement("box", {
top: "center",
left: "center",
width: "100%",
height: "100%"
}, "GAME OVER - Score:", /*#__PURE__*/_react["default"].createElement("box", {
top: 1
}, score), /*#__PURE__*/_react["default"].createElement("button", {
mouse: true,
top: 2,
height: 50,
width: "100%",
onPress: restart
}, "-- Press enter to play again --"));
};
var screen = _blessed["default"].screen({
autoPadding: false,
fastCSR: true,
title: "Snake Game!"
});
screen.key(["escape", "q", "C-c"], function () {
return process.exit(0);
});
var args = process.argv;
var difficultyIndex = args.findIndex(function (arg) {
return arg === "--difficulty";
});
var sizeIndex = args.findIndex(function (arg) {
return arg === "--size";
});
var difficulty = difficultyIndex > -1 ? args[difficultyIndex + 1] : "normal";
var size = sizeIndex > -1 ? args[sizeIndex + 1] : 10;
console.log("\n\n _______ __ _ _______ ___ _ _______ _______ _______ __ __ _______ \n| || | | || _ || | | || | | || _ || |_| || |\n| _____|| |_| || |_| || |_| || ___| | ___|| |_| || || ___|\n| |_____ | || || _|| |___ | | __ | || || |___ \n|_____ || _ || || |_ | ___| | || || || || ___|\n _____| || | | || _ || _ || |___ | |_| || _ || ||_|| || |___ \n|_______||_| |__||__| |__||___| |_||_______| |_______||__| |__||_| |_||_______|\n\n --difficulty easy|normal|hard|insane|catreflex\n\n --size n\n\n Resize the terminal to be square\n");
(0, _reactBlessed.render)( /*#__PURE__*/_react["default"].createElement(App, {
difficulty: difficulty,
size: size
}), screen);
;