Conveyor Bin somewhat working

This commit is contained in:
Kaloian Venkov 2021-03-13 16:47:26 +02:00
parent d0c539306d
commit c38fa0e43d
3 changed files with 72 additions and 42 deletions

View File

@ -3,7 +3,7 @@
<img src="/assets/images/conveyor-belt/conveyor-{{conveyorFrame + 1}}.png" class="image"> <img src="/assets/images/conveyor-belt/conveyor-{{conveyorFrame + 1}}.png" class="image">
<img src="/assets/images/conveyor-belt/conveyor-end-{{conveyorFrame + 1}}.png" class="image"> <img src="/assets/images/conveyor-belt/conveyor-end-{{conveyorFrame + 1}}.png" class="image">
</div> </div>
<div class="bins" [style.left]="(146 - 50) + 'px'" #bins> <div class="bins" [style.left]="(146 * (trashOffset + 1) - 50) + 'px'" #bins>
<img src="/assets/images/conveyor-belt/bin-plastic.png" class="image" #bin> <img src="/assets/images/conveyor-belt/bin-plastic.png" class="image" #bin>
<img src="/assets/images/conveyor-belt/bin-other.png" class="image" #bin> <img src="/assets/images/conveyor-belt/bin-other.png" class="image" #bin>
<img src="/assets/images/conveyor-belt/bin-paper.png" class="image" #bin> <img src="/assets/images/conveyor-belt/bin-paper.png" class="image" #bin>

View File

