Skip to content

Instantly share code, notes, and snippets.

@kallydev
Last active May 14, 2024 05:26
Show Gist options
  • Save kallydev/be78960420f536503c28eb4f8de34879 to your computer and use it in GitHub Desktop.
Save kallydev/be78960420f536503c28eb4f8de34879 to your computer and use it in GitHub Desktop.
Simple danmaku view implemented in JavaScript
class Danmaku {
elementQueue = null;
fps = 60;
trackSize = 8;
constructor(view) {
this.view = view;
this.view.width = 1920;
this.view.height = 1080;
this.context = view.getContext("2d");
this.width = this.view.width;
this.height = this.view.height;
this.trackHeight = this.height / this.trackSize;
this.tracks = new Array(this.trackSize);
for (let i = 0; i < this.trackSize; i++) {
this.tracks[i] = new Track(this.trackHeight * (i + 1), this.width);
}
console.log(this)
}
add() {
for (let i = 0; i < this.trackSize; i++) {
let track = this.tracks[i];
if (track.distance > 16) {
let element = this.poll();
if (element != null) {
track.add(element.text, element.color);
}
break;
}
}
}
offer(text, color) {
let element = new Element(text, color, this.width);
if (this.elementQueue == null) {
this.elementQueue = element;
return
}
let tempElement = this.elementQueue;
while (tempElement != null) {
if (tempElement.nextElement == null) {
tempElement.nextElement = element;
return;
}
tempElement = tempElement.nextElement;
}
}
poll() {
let resultElement = this.elementQueue;
if (this.elementQueue != null) {
this.elementQueue = this.elementQueue.nextElement;
}
return resultElement;
}
draw() {
this.context.clearRect(0, 0, 1920, 1080);
this.context.save();
for (let i = 0; i < this.trackSize; i++) {
let track = this.tracks[i];
if (track.firstElement != null) {
let width = this.context.measureText(track.firstElement.text).width;
if (track.firstElement.left + width < 0) {
track.firstElement = track.firstElement.nextElement;
}
}
for (let tempElement = track.firstElement; tempElement != null; tempElement = tempElement.nextElement) {
this.context.font = "bold " + 64 + "px Arial";
this.context.fillStyle = tempElement.color;
this.context.fillText(tempElement.text, tempElement.left, track.top);
tempElement.left -= 2;
if (tempElement.nextElement == null) {
let width = this.context.measureText(track.firstElement.text).width;
track.distance = this.width - (tempElement.left + width);
}
}
}
}
play() {
this.drawInterval = setInterval(() => {
this.draw();
}, 1000 / this.fps);
this.putInterval = setInterval(() => {
this.add();
}, 1000 / this.fps);
}
plase() {
clearInterval(this.drawInterval);
clearInterval(this.putInterval);
}
}
class Track {
constructor(top, left) {
this.top = top;
this.left = left;
this.distance = left;
this.firstElement = null;
}
add(text, color) {
let element = new Element(text, color, this.left);
if (this.firstElement == null) {
this.firstElement = element;
return
}
let tempElement = this.firstElement;
while (tempElement != null) {
if (tempElement.nextElement == null) {
tempElement.nextElement = element;
return;
}
tempElement = tempElement.nextElement;
}
}
}
class Element {
constructor(text, color, left) {
this.text = text;
this.color = color;
this.left = left;
this.nextElement = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment