ruins, level

new level: ruins, let me know about combat and platforming difficulty balance

vanish elements now shrink horizontally
  now colored dark blue to not look like mobs
This commit is contained in:
landgreen
2022-01-01 20:22:00 -08:00
parent 7d1b212c8a
commit 1ef77b7971
5 changed files with 200 additions and 81 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -7,7 +7,7 @@ const level = {
defaultZoom: 1400, defaultZoom: 1400,
onLevel: -1, onLevel: -1,
levelsCleared: 0, levelsCleared: 0,
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"], //intro, gauntlet, final are added in at the start and end of level order playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "ruins"], //intro, gauntlet, final are added in at the start and end of level order
communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"], communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"],
trainingLevels: [ trainingLevels: [
"walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect",
@@ -20,7 +20,7 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("plasma torch") // m.setField("plasma torch")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
@@ -34,7 +34,7 @@ const level = {
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// level.harpoon(); // level.ruins();
if (simulation.isTraining) { level.walk(); } else { level.intro(); } if (simulation.isTraining) { level.walk(); } else { level.intro(); }
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
@@ -45,7 +45,7 @@ const level = {
// level.testChamber() // level.testChamber()
// level.sewers(); // level.sewers();
// level.satellite(); // level.satellite();
// level.skyscrapers(); // level.skyscrapers();
// level.aerie(); // level.aerie();
// level.rooftops(); // level.rooftops();
// level.warehouse(); // level.warehouse();
@@ -753,10 +753,12 @@ const level = {
} }
} }
}, },
vanish(x, y, width, height, hide = { x: 0, y: 100 }) { vanish(x, y, width, height, hide = { x: 0, y: 150 }) {
x = x + width / 2 x = x + width / 2
y = y + height / 2 y = y + height / 2
const block = body[body.length] = Bodies.rectangle(x, y, width, height, { const vertices = [{ x: x, y: y, index: 0, isInternal: false }, { x: x + width, y: y, index: 1, isInternal: false }, { x: x + width, y: y + height, index: 4, isInternal: false }, { x: x, y: y + height, index: 3, isInternal: false }]
const block = body[body.length] = Bodies.fromVertices(x, y, vertices, {
// const block = body[body.length] = Bodies.rectangle(x, y, width, height, {
collisionFilter: { collisionFilter: {
category: cat.map, category: cat.map,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
@@ -766,21 +768,29 @@ const level = {
isNotHoldable: true, isNotHoldable: true,
isNonStick: true, //this keep sporangium from sticking isNonStick: true, //this keep sporangium from sticking
isTouched: false, isTouched: false,
fadeTime: 30, fadeTime: 60,
fadeCount: 30, fadeCount: 60,
isThere: true, isThere: true,
returnTime: 180, returnTime: 120,
returnCount: 0, returnCount: 0,
query() { query() {
if (this.isThere) { if (this.isThere) {
if (this.isTouched) { if (this.isTouched) {
if (!m.isBodiesAsleep) this.fadeCount-- if (!m.isBodiesAsleep) {
this.fadeCount--
const size = Math.max(this.fadeCount / this.fadeTime, 0.03)
const vertices = [{ x: x * size, y: y, index: 0, isInternal: false }, { x: (x + width) * size, y: y, index: 1, isInternal: false }, { x: (x + width) * size, y: y + height, index: 4, isInternal: false }, { x: x * size, y: y + height, index: 3, isInternal: false }]
Matter.Body.setVertices(this, vertices) //take on harpoon shape
}
if (this.fadeCount < 1) { if (this.fadeCount < 1) {
Matter.Body.setPosition(this, hide) Matter.Body.setPosition(this, hide)
this.isThere = false this.isThere = false
this.isTouched = false this.isTouched = false
this.collisionFilter.mask = 0 //cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet this.collisionFilter.mask = 0 //cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
this.returnCount = this.returnTime this.returnCount = this.returnTime
const size = 1
const vertices = [{ x: x * size, y: y, index: 0, isInternal: false }, { x: (x + width) * size, y: y, index: 1, isInternal: false }, { x: (x + width) * size, y: y + height, index: 4, isInternal: false }, { x: x * size, y: y + height, index: 3, isInternal: false }]
Matter.Body.setVertices(this, vertices) //take on harpoon shape
} }
} else if (Matter.Query.collides(this, [player]).length) { // || (Matter.Query.collides(this, body).length)) { } else if (Matter.Query.collides(this, [player]).length) { // || (Matter.Query.collides(this, body).length)) {
this.isTouched = true this.isTouched = true
@@ -808,15 +818,17 @@ const level = {
for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y); for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y);
ctx.lineTo(v[0].x, v[0].y); ctx.lineTo(v[0].x, v[0].y);
const color = 220 * (1 - this.fadeCount / this.fadeTime) const color = 220 * (1 - this.fadeCount / this.fadeTime)
ctx.fillStyle = `rgb(${color},220, 200)` // ctx.fillStyle = `rgb(${color},220, 200)`
// ctx.fillStyle = `rgba(0,220,200,${this.fadeCount/this.fadeTime+0.05})` // ctx.fillStyle = `rgba(0,220,200,${this.fadeCount/this.fadeTime+0.05})`
ctx.fillStyle = "#586370"
ctx.fill(); ctx.fill();
// ctx.strokeStyle = `#bff` // ctx.strokeStyle = `#bff`
// ctx.stroke(); // ctx.stroke();
}, },
}); });
Matter.Body.setStatic(block, true); //make static Matter.Body.setStatic(block, true); //make static
Composite.add(engine.world, block); //add to world // Composite.add(engine.world, block); //add to world
if (simulation.isHorizontalFlipped) x *= -1
return block return block
}, },
door(x, y, width, height, distance, speed = 1) { door(x, y, width, height, distance, speed = 1) {
@@ -2494,7 +2506,7 @@ const level = {
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.defaultZoom = 1800 level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#d8dadf";
// powerUps.spawnStartingPowerUps(1475, -1175); // powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level // spawn.debris(750, -2200, 3700, 16); //16 debris per level
@@ -2895,6 +2907,155 @@ const level = {
spawn.bodyRect(2400, -100, 100, 60); spawn.bodyRect(2400, -100, 100, 60);
spawn.bodyRect(2500, -150, 100, 150); //exit step spawn.bodyRect(2500, -150, 100, 150); //exit step
}, },
ruins() {
const vanish = []
level.exit.x = -390;
level.exit.y = -1835;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 25);
level.setPosToSpawn(-25, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde";
spawn.debris(-150, -775, 1425, 3); //16 debris per level
spawn.debris(1525, -25, 950, 3); //16 debris per level
spawn.debris(-650, -2100, 575, 2); //16 debris per level
//bottom floor
powerUps.spawnStartingPowerUps(1175, -50);
spawn.mapRect(2475, -1800, 275, 2300);
spawn.mapRect(-200, -750, 1500, 450);
spawn.mapRect(150, -425, 1150, 325);
vanish.push(level.vanish(1300, -225, 200, 225))
vanish.push(level.vanish(1300, -450, 200, 223))
spawn.mapRect(-700, 0, 3400, 500);
vanish.push(level.vanish(-300, -500, 100, 25))
vanish.push(level.vanish(-450, -200, 100, 25))
spawn.bodyRect(-450, -175, 100, 175, 0.7);
spawn.bodyRect(-250, -550, 50, 50, 0.7);
//middle floor
spawn.bodyRect(215, -1175, 100, 100, 0.3);
spawn.mapRect(-700, -2075, 250, 2575);
if (Math.random() < 0.5) {
spawn.mapRect(550, -1350, 425, 425);
spawn.mapRect(25, -1075, 300, 222);
} else {
spawn.mapRect(25, -1075, 300, 150);
spawn.mapRect(550, -1350, 425, 497);
}
spawn.bodyRect(225, -850, 50, 100, 0.4);
spawn.mapRect(600, -1800, 325, 225);
spawn.mapRect(1900, -1500, 325, 25);
vanish.push(level.vanish(1100, -1800, 225, 25))
vanish.push(level.vanish(1500, -1800, 225, 25))
if (simulation.difficulty > 20) vanish.push(level.vanish(975, -2275, 150, 25))
if (Math.random() < 0.5) {
vanish.push(level.vanish(750, -1575, 25, 225))
} else {
vanish.push(level.vanish(848, -1575, 75, 225))
}
spawn.bodyRect(1000, -1825, 250, 20, 0.2);
if (Math.random() < 0.5) {
vanish.push(level.vanish(1400, -1000, 200, 25))
vanish.push(level.vanish(1625, -1250, 200, 25))
} else {
vanish.push(level.vanish(1400, -1075, 175, 175))
vanish.push(level.vanish(1575, -1250, 175, 175))
}
if (Math.random() < 0.5) {
vanish.push(level.vanish(750, -2075, 200, 25))
vanish.push(level.vanish(450, -2425, 200, 25))
} else {
vanish.push(level.vanish(400, -2150, 150, 25))
}
spawn.bodyRect(2100, -1625, 75, 125, 0.3);
vanish.push(level.vanish(100, -2250, 225, 25))
if (simulation.difficulty > 20) {
vanish.push(level.vanish(-225, -1800, 200, 25))
spawn.mapRect(-475, -1800, 250, 25);
} else {
spawn.mapRect(-475, -1800, 450, 25);
}
spawn.bodyRect(-150, -1825, 200, 20, 0.2);
spawn.bodyRect(175, -2325, 75, 75, 0.3);
spawn.mapRect(-475, -2075, 250, 25);
spawn.mapRect(-250, -2075, 25, 75);
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// m.immuneCycle = Infinity //you can't take damage
spawn.randomMob(725, -850, -0.3);
spawn.randomMob(275, -1125, 0.2);
spawn.randomMob(700, -1875, 0);
spawn.randomMob(-150, -1975, 0.5);
spawn.randomMob(2025, -1600, 0.3);
spawn.randomMob(1650, -100, 0.2);
spawn.randomMob(1425, -525, 0.1);
spawn.randomMob(1625, -1875, 0.3);
spawn.randomMob(1125, -850, 0.3)
spawn.randomLevelBoss(2050, -2025)
spawn.randomGroup(1750, -650, 0.4)
if (simulation.difficulty > 15) {
spawn.randomMob(2600, -1850, 0.2);
spawn.randomMob(850, -1400, 0.2);
spawn.randomMob(2000, -800, -0.1);
spawn.randomMob(175, -1125, -0.2);
spawn.randomGroup(1225, -1475, 0.3);
spawn.randomGroup(-375, -2400, 0.3);
}
spawn.secondaryBossChance(100, -1500)
powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
level.custom = () => {
level.playerExitCheck();
ctx.fillStyle = "#d0d3d9"
ctx.fillRect(-2500, -1800, 2975, 1825);
ctx.fillStyle = "#c0c3c9"
ctx.fillRect(-2075, -1475, 25, 1500);
ctx.fillStyle = "#cff" //exit
ctx.fillRect(225, -2050, 225, 250)
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
//shadow
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(-1300, -125, 1150, 150)
ctx.fillRect(-1300, -325, 1500, 350)
ctx.fillRect(-325, -950, 300, 225)
ctx.fillRect(-975, -950, 425, 225);
ctx.fillRect(-925, -1600, 325, 275);
for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
};
} else {
level.custom = () => {
level.playerExitCheck();
ctx.fillStyle = "#d0d3d9"
ctx.fillRect(-475, -1800, 2975, 1825);
ctx.fillStyle = "#c0c3c9"
ctx.fillRect(2050, -1475, 25, 1500);
ctx.fillStyle = "#cff" //exit
ctx.fillRect(-450, -2050, 225, 250)
level.exit.draw();
level.enter.draw();
};
level.customTopLayer = () => {
//shadow
// ctx.fillStyle = "rgba(0,10,30,0.2)"
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(150, -125, 1150, 150)
ctx.fillRect(550, -950, 425, 225);
ctx.fillRect(600, -1600, 325, 275);
ctx.fillRect(-200, -325, 1500, 350)
ctx.fillRect(25, -950, 300, 225)
for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
};
}
},
testChamber() { testChamber() {
level.setPosToSpawn(0, -50); //lower start level.setPosToSpawn(0, -50); //lower start
level.exit.y = level.enter.y - 550; level.exit.y = level.enter.y - 550;
@@ -8105,7 +8266,7 @@ const level = {
}; };
if (!initialSpawn) { if (!initialSpawn) {
level.defaultZoom = 1000 //was 800 I changed this level.defaultZoom = 1300 //was 800 I changed this
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#dcdcde";
//Level //Level
@@ -9598,7 +9759,6 @@ const level = {
b.removeAllGuns(); b.removeAllGuns();
b.giveGuns("harpoon") b.giveGuns("harpoon")
let instruction = 0 let instruction = 0
level.trainingText(`climb up to the exit`) level.trainingText(`climb up to the exit`)
level.custom = () => { level.custom = () => {

View File

@@ -1243,9 +1243,9 @@ const simulation = {
if (e.which === 2) { if (e.which === 2) {
if (level.isProcedural) { if (level.isProcedural) {
simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y},0.5);`); simulation.outputMapString(`spawn.randomMob(x+${x}, y+${y}, 0);`);
} else { } else {
simulation.outputMapString(`spawn.randomMob(${x}, ${y},0.5);`); simulation.outputMapString(`spawn.randomMob(${x}, ${y}, 0);`);
} }
} else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive } else if (simulation.mouseInGame.x > simulation.constructMouseDownPosition.x && simulation.mouseInGame.y > simulation.constructMouseDownPosition.y) { //make sure that the width and height are positive

View File

@@ -5161,7 +5161,7 @@ const spawn = {
spawn = "striker", spawn = "striker",
nodes = Math.min(2 + Math.ceil(Math.random() * (simulation.difficulty + 2)), 8), nodes = Math.min(2 + Math.ceil(Math.random() * (simulation.difficulty + 2)), 8),
//Math.ceil(Math.random() * 3) + Math.min(4,Math.ceil(simulation.difficulty/2)), //Math.ceil(Math.random() * 3) + Math.min(4,Math.ceil(simulation.difficulty/2)),
radius = Math.ceil(Math.random() * 10) + 17, // radius of each node mob radius = Math.ceil(Math.random() * 10) + 18, // radius of each node mob
sideLength = Math.ceil(Math.random() * 100) + 70, // distance between each node mob sideLength = Math.ceil(Math.random() * 100) + 70, // distance between each node mob
stiffness = Math.random() * 0.03 + 0.005 stiffness = Math.random() * 0.03 + 0.005
) { ) {

View File

@@ -1,14 +1,19 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
new training levels "stack", "mine", "grenades", "harpoon" new level: ruins, let me know about combat and platforming difficulty balance
new map element vanish goes away after you touch it, returns in 3 seconds vanish elements now shrink horizontally
bug fixes now colored dark blue to not look like mobs
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
shrink crumble width as it fades out vanish element
player moves through a grid of stacked crumble blocks grow as it returns?
pull bullets back to player with crouch/field
bullets type?: drones, spores, missiles,
works for all bullets, write custom code based on bullet type
bad for: laser, harpoon?, missile and grenade?
boss that gives nearby mobs invulnerability boss that gives nearby mobs invulnerability
boss is only mildly aggressive boss is only mildly aggressive
@@ -32,8 +37,6 @@ training
spores - use 1 ammo to take out several mobs at once, you have to block with your shield until the mobs die spores - use 1 ammo to take out several mobs at once, you have to block with your shield until the mobs die
drones - use mouse to bring drones around a couple corners drones - use mouse to bring drones around a couple corners
foam - slow boss mob, and run away foam - slow boss mob, and run away
harpoon - kill one close mob, pick up ammo that is out of reach, first at several far away mobs with crouch
or just some hard melee combat
laser - reflect off walls to hit mobs laser - reflect off walls to hit mobs
field rooms: field rooms:
standing wave - bullets come from every direction standing wave - bullets come from every direction
@@ -47,6 +50,8 @@ training
worm hole - teleport past lasers worm hole - teleport past lasers
puzzle/platforming rooms: puzzle/platforming rooms:
use the double constrained platforms use the double constrained platforms
stealth room
probably should make 2+
combat rooms: combat rooms:
boss gauntlet, spawn with nothing but a few power ups and fight 10 bosses boss gauntlet, spawn with nothing but a few power ups and fight 10 bosses
use no gun, just bots to kil stuff use no gun, just bots to kil stuff
@@ -58,7 +63,7 @@ balance time dilation with bose einstein (you can freeze everything and take no
overflowing energy does harm? overflowing energy does harm?
or just reduces harm reduction? or just reduces harm reduction?
make a line of constained mobs move like a snake make a line of constrained mobs move like a snake
apply forces with directions determined by time and position on the snake apply forces with directions determined by time and position on the snake
tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health) tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health)
@@ -96,22 +101,11 @@ intro map: diegeticly draw a mouse with field highlighted
also indicate space? also indicate space?
dynamically adjust drawing after picking up a gun dynamically adjust drawing after picking up a gun
increase mass and movement speed at the same time increase mass and movement speed at the same time
increase jump differently because it scales extra with mass increase jump differently because it scales extra with mass
m.defaultMass = 4.5 m.defaultMass = 4.5
m.definePlayerMass() m.definePlayerMass()
tech selection menu choices randomize every 1 second
cycles for 10 cycles before it stops cycling
new late game level that is easier if you can: platform well, jump high, immune to slime, wormhole through walls, fly fast
climb vertically to avoid rising slime
populate with multiple boss mobs that can't drop tech
bosses spawn in pairs
antimatter (assuming something else isn't already named this); requires negative mass, causes damage to self and enemies within range while active
give history boss legs? give history boss legs?
field tech - disable blocking, but does high damage to mobs inside field field tech - disable blocking, but does high damage to mobs inside field
@@ -366,8 +360,6 @@ player can become crouched while not touching the ground if they exit the ground
a couple times people have reported the final boss dropping extra bodies on death a couple times people have reported the final boss dropping extra bodies on death
Why does micro-extruder lag so much
blue triangle boss can move backwards and aim away from you if set up properly blue triangle boss can move backwards and aim away from you if set up properly
issues with dot product probably, but might not be worth fixing issues with dot product probably, but might not be worth fixing
@@ -384,10 +376,15 @@ is there a way to check if the player is stuck inside the map or block
******************************************************** LEVELS ******************************************************** ******************************************************** LEVELS ********************************************************
level element that goes away after touching player (also bullets?) new late game level that is easier if you can: platform well, jump high, immune to slime, wormhole through walls, fly fast
returns after a set time, or doesn't climb vertically to avoid rising slime
applications: populate with multiple boss mobs that can't drop tech
doors, quick jumping platforming, secrets, bosses spawn in pairs
map: observatory
button controls rotation of telescope
laser beam shoots out of telescope
button opens the dome
level with mobs that follow a genetic algorithm level with mobs that follow a genetic algorithm
mobs have genes mobs have genes
@@ -427,39 +424,6 @@ level with mobs that follow a genetic algorithm
rename intro level to something lore related rename intro level to something lore related
labs - procedural generation
bugs
mob spawns shouldn't be based on probability?
style
graphics look too bright?
add shadows and lighting and graphic details?
what about performance?
with the mobs staggered spawning it should be fine
feel
disrupt the flat ground
less platforming / easier platforming
the spinners on exit are still too hard...
make combat more interesting
is it laggy?
in loot room, spawn mobs after power up is grabbed
more background graphics, better colors
loot room:
make it more interesting to get the power up
slow player and reduce damage in region
increase the size of the region
don't have space for much
make graphics more unique
push player away, so that normal pick up methods don't work, but add a button to disable region
room ideas -
portal room
endlessly falling blocks down a slide, that the player has to climb up
portal + rotor + falling blocks = perpetual motion
slime room
sound room, with buttons to control sound
color room with r,g,b buttons to control color
mob buff zone: Map element: "Orbital Pickup Zone": Mobs that enter a specific area of the map gain +1 orbital per second, or a shield
could put in the loot room
buttons can now on/off boosts buttons can now on/off boosts
repeat map in vertical when you fall teleport to above the mab, as if the map repeats repeat map in vertical when you fall teleport to above the mab, as if the map repeats
@@ -470,11 +434,6 @@ map element - player rotates a rotor that makes a platform go up or down
level element: a zone with wind, anti-gravity, extra gravity level element: a zone with wind, anti-gravity, extra gravity
control with button control with button
map: observatory
button controls rotation of telescope
laser beam shoots out of telescope
button opens the dome
******************************************************** MOBS ******************************************************** ******************************************************** MOBS ********************************************************
mob that charges up and then fires many bullets at once in a connect mob that charges up and then fires many bullets at once in a connect