@ -1,17 +1,24 @@
img { img {
image-rendering: crisp-edges; image-rendering: crisp-edges;
} }
.conveyor { .container {
position: absolute; position: absolute;
top: 30vh; top: 30vh;
} display: flex;
.bins { flex-direction: column;
position: absolute; gap: 3em;
bottom: 10vh; .bins {
position: relative;
display: flex;
.image { .image {
max-height: unset; max-height: unset;
} }
transition: left 100ms; transition: left 100ms;
}
.conveyor {
display: flex;
width: max-content;
}
} }
:host { :host {

View File

@ -45,21 +45,21 @@ class Conveyor {
public speed: number; public speed: number;
public checkCollision(el: HTMLElement): boolean { public checkCollision(rect: Rect): boolean {
const a = new Rect(this.element.getBoundingClientRect()); const a = new Rect(this.element.getBoundingClientRect());
const b = new Rect(el.getBoundingClientRect()); const b = rect;
return a.collidesWith(b); return a.collidesWith(b);
} }
public getUpVelocity(el: HTMLElement): number { public getUpVelocity(rect: Rect): number {
return this.element.getBoundingClientRect().top - el.getBoundingClientRect().bottom; return this.element.getBoundingClientRect().top - rect.bottom;
} }
} }
class Bin { class Bin {
public acceptedTypes: string[]; public acceptedTypes: string[];
public element: HTMLElement; public element: HTMLElement;
public checkTrashColission(trash: Trash): boolean { public checkTrashColission(trash: Trash): boolean {
return new Rect(trash.element.getBoundingClientRect()).collidesWith(new Rect(this.element.getBoundingClientRect())); return trash.rect.collidesWith(new Rect(this.element.getBoundingClientRect()));
} }
public correctTrash(trash: Trash): boolean { public correctTrash(trash: Trash): boolean {
return this.acceptedTypes.includes(trash.type); return this.acceptedTypes.includes(trash.type);
@ -77,34 +77,48 @@ class Trash {
public thrownOut = new EventEmitter<boolean>(); public thrownOut = new EventEmitter<boolean>();
public dropped = new EventEmitter(); public dropped = new EventEmitter();
public rect: Rect;
public update(gravity: number, friction: number, conveyor: Conveyor, ...bins: Bin[]): { x: number, y: number, bin?: Bin } { public update(gravity: number, friction: number, conveyor: Conveyor, ...bins: Bin[]): { x: number, y: number, bin?: Bin } {
let x; let x;
let y; let y;
const rect = this.element.getBoundingClientRect(); x = this.rect.left;
x = rect.left; y = this.rect.top;
y = rect.top;
this.velY += gravity; this.velY += gravity;
y += this.velY; y += this.velY;
if (conveyor.checkCollision(this.element)) { this.rect.top += this.velY;
const velCorrection = conveyor.getUpVelocity(this.element); this.rect.bottom += this.velY;
if (conveyor.checkCollision(this.rect)) {
const velCorrection = conveyor.getUpVelocity(this.rect);
this.velY = 0; this.velY = 0;
y += velCorrection; y += velCorrection;
this.velX = conveyor.speed; this.velX = conveyor.speed;
this.rect.top -= this.velY;
this.rect.bottom -= this.velY;
} }
else if (Math.abs(this.velX) > 0) { else if (Math.abs(this.velX) > 0) {
this.velX = Math.sign(this.velX) * (Math.abs(this.velX) - friction); this.velX = Math.sign(this.velX) * (Math.abs(this.velX) - friction);
} }
const bin = bins.find(v => new Rect(rect).collidesWith(new Rect(v.element.getBoundingClientRect()))); const bin = bins.find(v => v.checkTrashColission(this));
x += this.velX; x += this.velX;
this.element.style.left = x + 'px'; const offsetX = -this.rect.left + x;
this.element.style.top = y + 'px'; const offsetY = -this.rect.top + y;
return {x, y, bin}; this.rect.left += offsetX;
this.rect.top += offsetY;
this.rect.right += offsetX;
this.rect.bottom += offsetY;
this.element.style.top = y + 'px';
this.element.style.left = x + 'px';
return { x, y, bin };
} }
} }
@ -118,8 +132,11 @@ export class MinigameConveyorRecyclingComponent implements AfterViewInit {
frameCounterID: number; frameCounterID: number;
trashTrowerID: number; trashTrowerID: number;
trashSpeed = 1000; trashSpeed = 1000;
trashTypes: string[] = [ 'plastic', 'metal', 'glass', 'paper', 'other' ]; trashTypes: string[] = ['plastic', 'metal', 'glass', 'paper', 'other'];
nextId = 0; nextId = 0;
simulationSpeed = 10;
trashOffset = 0;
@ViewChildren('conveyor') conveyorElement; @ViewChildren('conveyor') conveyorElement;
@ViewChildren('bin') binElements; @ViewChildren('bin') binElements;
@ -136,8 +153,11 @@ export class MinigameConveyorRecyclingComponent implements AfterViewInit {
keydownListener = (e) => { keydownListener = (e) => {
const code = e.keyCode as number; const code = e.keyCode as number;
if (code === 65) console.log('move left'); if (code === 65) this.trashOffset--;
if (code === 68) console.log('move right'); if (code === 68) this.trashOffset++;
if (this.trashOffset < 0) this.trashOffset = this.bins.length - 1;
if (this.trashOffset >= this.bins.length) this.trashOffset = 0;
} }
constructor( constructor(
@ -183,32 +203,35 @@ export class MinigameConveyorRecyclingComponent implements AfterViewInit {
}); });
}, 1000) as any as number; }, 1000) as any as number;
this.frameCounterID = setInterval(() => { this.frameCounterID = setInterval(() => {
if (this.milliseconds % (1000 / 10) === 0) { if (this.milliseconds % (1000 / (this.simulationSpeed)) === 0) {
const trash = new Trash(); const trash = new Trash();
const element = document.createElement('img'); const element = document.createElement('img');
element.style.position = 'absolute'; element.style.position = 'absolute';
trash.dropped.subscribe(() => { trash.velX = 0;
trash.element.remove();
});
trash.velX = 2;
trash.velY = 0; trash.velY = 0;
trash.type = this.getRandomType(); trash.type = this.getRandomType();
trash.imageUrl = `/assets/images/conveyor-belt/${trash.type}-${Math.floor(Math.random() * 3) + 1}.png`; trash.imageUrl = `/assets/images/conveyor-belt/${trash.type}-${Math.floor(Math.random() * 3) + 1}.png`;
element.src = trash.imageUrl; element.src = trash.imageUrl;
element.decode().then(() => {
trash.element = element; trash.element = element;
this.element.nativeElement.prepend(element); this.element.nativeElement.prepend(element);
trash.rect = new Rect(0, 0, element.width, element.height);
this.trashes.push({ id: (this.nextId++).toString(), el: trash }); this.trashes.push({ id: (this.nextId++).toString(), el: trash });
});
} }
this.trashes.forEach((trash, i) => { this.trashes.forEach((trash, i) => {
const newPos = trash.el.update(9 / 100, .05, this.conveyor, ...this.bins); const newPos = trash.el.update(
9 / (1000 / this.simulationSpeed),
10 / (1000 / this.simulationSpeed),
this.conveyor, ...this.bins
);
if (newPos.y > document.body.getBoundingClientRect().bottom) { if (newPos.y > document.body.getBoundingClientRect().bottom) {
trash.el.element.remove(); trash.el.element.remove();
this.trashes.splice(i, 1); this.trashes.splice(i, 1);
@ -221,7 +244,7 @@ export class MinigameConveyorRecyclingComponent implements AfterViewInit {
}); });
this.milliseconds++; this.milliseconds++;
}, 10) as any as number; }, this.simulationSpeed) as any as number;
} }