let images = {}; let simulator = []; let maxSpeed = 1; let backgroundImage; let worldScale; let LEFT = [-1,0]; const entityTypes = Object.freeze({ METERORITE_SMALL: "meteorite_small", METERORITE_LARGE: "meteorite_large", COMET: "comet", }); var Settings = { windowWrap: true, physics: true, respawn: true, devMode: false, maxSpeed: 1, backgroundImage: "/media/Art/EmptySpace.png", entityCount: 50, emptyEntries: [], rarity: { "comet": .9, "meteorite_small": 500.0, "meteorite_large": 1000.0, }, mass: { "comet": 1400.0, "meteorite_small": 500.0, "meteorite_large": 1000.0, }, } function distance(entity1, entity2){ return Math.sqrt( ((entity2.x-entity1.x)*(entity2.x-entity1.x)) + ((entity2.y-entity1.y)*(entity2.y-entity1.y)) ); } function getMass(type){ switch (type){ case entityTypes.COMET: return Settings.mass[entityTypes.COMET] case entityTypes.METERORITE_SMALL: return Settings.mass[entityTypes.METERORITE_SMALL]; case entityTypes.METERORITE_LARGE: return Settings.mass[entityTypes.METERORITE_LARGE]; } } function createEntity(x, y, vx, vy, ax, ay, rot, rotv, type, id=0, iframes=Math.floor(Math.random()*100)){ if (Settings.emptyEntries.length > 1){ var entryID = Settings.emptyEntries.pop(); if (Settings.devMode) console.warn("Creating new enity from old", entryID); if (entryID <= simulator.length && entryID >= 0){ entity = simulator[entryID]; entity.x = x; entity.y = y; entity.vx = vx; entity.vy = vy; entity.ax = ax; entity.ay = ay; entity.rot = rot; entity.rotv = rotv; entity.iframes = 1000; entity.show = true; entity.type = type }else{ if (Settings.devMode) console.error("Entry ID out of bounds", Settings.emptyEntries.length, id, entryID); } }else{ simulator.push({ x: x, y: y, ax: ax, ay: ay, vx: vx, vy: vy, rot: rot, rotv: rotv, mass: getMass(type), forcex: 0.0, forcey: 0.0, type: type, show: true, ueid: id, iframes: iframes }); } } function getRandomType(){ let rand = Math.random(); if (rand > 0.955){ console.log("Comet made"); return entityTypes.COMET; }if(rand > 0.4){ return entityTypes.METERORITE_SMALL; }else{ return entityTypes.METERORITE_LARGE; } } function physicsUpdate(entity){ if (entity.show){ entity.vx += entity.ax; entity.vy += entity.ay; entity.x += entity.vx; entity.y += entity.vy; entity.rot += entity.rotv; if (entity.iframes > 0) entity.iframes -= 1; if (entity.iframes == 0) simulator.forEach((other_entity) =>{ checkCollision(entity, other_entity); }); } } function checkCollision(entity1, entity2){ if (entity1.type == entityTypes.COMET && entity2.type == entityTypes.COMET){ }else if (entity1.ueid != entity2.ueid && entity1.show && entity2.show){ var dist = distance(entity1, entity2); if(dist < 15){ if (Settings.devMode) { stroke('magenta'); strokeWeight(5); line(entity1.x,entity1.y, entity2.x, entity2.y); console.log("Collision at", entity1.x, entity1.y, entity1.iframes, entity2.x, entity2.y, dist); } Explode(entity1); Explode(entity2); } } } function Explode(entity){ if(entity.type == entityTypes.METERORITE_SMALL){ entity.show = false; Settings.emptyEntries.push(entity.ueid); }if(entity.type == entityTypes.METERORITE_LARGE){ entity.type = entityTypes.METERORITE_SMALL entity.iframes = 1000; createEntity(entity.x, entity.y, entity.vx + Math.random(), entity.vy + Math.random(), 0.0,0.0,0.0,0.0, entityTypes.METERORITE_SMALL, id=entity.ueid, iframes=1000); } } function Explode(entity){ } function drawBackground(refImage){ let w = windowWidth / refImage.width; let h = windowHeight / refImage.height; for (let iy = 0; iy <= h; iy++){ for (let ix = 0; ix <= w; ix++){ image(refImage, refImage.width * ix, refImage.height * iy); } } } function drawEntity(entity){ push(); imageMode(CENTER); translate(entity.x*(worldScale.value()/100), entity.y*(worldScale.value()/100), 0); if (entity.type == entityTypes.COMET){ rotate((Math.atan2(entity.vx, entity.vy) - Math.atan2(-1,0)) * 180/Math.PI); }else{ rotate(entity.rot); } image(images[entity.type], 0,0); pop(); } function preload(){ images[entityTypes.METERORITE_SMALL] = loadImage("/media/Art/meteorite_small_1.png"); images[entityTypes.METERORITE_LARGE] = loadImage("/media/Art/Meteorite_Large_1_100.png"); images[entityTypes.COMET] = loadImage("/media/Art/comet.png"); //images["ship"] = loadImage("/media/Art/ship.png"); #Make Ship asset for game portion images["background"] = loadImage("/media/Art/EmptySpace.png"); } function setup(){ let canvas = createCanvas(windowWidth, windowHeight); background(255); describe("A space physics simulator"); canvas.position(0,0); worldScale = createSlider(); //Load Entities for(var i = 0; i <= entityCount; i+=1){ createEntity( Math.floor(Math.random() * windowWidth), //X Location Math.floor(Math.random() * windowHeight), //Y Location (Math.random() * maxSpeed * 2)-maxSpeed, //X Velocity (Math.random() * maxSpeed * 2)-maxSpeed, //Y Velocity 0.0, //X Acceleration 0.0, //Y Acceleration 0.0, //Current Rotation (Math.random() * 2 *(Math.PI / rotationSpeed))-(Math.PI / rotationSpeed), //Rotation Velocity getRandomType(), id=i ); } } function mouseClicked(){ console.log(mouseX, mouseY); simulator.forEach((entity) =>{ }) console.log(worldScale.value()); } function draw(){ //background(images["background"]); //Draw Tiled Background drawBackground(images["background"]); for(let e = 1; e < simulator.length; e++){ let entity = simulator[e] //Physics Update if (Settings.physics){ physicsUpdate(entity) } //Window Wrap if (Settings.windowWrap){ if (entity.x * (worldScale.value() /100) > windowWidth){ entity.x = 0; } if (entity.x < 0){ entity.x = windowWidth / (worldScale.value() /100); } if (entity.y * (worldScale.value() /100) > windowHeight){ entity.y = 0; } if (entity.y < 0){ entity.y = windowHeight / (worldScale.value() /100); } } //Draw Entity drawEntity(entity); } } function windowResized() { resizeCanvas(windowWidth, windowHeight); }