Skip to content

Instantly share code, notes, and snippets.

@oskarrough
Created December 23, 2020 20:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oskarrough/da46aa7c866e9a8a7672184481398953 to your computer and use it in GitHub Desktop.
Save oskarrough/da46aa7c866e9a8a7672184481398953 to your computer and use it in GitHub Desktop.
stwmap
<button onClick="generate()">Generate</button>
<slay-map rows="10" columns="6"></slay-map>
// Returns a random number between min (inclusive) and max (inclusive)
function randomBetween(min, max) {
return Math.floor(
Math.random() * (max - min + 1) + min
)
}
// Returns a new, shuffled version of an array.
// See https://bost.ocks.org/mike/shuffle/
function shuffle(array) {
// Make a copy
array = array.slice()
var m = array.length
var t
var i
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(Math.random() * m--)
// And swap it with the current element.
t = array[m]
array[m] = array[i]
array[i] = t
}
return array
}
// Returns a "graph" of the map we want to render,
// using nested arrays for the rows and columns.
function generateGraph(rows, columns) {
const graph = []
const size = columns * rows
for (let r = 0; r<rows; r++) {
const row = []
// In each row we want from a to b encounters.
const encounters = randomBetween(2,5)
for (let i = 0; i<encounters; i++) {
row.push({type: 'encounter'})
}
// Fill empty columns.
while (row.length < columns) {
row.push({type: false})
}
// Randomize the order.
graph.push(shuffle(row))
}
return graph
}
// This is an example of how you can render the graph as a map.
class SlayMap extends HTMLElement {
connectedCallback() {
this.state = {
rows: this.getAttribute('rows'),
columns: this.getAttribute('columns')
}
this.render()
}
randomEncounter() {
return shuffle(Array.from('πŸ’€πŸ’€πŸ’€πŸ’°β“'))[0]
}
render() {
const {rows, columns} = this.state
const graph = generateGraph(rows, columns)
this.innerHTML = `
<slay-map-row center>
<slay-map-encounter>πŸ’€πŸ’€</slay-map-encounter>
</slay-map-row>
${graph.map((row) => `
<slay-map-row>
${row.map((col) => {
if (col.type === 'encounter') {
return `<slay-map-encounter>${this.randomEncounter()}</slay-map-encounter>`
}
return `<slay-map-node></slay-map-node>`
}).join('')}
</slay-map-row>
`).join('')}
<slay-map-row center>
<slay-map-encounter>πŸ•οΈ</slay-map-encounter>
</slay-map-row>
<svg class="paths"><rect width="20" height="20" fill="red" /></svg>
`
this.scatter()
this.drawPaths()
}
// Move the encounters around a bit.
scatter() {
const nodes = this.querySelectorAll('slay-map-encounter')
nodes.forEach(node => {
node.style.transform = `translate3d(
${randomBetween(-35,35)}%,
${randomBetween(-40,40)}%,
0)
`
})
}
// Playing around with connecting the nodes #naive
drawPaths() {
const parent = this.getBoundingClientRect()
function getPos(el) {
const rect = el.getBoundingClientRect()
return {
top: rect.top - parent.top,
left: rect.left - parent.left,
width: rect.width,
height: rect.height
}
}
const connectNodes = (a, b) => {
if (!a || !b) return
const svg = this.querySelector('svg.paths')
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line')
const aPos = getPos(a)
const bPos = getPos(b)
line.setAttribute('x1', aPos.left + aPos.width / 2)
line.setAttribute('y1', aPos.top + aPos.height / 2)
line.setAttribute('x2', bPos.left + bPos.width / 2)
line.setAttribute('y2', bPos.top + bPos.height / 2)
svg.appendChild(line)
console.log({a, b, line})
}
const getEncounter = (row, index) => this.querySelector(`slay-map-row:nth-child(${row}) slay-map-encounter:nth-of-type(${index})`)
const rows = this.querySelectorAll('slay-map-row')
rows.forEach((row, i) => {
connectNodes(getEncounter(i, 1), getEncounter(i+1, 1))
// connectNodes(getEncounter(i, 2), getEncounter(i+1, 2))
// connectNodes(getEncounter(i, 3), getEncounter(i+1, 3))
// connectNodes(getEncounter(i, 4), getEncounter(i+1, 4))
// const encounters = rows[i].querySelectorAll('slay-map-encounter')
// encounters.forEach(encounter => {
// let nextEncounters = rows[i+1].querySelectorAll('slay-map-encounter')
// nextEncounters.forEach(encounter2 => {
// connectNodes(encounter, getEncounter(i+2, 1))
// })
// })
})
// connect bottom
connectNodes(getEncounter(12, 1), getEncounter(11, 2))
connectNodes(getEncounter(12, 1), getEncounter(11, 3))
connectNodes(getEncounter(12, 1), getEncounter(11, 4))
connectNodes(getEncounter(12, 1), getEncounter(11, 5))
connectNodes(getEncounter(11, 2), getEncounter(10, 2))
connectNodes(getEncounter(10, 2), getEncounter(9, 2))
// connectNodes(getEncounter(1, 1), getEncounter(2, 3))
// connectNodes(getEncounter(1, 1), getEncounter(2, 4))
// connectNodes(getEncounter(1, 1), getEncounter(2, 5))
}
}
customElements.define('slay-map', SlayMap)
function generate() {
let slayMap = document.querySelector('slay-map')
slayMap.render()
}
// https://github.com/oskarrough/slaytheweb/issues/28
// https://i.imgur.com/oAofMa0.jpg
// https://github.com/yurkth/stsmapgen
// https://github.com/SunnySunMoon/Slay-the-Spire-Map
///// ARCHIVE BELOW
/*
createMap({columns, rows}) {
const graph = generateGraph(columns, rows)
const element = this
graph.forEach((row, rowIndex) => {
const r = document.createElement('div')
r.classList.add('Map-row')
for (let i = 0; i<columns; i++) {
// Render columns.
var c = document.createElement('div')
const type = row[i].type
c.classList.add(`Map-${type}`)
if (type === 'encounter') {
//πŸ˜€πŸ˜ˆπŸ’€πŸ’°β“
c.textContent = shuffle(Array.from("πŸ’€πŸ’€πŸ’€πŸ’°β“"))[0]
}
// c.style.transform = `translateY(${randomBetween(-50,50)}%)`
r.appendChild(c)
}
element.appendChild(r)
})
return element
}
render2() {
this.innerHTML = ''
this.createMap({
columns: 6,
rows: 10
})
}
*/
slay-map {
box-sizing: border-box;
display: grid;
/* grid-template-rows: repeat(12, 1fr); */
/* grid-gap: 1em; */
background: darkgreen;
width: 28rem;
max-width: 100%;
height: 40rem;
border: 4px solid black;
/* margin: 1em 0; */
padding: 1em;
position: relative;
}
slay-map-row {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-gap: 1em;
/* background: hsla(0,0%,0%, 0.1); */
}
slay-map-row[center] {
grid-template-columns: repeat(12, 1fr);
}
slay-map-row[center] slay-map-encounter {
grid-column-start: 6;
grid-column-end: 8;
transform: none !important;
background: hsla(0,0%,0%, 0.5);
}
slay-map-node,
slay-map-encounter {
margin: 0.25rem;
/* border: 1px solid; */
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
slay-map-encounter {
background: hsla(0,0%,0%, 0.05);
color: gold;
}
slay-map-encounter:hover {
background: hsla(0,0%,0%, 0.9);
transition: background 250ms;
cursor: pointer;
}
slay-map svg.paths {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
slay-map svg.paths line {
stroke: black;
stroke-width: 3px;
stroke-dasharray: 7px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment