I want enities to have analogical physical model as player has, and be able to randomly spawn from right side and jump to the left side of canvas through platforms where they eventually disappears by reaching the very left side.
I need clear explanation for further investigations on why entities simply standing at right and jumping in place without going left? could be that the velocity is too low for entities to be able to move left because of some factor affecting it? output full fixed code. maybe problem is in platform movement and wrong "vx" values used and thats why enities got stuck at right and only jumping there?: class Platform{constructor(x,y,w,h){this.x=x;this.y=y;this.w=w;this.h=h}collidesWith(obj){if(obj.y+obj.h<=this.y)return false;if(obj.y>=this.y+this.h)return false;if(obj.x+obj.w<=this.x)return false;if(obj.x>=this.x+this.w)return false;const objAbove=obj.y+obj.h-obj.vy<=this.y;const objBelow=obj.y-obj.vy>=this.y+this.h;const objLeft=obj.x+obj.w-obj.vx<=this.x;const objRight=obj.x-obj.vx>=this.x+this.w;if(obj.vy>0&&objAbove&&!objBelow){obj.y=this.y-obj.h;obj.vy=0;obj.jumping=false;return true}if(obj.vy<0&&!objAbove&&objBelow){obj.y=this.y+this.h;obj.vy=0;return true}if(obj.vx<0&&objRight){obj.x=this.x+this.w;obj.vx=0;return true}if(obj.vx>0&&objLeft){obj.x=this.x-obj.w;obj.vx=0;return true}return false}}class Player{constructor(x,y,w,h){this.x=x;this.y=y;this.w=w;this.h=h;this.vx=0;this.vy=0;this.jumping=false}move(keys){const friction=.9;const gravity=1;if(keys[87]&&!this.jumping){this.vy-=20;this.jumping=true}if(keys[68]){this.vx+=5}if(keys[65]){this.vx-=5}this.vx*=friction;this.vy+=gravity;this.x+=this.vx;this.y+=this.vy;if(this.x<0){this.x=0}if(this.y<0){this.y=0}if(this.x+this.w>canvas.width){this.x=canvas.width-this.w;this.vx=0}if(this.y+this.h>canvas.height){this.y=canvas.height-this.h;this.vy=0;this.jumping=false}}}class Projectile{constructor(x,y,vx,vy){this.x=x;this.y=y;this.vx=vx;this.vy=vy;this.radius=10;this.color=“red”}update(){this.x+=this.vx;this.y+=this.vy}draw(ctx){ctx.beginPath();ctx.arc(this.x,this.y,this.radius,0,2*Math.PI);ctx.fillStyle=this.color;ctx.fill()}}class Entity{constructor(){this.x=canvas.width;this.y=Math.random()*canvas.height;this.w=20;this.h=20;this.vx=-1-Math.random()3;this.vy=0;this.jumping=false;this.projectiles=[];this.color=“blue”}jump(){if(!this.jumping){this.vy-=10;this.jumping=true}}update(platforms){for(let i=0;i<platforms.length;i++){platforms[i].collidesWith(this)}const friction=.9;const gravity=1;this.vx=friction;this.vy+=gravity;this.x+=this.vx;this.y+=this.vy;if(Math.random()<.01){this.projectiles.push(new Projectile(this.x,this.y,-2-Math.random()*6,-2+Math.random()*8))}for(let i=0;i<this.projectiles.length;i++){this.projectiles[i].update();if(this.projectiles[i].x<0||this.projectiles[i].y<0||this.projectiles[i].x>canvas.width||this.projectiles[i].y>canvas.height){this.projectiles.splice(i,1);i}}if(Math.random()<.01){this.jump()}}draw(ctx){ctx.fillStyle=this.color;ctx.fillRect(this.x,this.y,this.w,this.h);for(let i=0;i<this.projectiles.length;i++){this.projectiles[i].draw(ctx)}}}class Game{constructor(canvas){this.canvas=canvas;this.ctx=canvas.getContext(“2d”);this.platforms=[];this.player=new Player(100,100,50,50);this.scrollSpeed=1;this.entities=[];this.entitySpawnRate=.1;this.entitySpawnTimer=1;this.entityIncreaseFactor=.1;this.keys={};this.platforms.push(new Platform(0,canvas.height-50,50,10));for(let i=0;i<10;i++){this.createRandomPlatform()}document.addEventListener(“keydown”,evt=>{this.keys[evt.keyCode]=true});document.addEventListener(“keyup”,evt=>{delete this.keys[evt.keyCode]});requestAnimationFrame(this.update.bind(this))}createRandomPlatform(){const x=this.canvas.width;const y=Math.random()*this.canvas.height;const w=200+Math.random()500;const h=10;this.platforms.push(new Platform(x,y,w,h))}update(){this.player.move(this.keys);for(let i=0;i<this.platforms.length;i++){this.platforms[i].collidesWith(this.player);this.platforms[i].x-=this.scrollSpeed}for(let i=0;i<this.entities.length;i++){if(this.entities[i]){this.entities[i].update(this.platforms);if(this.entities[i].x<0){this.entities.splice(i,1);i;for(let j=0;j<this.entityIncreaseFactor;j++){this.entities.push(new Entity)}}else{for(let j=0;j<this.entities[i].projectiles.length;j++){if(this.entities[i].projectiles[j].x>this.player.x&&this.entities[i].projectiles[j].x<this.player.x+this.player.w&&this.entities[i].projectiles[j].y>this.player.y&&this.entities[i].projectiles[j].y<this.player.y+this.player.h){this.player.vy-=20;this.player.jumping=true;this.entities[i].projectiles.splice(j,1);j}}this.entities[i].draw(this.ctx)}}}this.player.x-=this.scrollSpeed;if(this.platforms[this.platforms.length-1].x<this.canvas.width-200){this.createRandomPlatform()}this.entitySpawnTimer++;if(this.entitySpawnTimer>=60/this.entitySpawnRate){this.entitySpawnTimer=0;this.entities.push(new Entity);this.entitySpawnRate+=.001;this.entityIncreaseFactor=.001;this.entityIncreaseFactor=Math.min(this.entityIncreaseFactor,.001)}this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);for(let i=0;i<this.platforms.length;i++){let p=this.platforms[i];this.ctx.fillRect(p.x,p.y,p.w,p.h)}for(let i=0;i<this.entities.length;i++){this.entities[i].draw(this.ctx)}this.ctx.fillRect(this.player.x,this.player.y,this.player.w,this.player.h);requestAnimationFrame(this.update.bind(this))}}let canvas=document.createElement(“canvas”);canvas.width=window.innerWidth;canvas.height=window.innerHeight;document.body.appendChild(canvas);new Game(canvas);