xxxxxxxxxx
315
var canvas;
const generatedChunks = new Set();
const CHUNKSIZE=64
const itemSpawnMin = 1
const itemSpawnMax = 10
var ispawned = 0;
function setup() {
// noiseSeed(1) // todo use mersenne twister.
canvas = createCanvas(400, 400);
// generateObjects();
for (var xx = -3; xx < 4; xx++){
for (var yy = -3; yy < 4 ;yy ++){
generateChunkItems(64, 128, { x: player.x+xx*CHUNKSIZE, y: player.y+yy*CHUNKSIZE}, tree);
}
}
}
function generateAroundPlayer(){
for (var xx = -3; xx < 4; xx++){
for (var yy = -3; yy < 4 ;yy ++){
generateChunkItems(64, 128, { x: player.x+xx*CHUNKSIZE, y: player.y+yy*CHUNKSIZE}, tree);
}
}
}
setInterval(generateAroundPlayer, 2500)
const player = {
x: 0,
y: 0,
hpmax: 100,
hp: 100,
inventory: {
money: 0,
items: [],
},
size: 10,
detectionRange: 50,
speed: 2,
move(direction) {
var mod = (keyIsDown(SHIFT)) ? 2 : 1
if (direction === "up" && this.y > 0) this.y -= mod*this.speed;
if (direction === "down") this.y += mod*this.speed;
if (direction === "left") this.x -= mod*this.speed;
if (direction === "right") this.x += mod*this.speed;
},
heal(amount) {
this.hp = max(this.hpmax, this.hp + amount);
},
pickup(item) {
switch (item.type) {
case "money":
print(`found \$ ${item.amount}`);
this.inventory.money += item.amount;
break;
case "fruit":
this.heal(item.amount);
break;
default:
print(`picked up ${item}`);
this.inventory.items.push(item);
break;
}
tree.remove(item);
},
};
var zoomLevel = 1;
const zoomSpeed = 0.1;
const tree = d3
.quadtree()
.x((d) => d.x)
.y((d) => d.y);
// deprecated
// function generateObjects() {
// for (let i = 0; i < 100; i++) {
// const ox = random(0, width);
// const oy = random(0, height);
// const object = {
// x: ox,
// y: oy,
// size: 5,
// amount: Math.floor(random() * dist(width / 2, height / 2, ox, oy)),
// type: random(["money", "fruit"]),
// };
// // Add the object to the quadtree
// tree.add(object);
// }
// }
function drawHUD() {
// Set the font and text size
textSize(12);
textFont("Helvetica");
// Draw the text for the player's position
text(`Player position: (${player.x}, ${player.y})`, player.x-width/2+10, player.y-height/2+12);
text(`HP : ${player.hp}`, player.x-width/2+10, player.y-height/2+24);
text(`Coins : ${player.inventory.money}`, player.x-width/2+10, player.y-height/2+36);
text(`isRunning(SHIFT) ${(keyIsDown(SHIFT))}`, player.x-width/2+10, player.y-height/2+48);
}
function mouseWheel(event) {
print(event.delta);
if (event.delta > 0) {
zoomLevel -= zoomSpeed;
} else {
zoomLevel += zoomSpeed;
}
}
// finds the objects in a range around another object.
function search(quadtree, xmin, ymin, xmax, ymax) {
const results = [];
quadtree.visit((node, x1, y1, x2, y2) => {
if (!node.length) {
do {
let d = node.data;
if (d.x >= xmin && d.x < xmax && d.y >= ymin && d.y < ymax) {
results.push(d);
}
} while ((node = node.next));
}
return x1 >= xmax || y1 >= ymax || x2 < xmin || y2 < ymin;
});
return results;
}
function draw() {
// Check for user input and update player position
if (keyIsDown(UP_ARROW)) player.move("up");
if (keyIsDown(DOWN_ARROW)) player.move("down");
if (keyIsDown(LEFT_ARROW)) player.move("left");
if (keyIsDown(RIGHT_ARROW)) player.move("right");
translate(width / 2, height / 2);
scale(zoomLevel);
translate(-player.x*zoomLevel, -player.y*zoomLevel);
// Check for zooming in/out
// Clear the canvas
const colors = [color('rgb(69,230,69)'), color('#5A2D1CE5'), color('rgba(255,0,0,0.5)'), color('#800080'), color('#0000FF')]
for (let i = 0; i < colors.length - 1; i++) {
let start = 1000 * i;
let end = 1000 * (i + 1);
if (player.y >= start && player.y < end) {
background(lerpColor(colors[i], colors[i + 1], (player.y - start) / (end - start)));
break;
}
}
// draw sky if player approached y=0,
if(player.y < height/2){
push()
noStroke()
fill('cyan')
rect(player.x+200,0,-200-200)
pop()
}
// Set the zoom level
scale(zoomLevel);
// Draw the player
circle(player.x, player.y, player.size);
push()
noFill()
stroke('gray')
tree.data().filter(o => o.y > 0).map((o) => {
circle(o.x, o.y, o.size)
});
pop()
// Find objects near the player and draw them
push()
search(
tree,
player.x - player.detectionRange,
player.y - player.detectionRange,
player.x + player.detectionRange,
player.y + player.detectionRange
).filter(o => o.y > 0).map((o) => {
fill(o.color)
circle(o.x, o.y, o.size)
});
pop()
// tree.data().map(o => print(o))
// Check for interactions with objects
interact();
drawHUD();
}
function generateChunkItems(chunkSize, spawnDistance, playerPos, quadtree) {
// Calculate the player's chunk coordinates
const chunkX = Math.floor(playerPos.x / chunkSize);
const chunkY = Math.floor(playerPos.y / chunkSize);
// Generate items for the current chunk if it hasn't been generated yet
if (!generatedChunks.has(`${chunkX},${chunkY}`)) {
// Loop through the chunk coordinates within the spawn distance
// Generate items for each chunk coordinate
for (let i = 0; i < random(itemSpawnMin,itemSpawnMax); i++) {
ispawned++
const ox = random(chunkX*chunkSize-chunkSize,chunkX*chunkSize+chunkSize);
const oy = random(chunkY*chunkSize-chunkSize, chunkY*chunkSize+chunkSize);
const otype = random(["money", "fruit"])
var ocol;
switch(otype){
case 'fruit':
ocol = random(['red','orange','yellow','green'])
break;
case 'money':
ocol = 'rgb(225,225,46)'
break;
default:
ocol = 'gray'
break;
}
const object = {
x: ox,
y: oy,
size: 5,
color: ocol,
amount: Math.floor(random() * dist(width / 2, height / 2, ox, oy)),
type: otype
};
tree.add(object);
}
// Mark the current chunk as generated
generatedChunks.add(`${chunkX},${chunkY}`);
}
}
function noisygenerateChunkItems(chunkSize, spawnDistance, playerPos, quadtree) {
// Calculate the player's chunk coordinates
const chunkX = Math.floor(playerPos.x / chunkSize);
const chunkY = Math.floor(playerPos.y / chunkSize);
// Generate items for the current chunk if it hasn't been generated yet
if (!generatedChunks.has(`${chunkX},${chunkY}`)) {
// Loop through the chunk coordinates within the spawn distance
for (let x = chunkX*chunkSize-chunkSize; x <= chunkX*chunkSize+chunkSize; x+=4) {
for (let y = chunkY*chunkSize-chunkSize; y <= chunkY*chunkSize+chunkSize ; y+=4) {
// Generate items for each chunk coordinate
// for (let i = 0; i < random(itemSpawnMin,itemSpawnMax); i++) {
if (noise(x*x,y*y,ispawned)>.75){
ispawned++
const ox = x // random(chunkX*chunkSize-chunkSize,chunkX*chunkSize+chunkSize);
const oy = y // random(chunkY*chunkSize-chunkSize, chunkY*chunkSize+chunkSize);
const otype = random(["money", "fruit"])
var ocol;
switch(otype){
case 'fruit':
ocol = random(['red','orange','yellow','green'])
break;
case 'money':
ocol = 'rgb(225,225,46)'
break;
default:
ocol = 'gray'
break;
}
const object = {
x: ox,
y: oy,
size: 5,
color: ocol,
amount: Math.floor(random() * dist(width / 2, height / 2, ox, oy)),
type: otype
};
tree.add(object);
}
}
}
// Mark the current chunk as generated
generatedChunks.add(`${chunkX},${chunkY}`);
}
}
function interact() {
// Check for user input to interact with objects
// Check if the player is interacting with any objects
const object = tree.find(player.x, player.y, player.size);
if (object) {
player.pickup(object);
}
}