Created
February 15, 2019 14:46
-
-
Save hohoonlee/c22c67a52baddda72e04d7088545c1b3 to your computer and use it in GitHub Desktop.
한붓그리기 1차
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>Document</title> | |
</head> | |
<body> | |
<table id='t'></table> | |
<script> | |
const blockTypes = [0, 1, 2, 3, 4]; | |
const minSelected = 3; | |
const Block = class { | |
static getInstance(type = parseInt(Math.random() * 5)) {return new Block(type);} | |
constructor(type) { | |
this._type = type; | |
} | |
// get image() { return `url('img/icon${this._type}.png');`;} | |
get image() { return `url('http://www.bsidesoft.com/summer/project/07_tower/img/block${this._type}.png');`;} | |
get type() { return this._type; } | |
}; | |
const Game = (()=>{ | |
const [stageWidth, stageHeight] = [8, 8]; | |
const blockSize = 80; | |
const data = []; | |
let table; | |
let startBlock, currBlock, isDown; | |
const selected = []; | |
const init = tableId => { | |
table = document.querySelector(tableId); | |
for(let i = 0; i < stageHeight; i++) { | |
const row = []; | |
data.push(row); | |
for(let j = 0; j < stageWidth; j++) row[j] = Block.getInstance(); | |
} | |
table.innerHTML = ''; | |
data.forEach(row=>table.appendChild(row.reduce((tr, block)=>{ | |
tr.appendChild(el('td')); | |
return tr; | |
}, el('tr')))); | |
table.addEventListener('mousedown', down); | |
table.addEventListener('mouseup', up); | |
table.addEventListener('mouseleave', up); | |
table.addEventListener('mousemove', move); | |
render(); | |
}; | |
const getBlock = (x,y)=> { | |
const {top:T, left:L} = table.getBoundingClientRect(); | |
if(x < L || x > (L + blockSize * stageWidth) || y < T || y > (T + blockSize * stageHeight)) return null; | |
return data[parseInt((y-T)/blockSize)][parseInt((x-L)/blockSize)]; | |
}; | |
const isNext = curr => { | |
let r0, c0, r1, c1, cnt = 0; | |
data.some((row, i)=>{ | |
let j; | |
if((j = row.indexOf(currBlock)) !== -1) r0 = i, c0 = j, cnt++; //마지막 선택블럭 위치 | |
if((j = row.indexOf(curr)) !== -1) r1 = i, c1 = j, cnt++; //현재의 선택블럭 위치 | |
return cnt === 2; | |
}); | |
return curr != currBlock && Math.abs(r0 - r1) <= 1 && Math.abs(c0 - c1) <= 1; | |
} | |
const down = ({pageX:x, pageY:y})=>{ | |
if(isDown) return; | |
const curr = getBlock(x,y); | |
if(!curr) return; | |
isDown = true; | |
selected.length = 0; | |
selected[0] = startBlock = currBlock = curr; | |
render(); | |
}; | |
const move = ({pageX:x, pageY:y})=>{ | |
if(!isDown) return; | |
const curr = getBlock(x,y); | |
if(!curr || curr.type !== startBlock.type || !isNext(curr)) return; | |
if(selected.indexOf(curr) === -1) { | |
selected.push(curr); | |
}else if(selected[selected.length -2] === curr) { | |
selected.pop(); | |
} | |
currBlock = curr; | |
render(); | |
}; | |
const up = ()=> selected.length >= minSelected?remove():reset(); | |
const reset = ()=>{ | |
startBlock = currBlock = null; | |
selected.length = 0; | |
isDown = false; | |
render(); | |
} | |
const remove = ()=> { | |
data.forEach(r=>{ | |
selected.forEach(v=>{ | |
let i; | |
if((i = r.indexOf(v)) != -1) r[i] = null; | |
}); | |
}); | |
render(); | |
setTimeout(drop, 300); | |
} | |
const drop = () => { | |
let isNext = false; | |
for(let j = 0; j < stageWidth; j++) { | |
for(let i = stageHeight -1; i > -1; i--) { | |
if(!data[i][j] && i) { | |
let k = i, isEmpty = true; | |
while(k--) { | |
if(data[k][j]) { | |
isEmpty = false; | |
break; | |
} | |
} | |
if(isEmpty) break; | |
isNext = true; | |
while(i--) { | |
data[i+1][j] = data[i][j]; | |
data[i][j] = null; | |
} | |
break; | |
} | |
} | |
} | |
render(); | |
isNext ? setTimeout(drop, 300):readyToFill(); | |
}; | |
const fills = []; | |
let fillCnt = 0; | |
const readyToFill = () => { | |
fills.length = 0; | |
data.some(row=>{ | |
if(row.indexOf(null) === -1) return true; | |
const r = [...row].fill(null); | |
fills.push(r); | |
row.forEach((v,i)=>!v && (r[i] = Block.getInstance())); | |
}); | |
fillCnt = 0; | |
setTimeout(fill, 300); | |
}; | |
const fill = () => { | |
if(fillCnt > fills.length) { | |
isDown = false; | |
return; | |
} | |
for(let i = 0; i < fillCnt; i++) { | |
fills[fills.length -i -1].forEach((v,j)=>{ | |
if(v) data[fillCnt - i -1][j] = v; | |
}); | |
} | |
fillCnt++; | |
render(); | |
setTimeout(fill, 300); | |
} | |
const el = tag => document.createElement(tag); | |
const render = () => { | |
data.forEach((row, i)=>{ | |
const tr = table.rows[i]; | |
row.forEach((block, j)=>{ | |
tr.cells[j].style.cssText = ` | |
${block?`background:${block.image};`:''}; | |
background-size:${blockSize}px; | |
width:${blockSize}px; | |
height:${blockSize}px; | |
cursor:pointer; | |
background-color:${selected.indexOf(block) >= 0?'yellow':'white'}; | |
`; | |
}); | |
}); | |
// table.innerHTML = ''; | |
// data.forEach(row=>table.appendChild(row.reduce((tr, block)=>{ | |
// tr.appendChild(el('td')).style.cssText = ` | |
// ${block?`background:${block.image};`:''}; | |
// background-size:${blockSize}px; | |
// width:${blockSize}px; | |
// height:${blockSize}px; | |
// cursor:pointer; | |
// `; | |
// return tr; | |
// }, el('tr')))); | |
}; | |
return init; | |
})(); | |
Game('#t'); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment