Leaderboard

It's like the high score screen in your (least?) favorite arcade game. Names borrowed from SSA.gov's most popular baby names.

Source Code for this Sketch

const names = ["Aaron", "Abigail", "Adam", "Alan", "Albert", "Alexander", "Alexis", "Alice", "Amanda", "Amber", "Amy", "Andrea", "Andrew", "Angela", "Ann", "Anna", "Anthony", "Arthur", "Ashley", "Austin", "Barbara", "Benjamin", "Betty", "Beverly", "Billy", "Bobby", "Bradley", "Brandon", "Brenda", "Brian", "Brittany", "Bruce", "Bryan", "Caleb", "Carl", "Carol", "Carolyn", "Catherine", "Charles", "Charlotte", "Cheryl", "Christian", "Christina", "Christine", "Christopher", "Cynthia", "Daniel", "Danielle", "David", "Deborah", "Debra", "Denise", "Dennis", "Diana", "Diane", "Donald", "Donna", "Dorothy", "Douglas", "Dylan", "Edward", "Elijah", "Elizabeth", "Emily", "Emma", "Eric", "Ethan", "Evelyn", "Frances", "Frank", "Gabriel", "Gary", "George", "Gerald", "Gloria", "Grace", "Gregory", "Hannah", "Harold", "Heather", "Helen", "Henry", "Isaac", "Isabella", "Jack", "Jacob", "Jacqueline", "James", "Janet", "Janice", "Jason", "Jean", "Jeffrey", "Jennifer", "Jeremy", "Jerry", "Jesse", "Jessica", "Joan", "Joe", "John", "Jonathan", "Jordan", "Jose", "Joseph", "Joshua", "Joyce", "Juan", "Judith", "Judy", "Julia", "Julie", "Justin", "Karen", "Katherine", "Kathleen", "Kathryn", "Kathy", "Kayla", "Keith", "Kelly", "Kenneth", "Kevin", "Kimberly", "Kyle", "Larry", "Laura", "Lauren", "Lawrence", "Liam", "Linda", "Lisa", "Logan", "Lori", "Lucas", "Luke", "Madison", "Margaret", "Maria", "Marilyn", "Mark", "Martha", "Mary", "Mason", "Matthew", "Megan", "Melissa", "Michael", "Michelle", "Nancy", "Natalie", "Nathan", "Nicholas", "Nicole", "Noah", "Olivia", "Pamela", "Patricia", "Patrick", "Paul", "Peter", "Rachel", "Randy", "Raymond", "Rebecca", "Richard", "Robert", "Roger", "Ronald", "Ruth", "Ryan", "Samantha", "Samuel", "Sandra", "Sara", "Sarah", "Scott", "Sean", "Sharon", "Shirley", "Sophia", "Stephanie", "Stephen", "Steven", "Susan", "Teresa", "Terry", "Theresa", "Thomas", "Tiffany", "Timothy", "Tyler", "Victoria", "Vincent", "Virginia", "Walter", "Wayne", "William", "Willie", "Zachary"]

let scores = []
let particles = []
let scoreboard

class Particle{
	constructor() {
		this.x = Math.random() * width
		this.y = Math.random() * height
	}

	draw() {
		this.x += deltaTime/1000 * 10
		if(this.x > width) {
			this.x = 0
		}
		fill(240, 90, 70)
		noStroke()
		circle(this.x, this.y, 4)
	}
}

function chrisRandom(min, max, step) {
	let result = 0

	if(step === 0) {
		// kludge because we want this to be inclusive
		result = Math.random() * (max+.00000001 - min) + min
		while(result > max) {
			result = random(min, max, step)
		}
	} else {
		// We need to make sure that max is a multiple of step relative to the
		// minimum value. E.g. if we do range 1 to 6 step 2 then our maximum
		// should be 5, giving us valid outputs of 1, 3, and 5 in even
		// distribution. So even though the user asked for 1-6, 6 is not
		// actually a valid output.
		result = Math.random() * (Math.floor((max-min+step)/step)*step)
		result =  Math.floor(result / step) * step + min
	}

	if (step %1 < 1 && step%1 !== 0) {
		return result.toFixed(String(step%1).length-2)
	} else {
		return result
	}
}

class Scoreboard{
	constructor(scores) {
		this.scores = scores
		this.highScore = scores[0].score

		// Text size
		this.size = 16

		// Scrolling through the list
		this.frame = 0
		this.maxHeight = scores.length * (this.size+8) - height + 50
		this.offset = this.size * 3.5
		this.wait = 0
	}

	draw() {

		// Our timing logic should go like this:
		//
		// Show the high scores for 2 seconds. Then start scrolling. Scroll the
		// entire list until the last item is visible. Pause for 2 seconds. Then
		// blank for 2 seconds. Then repeat.
		//
		// The math is a bit of a headache because we're using a single unit,
		// frames, to control timing, pixel coordinates, and track scrolling
		// progress. It could definitely be improved, but it works and I'm tired
		// of messing with it.

		// wait 120 frames before scrolling
		if(this.frame > 120) {
			// If our scroll position has reached the maximum height, stop
			if (Math.abs(this.offset) > this.maxHeight) {
				this.wait++
			} else {
				// Scroll
				this.offset--
			}
		}
		// reset 240 frames after scrolling has finished (we have 120 frames of
		// showing nothing)
		if(this.wait > 240) {
			this.frame = 0
			this.wait = 0
			this.offset = this.size * 3.5
		}

		// after we've scrolled, show high scores for 120 frames
		if(this.wait < 120) {
			textAlign(CENTER, CENTER)
			textSize(this.size * 2)
			textStyle(BOLD)
			fill(100)
			text("TOP SCORES", width / 2, this.offset - this.size * 1.5)

			textSize(this.size)
			for (let i = 0; i < this.scores.length; i++) {

				let rightSide = 300 * (this.scores[i].score / this.highScore)
				fill(50, 100, 50, .9)
				rect(50, i * (this.size + 8) + 2 + this.offset, rightSide, this.size + 4)
				fill(0)
				textAlign(LEFT, CENTER)
				text(this.scores[i].name, 55, i * (this.size + 8) + (this.size + 8) / 2 + this.offset)
				textAlign(RIGHT, CENTER)
				text(this.scores[i].score, rightSide + 45, i * (this.size + 8) + (this.size + 8) / 2 + this.offset)
			}
		}

		this.frame++
	}
}

function setup() {
	createCanvas(400, 800, P2D, canvas)
	chrisDefaults()

	// Generate random leaderboard data
	for(let i = 0; i < 50; i++) {
		scores.push({name: random(names), score: chrisRandom(80000, 100000, 1000)})
	}
	scores.sort((a, b) => b.score- a.score)

	for(let i = 0; i < 1000; i++) {
		particles.push(new Particle())
	}

	scoreboard = new Scoreboard(scores)
}


function draw() {
	background(240, 100, 20)

	for (let i = 0; i < particles.length; i++) {
		particles[i].draw()
	}

	scoreboard.draw()
}

You may use all or part of the p5 code seen on this page for your own creations, without restriction. Attribution is appreciated but not required.

This sketch also includes the following sources: p5common.js . Sources are available under their respective licenses.

See all p5.js sketches