UNPKG

flowfield

Version:

This library provides a pathfinding mechanism based on vectors field.

152 lines (137 loc) 4.49 kB
<html> <head> <link href="https://fonts.googleapis.com/css?family=Inconsolata" rel="stylesheet"> </head> <style> .title { text-align: center; font-size: 25px; margin-bottom: 30px; text-decoration: underline; } .container { display: flex; justify-content: center; } .cell { width: 55px; text-align: center; cursor: pointer; height: 55px; background-color: #e9e0e0; } .black { color: black; background-color: black; } .target { background-color: #cfc; } .path { background-color: #aaaaaa; } .obstacle { background-color: #ffcccc; } .panel { width: 200px; } .button { font: inherit; margin-top: 15px; padding: 8px; cursor: pointer; background-color: #ffcccc; } </style> <body style="font-family: 'Inconsolata', monospace;"> <div id="app" style></div> </body> </html> <script type="text/babel"> function init(w, h){ let FF = FlowField.default(1, h,w); FF.setTarget([4, 6]); return FF; } class App extends React.Component{ state={mode: 0, width: 10, height: 10, FF: null, path: []} componentDidMount(){ this.setState({FF : init(this.state.height,this.state.width) }); } switchMode= () => { this.setState({mode: !this.state.mode ? 1: 0}); } updateWidth = (e) => this.setState({width: parseInt(e.target.value,10)}, () => this.setState({FF: init(this.state.height, this.state.width)})) updateHeight = (e) => this.setState({height: parseInt(e.target.value,10)}, () => this.setState({FF: init(this.state.height, this.state.width)})) onCellClick(target){ const cell = this.state.FF.getCell(target); if(cell.distance === 0){ this.state.FF.setObstacle(target); } if(cell.obstacle){ this.state.FF.setTarget(target); } else { this.state.FF.setObstacle(target); } this.forceUpdate(); } render(){ if(!this.state.FF){ return <div>On going...</div>; } return ( [<div className="title">Try it.</div>, <div className="container"> <div className="panel"> <p>Width</p> <input onChange={this.updateWidth} type="range" min="4" max="15" placeholder="width" value={this.state.width}/> <p>Height</p> <input onChange={this.updateHeight} type="range" min="4" max="30" value={this.state.height}/> <div><button className='button' onClick={this.switchMode}>Switch Mode</button></div> </div> <table>{this.state.FF.getGrid().map((row,i) => <tr>{row.map((cell,j) => <td className={`cell ${!!this.state.path.filter(e => e[0] === i && e[1] === j)[0] && cell.distance !== 0 && !cell.obstacle ? 'path' : cell.obstacle ? 'black' : cell.distance===0 ? 'target' : ''}`} onClick={()=>this.onCellClick([i,j])} onMouseOver={() => this.state.FF && this.setState({path: this.state.FF.getPathFromCoordinates([i,j]) })}> {this.state.mode ? String.fromCharCode(parseInt(getArrow(cell.direction, cell.obstacle), 10)) : cell.distance} </td>)} </tr>)} </table> </div>]) } }; function getArrow(direction, obstacle){ if(!direction || direction.length === 0) { return '0'; } if(obstacle){ return '88'; } //bottom if(direction[0] === 1 && direction[1] === 0){ return "8595" }//right else if(direction[0] === 0 && direction[1] === 1){ return "8594" }//left else if(direction[0] === 0 && direction[1] === -1){ return "8592" }//top else if(direction[0] === -1 && direction[1] === 0){ return "8593" }//bottom right else if(direction[0] === 1 && direction[1] === 1){ return "8600" }//bottom left else if(direction[0] === 1 && direction[1] === -1){ return "8601" }//top left else if(direction[0] === -1 && direction[1] === -1){ return "8598" }//top right else if(direction[0] === -1 && direction[1] === 1){ return "8599" } return '33'; } ReactDOM.render( <App/>, document.getElementById('app')); </script>