colorise world-tree dependent of completion of levels
This commit is contained in:
@@ -26,7 +26,6 @@ function GithubIcon({url='https://github.com'}) {
|
||||
return <div className="github-link">
|
||||
<a title="view the Lean game server on Github" href={url}>
|
||||
<svg height="24" aria-hidden="true" viewBox="0 0 16 16" version="1.1" width="24" className="">
|
||||
{/* <circle className="world-circle" cx="8" cy="8" r="8" fill="#fff"/> */}
|
||||
<path fill="#fff" d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
@@ -18,26 +18,26 @@ import WorldSelectionMenu from './world_selection_menu';
|
||||
import {PrivacyPolicy} from './privacy_policy';
|
||||
import { Button } from './button';
|
||||
import { Documentation, Inventory } from './inventory';
|
||||
import { store } from '../state/store';
|
||||
|
||||
cytoscape.use( klay );
|
||||
|
||||
const N = 24 // max number of levels per world
|
||||
const N = 18 // max number of levels per world
|
||||
const R = 800 // radius of a world
|
||||
const r = 110 // radius of a level
|
||||
const s = 100 // global scale
|
||||
const r = 160 // radius of a level
|
||||
const s = 120 // global scale
|
||||
const padding = 2000 // padding of the graphic (on a different scale)
|
||||
|
||||
function LevelIcon({ worldId, levelId, position }) {
|
||||
function LevelIcon({ worldId, levelId, position, completed, available }) {
|
||||
const gameId = React.useContext(GameIdContext)
|
||||
const completed = useSelector(selectCompleted(gameId, worldId,levelId))
|
||||
|
||||
const x = s * position.x + Math.sin(levelId * 2 * Math.PI / N) * (R + 1.2*r + 2*Math.floor((levelId - 1)/N))
|
||||
const y = s * position.y - Math.cos(levelId * 2 * Math.PI / N) * (R + 1.2*r + 2*Math.floor((levelId - 1)/N))
|
||||
const x = s * position.x + Math.sin(levelId * 2 * Math.PI / N) * (R + 1.2*r + 2.4*r*Math.floor((levelId - 1)/N))
|
||||
const y = s * position.y - Math.cos(levelId * 2 * Math.PI / N) * (R + 1.2*r + 2.4*r*Math.floor((levelId - 1)/N))
|
||||
|
||||
// TODO: relative positioning?
|
||||
return (
|
||||
<Link to={`/${gameId}/world/${worldId}/level/${levelId}`}>
|
||||
<circle fill={completed ? "green" :"#999"} cx={x} cy={y} r={r} />
|
||||
<circle fill={completed ? "#139e13" : available? "#1976d2" : "#999"} cx={x} cy={y} r={r} />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -72,35 +72,64 @@ function Welcome() {
|
||||
|
||||
const svgElements = []
|
||||
|
||||
// For each `worldId` as index, this contains a list of booleans with indices
|
||||
// 0, 1, …, n. Index `0` will be set to `false` if any dependency is not completely solved.
|
||||
// Indices `1, …, n` indicate if the corresponding level is completed
|
||||
var completed = {}
|
||||
|
||||
if (gameInfo.data) {
|
||||
|
||||
// Fill `completed` with the level data.
|
||||
for (let worldId in nodes) {
|
||||
let position: cytoscape.Position = nodes[worldId].position
|
||||
let state = store.getState()
|
||||
|
||||
completed[worldId] = Array.from({ length: gameInfo.data.worldSize[worldId] + 1 }, (_, i) => {
|
||||
// Index `0` might be set to `false` in the loop over the edges
|
||||
if (!i) {return true}
|
||||
return selectCompleted(gameId, worldId, i)(state)
|
||||
})
|
||||
}
|
||||
|
||||
for (let i in gameInfo.data.worlds.edges) {
|
||||
const edge = gameInfo.data.worlds.edges[i]
|
||||
|
||||
// If the origin world is not completed, mark the target world as non-playable
|
||||
let unlocked = completed[edge[0]].slice(1).every(Boolean)
|
||||
if (!unlocked) {completed[edge[1]][0] = false}
|
||||
|
||||
// Draw the connection edges
|
||||
svgElements.push(
|
||||
<line key={`pathway${i}`} x1={s*nodes[edge[0]].position.x} y1={s*nodes[edge[0]].position.y}
|
||||
x2={s*nodes[edge[1]].position.x} y2={s*nodes[edge[1]].position.y} stroke="#1976d2" strokeWidth={s}/>
|
||||
x2={s*nodes[edge[1]].position.x} y2={s*nodes[edge[1]].position.y}
|
||||
stroke={unlocked ? "green" : "#bbb"} strokeWidth={s}/>
|
||||
)
|
||||
}
|
||||
|
||||
for (let id in nodes) {
|
||||
let position: cytoscape.Position = nodes[id].position
|
||||
|
||||
for (let i = 1; i <= gameInfo.data.worldSize[id]; i++) {
|
||||
for (let worldId in nodes) {
|
||||
// Draw the level bubbles
|
||||
let position: cytoscape.Position = nodes[worldId].position
|
||||
for (let i = 1; i <= gameInfo.data.worldSize[worldId]; i++) {
|
||||
svgElements.push(
|
||||
<LevelIcon
|
||||
key={`/${gameId}/world/${id}/level/${i}`}
|
||||
position={position} worldId={id} levelId={i} />
|
||||
key={`/${gameId}/world/${worldId}/level/${i}`}
|
||||
position={position} worldId={worldId} levelId={i}
|
||||
completed={completed[worldId][i]} available={completed[worldId][i-1]}/>
|
||||
)
|
||||
}
|
||||
|
||||
// Draw the worlds
|
||||
let worldUnlocked = completed[worldId][0]
|
||||
let worldCompleted = completed[worldId].slice(1).every(Boolean)
|
||||
svgElements.push(
|
||||
<Link key={`world${id}`} to={`/${gameId}/world/${id}/level/0`}>
|
||||
<Link key={`world${worldId}`} to={`/${gameId}/world/${worldId}/level/0`}>
|
||||
<circle className="world-circle" cx={s*position.x} cy={s*position.y} r={R}
|
||||
fill="#1976d2"/>
|
||||
fill={worldCompleted ? "green" : worldUnlocked ? "#1976d2": "#999"}/>
|
||||
<foreignObject className="world-title-wrapper" x={s*position.x} y={s*position.y}
|
||||
width={1.42*R} height={1.42*R} transform={"translate("+ -.71*R +","+ -.71*R +")"}>
|
||||
<div>
|
||||
<p className="world-title" style={{fontSize: Math.floor(R/4) + "px"}}>
|
||||
{nodes[id].data.title ? nodes[id].data.title : id}
|
||||
{nodes[worldId].data.title ? nodes[worldId].data.title : worldId}
|
||||
</p>
|
||||
</div>
|
||||
</foreignObject>
|
||||
|
||||
Reference in New Issue
Block a user