Class Extension Example
The recommended way to integrate the built-in primitives into your own code is by inheritance.
In ES6, this can easily be done by using classes and the extends
keyword.
The crucial part to make objects Quadtree-compatible is to implement the
Indexable interface –
that means to provide a qtIndex()
method, that returns the quadrant of the object
for any given Quadtree node. All Indexable objects can be inserted or used for retrieval.
The following code is reduced to the most important parts. View the full script.js of this example on GitHub.
HTML
<canvas id="canvas" width="640" height="480"></canvas>
Player.JS
// The Player class will inherit the `qtIndex` method from Rectangle
class Player extends Quadtree.Rectangle {
constructor(color) {
// Call the super constructor to set x, y, width and height initially
super({
x: Math.random() * 640,
y: Math.random() * 480,
width: 32,
height: 32,
});
// Store the color
this.color = color;
// Store a movement target position
this.moveTargetX = this.x;
this.moveTargetY = this.y;
}
// Draw the player
draw(ctx) {
// Draw the movement path
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.moveTargetX, this.moveTargetY);
ctx.strokeStyle = this.color;
ctx.stroke();
// Draw the player
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
// Update the player position
update() {
const dx = this.moveTargetX - this.x;
const dy = this.moveTargetY - this.y;
const distance = Math.sqrt(dx * dx + dy * dy);
// Move towards the target position
if (distance > 1) {
this.x += dx / distance;
this.y += dy / distance;
// Else, if the player is close enough, set a new target
} else {
this.moveTargetX = Math.random() * 640;
this.moveTargetY = Math.random() * 480;
}
}
}
Script.JS
// Create a new Quadtree
const tree = new Quadtree({
width: 640,
height: 480,
});
// Create a red and blue player
const redPlayer = new Player('red');
const bluePlayer = new Player('blue');
// Store all objects in an array
const myObjects = [];
// Create some objects
for(let i=0;i<50;i++) {
const rectangle = new Quadtree.Rectangle({
x: Math.random() * (canvas.width-32),
y: Math.random() * (canvas.height-32),
width: 4 + Math.random() * 28,
height: 4 + Math.random() * 28,
data: {
checkRed: false,
checkBlue: false,
}
});
tree.insert(rectangle);
myObjects.push(rectangle);
}
// Main loop
function loop() {
// Reset check flags
myObjects.forEach(obj => obj.data.checkRed = obj.data.checkBlue = false);
// Update players
redPlayer.update();
bluePlayer.update();
// Retrieve all objects that share nodes with the players
// Since the players extend Quadtree.Rectangle, we can use them with the retrieve function
const redCandidates = tree.retrieve(redPlayer);
const blueCandidates = tree.retrieve(bluePlayer);
// Flag retrieved objects
redCandidates.forEach(obj => obj.data.checkRed = true);
blueCandidates.forEach(obj => obj.data.checkBlue = true);
// Draw scene
draw();
window.requestAnimationFrame(loop);
};
loop();
To see the full example code please check the page source or visit this page on github.