Home > Software engineering >  I want to push a object into an array
I want to push a object into an array

Time:03-29

In js/script.js the function initEntity im trying to use the function to make a new object from the class Entity in js/classes.js but im not sure how I would do that and what I have right now doesnt work. I also want to be able to access the object created from the function. If I forgot any information that you would need then let me know because im not sure if I got everything but I think I did.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="js/classes.js" defer></script>
    <script src="js/script.js" defer></script>
    <style>
      #cvs {
        border: solid 1px black;
      }
    </style>
  </head>
  <body>
    <canvas width="0" height="0" id="cvs"></canvas>
  </body>
</html>

js/classes.js

class Entity {
  constructor(x, y, w, h, velX, velY, grav, img) {
    this.x = this.x || 0;
    this.y = this.y || 0;
    this.w = this.w || 0;
    this.h = this.h || 0;
    this.velX = this.velX || 0;
    this.velY = this.velY || 0;
    this.grav = this.grav || 0;
    this.img = this.img || null;
  }
}

class Blocks {
  constructor(x, y, w, h, img) {
    this.x = this.x || 0;
    this.y = this.y || 0;
    this.w = this.w || 0;
    this.h = this.h || 0;
    this.img = this.img || null;
  }
}
js/script.js

let cvs, ctx;
let entities = {};

function initEntity(name, x, y , w, h, velX, velY, grav, img) {
  name = new Entity(x,y,w,h,velX,velY,grav,img);
  entities.push(name);
}

function renderEntities() {
  initEntity(player, 300, 300, 5, 5, null, null, 0.95, null);//figure out how to fix this
  if(entities.player.img != null || entities.player.img != undefined) {
    ctx.drawImage(entities.player.img, entities.player.x, entities.player.y, entities.player.w, entities.player.h);
  } else {
    ctx.fillStyle = '#FF0000';
    ctx.fillRect(entities.player.x, entities.player.y, entities.player.w, entities.player.h);
  }
}

function render() {
  ctx.clearRect(0,0,cvs.width,cvs.height);
  renderEntities();
  requestAnimationFrame(render);
};

function mechanics() {
  
}

window.addEventListener('DOMContentLoaded', function() {
  cvs = document.getElementById('cvs');
  ctx = cvs.getContext('2d');
  cvs.height = 600;
  cvs.width = 600;
  
  render();
});

CodePudding user response:

You have the entities variable defined as an object ( = { }), therefore you cannot use the 'push' method. It is a method for arrays, so the solution would be:

let entities = [];

CodePudding user response:

Here a working skeleton to get you up and running with quite a lot of the errors you made removed. Let me explain a few of them.

  • As mentioned in my comment entities has to be an array as push() is not defined on an object, so use entities = [] instead
  • this.x and x are two totally unrelated variables. You need to use the value of x and assign it to this.x otherwise this.x will always be initialized to 0 as this.x = this.x || 0 evaluates to 0 because this.x is undefined.
  • You cannot access your array entities like an object. You have to loop over the array to be able to access the the objects within it. See the forEach() in your function renderEntities()
  • Your animation is not working because you call requestAnimationFrame() with the render function which renders the same values over and over again. You need to change some values in order to see some changes on the screen. I've implemented your method mechanics() now which will change some values, so the rectangles get wider until they reach the end of the canvas. When you are done changing values and drawing them to the screen you will then have to call requestAnimationFrame() again. This signals the browser you are done animating this frame and it should re-render the canvas so the changes you have made become visible. Additionally this will call your method mechanics() again so you can animate the next frame. Last but not least: Be specific, so call window.requestAnimationFrame() not just requestAnimationFrame(). You should probably familiarize yourself with how requestAnimationFrame() works

You will have to click on Full page when running the snippet to properly see what's going on

class Entity {
  constructor(x, y, w, h, velX, velY, grav, img) {
    // don't use this here this.x is undefined,
    // so this.x = this.x || 0 will always set to 0
    // you have to use the parameters that you provide!
    // Notice: this.x is not the same as x. These are two totally different variables
    this.x = x || 0;
    this.y = y || 0;
    this.w = w || 0;
    this.h = h || 0;
    this.velX = velX || 0;
    this.velY = velY || 0;
    this.grav = grav || 0;
    this.img = img || null;
  }
}

class Blocks {
  constructor(x, y, w, h, img) {
    this.x = x || 0;
    this.y = y || 0;
    this.w = w || 0;
    this.h = h || 0;
    this.img = img || null;
  }
}

let cvs, ctx;
// entities has to be an array
let entities = [];

// name is not a parameter that you should pass to this function as it is not required to create an instance of entity.
// create a local variable instead and push that onto the array
function initEntity(x, y, w, h, velX, velY, grav, img) {
  const newEntity = new Entity(x, y, w, h, velX, velY, grav, img);
  entities.push(newEntity);
}

function renderEntities() {
  // create 3 entities with different positions
  initEntity(300, 300, 5, 5, null, null, 0.95, null); //figure out how to fix this
  initEntity(200, 200, 5, 5, null, null, 0.95, null);
  initEntity(100, 100, 5, 5, null, null, 0.95, null);

  // now entities is an array so you can't access it like an object, you will have to loop over it to draw each and every entity to the screen
  entities.forEach((entity) => {
    // this logs the entity to the console so you can see what's going on
    console.log(entity);
    if (entity.img != null || entity.img != undefined) {
      ctx.drawImage(entity.img, entity.x, entity.y, entity.w, entity.h);
    } else {
      ctx.fillStyle = "#FF0000";
      ctx.fillRect(entity.x, entity.y, entity.w, entity.h);
    }
  });
}

function render() {
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  renderEntities();
  // explicitly use the window object here and you need to pass a function that actually does something
  // not just re-renders the same objects again and again
  window.requestAnimationFrame(mechanics);
}

function mechanics() {
  // this is where the animation happens
  // loop over all entities
  entities.forEach((entity) => {
    // for each entity check whether it's x value is smaller than the width of the canvas
    // if not increase the width by one and draw it to the screen
    if (entity.x < cvs.width) {
      entity.x  ;
      if (entity.img != null || entity.img != undefined) {
        ctx.drawImage(entity.img, entity.x, entity.y, entity.w, entity.h);
      } else {
        ctx.fillStyle = "#FF0000";
        ctx.fillRect(entity.x, entity.y, entity.w, entity.h);
      }
    }
  });
  // tell the browser that we have finished animating this frame and it should re-render to display our changes
  // and call mechanics again to animate the next frame
  window.requestAnimationFrame(mechanics);
}

window.addEventListener("DOMContentLoaded", function () {
  cvs = document.getElementById("cvs");
  ctx = cvs.getContext("2d");
  cvs.height = 600;
  cvs.width = 600;

  render();
});
<canvas width="0" height="0" id="cvs"></canvas>

Please note: this is not a perfect implementation but just to give you an idea on how it works conceptually.

  • Related