xxxxxxxxxx
200
var game;
function setup() {
createCanvas(400, 400);
game = new BallBreaker(25, 50);
}
function draw() {
background(220);
game.update();
}
function collide(ball, rect, M) {
const nearX = max(rect.x, min(ball.x, rect.x + M.x))
const nearY = max(rect.y, min(ball.y, rect.y + M.y))
const dist = createVector(ball.x-nearX, ball.y-nearY)
ball.hp-=ball.dmg;
if (ball.dir.dot(dist) < 0){
const tang_dir = p5.Vector.normalize(dist);
tang_dir.dot(ball.dir)
tang_dir.mult(2)
ball.dir.sub(tang_dir);
}
const overlap = ball.r - dist.mag();
const bounce_dir = p5.Vector.normalize(dist)
bounce_dir.mult(overlap)
// yooo this is not handy.
const ballpos = p5.Vector.sub(createVector(ball.x, ball.y), bounce_dir)
ball.x = ballpos.x
ball.y = ballpos.y
}
class BallBreaker {
/*
stuff i forget
this.COLS, this.ROWS, this.M.x. or y
this.bricks and this.balls are quadtrees. maybe easier to keep balls
just in an array
*/
constructor(COLS, ROWS) {
this.COLS = COLS
this.ROWS = ROWS
this.M = {x:width*.8/COLS , y:height*.8/ROWS}
this.setup()
}
resetStats() {
this.level = 1;
this.ballsAMT = 1;
this.balldmg = 1
this.ballradius = 7;
this.gfxBricks = createGraphics(width, height)
this.gfxBalls = createGraphics(width, height);
// @deprecated / unused
this.balls = d3.quadtree()
.x(function(o){return o.x})
.y(function(o){return o.y})
this.balls = [];
this.bricks = d3.quadtree()
.x(function(o){return o.x})
.y(function(o){return o.y})
for (var i = 0; i < this.COLS; i++){
// trying to keep both the fractional value of the pos on screen
// for resizing purposes and then also the absolute x and y for current resolution. idk if smart.
// it means updating more values. not handy for balls.
if(random()>0.3) this.bricks.add({
x:(i/this.COLS)*width, y:0*height, hp:this.level,
xfrac: (i/this.COLS), yfrac:0})
}
// @deprecated this.balls.add(...) not using quadtree for balls.
const xdir_fract_part = random(-1,1)*0.005; // for debugging
this.balls.push({ x:(1/2)*width, y: (1)*height,
xfrac:(1/2), yfrac:1,
dirfrac :createVector(xdir_fract_part,-.0025),
dir : createVector(xdir_fract_part*width, -.0025*height),
dmg:this.balldmg, r:this.ballradius})
}
drawAllBricks(){
for (const b of this.bricks.data()){
const {x,y} = b;
this.gfxBricks.rect(x, y, this.M.x, this.M.y)
}
}
setup(){
this.resetStats()
this.drawAllBricks()
}
redrawBrick(brick){
this.gfxBricks.push()
this.gfxBricks.fill('red')
this.gfxBricks.rect(brick.x, brick.y, this.M.x, this.M.y)
this.gfxBricks.pop()
}
updateBall(b){
// completely deprecated because i cba to also recalculate these in the collision so *** that
// erm. dont mind this . just testing. i swear.
// (too dumb to recalculate all positions on the fly when resizing so i want to keep them like this for now)
// b.xfrac += b.dirfrac.x
// b.yfrac += b.dirfrac.y
//
const closest_brick = this.bricks.find(b.x, b.y, b.r*2);
if(closest_brick != undefined) {
if(closest_brick.hp <= 0){
b.x += b.dir.x
b.y += b.dir.y
this.redrawBrick(closest_brick)
return
}
print(closest_brick.length)
//global static function
print(closest_brick)
collide(b, closest_brick, this.M)
this.gfxBalls.circle(b.x, b.y, b.r*2)
}
// lmao edge reflection not working, epicly.
// else if (b.x > width || b.x < 0) {
// b.dir.x = -b.dir.x
// b.x += b.dir.x
// b.y += b.dir.y
// } else if (b.y > height || b.y < 0 ) {
// b.dir.y = -b.dir.y;
// b.x += b.dir.x
// b.y += b.dir.y
// }
else {
b.x += b.dir.x
b.y += b.dir.y
}
}
updateBalls(){
this.gfxBalls.clear()
const collMap = new Map();
for (const b of this.balls){
this.updateBall(b)
this.gfxBalls.circle(b.x, b.y, b.r*2);
}
}
drawAll(){
image(this.gfxBricks, 0,0)
image(this.gfxBalls, 0,0)
}
update(){
this.updateBalls() // -> draws new bricks to the brick layer.
this.drawAll()
}
}