Implement 2D galaxy view
This commit is contained in:
parent
718a9b5da6
commit
b51200f3e8
|
@ -2,7 +2,6 @@
|
||||||
import Layout from '../../layouts/Layout.astro';
|
import Layout from '../../layouts/Layout.astro';
|
||||||
import NavBar from '../../components/NavBar.astro';
|
import NavBar from '../../components/NavBar.astro';
|
||||||
import { getUserByAccessToken } from '../../lib/db/users';
|
import { getUserByAccessToken } from '../../lib/db/users';
|
||||||
import { getAllPlanets } from '../../lib/db/planets';
|
|
||||||
import locationManager from '../../lib/classes/managers/LocationManager';
|
import locationManager from '../../lib/classes/managers/LocationManager';
|
||||||
import ResourceBar from '../../components/ResourceBar.astro';
|
import ResourceBar from '../../components/ResourceBar.astro';
|
||||||
|
|
||||||
|
@ -13,89 +12,157 @@ if(loggedToken === null || username === "") return Astro.redirect('/logout');
|
||||||
const checkUser = await getUserByAccessToken(loggedToken);
|
const checkUser = await getUserByAccessToken(loggedToken);
|
||||||
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
|
if(checkUser === null || checkUser.username !== username) return Astro.redirect('/logout');
|
||||||
|
|
||||||
const allPlanets = await getAllPlanets();
|
const allGalaxies = locationManager.galaxies;
|
||||||
|
|
||||||
const formattedPlanets = allPlanets.map(planet => {
|
let i = 0;
|
||||||
|
const galaxies = allGalaxies.map(galaxy => {
|
||||||
return {
|
return {
|
||||||
name: planet.name,
|
numericId: i++,
|
||||||
owner: locationManager.getUser(planet.owner)?.username ?? "Unowned"
|
name: galaxy.name,
|
||||||
|
style: {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
color: "red"
|
||||||
|
},
|
||||||
|
sectors: galaxy.sectors.map(sector => {
|
||||||
|
return {
|
||||||
|
id: sector._id.toString(),
|
||||||
|
name: sector.name
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
for(const galaxy of galaxies) {
|
||||||
|
for(let i = 0; i < 100; i++) {
|
||||||
|
galaxy.style.left = Math.random() * 1200 + 20;
|
||||||
|
galaxy.style.top = Math.random() * 380 + 20;
|
||||||
|
const overlap = galaxies.slice(0, galaxy.numericId).some(otherGalaxy => {
|
||||||
|
const dx = galaxy.style.left - otherGalaxy.style.left;
|
||||||
|
const dy = galaxy.style.top - otherGalaxy.style.top;
|
||||||
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
return distance < 100;
|
||||||
|
});
|
||||||
|
if(!overlap) {
|
||||||
|
galaxy.style.color = "white"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Galaxy view">
|
<Layout title="Galaxy view">
|
||||||
<NavBar loggedIn="true" active="galaxyView" />
|
<NavBar loggedIn="true" active="galaxyView" />
|
||||||
<ResourceBar />
|
<ResourceBar />
|
||||||
<ul>
|
<div class="container">
|
||||||
{formattedPlanets.map(planet => <li>{planet.name} ({planet.owner})</li>)}
|
<div class="galaxy-container">
|
||||||
</ul>
|
{galaxies.map(galaxy => <>
|
||||||
|
<a href="#">
|
||||||
|
<div class="galaxy-icon" style={`left: ${galaxy.style.left}px; top: ${galaxy.style.top}px; background-color: ${galaxy.style.color};`}>
|
||||||
|
<div class="galaxy-name" data-sectors={JSON.stringify(galaxy.sectors)}>{galaxy.name}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</>)}
|
||||||
|
</div>
|
||||||
|
<div class="galaxy-details">
|
||||||
|
<h2></h2>
|
||||||
|
<div class="galaxy-sector-list">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<style>
|
<style is:global>
|
||||||
* {
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
.galaxy-container {
|
||||||
margin: auto;
|
width: 70%;
|
||||||
padding: 1rem;
|
height: 500px;
|
||||||
width: 800px;
|
background-color: blue;
|
||||||
max-width: calc(100% - 2rem);
|
margin-left: 50px;
|
||||||
color: white;
|
margin-right: auto;
|
||||||
font-size: 20px;
|
margin-top: 50px;
|
||||||
line-height: 1.6;
|
position: relative;
|
||||||
}
|
}
|
||||||
.astro-a {
|
|
||||||
|
.galaxy-icon {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
top: -32px;
|
width: 40px;
|
||||||
left: 50%;
|
height: 40px;
|
||||||
transform: translatex(-50%);
|
background-color: white;
|
||||||
width: 220px;
|
border-radius: 20px;
|
||||||
height: auto;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
.galaxy-icon:hover {
|
||||||
font-size: 4rem;
|
background-color: yellow !important;
|
||||||
font-weight: 700;
|
}
|
||||||
line-height: 1;
|
|
||||||
|
.galaxy-name {
|
||||||
|
position: absolute;
|
||||||
|
top: 40px;
|
||||||
|
left: -5px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galaxy-details {
|
||||||
|
width: 23%;
|
||||||
|
height: 500px;
|
||||||
|
margin-top: 50px;
|
||||||
|
margin-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.galaxy-details h2 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-gradient {
|
.galaxy-sector-list {
|
||||||
background-image: var(--accent-gradient);
|
display: flex;
|
||||||
-webkit-background-clip: text;
|
flex-direction: column;
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
background-size: 400%;
|
|
||||||
background-position: 0%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions {
|
.galaxy-sector-list div {
|
||||||
margin-bottom: 2rem;
|
text-align: center;
|
||||||
border: 1px solid rgba(var(--accent-light), 25%);
|
background-color: gray;
|
||||||
background: linear-gradient(rgba(var(--accent-dark), 66%), rgba(var(--accent-dark), 33%));
|
margin-top: 10px;
|
||||||
padding: 1.5rem;
|
border-radius: 10px;
|
||||||
border-radius: 8px;
|
padding-top: 10px;
|
||||||
}
|
padding-bottom: 10px;
|
||||||
|
|
||||||
.instructions code {
|
|
||||||
font-size: 0.8em;
|
|
||||||
font-weight: bold;
|
|
||||||
background: rgba(var(--accent-light), 12%);
|
|
||||||
color: rgb(var(--accent-light));
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 0.3em 0.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instructions strong {
|
|
||||||
color: rgb(var(--accent-light));
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-card-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
|
|
||||||
gap: 2rem;
|
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script>
|
||||||
|
function gvinit() {
|
||||||
|
const galaxyIcons = document.querySelectorAll('.galaxy-icon');
|
||||||
|
const galaxyDetails = document.querySelector('.galaxy-details');
|
||||||
|
const galaxySectorList = document.querySelector('.galaxy-sector-list');
|
||||||
|
|
||||||
|
if(!galaxyIcons) return;
|
||||||
|
if(!galaxyDetails) return;
|
||||||
|
if(!galaxySectorList) return;
|
||||||
|
|
||||||
|
galaxyIcons.forEach(icon => {
|
||||||
|
icon.addEventListener('click', (e) => {
|
||||||
|
const galaxy = icon.querySelector('.galaxy-name');
|
||||||
|
if(!galaxy) return;
|
||||||
|
|
||||||
|
const sectors: Array<{ id: string, name: string }> = JSON.parse(galaxy.getAttribute('data-sectors') ?? "[]");
|
||||||
|
const galaxyNameField = galaxyDetails.querySelector('h2');
|
||||||
|
if(!galaxyNameField) return;
|
||||||
|
galaxyNameField.innerText = (icon.querySelector('.galaxy-name') as HTMLElement)?.innerText;
|
||||||
|
galaxySectorList.innerHTML = "";
|
||||||
|
sectors.forEach(sector => {
|
||||||
|
const sectorDiv = document.createElement('div');
|
||||||
|
sectorDiv.innerText = sector.name;
|
||||||
|
sectorDiv.setAttribute('data-id', sector.id);
|
||||||
|
galaxySectorList.appendChild(sectorDiv);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
gvinit();
|
||||||
|
</script>
|
Loading…
Reference in New Issue