I have the class Map with a property this.guns = [ ]. I deleted some parts of the code to make it easy to read.
class Maps {
constructor(canvas, sizeX, sizeY, sizeCase) {
this.guns = [];
}
} // end class
Inside this.weapon = [ ] I pushed some objects with its properties. Those objects were instantiated in the Map class.
/* eslint-disable no-console */
class Maps {
constructor(canvas, sizeX, sizeY, sizeCase) {
this.guns = [];
}
setGuns(quantity) {
// this.guns = [];
for (let index = 0; index < quantity; index++) {
const x = App.random(this.size.x);
const y = App.random(this.size.y);
let element;
if (this.mapGame[y][x] === 0) {
switch (index) {
case 0: {
element = new Gun(4, "watermelon", 15, y, x);
this.mapGame[element.y][element.x] = 2;
console.log(element);
this.guns.push(element);
break;
}
case 1: {
element = new Gun(5, "eggplant", 20, y, x);
this.mapGame[element.y][element.x] = 3;
console.log(element);
this.guns.push(element);
break;
}
default:
break;
}
} else {
index -= 1;
}
}
console.log(this.guns);
}
} // end class
I have an other class call Player with a method to move the players. When the player is over a weapon, take the weapon. To do this, I have done the checkWeapon method.
class Player {
constructor(imagePlayer, name, score, positionY, positionX) {
this.imagePlayer = imagePlayer;
this.name = name;
this.score = score;
this.x = positionX;
this.y = positionY;
this.movementAccumulator = 0;
this.limitMovement = 3;
this.weapon = {};
}
/**
* I deleted the not necessary methods, and then the rest of cases on the switch
*/
movement(direction, map, currentPlayer) {
const collision = this.rockCollision(direction, map);
switch (direction) {
case up:
if (this.y > 0) {
if (!collision) {
map.mapGame[this.y][this.x] = 0; // draw grass
this.y -= 1;
this.whoPlayerIsMoving(map, currentPlayer);
this.counterMovement();
this.checkWeapon(map);
}
}
break;
}
checkWeapon(map) {
this.weapon = map.getGun(this.y, this.x);
}
}
Player send throung the checkWeapon method the coordinates x and y, to an other method hosted on the class Map, the getGuns method.
/* eslint-disable no-console */
class Maps {
constructor(canvas, sizeX, sizeY, sizeCase) {
this.guns = [];
}
/**
* The console log are to render(or print) on the console and look if everything goes well.
* The following method is a test, is bad done and it have to be refatoriced
*/
getGun(y, x) {
console.log(`Re Y:${y}` + ` Re X: ${x}`);
console.log(`${this.guns[0].y} ${this.guns[0].x}`);
if (this.guns[0].y == y && this.guns[0].x == x) {
console.log("soy un arma");
}
return gunTaked;
}
} // end class
My main problem is, how to access to the properties of the Gun object. I did the method above, but I got stuck. I have reading about destructuring, but I am not sure if, should I apply it here. Thanks
I have this
class Maps {
constructor(canvas, sizeX, sizeY, sizeCase) {
this.canvas = document.getElementById("canvas");
this.canvas.width = sizeX * sizeCase;
this.canvas.height = sizeY * sizeCase;
this.size = { x: sizeX, y: sizeY, case: sizeCase };
this.ctx = this.canvas.getContext("2d");
this.tileMap = new Image();
this.tileMap.src = "img/tileMap.png";
this.mapGame = [];
this.FPS = 50;
this.weapons = [
{ idWeapon: 2, name: "watermelon", power: 15 },
{ idWeapon: 3, name: "eggplant", power: 20 },
{ idWeapon: 4, name: "pumkin", power: 25 },
{ idWeapon: 5, name: "broccoli", power: 30 }
];
}
}
The object array isn´t inside the code, I pasted like and example to add more information
Don´t worry by the sintaxis, I am breaking my class in small pieces to don´t paste all the code.
What I want to do, is: 1. find de the objecto I need, It is alredy done, checking the idWeapon
My main problem it is, how to extract the object and hosted in a variable and later if I find an other weapon, let the current weapon and take the new one
Related
I'm trying to create a very basic physics simulation in p5.js and I am using a class to create multiple instances of the shapes (which are currently all circles), I have a function that checks if the user clicks inside the area of a circle and if so allows them to drag it around but I ran into a problem. I need to have the program work out which object it is hovering but I'm not sure how I would do so, below I have the function working for only the first object (obj1). can I do something like {classname}.posX instead?
function whilePressed()
{
if (Math.pow(mouseX-obj1.posX,2)+(Math.pow(mouseY-obj1.posY,2))<=(Math.pow(obj1.size/2,2)) | grabbed == true)
{
grabbed = true;
if (firstGrab == true)
{
difX = (obj1.posX-mouseX);
difY = (obj1.posY-mouseY);
firstGrab = false;
}
obj1.posX = mouseX+difX;
obj1.posY = mouseY+difY;
}
}
below is the class (the draw function has a switch statement in it because I used to have a square as well but decided to get a circle working before implementing a square)
class primitive
{
constructor()
{
this.size = 50;
this.posX = canvasSize/2;
this.posY = canvasSize/2;
this.velX = 0;
this.velY = 0;
this.terminalVel = 15;
}
pos(x,y)
{
this.posX = x;
this.posY = y;
}
draw(shape = 'circle')
{
stroke(168,198,159);
fill(204,226,163);
switch (shape)
{
case 'circle':
circle(this.posX,this.posY,this.size);
break;
}
}
gravity()
{
if (this.velY < this.terminalVel)
{
this.velY = (this.velY+1);
}
else
{
this.velY = 20;
}
this.posY = this.posY+this.velY;
if (this.posY > groundLevel-(this.size/2))
{
this.posY = groundLevel-(this.size/2);
this.velY = 0;
}
}
}
You can create a static method on the primitive class like so:
First, create an array which has all the instances of the class in it.
This is the code:
Remember: I added the parameter name to the constructor. That means when creating an instance do it like so:
var foo = new primitive("foo");
var PRIMITIVES = [];
// ...
constructor(name)
{
this.name = name;
this.size = 50;
this.posX = canvasSize/2;
this.posY = canvasSize/2;
this.velX = 0;
this.velY = 0;
this.terminalVel = 15;
PRIMITIVES.push(name);
}
Now, using the same mouse find principle, you can create a static method that finds and return the right instance.
static findInstance(mouseX, mouseY) {
for (var i = 0; i < PRIMITIVES.length; i++)
{
obj = window[PRIMITIVES[i]];
if (Math.pow(mouseX-obj.posX,2)+(Math.pow(mouseY-obj.posY,2))<=(Math.pow(obj.size/2,2)))
{
return obj;
}
}
}
Then, you can call primitive.findInstance(mouseX, mouseY), and it will return the right instance. If this doesn't work, please comment. I hope this helped you.
Create an array of objects:
let objects = []
objects.push(obj1);
objects.push(obj2);
Implement an algorithm in the mousePressed() callback that detects the clicked object:
let draggedObject;
let dragOffsetX;
let dragOffsetY;
function mousePressed() {
draggedObject = null;
for (let i=0; i < objects.lenght; i++) {
obj = objects[i];
if (Math.pow(mouseX-obj.posX,2) + Math.pow(mouseY-obj.posY,2) <= Math.pow(obj.size/2,2)) {
draggedObject = obj;
dragOffsetX = draggedObject.posX - mouseX;
dragOffsetY = draggedObject.posY - mouseY;
break;
}
}
}
Change the position of the object in the mouseDragged() callback:
function mouseDragged() {
if (dragged_object) {
draggedObject.posX = mouseX + dragOffsetX;
draggedObject.posY = mouseY + dragOffsetY;
}
}
Consider this code for this scenario of creating an Array with value of "sideLength" and for "sides" times within this ES class, but I'm keep getting an empty array!! here is codepen link
class ShapeNew {
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
tryArray() {
let sides_array = [];
for (let i = 0; i < this.sides; i++) {
sides_array = sides_array.push(this.sideLength);
}
return sides_array;
}
newPerimeter() {
let peri = this.tryArray();
console.log(peri.reduce((sum, accum) => sum + accum));
}
}
let new_square = new ShapeNew("square", 4, 5);
new_square.newPerimeter();
All I'm trying to do is convert 4 into [5,5,5,5], how do I do that?
Thanks in advance for looking into this, I appreciate it :)
You want this
sides_array.push(this.sideLength);
Not this
sides_array = sides_array.push(this.sideLength);
Because Array.push() does not return anything.
You are assigning to the variable sides_array the returned value of pushing a new element which is the new length, instead just push the element each time
class ShapeNew {
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
tryArray() {
let sides_array = [];
for (let i = 0; i < this.sides; i++) {
sides_array.push(this.sideLength);
}
return sides_array;
}
newPerimeter() {
let peri = this.tryArray();
console.log(peri.reduce((sum, accum) => sum + accum));
}
}
let new_square = new ShapeNew("square", 4, 5);
new_square.newPerimeter();
But I was wondering, if all what you wanted to do is just calculating the perimeter, then why don't you just multiply the sides with side length?!
class ShapeNew {
constructor(name, sides, sideLength) {
this.name = name;
this.sides = sides;
this.sideLength = sideLength;
}
perimeter() {
return this.sideLength * this.sides;
}
}
let new_square = new ShapeNew("square", 4, 5);
console.log(new_square.perimeter());
This is the code. It is an assignment from a random stranger that asked me to solve it for him since he saw a post of mine on IG.
// Player class
class Player {
constructor(name, strength = 2, weapons) {
this.name = name;
this.health = 10;
this.strength = strength;
this.weapons = [...weapons];
}
applyDamage(int) {
this.health -= int;
}
isAlive() {
return this.health > 0;
}
attackWith() {
let randomNum = Math.floor(Math.random() * 8);
return this.weapons[randomNum];
}
}
// Weapon class
class Weapon {
constructor(name) {
this.name = name;
this.damage = Math.ceil(Math.random() * 5);
}
attack(player, enemy) {
if (player.isAlive() && player.isAlive()) {
let dmg = player.strength * this.damage;
enemy.applyDamage(dmg);
if (!enemy.isAlive()) {
return;
} else {
enemy.attack(player);
}
}
}
}
// Enemy class
class Enemy {
constructor(name = "Enemy", health = 5, strength = 2) {
this.name = name;
this.health = health;
this.strength = strength;
}
applyDamage(int) {
this.health -= int;
}
isAlive() {
return this.health > 0;
}
attack(player) {
player.applyDamage(this.strength);
}
}
// BattleSimulation class
class BattleSimulation {
constructor() {
this.players = [];
this.enemies = [];
}
createEnemies() {
for (let i = 0; i < 20; i += 1) {
this.enemies[i] = new Enemy();
}
}
createPlayers() {
// Weapons
let pencil = new Weapon("Pencil");
let book = new Weapon("Book");
let screwdriver = new Weapon("Screwdriver");
let theOneRing = new Weapon("Sauron's Ring");
let mustardGass = new Weapon("Mustard Gass");
let bigBoy = new Weapon("A Nuke");
let love = new Weapon("Power of Love");
let theForce = new Weapon("The Force");
let weaponsCache = [
pencil,
book,
screwdriver,
theOneRing,
mustardGass,
bigBoy,
love,
theForce
];
// Players
let luke = new Player("Luke", 5, weaponsCache);
let baldingCoder = new Player("DraciVik", 10, weaponsCache);
let trump = new Player("Trump", 1, weaponsCache);
let kikiMakarena = new Player("Kiki Makarena", 5, weaponsCache);
let johnWick = new Player("John Wick", 2, weaponsCache);
this.players = [luke, baldingCoder, trump, kikiMakarena, johnWick];
}
run() {
console.log("Simulating Battle");
this.createEnemies();
this.createPlayers();
while (this.players.length !== 0 || this.enemies.length !== 0) {
let randomPlayerIndex = Math.floor(Math.random() * this.players.length);
let randomPlayer = this.players[randomPlayerIndex];
let randomEnemyIndex = Math.floor(Math.random() * this.enemies.length);
let randomEnemy = this.enemies[randomEnemyIndex];
let weapon = randomPlayer.attackWith();
weapon.attack(randomPlayer, randomEnemy);
if (!randomPlayer.isAlive()) {
this.players.splice(randomPlayerIndex, 1);
}
if (!randomEnemy.isAlive()) {
this.enemies.splice(randomEnemyIndex, 1);
}
}
console.log(this.players);
if (this.players.length > 0) {
return "Congratulations, you have defeated Scarlet Byle";
}
return "Sorry, Scarlet Byle has defeated you and conquered the free world";
}
}
let battle = new BattleSimulation();
battle.run();
Anyone can see where the error is? I get a return error 'enemy.applyDamage(dmg)' is undefined.
What is this error that I need more writing than just code? Should I spam some letters?
The bug here is actually just in the condition of your while loop:
while(this.players.length !== 0 || this.enemies.length !== 0)
Your condition says to loop while there is at least one player OR there is at least one enemy. So as long as ONE of the arrays is not empty, it will continue to loop.
But when you first create this.players and this.enemies, they start at different sizes. Then when you remove one entry from each array, eventually one of the arrays is empty before the other.
Then your code has var randomEnemyIndex = Math.floor(Math.random() * this.enemies.length); which will evaluate to 0 when the array is empty. And when you do this.enemies[0], it returns undefined. When undefined is passed into weapon.attack like weapon.attack(randomPlayer, undefined), then it tries to call applyDamage(dmg) on the undefined, which throws your exception.
If you modify your code to have the following console logs, you will see the issue:
while (this.players.length !== 0 || this.enemies.length !== 0) {
console.log("PLAYERS: " + this.players.length.toString());
console.log("ENEMIES: " + this.enemies.length.toString());
...
You will see:
'Simulating Battle'
'PLAYERS: 5'
'ENEMIES: 20'
'PLAYERS: 5'
'ENEMIES: 20'
'PLAYERS: 5'
[...]
'PLAYERS: 4'
'ENEMIES: 1'
'PLAYERS: 4'
'ENEMIES: 0'
error: Uncaught TypeError: Cannot read property 'applyDamage' of undefined
So to fix this, you'll need to either change your conditional to this:
while (this.players.length !== 0 && this.enemies.length !== 0) {
Or you'll need to start both arrays off at the same size.
I have multiple objects like this(16)
function Baboo(x,y,size,speed,target,sps,life){
MobRoot.call(this,x,y,size,speed,target,sps,life);
this.spsCoord = [500*0,500*3,500,500];
this.coolDown = 60;
this.atack = 0;}
Baboo.prototype = Object.create(MobRoot.prototype);
Baboo.prototype.throw = function()
{
projectiles.push(new Arrow(this.x,this.y,10,10,this.angle,150,this.target));
}
Baboo.prototype.update = function(){
if(this.life>0)
{
this.sendBack();
this.draw();
this.checkClick();
this.angle = CalculateSlope(this,this.target);
this.directionUpdate();
this.updateBuffs();
this.x += this.direction.x;
this.y += this.direction.y;
}}
/*etc aditional methods*/
that inherit all from this object
function MobRoot(x,y,size,speed,target,sps,life)
{
this.size = size*WindowScale;
this.x = x;
this.y = y;
this.angle = 0;
this.speed=speed;
this.colided=false;
this.maxlife = life;
this.life = life;
this.buffArray = [];
this.sps = sps;
this.target = target;
this.direction =
{
x:0,
y:0
}
//x,y,w,h
//ex sprite[0][0] = 0,0,500,500;
this.spsCoord = [];
this.isBoss = false;
}
MobRoot.prototype.directionUpdate = function()
{
this.direction.x = this.speed*Math.cos(this.angle)*-1;
this.direction.y = this.speed*Math.sin(this.angle)*-1;
}
/*aditional methods for mobRoot*/
and I want to generate different mobs from an array. At the moment I'm assigning a number for each type (ex: 1-Baboo 2-Spider 3-Whatever) and storing these numbers in arrays, and when I'm generating them i use a switch for each mobIndex from the array like this
switch(wave[i])
{
case 1:
mobs.push(new Baboo(arg1,arg2,...));
break;
case 2:
mobs.push(new Spider(arg1,arg2,...));
break;
/*...*/
case 999:
mobs.push(new Whatever(arg1,arg2,...));
break;
}
Is there a more elegant way of solving this kind of problem?
You can put all the constructors into an array:
var constructors = [Baboo, Spider, Whatever, ...];
if (wave[i] < constructors.length) {
mobs.push(new constructors[wave[i]](arg1, arg2, arg3, ...));
}
I am writing three classes and want to display something, the last class uses an init function to assign values to its properties, see below. But it doesn't work as I expected.
class Circle1 {
constructor(options) {
}
render() {
document.getElementById('result').innerHTML = 'Hello, ';
}
}
class Circle2 {
constructor(options) {
}
render() {
document.getElementById('result').innerHTML += 'My';
}
}
class Circle {
constuctor(options) {
this.x = options.x;
this.y = options.y;
this.length = options.length;
this.bodies = [];
this.init(options);
}
init(options) {
this.first = new Circle1(options);
for (let i = 0; i < this.length; i++) {
this.bodies.push(new Circle2(options));
}
}
render() {
/**
this.first.render();
this.bodies.forEach(function(body) {
body.render();
});
**/
document.getElementById('result').innerHTML += 'World';
}
}
var c = new Circle({
x: 20,
y: 20,
length: 6
});
c.render();
This code will display "World" to the screen.
However, if I uncomment the commented code, and try to display "Hello, My (times length) World" to the screen but it doesn't show anything.
I am very confused with the init function in the class. I thought I can assign values to the properties in that function but the result tells me it doesn't work. What is wrong with my code?
Here is the jsfiddle link.
You have an error in the name of the constructor (constructor is not called):
class Circle {
constuctor(options) {
==>
class Circle {
constructor(options) {
[ https://jsfiddle.net/5sv5hwLb/ ]