Skip to content

Commit

Permalink
Merge pull request #76 from okwme/max-lvl-wither
Browse files Browse the repository at this point in the history
Max lvl withering
  • Loading branch information
okwme authored Apr 3, 2024
2 parents 022c615 + 877c977 commit 150ed14
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 94 deletions.
22 changes: 19 additions & 3 deletions src/anybody.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Prando from 'prando'

import EventEmitter from 'events'
import Sound from './sound.js'
import { Visuals } from './visuals.js'
import { Visuals, FPS } from './visuals.js'
import { _validateSeed, Calculations } from './calculations.js'

export class Anybody extends EventEmitter {
Expand Down Expand Up @@ -38,10 +38,10 @@ export class Anybody extends EventEmitter {
util: false,
optimistic: false,
paused: true,
timer: 60 * FPS, // 60 seconds * 50 frames per second
aimHelper: false,
target: 'outside', // 'outside' or 'inside'
showLives: true, // true or false
timer: 60 * 50 // 60 seconds * 50 frames per second
}

// Merge the default options with the provided options
Expand Down Expand Up @@ -490,7 +490,7 @@ export class Anybody extends EventEmitter {
}

prepareP5() {
this.p.frameRate(50)
this.p.frameRate(FPS)
this.p.createCanvas(this.windowWidth, this.windowWidth)
this.p.background('white')
}
Expand Down Expand Up @@ -531,6 +531,22 @@ export class Anybody extends EventEmitter {
this.sound?.playMissile()
this.missileInits.push(...this.processMissileInits([b]))
}

witherAllBodies() {
for (const body of this.bodies) {
// find the index in witheringBodies
const index = this.witheringBodies.findIndex(
(b) => b.bodyIndex == body.bodyIndex
)
// if it's there, update the position
if (index >= 0) {
this.witheringBodies[index].position = body.position
} else {
// if not, add it
this.witheringBodies.push({ ...body })
}
}
}
}
if (typeof window !== 'undefined') {
window.Anybody = Anybody
Expand Down
1 change: 1 addition & 0 deletions src/calculations.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ export const Calculations = {
this.sound?.playExplosion()

body.starLvl += 1

bodies[j].radius = 0n
}
}
Expand Down
261 changes: 170 additions & 91 deletions src/visuals.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const WITHERING_STEPS = 200
export const FPS = 50

