Compare commits
6 Commits
621630ebdf
...
256b79e01b
Author | SHA1 | Date |
---|---|---|
lee2sman | 256b79e01b | |
lee2sman | 76c8b6077d | |
lee2sman | 0d2922e9c0 | |
lee2sman | fe9b49da76 | |
lee2sman | e02cfaf2f9 | |
lee2sman | ba905e1443 |
|
@ -1,5 +1,7 @@
|
|||
# Resources
|
||||
|
||||
[Toward Qualitative Procedural Generation - PDF](https://web.archive.org/web/20170610155631/http://www.ccgworkshop.org:80/2016/Johnson.pdf)
|
||||
|
||||
[emoji-toolkit emoji font](https://github.com/joypixels/emoji-toolkit)
|
||||
|
||||
[useful unicode for roguelikes](https://github.com/globalcitizen/zomia/blob/master/USEFUL-UNICODE.md)
|
||||
|
|
20
TODO.md
20
TODO.md
|
@ -1,22 +1,13 @@
|
|||
# TODO
|
||||
|
||||
## Bugs
|
||||
- [ ] i'm creating terrain but it's being overwritten (?) by old terrain file. fix.
|
||||
|
||||
## Roadmap
|
||||
- [ ] instead of creating . for generic terrain, do like createItems and have it save array of objects which terrain symbol and x, y location instead. (buildings, plants, tombs, etc)
|
||||
- [o] add more procedurally-generated things
|
||||
- [X] tombstones
|
||||
- [X] books
|
||||
- [ ] signs?
|
||||
- [ ] art?
|
||||
- [ ] curses-like screendraw system
|
||||
- [X] curses-like screendraw system
|
||||
- [ ] ability to pray / sing / meditate / wonder / think / dance?
|
||||
- [o]
|
||||
- [X] fixed number of moves limit before you *fall asleep*
|
||||
- [ ] background of tiles becomes gray (twilight), then black (nightfall) before you fall asleep?
|
||||
- [ ] create, save and load all monsters,
|
||||
- [ ] create, save and load terrain positions
|
||||
- [X] generate descriptions for items that i'm happy with
|
||||
- [ ] ability to drop items
|
||||
- [ ] programmable robot pet? - (you feed it logo commands to retrieve things?)
|
||||
- [o] check collision with item, read out message
|
||||
|
@ -25,12 +16,19 @@
|
|||
- [ ] help system
|
||||
|
||||
## Completed
|
||||
|
||||
- [X] generate descriptions for items that i'm happy with
|
||||
- [X] inventory file to save inventory
|
||||
- [X] save date and check for today's date (if so, you cannot move, but can you do something else?)
|
||||
- [X] load items from disk
|
||||
- [X] what's the game mechanic / concept? should be one clear concept
|
||||
- [X] save item positions,
|
||||
- [X] add more procedurally-generated things
|
||||
- [X] tombstones
|
||||
- [X] books
|
||||
- [X] create, save and load terrain positions
|
||||
- [X] save player position,
|
||||
|
||||
## CLOSED Issues
|
||||
- [X] i'm creating terrain but it's being overwritten (?) by old terrain file. fix.
|
||||
- [X] not all emoji are same width so different size players cause map row to get off of lined up grid
|
||||
|
|
53
devlog.md
53
devlog.md
|
@ -4,6 +4,59 @@ lee2sman
|
|||
|
||||
# Devlog
|
||||
|
||||
## Day 7
|
||||
|
||||
Hard to believe it's my last day. Looking forward to finishing and having something playable!
|
||||
|
||||
With some sleep and brunch in me, I feel refreshed. First step, I do some initial tests, creating little example files with blessed and seems to render out okay. I test out loading in a file and render to screen. Great, now I can integrate this back into my main program.
|
||||
|
||||
I decided I was ready to try replacing emojis with unicode from the Useful Unicode page. I tried changing out each of my arrays of terrain or items or buildings, etc and creating ones of unicode instead of emjois. I finished this and tested and....crap... still doesn't align. I went through my code looking for errant emoji, and then realized I was using east asian extra wide latin characters and they seemed to be causing this mis-alignment, so I switched those out. I can't say I love the aesthetic of the unicode exactly either. I guess would have been better to change fonts perhaps.
|
||||
|
||||
Strangely, the smiley player character seems too wide, though it doesn't throw off the grid. One of the houses (hut) seems to as well. I'll switch those out.
|
||||
|
||||
Okay, starting to integrate screen rendering via blessed. There are a number of bugs and I can't figure out a simple reset and redraw screen. Their example code and documentation leaves a lot to be desired. This program is overkill compared to curses! Anyway, let's see if I can wrap this up. I'm in the home stretch. Almost gave up a little while ago. Not even kidding. I thought I'd just abandon and say I failed to complete and try to get it done later, but no, I want to finish this. I've put in so many hours so far and I want people to try this out. Now that i'm getting the program to recognize directional keypresses in a gameloop i'm feeling a bit better, but still need to get a better handle on how the screen refresh -> draw works so I can wrap this up. Taking a little break to come back at it fresh.
|
||||
|
||||
Making a bookmark here to say if I can build a simple example blessed file that can identify the 4 cardinal direction keypresses with arrow keys and to move a little @ symbol around the screen, I should publish that (and possibly do a pull-request). I'd be doing quite a service for future node.js/roguelikers!
|
||||
|
||||
## Day 6
|
||||
|
||||
Did no work all day. It's now 11:55pm and I'm starting. LOL.
|
||||
|
||||
Well, my generator still makes me laugh...
|
||||
|
||||
```
|
||||
🏛️: Great Pickle Camp
|
||||
⛺: Embarrassed Cake Watering Hole
|
||||
⛺: Fragile Actor Village
|
||||
⛺: Nasty Company Village
|
||||
🏚️: Toothsome Caption Camp
|
||||
⛺: Typical Purpose Hideout
|
||||
⛺: Cynical Credit House
|
||||
⛺: Tranquil Knife Shack
|
||||
```
|
||||
|
||||
First thing, fix the terrain generator. Ugh. Will report back. Goal is to get this working and switch to blessed (curses-like bindings) tonight.
|
||||
|
||||
Fixed terrain generator. Didn't take me that long.
|
||||
|
||||
Next step, looked into using blessed. I looked at some examples and played around with them. I tried changing colors of text, writing text to different lines, etc. That all went fine. Then I tried to load in a blank dungeon file and draw lines to the screen with blessed. That went okay. Then I tried to load in emojis. Darn, that didn't work. Emojis came out as ???? question marks. Time to abandon that.
|
||||
|
||||
[Useful Unicode](https://github.com/globalcitizen/zomia/blob/master/USEFUL-UNICODE.md/)
|
||||
|
||||
Ok, so next I tested loading an external savefile with unicode text as terrain. That seemed to render okay. I tried it in gnome-terminal, st and tilda terminal emulators and all seemed okay at loading all of these unicode, in monospaced.
|
||||
|
||||
Test unicode text:
|
||||
|
||||
```
|
||||
...▒....྿྿྿....
|
||||
...▙.......྿྿྿.
|
||||
.┼..྿...☭ .....
|
||||
...●/..፨....ᛍ..
|
||||
```
|
||||
|
||||
Next step is to build blessed into my full program file. Not looking forward to this. Probably should have done this from the beginning. I should still think about if I want this to have the program run as the "message of the day" when booting up a terminal. That was my original idea at least.
|
||||
|
||||
|
||||
## Day 5
|
||||
|
||||
Started at 11:30 and worked a few hours. Added random places/names, used a project-name-generator to get some honestly great (funny, silly) place-names generated.
|
||||
|
|
262
dotd.js
262
dotd.js
|
@ -3,6 +3,7 @@ const yargs = require('yargs/yargs')
|
|||
const { hideBin } = require('yargs/helpers')
|
||||
const argv = yargs(hideBin(process.argv)).argv
|
||||
const Charlatan = require('charlatan');
|
||||
const blessed = require('blessed');
|
||||
|
||||
const fs = require("fs");
|
||||
const generator = require("project-name-generator");
|
||||
|
@ -18,8 +19,13 @@ const placesFile = ".places.txt";
|
|||
const terrainFile = ".terrain.txt";
|
||||
|
||||
//globals
|
||||
const width = 20;
|
||||
const height = 5;
|
||||
//blessed-specific, to write to screen
|
||||
let screen, box;
|
||||
let gameTitle = "Embarassed Cake Watering Hole";
|
||||
|
||||
// game vars
|
||||
const width = 50;
|
||||
const height = 8;
|
||||
const movesInADay = 24;
|
||||
let dungeon;
|
||||
let roomItems = [];
|
||||
|
@ -48,10 +54,10 @@ let parseArgs = () => {
|
|||
createItems();
|
||||
createBooks();
|
||||
createPlaces();
|
||||
createGraves();
|
||||
createGraves();
|
||||
} else {
|
||||
loadDungeon();
|
||||
loadTerrain();
|
||||
//loadDungeon();
|
||||
loadItems();
|
||||
loadPlaces();
|
||||
loadPlayer();
|
||||
|
@ -151,7 +157,7 @@ let movePlayer = () => {
|
|||
}
|
||||
}
|
||||
} else { //you are asleep
|
||||
console.log("you've drifted off asleep for the night and will wake tomorrow refreshed.");
|
||||
console.log("You've drifted off asleep for the night and will wake tomorrow refreshed.");
|
||||
//player.avatar = '😴'
|
||||
}
|
||||
}
|
||||
|
@ -203,20 +209,17 @@ let grab = () => {
|
|||
let createDungeon = () => {
|
||||
dungeon = Array.from(Array(height), () => new Array(width))
|
||||
|
||||
for (let y = 0; y < height; y++){
|
||||
for (let x = 0; x < width; x++){
|
||||
dungeon[y][x] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------CREATE PLAYER ----------------------------------
|
||||
let createPlayer = () => {
|
||||
const avatars = ['👳','👶','🧛','🕵','👲','🧕','👵','👧','🧔','👸','🤠','@']
|
||||
//const avatars = ['👳','👶','🧛','🕵','👲','🧕','👵','👧','🧔','👸','🤠','@']
|
||||
//const avatars = ['☺','☺'];
|
||||
|
||||
let chooseAvatar = Math.floor(Math.random() * avatars.length);
|
||||
//let chooseAvatar = Math.floor(Math.random() * avatars.length);
|
||||
|
||||
player.avatar = avatars[chooseAvatar];
|
||||
//player.avatar = avatars[chooseAvatar];
|
||||
player.avatar = '@';
|
||||
|
||||
player.life = movesInADay;
|
||||
|
||||
|
@ -239,7 +242,9 @@ let createItems = () => {
|
|||
let currentItemsInRoom = [];
|
||||
|
||||
for (let i = 0; i < numToSpawn; i++){
|
||||
const items = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,.:;!?"'`^~ ̄_&#%+-*=<>()[]{}⦅⦆|¦/\¬$£¢₩¥".split("");
|
||||
//east asian wide unicode
|
||||
//const items = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,.:;!?"'`^~ ̄_&#%+-*=<>()[]{}⦅⦆|¦/\¬$£¢₩¥".split("");
|
||||
const items = "123456789ABCDEFHIJKLMNOPQRSTUVWXYZabcdefghijklmonqrsntuvwxyz,.:!?\"'`^~_&#%+-*=<>(){}/\$".split("");
|
||||
|
||||
//make sure it wasn't chosen previously in this board
|
||||
do {
|
||||
|
@ -279,7 +284,8 @@ let createBooks = () => {
|
|||
let numToSpawn = Math.round(Math.random() * 2)
|
||||
|
||||
for (let i = 0; i < numToSpawn; i++){
|
||||
const items = ["📗","📕","📘","📙","📒","📓","📔"];
|
||||
//const items = ["📗","📕","📘","📙","📒","📓","📔"];
|
||||
const items = ['⎅','⏍','◫'];
|
||||
|
||||
whichItem = Math.floor(Math.random()*items.length);
|
||||
|
||||
|
@ -337,7 +343,8 @@ let createPlaces = () => {
|
|||
|
||||
for (let i = 0; i < numToSpawn; i++){
|
||||
|
||||
const buildings = ['🏛️','⛺','🏚️','⛩️','🗿']
|
||||
//const buildings = ['🏛️','⛺','🏚️','⛩️','🗿']
|
||||
const buildings = ['⌂','⏏','☖','☗']
|
||||
const placeTypes = ['Village','Village','Village','House','House','Market','Market','Market','Crossroads','Place','Outpost','Trading Post','House','Shack','Meeting Place','Saloon','Watering Hole','Stall','Hideout','Cart','Camp','Camp','Camp','Camp','','','','Zone of Ill Repute']
|
||||
|
||||
let whichBuilding = buildings[Math.floor(Math.random()*3)];
|
||||
|
@ -370,6 +377,8 @@ let createGraves = () => {
|
|||
|
||||
let name = Charlatan.Name.name();
|
||||
|
||||
let gravestones = ['✝','✟','☨','✞'];
|
||||
let whichGravestone = choose(gravestones);
|
||||
let prefix = ["Here lies","RIP","","","","Resting place of ","Beloved"]
|
||||
let reason = ["Made an enemy","Wasn't afraid to be","Tried","Died while","Passed while performing","Tried out","Dissapeared investingating","Wandered off while looking for","Last seen","Loved","Adored","A lifelong fan of","Our favorite at","The best at","Always in our hearts","Keep","Always be","Always","Just","Tried","Couldn't stop","Only ever found","Died","Passed while","Couldn't stop","Forgot to try","Never stopped","We'll always think of you when we're","It's not the same"]
|
||||
|
||||
|
@ -378,7 +387,8 @@ let createGraves = () => {
|
|||
places.push(
|
||||
{
|
||||
"name": epitaph,
|
||||
"symbol": "⚰️",
|
||||
// "symbol": "⚰️",
|
||||
"symbol": whichGravestone,
|
||||
"position":
|
||||
{
|
||||
"x":Math.floor(Math.random()*width),
|
||||
|
@ -388,45 +398,8 @@ let createGraves = () => {
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
//-----------------PEOPLE----------------------------------------
|
||||
let people =
|
||||
[
|
||||
{
|
||||
"name": "wizard",
|
||||
"emoji": "🧙",
|
||||
"life": 3
|
||||
},
|
||||
{
|
||||
"name": "woman",
|
||||
"emoji": "🧝",
|
||||
"life": 3
|
||||
},
|
||||
{
|
||||
"name": "man",
|
||||
"emoji": "🧔",
|
||||
"life": 3
|
||||
},
|
||||
{
|
||||
"name": "woman",
|
||||
"emoji": "👵",
|
||||
"life": 3
|
||||
},
|
||||
{
|
||||
"name": "man",
|
||||
"emoji": "👴",
|
||||
"life": 3
|
||||
},
|
||||
{
|
||||
"name": "person",
|
||||
"emoji": "🧓",
|
||||
"life": 3
|
||||
}
|
||||
]
|
||||
|
||||
//----------------create zone---------------
|
||||
|
||||
|
||||
/*
|
||||
let landscapes = ['🏔️','🌿','🌱','🌾','🌻','🌵']
|
||||
|
||||
let plants = ['🌹','🌺','🌻','🌼','🌷','🎋']
|
||||
|
@ -434,6 +407,7 @@ let plants = ['🌹','🌺','🌻','🌼','🌷','🎋']
|
|||
let shrines = ['⛩️','🗿']
|
||||
|
||||
let emojiitems = ['🍄','🌰','🦴','🧵','🧶','👓','🕶','🥽','👞','👟','🥾','🥿','👑','💼']
|
||||
*/
|
||||
|
||||
let debug = () => {
|
||||
//console.log(dungeon)
|
||||
|
@ -453,8 +427,11 @@ let dungeonToStrings = () => {
|
|||
|
||||
let createTerrain = () => {
|
||||
|
||||
let forestTerrain = ['🎄', '🌳','🌲']
|
||||
let plants = ['🌹','🌺','🌻','🌼','🌷','🎋','🍄','🌰','🌿','🌱','🌾','🏔️']
|
||||
let forestTerrain = ['ᚠ','ᚡ','ᚴ','ᚵ','ᚶ','ᛉ','ᛘ','ᛠ'];
|
||||
//let forestTerrain = ['🎄', '🌳','🌲']
|
||||
let plants = ['ሥ','ሥ','ቂ','ቁ','ቄ','ቃ','ቅ','ቆ','ቇ','ቈ','ቊ','ቋ','ቌ','ቍ','ቜ','ቝ']
|
||||
//let plants = ['🌹','🌺','🌻','🌼','🌷','🎋','🍄','🌰','🌿','🌱','🌾','🏔️']
|
||||
//
|
||||
|
||||
for (let y = 0; y < height; y++){
|
||||
for (let x = 0; x < width; x++){
|
||||
|
@ -485,6 +462,18 @@ let createTerrain = () => {
|
|||
|
||||
let dungeonWithItemsToStrings = () => {
|
||||
|
||||
//start with dots
|
||||
for (let y = 0; y < height; y++){
|
||||
for (let x = 0; x < width; x++){
|
||||
dungeon[y][x] = ".";
|
||||
}
|
||||
}
|
||||
//specify terrain locations
|
||||
|
||||
for (let i = 0; i < terrain.length; i++){
|
||||
dungeon[terrain[i].position.y][terrain[i].position.x] = terrain[i].symbol;
|
||||
}
|
||||
|
||||
//specify item locations
|
||||
for (let i = 0; i < roomItems.length; i++){
|
||||
dungeon[roomItems[i].position.y][roomItems[i].position.x] = roomItems[i].symbol;
|
||||
|
@ -561,7 +550,140 @@ let checkDay = () => {
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------SET UP BLESSED----------------------
|
||||
let initBlessed = () => {
|
||||
screen = blessed.screen({
|
||||
smartCSR: true
|
||||
});
|
||||
|
||||
screen.title = gameTitle;
|
||||
|
||||
// Create a box perfectly centered horizontally and vertically.
|
||||
box = blessed.box({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
content: "Welcome to "+gameTitle,
|
||||
tags: true,
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'cyan',
|
||||
border: {
|
||||
fg: '#f0f0f0'
|
||||
},
|
||||
hover: {
|
||||
bg: 'green'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append our box to the screen.
|
||||
screen.append(box);
|
||||
|
||||
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
|
||||
screen.key(['right', 'l'], function(ch, key) {
|
||||
console.log('moved right');
|
||||
player.position.x++;
|
||||
loop();
|
||||
});
|
||||
screen.key(['left', 'h'], function(ch, key) {
|
||||
console.log('moved left');
|
||||
player.position.x--;
|
||||
loop();
|
||||
});
|
||||
screen.key(['down', 'j'], function(ch, key) {
|
||||
console.log('moved down');
|
||||
player.position.y++;
|
||||
loop();
|
||||
});
|
||||
screen.key(['up', 'k'], function(ch, key) {
|
||||
player.position.y--;
|
||||
console.log('moved up');
|
||||
loop();
|
||||
});
|
||||
|
||||
|
||||
screen.render();
|
||||
}
|
||||
|
||||
let keyHandler = () => {
|
||||
// If box is focused, handle `enter`/`return` and give us some more content.
|
||||
//
|
||||
|
||||
console.log('box.content: '+box.content);
|
||||
|
||||
//box.setContent('hello {red-fg}{green-bg}world{/}');
|
||||
box.key('enter', function(ch, key) { //writes to screen, focus needed
|
||||
|
||||
for (let i = 0; i < dungeon.length; i++){
|
||||
box.setLine(i, dungeon[i].join(''));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//box.content = "test test"; //writes to screen, no focus needed
|
||||
|
||||
screen.render();
|
||||
}
|
||||
|
||||
let drawToBox = () => {
|
||||
//start with dots
|
||||
for (let y = 0; y < height; y++){
|
||||
for (let x = 0; x < width; x++){
|
||||
dungeon[y][x] = ".";
|
||||
}
|
||||
}
|
||||
//specify terrain locations
|
||||
|
||||
for (let i = 0; i < terrain.length; i++){
|
||||
dungeon[terrain[i].position.y][terrain[i].position.x] = terrain[i].symbol;
|
||||
}
|
||||
|
||||
//specify item locations
|
||||
for (let i = 0; i < roomItems.length; i++){
|
||||
dungeon[roomItems[i].position.y][roomItems[i].position.x] = roomItems[i].symbol;
|
||||
}
|
||||
|
||||
//specify places location
|
||||
for (let i = 0; i < places.length; i++){
|
||||
dungeon[places[i].position.y][places[i].position.x] = places[i].symbol;
|
||||
}
|
||||
|
||||
//specify player location
|
||||
dungeon[player.position.y][player.position.x] = player.avatar;
|
||||
|
||||
let dungeonStr = "";
|
||||
for (let i = 0; i < height; i++){
|
||||
dungeonStr+=(dungeon[i].join("")+"\n");
|
||||
}
|
||||
|
||||
//return dungeonStr;
|
||||
//
|
||||
box.setContent(dungeonStr);
|
||||
|
||||
/*
|
||||
for (let i = 0; i < dungeon.length; i++){
|
||||
box.setLine(i, dungeonStr[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------MAIN GAME LOOP-------------------------
|
||||
|
||||
|
||||
let main = () => {
|
||||
//----INIT
|
||||
initBlessed();
|
||||
checkDay();
|
||||
parseArgs();
|
||||
|
||||
|
@ -572,8 +694,32 @@ let main = () => {
|
|||
|
||||
let dungeonWithItems = dungeonWithItemsToStrings();
|
||||
drawDungeon(dungeonWithItems);
|
||||
|
||||
//keyHandler();
|
||||
|
||||
//debug();
|
||||
//debug();
|
||||
}
|
||||
|
||||
let loop = () => {
|
||||
//
|
||||
//Probably need to reload these things as you move
|
||||
loadDungeon();
|
||||
loadTerrain();
|
||||
loadItems();
|
||||
loadPlaces();
|
||||
loadPlayer();
|
||||
loadInventory();
|
||||
|
||||
grab();
|
||||
movePlayer();
|
||||
checkCollision();
|
||||
|
||||
//blessed
|
||||
//
|
||||
screen.realloc();
|
||||
drawToBox();
|
||||
|
||||
screen.render();
|
||||
}
|
||||
|
||||
main()
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
var blessed = require('blessed');
|
||||
|
||||
// Create a screen object.
|
||||
var screen = blessed.screen({
|
||||
smartCSR: true
|
||||
});
|
||||
|
||||
screen.title = 'my window title';
|
||||
|
||||
// Create a box perfectly centered horizontally and vertically.
|
||||
var box = blessed.box({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
content: 'Hello {bold}world{/bold}!',
|
||||
tags: true,
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'magenta',
|
||||
border: {
|
||||
fg: '#f0f0f0'
|
||||
},
|
||||
hover: {
|
||||
bg: 'green'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append our box to the screen.
|
||||
screen.append(box);
|
||||
|
||||
// Add a png icon to the box
|
||||
var icon = blessed.image({
|
||||
parent: box,
|
||||
top: 0,
|
||||
left: 0,
|
||||
type: 'overlay',
|
||||
width: 'shrink',
|
||||
height: 'shrink',
|
||||
file: __dirname + '/my-program-icon.png',
|
||||
search: false
|
||||
});
|
||||
|
||||
// If our box is clicked, change the content.
|
||||
box.on('click', function(data) {
|
||||
box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// If box is focused, handle `enter`/`return` and give us some more content.
|
||||
box.key('enter', function(ch, key) {
|
||||
box.setContent('{right}Even different {black-fg}content{/black-fg}.{/right}\n');
|
||||
box.setLine(1, 'bar');
|
||||
box.insertLine(1, 'foo');
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// Quit on Escape, q, or Control-C.
|
||||
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
// Focus our element.
|
||||
box.focus();
|
||||
|
||||
// Render the screen.
|
||||
screen.render();
|
|
@ -0,0 +1,67 @@
|
|||
//source: https://recodes.co/being-blessed/
|
||||
// Require the Blessed API.
|
||||
var Blessed = require('blessed');
|
||||
|
||||
// Initialize the screen widget.
|
||||
var screen = Blessed.screen({
|
||||
// Example of optional settings:
|
||||
smartCSR: true,
|
||||
useBCE: true,
|
||||
cursor: {
|
||||
artificial: true,
|
||||
blink: true,
|
||||
shape: 'underline'
|
||||
},
|
||||
log: `${__dirname}/application.log`,
|
||||
debug: true,
|
||||
dockBorders: true
|
||||
});
|
||||
|
||||
// Specify the title of the application.
|
||||
screen.title = 'La pizza de Don Cangrejo.';
|
||||
|
||||
// Creating a textarea on the bottom of the screen.
|
||||
var input = Blessed.textarea({
|
||||
bottom: 0,
|
||||
height: 3,
|
||||
inputOnFocus: true,
|
||||
padding: {
|
||||
top: 1,
|
||||
left: 2
|
||||
},
|
||||
style: {
|
||||
fg: '#787878',
|
||||
bg: '#454545',
|
||||
|
||||
focus: {
|
||||
fg: '#f6f6f6',
|
||||
bg: '#353535'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append the widget to the screen.
|
||||
screen.append(input);
|
||||
|
||||
// Render the screen.
|
||||
screen.render();
|
||||
|
||||
|
||||
// Quit on `q`, or `Control-C` when the focus is on the screen.
|
||||
screen.key(['q', 'C-c'], function(ch, key) {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Focus on `escape` or `i` when focus is on the screen.
|
||||
screen.key(['escape', 'i'], function() {
|
||||
// Set the focus on the input.
|
||||
input.focus();
|
||||
});
|
||||
|
||||
// If box is focused, handle `Control+s`.
|
||||
input.key('C-s', function(ch, key) {
|
||||
var message = this.getValue();
|
||||
// Send the message somehow.
|
||||
this.clearValue();
|
||||
screen.render();
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
const fs = require('fs');
|
||||
const Charlatan = require('charlatan');
|
||||
|
||||
let createGraves = () => {
|
||||
|
||||
//ingest verbs
|
||||
verbs = fs.readFileSync("../.verbs.txt").toString().split("\n");
|
||||
|
||||
let name = Charlatan.Name.name();
|
||||
|
||||
let prefix = ["Here lies","RIP","","","","Resting place of ","Beloved"]
|
||||
let reason = ["Made an enemy","Wasn't afraid to be","Tried","Died while","Passed while performing","Tried out","Dissapeared investingating","Wandered off while looking for","Last seen","Loved","Adored","A lifelong fan of","Our favorite at","The best at","Always in our hearts","Keep","Always be","Always","Just","Tried","Couldn't stop","Only ever found","Died","Passed while","Couldn't stop","Forgot to try","Never stopped","We'll always think of you when we're","It's not the same"]
|
||||
|
||||
let epitaph = prefix[Math.floor(Math.random() * prefix.length)] + " " + name +"\n"+reason[Math.floor(Math.random() * reason.length)]+" " + verbs[Math.floor(Math.random()*verbs.length)] + ".";
|
||||
|
||||
console.log(epitaph);
|
||||
}
|
||||
|
||||
createGraves();
|
|
@ -0,0 +1,31 @@
|
|||
const generator = require("project-name-generator");
|
||||
|
||||
let createPlace = () => {
|
||||
let numToSpawn = Math.round(Math.random() * 3) + 3
|
||||
|
||||
for (let i = 0; i < numToSpawn; i++){
|
||||
|
||||
const buildings = ['🏛️','⛺','🏚️','⛩️','🗿']
|
||||
const placeTypes = ['Village','Village','Village','House','House','Market','Market','Market','Crossroads','Place','Outpost','Trading Post','House','Shack','Meeting Place','Saloon','Watering Hole','Stall','Hideout','Cart','Camp','Camp','Camp','Camp','','','','Zone of Ill Repute']
|
||||
|
||||
let whichBuilding = buildings[Math.floor(Math.random()*3)];
|
||||
|
||||
let loc = generator.generate().spaced;
|
||||
|
||||
let suffix = placeTypes[Math.floor(Math.random() * placeTypes.length)];
|
||||
|
||||
let locName = capitalize(loc + ' ' + suffix);
|
||||
|
||||
console.log(whichBuilding + ": "+locName)
|
||||
}
|
||||
}
|
||||
|
||||
let capitalize = (str) => {
|
||||
let arr = str.split(' ');
|
||||
for(let i = 0; i < arr.length; i++ ) {
|
||||
arr[i] = arr[i].replace(arr[i].charAt(0), arr[i].charAt(0).toUpperCase());
|
||||
}
|
||||
return arr.join(' ');
|
||||
}
|
||||
|
||||
createPlace();
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Example Program for Blessed
|
||||
* Copyright (c) 2013, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/chjj/blessed
|
||||
*/
|
||||
|
||||
var blessed = require('blessed')
|
||||
, program = blessed.program();
|
||||
|
||||
process.title = 'blessed';
|
||||
|
||||
program.on('keypress', function(ch, key) {
|
||||
if (key.name === 'q') {
|
||||
program.clear();
|
||||
program.disableMouse();
|
||||
program.showCursor();
|
||||
program.normalBuffer();
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
program.on('mouse', function(data) {
|
||||
if (data.action === 'mouseup') return;
|
||||
program.move(1, program.rows);
|
||||
program.eraseInLine('right');
|
||||
if (data.action === 'wheelup') {
|
||||
program.write('Mouse wheel up at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'wheeldown') {
|
||||
program.write('Mouse wheel down at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'mousedown' && data.button === 'left') {
|
||||
program.write('Left button down at: ' + data.x + ', ' + data.y);
|
||||
} else if (data.action === 'mousedown' && data.button === 'right') {
|
||||
program.write('Right button down at: ' + data.x + ', ' + data.y);
|
||||
} else {
|
||||
program.write('Mouse at: ' + data.x + ', ' + data.y);
|
||||
}
|
||||
program.move(data.x, data.y);
|
||||
program.bg('red');
|
||||
program.write(' ');
|
||||
program.bg('!red');
|
||||
});
|
||||
|
||||
program.on('focus', function() {
|
||||
program.move(1, program.rows);
|
||||
program.write('Gained focus.');
|
||||
});
|
||||
|
||||
program.on('blur', function() {
|
||||
program.move(1, program.rows);
|
||||
program.write('Lost focus.');
|
||||
});
|
||||
|
||||
program.alternateBuffer();
|
||||
program.enableMouse();
|
||||
program.hideCursor();
|
||||
program.clear();
|
||||
|
||||
program.move(1, 1);
|
||||
program.bg('black');
|
||||
program.write('Hello world', 'blue fg');
|
||||
program.setx((program.cols / 2 | 0) - 4);
|
||||
program.down(5);
|
||||
program.write('Hi again!');
|
||||
program.bg('!black');
|
||||
program.feed();
|
||||
|
||||
program.getCursor(function(err, data) {
|
||||
if (!err) {
|
||||
program.write('Cursor is at: ' + data.x + ', ' + data.y + '.');
|
||||
program.feed();
|
||||
}
|
||||
|
||||
program.charset('SCLD');
|
||||
program.write('abcdefghijklmnopqrstuvwxyz0123456789');
|
||||
program.charset('US');
|
||||
program.setx(1);
|
||||
});
|
|
@ -0,0 +1,4 @@
|
|||
const Charlatan = require('charlatan');
|
||||
|
||||
let name = Charlatan.Name.name();
|
||||
console.log(name);
|
|
@ -0,0 +1,20 @@
|
|||
const generator = require("project-name-generator");
|
||||
|
||||
let firstSubject = generator.generate().spaced;
|
||||
let secondSubject = generator.generate({ words: 2, alliterative: true }).spaced;
|
||||
|
||||
let pre = ["My Year of","A Guide To","Simply","A Cook's Guide to","The Book of","A tale of","To","A","The","The","The","One","Beginning","My","A Manual of","",""];
|
||||
let connector = [" of"," for"," for"," with"," and"," on",":",": on"," OR"];
|
||||
let choose = arr => arr[Math.floor(Math.random()*arr.length)];
|
||||
|
||||
|
||||
let book;
|
||||
|
||||
if (Math.random()<0.4){
|
||||
book = choose(pre) + " " + firstSubject + choose(connector) + " " + secondSubject;
|
||||
} else if (Math.random()<0.5){
|
||||
book = choose(pre) + " " + firstSubject;
|
||||
} else {
|
||||
book = choose(pre) + " " + secondSubject;
|
||||
}
|
||||
console.log(book);
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
|
@ -0,0 +1,88 @@
|
|||
var fs = require('fs');
|
||||
var blessed = require('blessed');
|
||||
|
||||
let dungeon;
|
||||
const descriptionsFile = "../.nonKittenItems.txt";
|
||||
let itemDescriptions = fs.readFileSync(descriptionsFile).toString().split("\n");
|
||||
|
||||
let loadDungeon = () => {
|
||||
const dungeonInput = fs.readFileSync(".dungeonfile.txt",'utf8')
|
||||
dungeon = dungeonInput.split("\n");
|
||||
|
||||
}
|
||||
|
||||
loadDungeon();
|
||||
|
||||
// Create a screen object.
|
||||
var screen = blessed.screen({
|
||||
smartCSR: true
|
||||
});
|
||||
|
||||
screen.title = 'my window title';
|
||||
|
||||
// Create a box perfectly centered horizontally and vertically.
|
||||
var box = blessed.box({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
width: '50%',
|
||||
height: '50%',
|
||||
content: dungeon[0],
|
||||
tags: true,
|
||||
border: {
|
||||
type: 'line'
|
||||
},
|
||||
style: {
|
||||
fg: 'cyan',
|
||||
bg: 'white',
|
||||
border: {
|
||||
fg: '#f0f0f0'
|
||||
},
|
||||
hover: {
|
||||
bg: 'green'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append our box to the screen.
|
||||
screen.append(box);
|
||||
|
||||
// Add a png icon to the box
|
||||
var icon = blessed.image({
|
||||
parent: box,
|
||||
top: 0,
|
||||
left: 0,
|
||||
type: 'overlay',
|
||||
width: 'shrink',
|
||||
height: 'shrink',
|
||||
file: __dirname + '/my-program-icon.png',
|
||||
search: false
|
||||
});
|
||||
|
||||
// If our box is clicked, change the content.
|
||||
box.on('click', function(data) {
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// If box is focused, handle `enter`/`return` and give us some more content.
|
||||
box.key('enter', function(ch, key) {
|
||||
|
||||
for (let i = 0; i < dungeon.length; i++){
|
||||
box.setLine(i, dungeon[i]);
|
||||
}
|
||||
|
||||
|
||||
screen.render();
|
||||
});
|
||||
|
||||
// Quit on Escape, q, or Control-C.
|
||||
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
// Focus our element.
|
||||
box.focus();
|
||||
|
||||
// Render the screen.
|
||||
screen.render();
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
var blessed = require('blessed')
|
||||
, program = blessed.program();
|
||||
|
||||
process.title = 'blessed';
|
||||
|
||||
program.on('keypress', function(ch, key) {
|
||||
if (key.name === 'q') {
|
||||
program.clear();
|
||||
program.disableMouse();
|
||||
program.showCursor();
|
||||
program.normalBuffer();
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
program.alternateBuffer();
|
||||
//program.enableMouse();
|
||||
program.hideCursor();
|
||||
program.clear();
|
||||
|
||||
program.move(1, 1);
|
||||
program.bg('#0000ff');
|
||||
program.write('Hello world', 'blue fg');
|
||||
program.setx((program.cols / 2 | 0) - 4);
|
||||
program.down(5);
|
||||
program.write('Hi again!');
|
||||
program.bg('!black');
|
||||
program.feed();
|
||||
|
||||
program.getCursor(function(err, data) {
|
||||
if (!err) {
|
||||
program.write('Cursor is at: ' + data.x + ', ' + data.y + '.');
|
||||
program.feed();
|
||||
}
|
||||
|
||||
program.charset('SCLD');
|
||||
program.write('abcdefghijklmnopqrstuvwxyz0123456789');
|
||||
program.charset('US');
|
||||
program.setx(1);
|
||||
});
|
Loading…
Reference in New Issue