I am currently evaluating a Framework / Possibility to create a Game inside of an Angular Application. I have tried Canvas, now I want to use P5.
The Problem is, that it runs the whole draw function just once.
ngOnInit(): void {
this.scrWidth = window.innerWidth;
this.scrHeight = window.innerHeight;
this.createCanvas();
}
private createCanvas() {
const sketch = (s: p5) => {
s.preload = () => {};
s.setup = () => {
s.frameRate(30);
s.createCanvas(this.scrWidth, this.scrHeight - 10);
s.background(50);
this.objLayer = new ObjectLayer();
this.player = new Player(
this.scrHeight / 20, // Width (Using the screen height to scale the player)
(this.scrHeight / 20) * 1.5, // Height (Using the screen height to scale the player)
30, // X Starting Position
30 // Y Starting Position
);
this.objLayer.children.push(this.player);
};
s.draw = () => {
this.update(); //Updating states, coordinates, ..
this.render(); // Drawing Objects to the sketch
};
};
this.p5 = new p5(sketch.bind(this), this.container.nativeElement);
}
I don't know if Angular is blocking the loop in someway, or if I just made a mistake. unfortunately, there's almost no help on the internet for using P5.js with Angular/Typescript.
I am very thankful for any ideas.
CodePudding user response:
I cannot reproduce your problem. You haven't provided enough of your code to constitute a minimal reproducible example. Here's the complete code of a working Angular 12 component:
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import p5 from 'p5';
class Ball {
public x: number;
public y: number;
public velocity: p5.Vector;
public radius: number;
constructor(x: number, y: number, velocity: p5.Vector, radius: number = 20) {
this.x = x;
this.y = y;
this.velocity = velocity;
this.radius = radius;
}
public render(p: p5) {
p.circle(this.x, this.y, this.radius);
}
public update(p: p5) {
// update position
this.x = this.velocity.x * (p.deltaTime / 1000);
this.y = this.velocity.y * (p.deltaTime / 1000)
// check for collisions
if (this.x < this.radius) {
// Collision with the left hand edge of the "room" reverses the horizontal component of the velocity
this.velocity.x *= -1;
this.x = this.radius (this.radius - this.x);
} else if (this.x > p.width - this.radius) {
this.velocity.x *= -1;
this.x = p.width - this.radius - (this.x - (p.width - this.radius));
}
if (this.y < this.radius) {
this.velocity.y *= -1;
this.y = this.radius (this.radius - this.y);
} else if (this.y > p.height - this.radius) {
this.velocity.y *= -1;
this.y = p.height - this.radius - (this.y - (p.height - this.radius));
}
}
}
@Component({
selector: 'app-p5js-sample',
templateUrl: './p5js-sample.component.html',
styleUrls: ['./p5js-sample.component.css']
})
export class P5jsSampleComponent {
public instance?: p5;
public ball?: Ball;
@ViewChild('container')
public container?: ElementRef<HTMLDivElement>;
constructor() { }
// Switched to ngAfterViewInit instead of ngOnInit just to support
// the parent element for the sketch (not strictly necessary)
ngAfterViewInit(): void {
this.createSketch();
}
private createSketch() {
const sketch = (p: p5) => {
p.setup = () => {
p.createCanvas(p.windowWidth - 20, p.windowHeight - 50);
p.ellipseMode(p.RADIUS);
p.fill('green');
this.ball = new Ball(
p.random(20, p.width - 20),
p.random(20, p.height - 20),
p.createVector(100, 0).rotate(p.random(0, p.TWO_PI))
);
};
p.draw = () => {
p.background(0);
if (this.ball) {
this.ball.update(p);
this.ball.render(p);
}
};
};
this.instance = new p5(
// this bind is not necessary
sketch.bind(this),
// Specifying a parent element is good practice, but is also
// not strictly necessary
this.container?.nativeElement
);
}
}
The complete, runnable example can be found here: https://replit.com/@KumuPaul/Angular-P5js-Sample
CodePudding user response:
I found a solution myself. It was my fault and yes I provided to less code. I actually was sure, that the mistake is not on my side, because there where no errors and it seemed like I did everything wrong.
In my class for the player, I created a draw function. This draw function was written wrong, because I recalled the draw function from P5js. Because of that my Player was rendered but the loop broke.
That's how it was:
public draw(p: p5) {
s.draw = () => {
p.fill(255);
p.rect(this.x, this.y, this.width, this.height);
}
}
That's how it works:
public draw(p: p5) {
p.fill(255);
p.rect(this.x, this.y, this.width, this.height);
}