const WITHERING_STEPS = 3000
const FACE_PNGS = [
new URL('/public/faces/face1.png', import.meta.url).href,
// new URL('/public/faces/face2.png', import.meta.url).href,
Expand All @@ -22,18 +24,12 @@ export const Visuals = {
return
}
const enoughBodies =
this.bodies.filter((b) => !b.life || b.life > 0).length >= 3
-this.bodies.filter((b) => !b.life || b.life > 0).length >= 3

// when there are 3 or more bodies, step the simulation
if (enoughBodies) {
this.frames++
const results = this.step(this.bodies, this.missiles)
this.bodies = results.bodies || []
this.missiles = results.missiles || []
} else {
// if less than 3 just finish the withering animation
// TODO: add some sort of instructional message to screen that new bodies are needed to progress the simulation
}
this.frames++
const results = this.step(this.bodies, this.missiles)
this.bodies = results.bodies || []
this.missiles = results.missiles || []

this.p.noFill()
this.drawBg()
Expand Down Expand Up @@ -83,6 +79,10 @@ export const Visuals = {
} else {
this.justPaused = false
}
if (this.frames >= this.timer) {
this.witherAllBodies()
this.gameOver = true
}
if (
this.stopEvery == 0 &&
this.mode == 'game' &&
Expand Down Expand Up @@ -157,8 +157,10 @@ export const Visuals = {
// }
}

const basicX = ((this.frames / 50) * (this.frames / 50)) % this.windowWidth
const basicY = ((this.frames / 50) * (this.frames / 50)) % this.windowHeight
const basicX =
((this.frames / FPS) * (this.frames / FPS)) % this.windowWidth
const basicY =
((this.frames / FPS) * (this.frames / FPS)) % this.windowHeight

// const basicX = this.accumX % this.windowWidth
// const basicY = this.accumY % this.windowHeight
Expand Down Expand Up @@ -320,69 +322,110 @@ export const Visuals = {
}
},

// This is the admin/debug version of the drawScore.
// drawScore() {
// this.p.noStroke()
// if (this.mode == 'nft') {
// // this.accumulateFrameRate += this.frameRate()
// // console.log(this.accumulateFrameRate, this.p.frameRate())
// // if (this.frames % 10 == 0) {
// // this.averageFrameRate = this.accumulateFrameRate / 10
// // this.accumulateFrameRate = 0
// // }
// this.p.fill('white')
// // this.p.rect(0, 0, 50, 20)
// // this.p.fill(this.getNotGrey())
// this.p.textSize(50)
// this.p.textAlign(this.p.LEFT) // Right-align the text
// this.p.text(`${this.frames} t`, 65, 50) // Adjust the x-coordinate to align the text
// this.p.text(`${this.frameRate().toFixed(2)} fps`, 65, 100)
// } else {
// this.p.fill('white')
// // this.p.rect(0, 0, 50, 20)
// // this.p.fill('black')
// // this.p.textAlign(this.p.RIGHT) // Right-align the text
// const secondsAsTime = new Date(this.totalSec * 1000)
// .toISOString()
// .substr(14, 5)
// const thisLevelSecondsAsTime = new Date(this.thisLevelSec * 1000)
// .toISOString()
// .substr(14, 5)
// this.p.text('Total Frames: ' + this.preRun + this.frames, 50, 10) // Adjust the x-coordinate to align the text
// this.p.text('Total Time: ' + secondsAsTime, 50, 20) // Adjust the x-coordinate to align the text
// this.p.text('Total Shots: ' + this.missileCount, 50, 30) // Adjust the x-coordinate to align the text
// this.p.text(
// 'Lvl ' +
// (this.startingBodies - 2) +
// ' - ' +
// thisLevelSecondsAsTime +
// ' - ' +
// (this.startingBodies - this.bodies.length) +
// '/' +
// this.startingBodies +
// ' - ' +
// this.thisLevelMissileCount +
// ' shots',
// 50,
// 40
// ) // Adjust the x-coordinate to align the text
// for (let i = 0; i < this.allLevelSec.length; i++) {
// const prevLevel = this.allLevelSec[i]
// const prevLevelSecondsAsTime = new Date(prevLevel.thisLevelSec * 1000)
// .toISOString()
// .substr(14, 5)
// this.p.text(
// 'Lvl ' +
// (this.allLevelSec.length - i) +
// ' - ' +
// prevLevelSecondsAsTime +
// ' - ' +
// prevLevel.thisLevelMissileCount +
// ' shots',
// 50,
// i * 10 + 50
// ) // Adjust the x-coordinate to align the text
// }
// }
// },

drawScore() {
this.p.noStroke()
if (this.mode == 'nft') {
// this.accumulateFrameRate += this.frameRate()
// console.log(this.accumulateFrameRate, this.p.frameRate())
// if (this.frames % 10 == 0) {
// this.averageFrameRate = this.accumulateFrameRate / 10
// this.accumulateFrameRate = 0
// }
this.p.fill('white')
// this.p.rect(0, 0, 50, 20)
// this.p.fill(this.getNotGrey())
this.p.textSize(50)
this.p.textAlign(this.p.LEFT) // Right-align the text
this.p.text(`${this.frames} t`, 65, 50) // Adjust the x-coordinate to align the text
this.p.text(`${this.frameRate().toFixed(2)} fps`, 65, 100)
} else {
this.p.fill('white')
// this.p.rect(0, 0, 50, 20)
// this.p.fill('black')
// this.p.textAlign(this.p.RIGHT) // Right-align the text
const secondsAsTime = new Date(this.totalSec * 1000)
.toISOString()
.substr(14, 5)
const thisLevelSecondsAsTime = new Date(this.thisLevelSec * 1000)
.toISOString()
.substr(14, 5)
this.p.text('Total Frames: ' + this.preRun + this.frames, 50, 10) // Adjust the x-coordinate to align the text
this.p.text('Total Time: ' + secondsAsTime, 50, 20) // Adjust the x-coordinate to align the text
this.p.text('Total Shots: ' + this.missileCount, 50, 30) // Adjust the x-coordinate to align the text
this.p.text(
'Lvl ' +
(this.startingBodies - 2) +
' - ' +
thisLevelSecondsAsTime +
' - ' +
(this.startingBodies - this.bodies.length) +
'/' +
this.startingBodies +
' - ' +
this.thisLevelMissileCount +
' shots',
50,
40
) // Adjust the x-coordinate to align the text
for (let i = 0; i < this.allLevelSec.length; i++) {
const prevLevel = this.allLevelSec[i]
const prevLevelSecondsAsTime = new Date(prevLevel.thisLevelSec * 1000)
.toISOString()
.substr(14, 5)
this.p.text(
'Lvl ' +
(this.allLevelSec.length - i) +
' - ' +
prevLevelSecondsAsTime +
' - ' +
prevLevel.thisLevelMissileCount +
' shots',
50,
i * 10 + 50
) // Adjust the x-coordinate to align the text
}
const { p } = this
p.push()
p.translate(20, 10)
p.fill('white')
p.noStroke()

const initialScoreSize = 60
this.scoreSize ||= initialScoreSize
p.textStyle(p.BOLDITALIC)
p.textAlign(p.LEFT, p.TOP)
const secondsLeft = (this.timer - this.frames) / FPS

if (this.gameOver) {
p.textSize(100)
// game over in the center of screen
p.textAlign(p.CENTER)
p.text('GAME OVER', this.windowWidth / 2, this.windowHeight / 2 - 60)
p.pop()
return
}

// make the timer bigger as time runs out
if (secondsLeft < 10 && this.scoreSize < 420) {
this.scoreSize += 5
p.fill(255, 255, 255, 150)
} else if (secondsLeft < 30 && this.scoreSize < 160) {
this.scoreSize += 2
p.fill(255, 255, 255, 150)
} else if (secondsLeft < 50 && this.scoreSize < 80) {
this.scoreSize += 1
p.fill(255, 255, 255, 150)
}
p.textSize(this.scoreSize)

p.text(secondsLeft.toFixed(0), 0, 0)

p.pop()
},

drawGun() {
Expand Down Expand Up @@ -452,6 +495,7 @@ export const Visuals = {
for (let i = 0; i < this.explosions.length; i++) {
const _explosion = this.explosions[i]
const bomb = _explosion[0]
console.log(i / this.explosions.length)
this.p.fill('red')
this.p.ellipse(bomb.x, bomb.y, bomb.i * 2, bomb.i * 2)
_explosion.shift()
Expand Down Expand Up @@ -786,29 +830,63 @@ export const Visuals = {
},

drawWitheringBodies() {
this.bodiesGraphic ||= this.p.createGraphics(
this.windowWidth,
this.windowHeight
)
const { p } = this

// draw a fake withering body for development
// if (this.witheringBodies.length === 0) {
// this.witheringBodies = [{ position: p.createVector(100, 100) }]
// }

this.bodiesGraphic ||= p.createGraphics(this.windowWidth, this.windowHeight)
this.bodiesGraphic.noStroke()
for (const body of this.witheringBodies) {
// the body should shrink to nothing as HP goes from 0 to -WITHERING_STEPS
const witherMultiplier = 1 + body.life / WITHERING_STEPS
const radius =
(body.radius * 4 + this.radiusMultiplyer) * witherMultiplier

// render as a white circle
this.bodiesGraphic.fill('white')
this.bodiesGraphic.ellipse(
body.position.x,
body.position.y,
radius,
radius
p.push()
p.translate(body.position.x, body.position.y)
body.witherSteps ||= 0
body.witherSteps++
if (body.witherSteps > WITHERING_STEPS) {
this.witheringBodies = this.witheringBodies.filter((b) => b !== body)
continue
}

// the body should shrink to nothing over WITHERING_STEPS
const radius = p.map(
WITHERING_STEPS - body.witherSteps,
0,
WITHERING_STEPS,
1,
30 // start radius
)

// the ghost body pulses a little bit, isn't totally round
body.zoff ||= 0
p.stroke(255)
p.noFill()
p.fill(255, 255, 255, 230)
p.beginShape()
for (let a = 0; a < p.TWO_PI; a += 0.02) {
let xoff = p.map(p.cos(a), -1, 1, 0, 2)
let yoff = p.map(p.sin(a), -1, 1, 0, 2)
const r = p.map(
p.noise(xoff, yoff, body.zoff),
0,
1,
radius - 10,
radius
)
let x = r * p.cos(a)
let y = r * p.sin(a)
p.vertex(x, y)
}
p.endShape(p.CLOSE)
body.zoff += 0.01

p.pop()
}
},

async drawBodies(attachToCanvas = true) {
if (this.gameOver) return
this.bodiesGraphic ||= this.p.createGraphics(
this.windowWidth,
this.windowHeight
Expand Down Expand Up @@ -1106,6 +1184,7 @@ export const Visuals = {
},

drawTails() {
if (this.gameOver) return
// this.p.blendMode(this.p.DIFFERENCE)

// this.bodiesGraphic.filter(this.p.INVERT)
Expand Down

0 comments on commit 150ed14

Please sign in to comment.