function .push keep replacing all elements same as last one in array - javascript

I'm trying to make trails of moving objects by using vector history array in p5js.
but after push updated vector, all elements in this.history replaced as last one.
I've searched some question here but still can't understand.
let ppp = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 3; i++) {
let p = new Particle();
ppp.push(p);
}
}
function draw() {
background(220);
for (let i = 0; i < ppp.length; i++) {
ppp[i].display();
ppp[i].update();
}
}
function Particle() {
this.pv = createVector(random(width), random(height));
this.history = [];
let rndV = p5.Vector.random2D();
this.spdV = rndV.mult(random(1, 3));
this.update = function() {
this.pv.add(this.spdV);
this.history.push(this.pv); // replace all vector element
console.log(this.history);
}
this.display = function() {
fill(30);
ellipse(this.pv.x, this.pv.y, 30);
for (let i = 0; i < this.history.length; i++) {
let trail = this.history[i];
ellipse(trail.x, trail.y, 10);
}
}
}
or if you think my approach isn't the best, I'll be happy to hear any suggestion^^
Thanks,

This can be a bit misleading in javascript:
this.history.push(this.pv);
You're pushing a reference to the same this.pv pre-allocated vector
What you are trying to do is something like:
this.history.push(this.pv.copy());
Where you are allocating memory for a completely new p5.Vector object with the x,y coordinates copied from this.pv (using the copy() method)
Demo:
let ppp = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 3; i++) {
let p = new Particle();
ppp.push(p);
}
}
function draw() {
background(220);
for (let i = 0; i < ppp.length; i++) {
ppp[i].display();
ppp[i].update();
}
}
function Particle() {
this.pv = createVector(random(width), random(height));
this.history = [];
let rndV = p5.Vector.random2D();
this.spdV = rndV.mult(random(1, 3));
this.update = function() {
this.pv.add(this.spdV);
this.history.push(this.pv.copy()); // replace all vector element
//console.log(this.history);
}
this.display = function() {
fill(30);
ellipse(this.pv.x, this.pv.y, 30);
for (let i = 0; i < this.history.length; i++) {
let trail = this.history[i];
ellipse(trail.x, trail.y, 10);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
Bare in mind as the sketch runs this will use more and more memory.
If simply need to render the trails and don't need the vector data for anything else you can simply render into a separate graphics layer (using createGraphics()) immediately which will save memory on the long run:
let ppp = [];
let trailsLayer;
function setup() {
createCanvas(400, 400);
// make a new graphics layer for trails
trailsLayer = createGraphics(400, 400);
trailsLayer.noStroke();
trailsLayer.fill(0);
for (let i = 0; i < 3; i++) {
let p = new Particle();
ppp.push(p);
}
}
function draw() {
background(220);
// render the trails layer
image(trailsLayer, 0, 0);
for (let i = 0; i < ppp.length; i++) {
ppp[i].display();
ppp[i].update();
}
}
function Particle() {
this.pv = createVector(random(width), random(height));
let rndV = p5.Vector.random2D();
this.spdV = rndV.mult(random(1, 3));
this.update = function() {
this.pv.add(this.spdV);
// render trails
trailsLayer.ellipse(this.pv.x, this.pv.y, 10);
}
this.display = function() {
fill(30);
ellipse(this.pv.x, this.pv.y, 30);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
Update to fade trails you could try something like Moving On Curves example. Notice noStroke(); is called in setup() and
fill(0, 2);
rect(0, 0, width, height);
render a faded out (alpha=2) rectangle ?
You could do something similar:
let ppp = [];
let trailsLayer;
function setup() {
createCanvas(400, 400);
background(255);
// make a new graphics layer for trails
trailsLayer = createGraphics(400, 400);
trailsLayer.noStroke();
// set translucent fill for fade effect
trailsLayer.fill(255, 25);
for (let i = 0; i < 3; i++) {
let p = new Particle();
ppp.push(p);
}
}
function draw() {
background(220);
// fade out trail layer by rendering a faded rectangle each frame
trailsLayer.rect(0, 0, width, height);
// render the trails layer
image(trailsLayer, 0, 0);
for (let i = 0; i < ppp.length; i++) {
ppp[i].display();
ppp[i].update();
}
}
function Particle() {
this.pv = createVector(random(width), random(height));
let rndV = p5.Vector.random2D();
this.spdV = rndV.mult(random(1, 3));
this.update = function() {
this.pv.add(this.spdV);
// reset at bounds
if(this.pv.x > width){
this.pv.x = 0;
}
if(this.pv.y > height){
this.pv.y = 0;
}
if(this.pv.x < 0){
this.pv.x = width;
}
if(this.pv.y < 0){
this.pv.y = height;
}
// render trails
trailsLayer.push();
trailsLayer.fill(0);
trailsLayer.noStroke();
trailsLayer.ellipse(this.pv.x, this.pv.y, 10);
trailsLayer.pop();
}
this.display = function() {
fill(30);
ellipse(this.pv.x, this.pv.y, 30);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
For the sake of completeness here's a version using the history vector array, but limiting that to a set size and reusing vectors allocated once (instead making new ones continuously):
let ppp = [];
function setup() {
createCanvas(400, 400);
noStroke();
for (let i = 0; i < 3; i++) {
let p = new Particle();
ppp.push(p);
}
}
function draw() {
background(220);
for (let i = 0; i < ppp.length; i++) {
ppp[i].display();
ppp[i].update();
}
}
function Particle() {
this.pv = createVector(random(width), random(height));
// limit number of history vectors
this.historySize = 24;
this.history = new Array(this.historySize);
// pre-allocate all vectors
for(let i = 0 ; i < this.historySize; i++){
this.history[i] = this.pv.copy();
}
let rndV = p5.Vector.random2D();
this.spdV = rndV.mult(random(1, 6));
this.update = function() {
this.pv.add(this.spdV);
this.resetBounds();
this.updateHistory();
};
this.updateHistory = function(){
// shift values back to front by 1 (loop from last to 2nd index)
for(let i = this.historySize -1; i > 0; i--){
// copy previous to current values (re-using existing vectors)
this.history[i].set(this.history[i-1].x, this.history[i-1].y);
}
// finally, update the first element
this.history[0].set(this.pv.x, this.pv.y);
};
this.resetBounds = function(){
// reset at bounds
if(this.pv.x > width){
this.pv.x = 0;
}
if(this.pv.y > height){
this.pv.y = 0;
}
if(this.pv.x < 0){
this.pv.x = width;
}
if(this.pv.y < 0){
this.pv.y = height;
}
};
this.display = function() {
fill(30);
ellipse(this.pv.x, this.pv.y, 30);
for (let i = 0; i < this.historySize; i++) {
let trail = this.history[i];
// fade trails
let alpha = map(i, 0, this.historySize -1, 192, 0);
fill(30, alpha);
ellipse(trail.x, trail.y, 10);
}
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>

Related

Javascript - get neighbor cells in a 2D array?

I've been trying to follow this tutorial: https://www.youtube.com/watch?v=aKYlikFAV4k&t=1848s&ab_channel=TheCodingTrain
However, I'm using vanilla Javascript. I'm struggling to get the neighboring cells for each cell in my grid. I'm pretty new to coding so help would be very much appreciated!
Here is my code so far:
//GLOBAL VARIABLES
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const wh = 600;
const cellSize = 30;
const rows = 20;
const cols = 20;
const grid = new Array(rows);
const open = [];
const closed = [];
let start;
let end;
//FUNCTIONS
//Immediately-invoked function expression
//Runs code immediately when the page loads and keeps it out of the global scope (avoids naming conflicts)
(function() {
setup();
})();
function Cell(x, y) { //Constructor function for each cell in the array
this.x = 0;
this.y = 0;
this.f = 0;
this.g = 0;
this.h = 0;
this.show = function(color) { //Function to show cell on grid
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, cellSize, cellSize);
ctx.strokeStyle = 'white';
ctx.strokeRect(this.x, this.y, cellSize, cellSize);
}
}
//Function to setup the canvas
function setup() {
let interval = setInterval(update, 120);
canvas.setAttribute('width', wh);
canvas.setAttribute('height', wh);
document.body.insertBefore(canvas, document.body.childNodes[0]); //Inserts canvas before the first element in body
createGrid();
setStartEnd();
}
//Function to create grid
function createGrid() {
for (let i = 0; i < rows; i++) { //Creating 2D array
grid[i] = new Array(cols);
}
let x = 0;
let y = 0;
for (let i = 0; i < rows; i++) { //Creating a new cell for each spot in the array
for (let j = 0; j < cols; j++) {
grid[i][j] = new Cell();
grid[i][j].x = x;
grid[i][j].y = y;
grid[i][j].show();
x = x + 1 * 30;
}
x = 0;
y = y + 1 * 30;
}
}
//Function that defines the start and end points
function setStartEnd() {
start = grid[0][0];
end = grid[cols - 1][rows - 1];
open.push(start);
}
//Function to remove a node from an array
function removeArray(arr, e) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === e) {
arr.splice(i, 1);
}
}
}
//Main function
function update() {
//nodes part of "open" array are green
for (let i = 0; i < open.length; i++) {
open[i].show('green');
}
//nodes part of "closed" array are red
for (let i = 0; i < closed.length; i++) {
closed[i].show('red');
}
}
You've made it a bit hard for yourself by having Cell not store its own x,y position in the grid.
If you move some logic from your nested i,j for loop to your Cell class, it gets easier. I modified Cell to store its x and y grid coordinate rather than pixel coordinate. You can then, in update, do something like this:
const nextOpenSet = new Set();
open.forEach(cell => {
const above = grid[cell.y - 1]?.[cell.x];
if (above) nextOpenSet.add(above);
const below = grid[cell.y + 1]?.[cell.x];
if (below) nextOpenSet.add(below);
const left = grid[cell.y][cell.x - 1];
if (left) nextOpenSet.add(left);
const right = grid[cell.y][cell.x + 1];
if (right) nextOpenSet.add(right);
});
open = Array.from(nextOpenSet);
Here's a runnable example:
//GLOBAL VARIABLES
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const wh = 600;
const cellSize = 30;
const rows = 20;
const cols = 20;
const grid = new Array(rows);
let open = [];
const closed = [];
let start;
let end;
//FUNCTIONS
//Immediately-invoked function expression
//Runs code immediately when the page loads and keeps it out of the global scope (avoids naming conflicts)
(function() {
setup();
})();
function Cell(x, y) { //Constructor function for each cell in the array
this.x = x;
this.y = y;
this.show = function(color) { //Function to show cell on grid
ctx.fillStyle = color;
ctx.fillRect(this.x * cellSize, this.y * cellSize, cellSize, cellSize);
ctx.strokeStyle = 'white';
ctx.strokeRect(this.x * cellSize, this.y * cellSize, cellSize, cellSize);
}
}
//Function to setup the canvas
function setup() {
let interval = setInterval(update, 120);
canvas.setAttribute('width', wh);
canvas.setAttribute('height', wh);
document.body.insertBefore(canvas, document.body.childNodes[0]); //Inserts canvas before the first element in body
createGrid();
setStartEnd();
}
//Function to create grid
function createGrid() {
for (let i = 0; i < rows; i++) { //Creating 2D array
grid[i] = new Array(cols);
}
for (let i = 0; i < rows; i++) { //Creating a new cell for each spot in the array
for (let j = 0; j < cols; j++) {
grid[i][j] = new Cell(i, j);
grid[i][j].show();
}
}
}
//Function that defines the start and end points
function setStartEnd() {
start = grid[0][0];
end = grid[cols - 1][rows - 1];
open.push(start);
}
//Function to remove a node from an array
function removeArray(arr, e) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === e) {
arr.splice(i, 1);
}
}
}
//Main function
function update() {
//nodes part of "open" array are green
for (let i = 0; i < open.length; i++) {
open[i].show('green');
}
//nodes part of "closed" array are red
for (let i = 0; i < closed.length; i++) {
closed[i].show('red');
}
const nextOpenSet = new Set();
open.forEach(cell => {
const above = grid[cell.y - 1]?.[cell.x];
if (above) nextOpenSet.add(above);
const below = grid[cell.y + 1]?.[cell.x];
if (below) nextOpenSet.add(below);
const left = grid[cell.y][cell.x - 1];
if (left) nextOpenSet.add(left);
const right = grid[cell.y][cell.x + 1];
if (right) nextOpenSet.add(right);
});
open = Array.from(nextOpenSet);
}

p5.js: Assigning a static unique colour to each ellipse in a group

As you can see, each ellipse is part of a wave object and the fill is getting applied on each frame over and over and giving this blinking effect on all ellipses. I want to take a random colour and assign to each ellipse when it is drawn so that it remains with that fill colour instead of defining a new colour at each frame. I tried a lot but couldn't achieve that. Any help would be appreciated.
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
}
}
function draw() {
background(0);
for (let x = 0; x < width; x += 10) {
for (let wave of waves) {
y = wave.evaluate(x);
noStroke();
fill(random(255), random(255), random(255));
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Create a list of about 20 colors for each wave. Use color() to create a color:
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
Use this color to draw the waves. Use the % (modulo) operator to compute the rest of an integra division. The colors are repeated after every 20 points:
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
class Wave {
constructor(amp, period, phase) {
this.amplitude = amp;
this.period = period;
this.phase = phase;
}
evaluate(x) {
return sin(this.phase + (TWO_PI * x) / this.period) * this.amplitude;
}
update() {
this.phase += 0.05;
}
}
let waves = [];
let waves_colors = [];
let y;
function setup() {
createCanvas(600, 400);
for (let i = 0; i < 5; i++) {
waves[i] = new Wave(random(20, 80), random(100, 600), random(TWO_PI));
colors = [];
for (let j = 0; j < 20; j++) {
if (i % 2 == 1)
colors.push(color(0, 0, 255, random(128,255)));
else
colors.push(color(random(255), random(255), random(255)))
}
waves_colors.push(colors);
}
}
function draw() {
background(0);
noStroke();
for (let i = 0; i < 5; i++) {
wave = waves[i];
colors = waves_colors[i];
for (let j = 0; j < width/10; j ++) {
x = j*10;
y = wave.evaluate(x);
fill(colors[j % colors.length]);
ellipse(x, y + height / 2, 6);
}
}
for (let wave of waves) {
wave.update();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

javascript P5 function creates endless loop

I can't for the life of me work out how to reset the function createAliens below so I can begin a new game - I'm basically looking for a way to clear the sprites off the canvas so I can reset the game.
Any help would be seriously appreciated :)
const BORDER = 60;
const SPEED = 3;
let score = 0;
let numAliens = 3;
let alienSpeed = 5;
let aliensArray = [];
let ship;
let laser;
let lasers = [];
function preload() {
}
function setup() {
createCanvas(1000, 700);
aliens = new Group();
ships = new Group();
lasers = new Group();
createAliens(numAliens);
ship = createSprite(width/2, height/1.15, 40, 60);
ship.setCollider('rectangle', 0, 0, 40, 60);
ships.add(ship);
}
function draw() {
background(0);
if(aliens == 0) {
createAliens(numAliens + 2);
}
aliens.bounce(aliens); // p5 game methods - collision etc using callbacks
aliens.overlap(lasers, scoreTotal);
aliens.collide(lasers, die);
ship.bounce(aliens, reset);
keyPressed();
drawSprites();
for (let i = 0; i < allSprites.length; i++) { // game borderless
let all = allSprites[i];
if (all.position.x < - BORDER) {
all.position.x = width + BORDER;
}
if (all.position.x > width + BORDER) {
all.position.x = - BORDER;
}
if (all.position.y < - BORDER) {
all.position.y = height + BORDER;
}
if (all.position.y > height + BORDER) {
all.position.y = - BORDER;
}
}
}
function createAliens(numAliens) { // spawn some aliens
for (let j = 0; j < numAliens; j++) {
alien = createSprite(random(width), 0, 50, 60);
alien.shapeColor = color('red');
alien.setSpeed(random(0.3, alienSpeed), random(45, 150));
aliensArray.push(alien);
aliens.add(alien);
}
}
function die(alien) { // kill the alien
alien.remove();
}
function scoreTotal() {
score += 10;
}
function reset() {
console.log('RESET FIRING');
}
function keyPressed() {
if (keyDown(LEFT_ARROW)) {
ship.setSpeed(SPEED, 180);
ship.friction = 0.01;
}
else if (keyDown(RIGHT_ARROW)) {
ship.setSpeed(SPEED, 0);
ship.friction = 0.01;
}
else if (keyDown(UP_ARROW)) {
ship.setSpeed(SPEED, 270);
ship.friction = 0.01;
}
else if (keyDown(DOWN_ARROW)) {
ship.setSpeed(SPEED, 90);
ship.friction = 0.01;
}
if(keyWentDown(' ')) {
let laser = createSprite(ship.position.x, ship.position.y, 5, 5);
laser.setSpeed(10, 270);
laser.shapeColor = color('red');
laser.life = 30;
lasers.add(laser);
}
}
I have got the aliens spawning with the simple conditional logic:
if(aliens == 0) {
createAliens(numAliens + 2);
}

Game slows down after a while, potential data leak?

I'm making a javascript game using p5 and p5.play and for some reason after the simulation runs for more than 20 seconds the entire thing really slows down. I think it may be a data leak but am unsure of what is truly harming performance.
Update: After some poking around I found that I was successfully removing the sprites from the plain group however there is some other Object called allSprites that is collecting the sprites no matter what. How I remove said sprites from this object is still unknown.
Update: Came up with way to remove them from object, still did not fix data leak.
var players;
var deadly;
var powerUp;
var plain;
var penguinSheet;
var penguinAnimation;
var willLoad;
var harmless;
var score = 0;
function preload(){
penguinSheet = loadSpriteSheet('./assets/BoxPenguinSprites.png', 64, 64, 3);
penguinAnimation = loadAnimation(penguinSheet);
}
function setup() {
createCanvas(700, 600);
// players = new Group();
// deadly = new Group();
// powerUp = new Group();
// harmless = new Group();
plain = new Group();
useQuadTree(true);
player = createSprite(100, 100, 20, 20);
player.debug = true;
}
function update(){
for (var i = 0; i < 10; i++) {
var c = createSprite(
random(width), 0,
random(25, 75), random(10, 30));
c.addSpeed(random(1,3), 90);
c.shapeColor = color(random(30, 50), random(180, 220), random(80, 130));
plain.add(c);
}
// for (var k = 0; k < 3; k++) {
// var d = createSprite(
// random(width), 0,
// random(25, 75), random(10, 30));
// d.addSpeed(random(1,3), 90);
// d.shapeColor = color(random(0, 30), random(150, 160), random(50, 80));
// harmless.add(d);
// }
}
function cleanUp(){
for (var j = 0; j < plain.length; j++){
if (plain[j].newPosition.y > height){
plain.remove(plain[j]);
}
}
// for (j = 0; j< harmless.length; j++){
// if (harmless[j].newPosition.y > height){
// harmless.remove(harmless[j]);
// }
// }
}
function pixleBuffer(){
var offsetX = 0;
var offsetY = 0;
if (keyIsDown(LEFT_ARROW)){
offsetX = -3;
}
if (keyIsDown(RIGHT_ARROW)){
offsetX = 3;
}
if (keyIsDown(UP_ARROW)){
offsetY = -3;
}
if (keyIsDown(DOWN_ARROW)){
offsetY = 3;
}
player.setCollider("rectangle", offsetX , offsetY, 20, 20);
}
//
function draw() {
if (frameCount == 1 || frameCount % 100 == 0){
update();
}
// player.overlap(harmless);
// plain.collide(harmless);
// harmless.collide(plain);
// harmless.collide(harmless);
player.collide(plain);
plain.collide(plain);
if(keyIsDown(LEFT_ARROW)){
player.position.x -= 3
}
if(keyIsDown(RIGHT_ARROW)){
player.position.x += 3
}
if(keyIsDown(UP_ARROW)){
player.position.y -=3
}
if(keyIsDown(DOWN_ARROW)){
player.position.y += 3
}
pixleBuffer();
clear();
cleanUp();
drawSprites();
}

Objects in P5 do not collide when using collide() function

I'm working on getting all the components for my final together using the P5.play engine and while I have made some progress with setting up aspects of my mini game I'm having a hard time with the collision. It should be easy but for whatever reason when I set up my two objects (the fish and the garbage) they do not collide. I am trying to set it up so that when the garbage collides with the fish the fish either get removed or are reset to a place where they can continue to move on the screen while tallying the score. I managed to get the player sprite to collect the garbage and add to the score using overlapPoint and placing the condition in the update for the garbage object. But when I attempt the same technique for the fish on the garbage object an error occurs and everything disappears on the screen. I commented out the portion that is I have tried multiple ways including the collide() function on the objects with the proper conditionals but nothing seems to work. A bit frustrating. I have tried various other ways. So I'm asking for expert advice. Any assistance is appreciated. this is the code that i have thus far:
var bg;
var player;
var player_stand_sprites;
var player_stand;
var fish_swim_sprites;
var fish_swim;
var fish = [];
var garbage_drop_sprites;
var garbage_drop;
var garbage = [];
var score = 0;
function preload() {
bg = loadImage("final-bg.png");
player_stand_sprites = loadSpriteSheet("player2.png", 100, 100, 1);
player_stand = loadAnimation(player_stand_sprites);
fish_swim_sprites = loadSpriteSheet("fish.png", 75, 75, 1);
fish_swim = loadAnimation(fish_swim_sprites);
garbage_drop_sprites = loadSpriteSheet("metal.png", 41, 75, 1);
garbage_drop = loadAnimation(garbage_drop_sprites);
}
function setup() {
createCanvas(720, 360);
player = createSprite(100, 0);
player.addAnimation("stand", player_stand);
player.setCollider("circle", 0, 0, 32, 32);
player.depth = 10;
//player.debug = true;
//to make fish
for (var i = 0; i < 10; i++){
fish.push( new Fish(random(0,width), random(height/2, height)) );
for (var i = 0; i < fish.length; i++) {
fish[i].init();
}
}
//to make garbage
for (var a = 0; a < 5; a++){
garbage.push( new Garbage(random(0,width), random(width/2, width)));
}
}
function draw() {
background(bg);
player.position.x = mouseX;
player.position.y = mouseY;
for (var i = 0; i < fish.length; i++) {
fish[i].update();
}
for (var a = 0; a < garbage.length; a++) {
garbage[a].update();
}
/**for (var b = 0; b < fish.length; b++) {
if(fish[b].collide(garbage[b])){
fish[b].remove;
}
}**/
text(score,100,100);
drawSprites();
}
function Garbage(x,y){
this.sprite = createSprite(x, y);
this.sprite.addAnimation("drop", garbage_drop);
this.sprite.setCollider("circle",0,0,32,32);
this.speed = random(1,2);
this.sprite.debug = true;
this.update = function() {
this.sprite.position.y += this.speed;
if(this.sprite.position.y > height){
this.sprite.position.y = 0;
}
if(this.sprite.overlapPoint(player.position.x, player.position.y)){
this.sprite.position.x = random(0,width);
this.sprite.position.y = -75;
score++;
}
}
}
function Fish(x,y) {
this.sprite = createSprite(x, y);
this.sprite.addAnimation("swim", fish_swim);
this.sprite.setCollider("rectangle",0,0,75,32);
this.speed = 0;
this.sprite.debug = true;
this.init = function() {
if (this.sprite.position.x < width/2) {
this.sprite.mirrorX(-1);
this.speed = random(1, 2);
} else {
this.speed = -random(1,2);
}
}
this.update = function() {
this.sprite.position.x += this.speed;
if(this.sprite.position.x > width){
this.sprite.position.x = 0;
}else if(this.sprite.position.x < -width){
this.sprite.position.x = width;
}
}
}
I actually found the answer to my question a while back but am going to post it here.
The initial problem was that the sprites would not collide but with a simple for loop nested within another for loop and adding a .sprite to each of the objects being checked, I was able to get all the elements to collide properly.
Here is the code I revised to make it work seamlessly using the P5.play.js library:
var bg;
var img;
var dead = false;
var deadFish = 0;
var player;
var player_stand_sprites;
var player_stand;
var fish_swim_sprites;
var fish_swim;
var fish = [];
var garbage_drop_sprites;
var garbage_drop;
var garbage = [];
var score = 0;
//////////////////////////////////////////
function preload() {
bg = loadImage("final-bg.png");
img = loadImage("fish.png");
player_stand_sprites = loadSpriteSheet("player2.png", 100, 100, 1);
player_stand = loadAnimation(player_stand_sprites);
fish_swim_sprites = loadSpriteSheet("fish.png", 75, 75, 1);
fish_swim = loadAnimation(fish_swim_sprites);
garbage_drop_sprites = loadSpriteSheet("metal.png", 41, 75, 1);
garbage_drop = loadAnimation(garbage_drop_sprites);
}
//////////////////////////////////////////
function setup() {
createCanvas(720, 360);
player = createSprite(100, 0);
player.addAnimation("stand", player_stand);
player.setCollider("circle", 0, 0, 32, 32);
player.depth = 10;
//player.debug = true;
//to make fish
for (var i = 0; i < 10; i++){
fish.push( new Fish(random(0,width), random(height/2, height)) );
for (var i = 0; i < fish.length; i++) {
fish[i].init();
}
}
//to make garbage
for (var a = 0; a < 5; a++){
garbage.push( new Garbage(random(0,width), random(width/2, width)));
}
}
function draw() {
scene_start();
}
//////////////////////////////////////////
function scene_start(){
push();
background("green");
fill("white");
textAlign(CENTER);
textSize(50);
textStyle(BOLD);
text("SPOT A FISH", width/2,height/3.5);
image(img, width/2.3, height/3);
textSize(15);
text("Rules: dont let the cans touch the fish. 5 fish die and you must start over", width/2, height/1.5);
textSize(30);
text("press up arrow key to start", width/2, height/1.2);
pop();
if (keyCode == UP_ARROW) {
scene_1();
}
}
function scene_1(){
background(bg);
score_card();
if(!dead){
player.position.x = mouseX;
player.position.y = mouseY;
for (var i = 0; i < fish.length; i++) {
fish[i].update();
}
for (var i = 0; i < garbage.length; i++) {
garbage[i].update();
}
for (var a = 0; a < garbage.length; a++) {
for (var b = 0; b < fish.length; b++) {
if(fish[b].sprite.collide(garbage[a].sprite)){
fish[b].sprite.position.x = random(-500, -100);
deadFish ++;
if(deadFish === 5){
dead = true;
}
}
}
}
drawSprites();
}else{
score_card();
textSize(30);
textStyle(BOLD);
textAlign(CENTER);
text("YOU DIED PLEASE TRY AGAIN",width/2,height/2);
text("press any button to start again",width/2,height/1.5);
if(keyIsPressed === true){
deadFish = 0;
dead = false;
}
}
}
function Garbage(x,y){
this.sprite = createSprite(x, y);
this.sprite.addAnimation("drop", garbage_drop);
this.sprite.setCollider("circle",0,0,32,32);
this.speed = random(1,2);
//this.sprite.debug = true;
this.update = function() {
this.sprite.position.y += this.speed;
if(this.sprite.position.y > height){
this.sprite.position.y = 0;
}
if(this.sprite.overlapPoint(player.position.x, player.position.y)){
this.sprite.position.x = random(0,width);
this.sprite.position.y = random(-200,-75);
score++;
}
if(score === 100){
this.speed = random(2,3);
score += 1000;
}else if(score === 1200){
this.speed = random(3,3.5);
score += 1000;
}
}
}
var score_card = function(){
fill("black");
rect(0,0,width,30);
textStyle(BOLD);
fill("white");
text("SCORE: "+score,10,20);
text("DEAD FISH: "+deadFish,width/1.2,20)
}
function Fish(x,y) {
this.sprite = createSprite(x, y);
this.sprite.addAnimation("swim", fish_swim);
this.sprite.setCollider("rectangle",0,0,75,32);
this.speed = 0;
this.sprite.debug = true;
this.init = function() {
if (this.sprite.position.x < width/2) {
this.sprite.mirrorX(-1);
this.speed = random(1, 2);
} else {
this.speed = -random(1,2);
}
}
this.update = function() {
this.sprite.position.x += this.speed;
if(this.sprite.position.x > width){
this.sprite.position.x = 0;
}else if(this.sprite.position.x < -width){
this.sprite.position.x = width;
}
}
}

Categories