Skip to content

Cursor survival

What happens if the mouse cursor is the protagonist of a game? (Inspired by Alan Becker's "Animation vs Animator" series, as well as Cursorblade)

Hover over the game rectangle to start; avoid getting hit; fight off the amassing mob by hovering over them. Likely unplayable on mobile; may contain flashing pictures.

A group of triangles chase and shoot at the mouse cursor.

function setup() {
  createCanvas(500, 500);
  background(220);
  textAlign(CENTER)
}

let t = 0
let h = -1
let ae = new Set()
let as = new Set()
let ah = new Set()
let v = {x: 0, y: 0}
let r = 150

const es = 0.7 * 0.4
const et = 0.1
const ss = 2.1 * 2.1
const ess = es * 5
const est = 0.1 * 3
let ts = false

function draw() {
  if (mouseX <= 0 || mouseX > width || mouseY < 0 || mouseY > height) {
    if (!ts) {
      noStroke()
      fill(0)
      textSize(30)
      text("Hover to continue", width/2, height/2)
      ts = true
    }
    return
  }
  fill(255)
  stroke(0)
  ts = false
  
  background(220);
  
  h = min(h + 0.003, 1)
  
  if ((frameCount / 4) % 1 <= h) {
    cursor(ARROW)
  } else {
    noCursor()
  }
  
  t --
  if (t < 0) {
    r *= pow(0.96, 1/(ae.size + 1))
    t += r
    let x, y
    if (random() < 0.5) {
      x = random(width)
      y = random([0, height])
    } else {
      x = random([0, width])
      y = random(height)
    }
    ae.add({ x, y, ox: random(-40, 40), oy: random(-40, 40), oa: random(-0.5, 0.5), a: random(TAU), t: random(100), s: round(random(0, 0.52))})
  }
  
  for (let s of as) {
    if (s.x < 0 || s.x > width || s.y < 0 || s.y > height) {
      as.delete(s)
    } else if ((s.x - mouseX - 2) ** 2 + (s.y - mouseY - 5) ** 2 < 9 ** 2) {
      as.delete(s)
      ah.add(s)
      h = h * 0.5 - 0.1
    } else {
      s.x += cos(s.a) * ss
      s.y += sin(s.a) * ss
      push()
      translate(s.x, s.y)
      rotate(s.a)
      line(10, 0, -10, 0)
      pop()
    }
  }
  
  for (let h of ah) {
    h.t = h.t || 1
    h.t -= 0.01
    if (h.t < 0) {
      ah.delete(h)
    } 
    stroke(255, 0, 0)
    push()
    translate(h.x, h.y)
    rotate(h.a)
    let x1 = lerp(15, 10, h.t)
    let x2 = lerp(15, -10, h.t)
    line(x1, 0, x2, 0)
    pop()
  }
  stroke(0)
  for (let e of ae) {
    e.x += cos(e.a) * (e.s ? ess : es)
    e.y += sin(e.a) * (e.s ? ess : es)
    let ad = sin(atan2(mouseY - e.y + e.oy + 5 + v.y, mouseX - e.x + e.ox + 2 + v.x) - e.a + e.oa)
    e.a += ad * (e.s ? est : et)
    e.oa = e.oa * 0.93 + random(-1, 1) * 0.1
    e.ox = e.ox * 0.94 + random(-1, 1)
    e.oy = e.oy * 0.94 + random(-1, 1)
    e.t --
    if (e.t < 0) {
      e.t += 27.3 + random(20)
      as.add({x: e.x, y: e.y, a: e.a})
    }
    push()
    translate(e.x, e.y)
    rotate(e.a)
    triangle(10, 0, -10, 8, -10, -8)
    pop()
    if ((e.x - mouseX - 2) ** 2 + (e.y - mouseY - 5) ** 2 < 9 ** 2) {
      ae.delete(e)
    }
  }
  v.x = lerp(v.x, movedX, 0.2)
  v.y = lerp(v.y, movedY, 0.2)
  
  if (h < 0) {
    h = 1
    ae = new Set()
    as = new Set()
    t = 0
    r = 150
  }
}

(Originally seen at https://editor.p5js.org/bojidar-bg/sketches/H_QmdL0hU)

Experiments tagged p5 (85/85) →|

Experiments tagged game (11/11) →|

Experiments on this site (85/85) →|