I'm trying to create a board game and would like to instantiate the class Human based on a number of times provided by the user. Obviously I'm trying to assign a different ID per object and the following loop doesn't work in order to instantiate the number of players:
var question = prompt('how many players');
var numOfPlayers = parseInt(question);
class Human {
constructor (id) {
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x: Math.floor(Math.random() * 8),
y: Math.floor(Math.random() * 8)
}
}
moveTo(x, y){
this.location.x += x;
this.location.y += y;
}
}
var i;
for (i = 0; i < numOfPlayers; i++) {
const player = new Human(id = i);
}
Firstly, I hope I have understood what you are trying to achieve here. The scope of the "const player" is limited within the loop. If you want to be able to access it outside the loop you need to declare a list/array likewise.
Code may go like this for the same:
var players = [];
for(let i = 0; i < numOfPlayers; i++) {
players.push(new Human(i));
}
Note: If you don't want to use variable 'i' outside the loop you can declare it inside 'for' using 'let' keyword as can be seen in the code above.
class Human {
constructor (id){
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x:Math.floor(Math.random()*8),
y:Math.floor(Math.random()*8)
}
console.log(`Human created with id of ${id}`); //Remove this just to show you that your class is being instantiated for each 'player'
}
moveTo(x,y){
this.location.x += x;
this.location.y += y;
}
}
let numOfPlayers = prompt('How many players?');
const _init = () => {
if(parseInt(numOfPlayers) > 0) {
for (let i = 0; i < numOfPlayers; i++) {
new Human(i)
}
}
}
_init();
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());
I'm going through Codecademy's lesson on building a Blackjack game with Javascript.
I'm having trouble coming up with code to put in the for-loop. I'm supposed to write a "score" method in the Hand constructor. It should loop over all of the cards in the Hand, summing up the result of the "getValue" call to each and return that sum.
Can someone help me out please? Thank You.
Here's my attempt, the relevant code is inside the for-loop at the bottom:
// Card Constructor
function Card(s, n) {
var suit = s;
var number = n;
this.getSuit = function() {
return suit;
};
this.getNumber = function() {
return number;
};
this.getValue = function() {
if (number >= 10) {
return 10;
} else if (number === 1) {
return 11;
} else {
return number;
}
};
};
//deal function
var deal = function() {
var randNum = Math.floor(Math.random() * 13) + 1;
var randSuit = Math.floor(Math.random() * 4) + 1;
console.log(randNum, randSuit);
return new Card(randSuit, randNum);
};
function Hand() {
var handArray = [];
handArray[0] = deal();
handArray[1] = deal();
this.getHand = function() {
return handArray;
};
this.score = function() {
var sum;
for (var i = 0; i < handArray; i++) {
sum += handArray[i].getValue;
return sum;
}
};
};
Well something like this should work :
this.score = function() {
return handArray.reduce( function( memo, val){
return memo + val.getValue();
});
};
I think you need to return the score, outside of the loop, like so:
this.score = function() {
var sum;
for (var i = 0; i < handArray; i++) {
sum += handArray[i].getValue();
}
return sum;
};
This fixed it. Thanks for your help!
this.score = function(){
var sum =0;
for(var i =0; i<handArray.length; i++){
sum += handArray[i].getValue();
};
return sum;
};
I have following issue.
I have array of objects, and when I want to get one of the items and update data, it updates last data.
for example:
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
and the MyClass1
(function () {
var score = 0;
function MyClass1(id){
this.id = id;
this.x = 100;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
score = s;
}
window.MyClass1 = MyClass1;
}());
and function which returns one of these classes
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
Finally I'm calling function and want to update Score
getMyClassesById(1).updateScore (122);
it's updates last index item Score, and calls last item "updateScore" function... why?
but when i'm changing some other property its changes correctly for example "x". I can't understand is here something not right with prototypes?
Your variable score is not defined as a member of MyClass - it is only defined in the scope of your closure. Your code will work, but there will only be 1 "score" for all instances of MyClass.
If score is supposed to be part of MyClass then move it
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0
//some code. not important
}
And update the method:
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
(function () {
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
window.MyClass1 = MyClass1;
}());
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
getMyClassesById(1).updateScore (122);
console.log(arr);
here is my code :
var BoxUtility = function() {
var boxList = Array.prototype.pop.apply(arguments);
};
Object.defineProperties(BoxUtility, {
totalArea: {
value: function(){
var x = 0;
for(var i = 0, len = boxList.length; i <= len - 1; i++){
x = x + boxList[i].area;
};
return x;
}
}
});
I'm trying to achieve this syntax for my Code :
var boxArray = [box01, box02, box03];
box are objects, box01.area => boxes have area property
var newElement = new BoxUtility(boxArray);
alert(newElement.totalArea);
I WANT TO SEE THE RESULT AS I EXPECT but I think boxList is in another scope
How can I reach it in defineProperties
You have to assign the value to a property of this in your constructor.
var BoxUtility = function() {
// this.boxList
this.boxList = Array.prototype.pop.apply(arguments);
};
// instance methods go on the prototype of the constructor
Object.defineProperties(BoxUtility.prototype, {
totalArea: {
// use get, instead of value, to execute this function when
// we access the property.
get: function(){
var x = 0;
// this.boxList
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});
var boxUtil = new BoxUtility([{area:123}, {area:456}]);
console.log(boxUtil.totalArea); // 579
Variable scope is always at the function level. So you declared a local variable that is only usable inside your constructor function. But every time you call the constructor function you get a new object (this). You add properties to this in order to have those properties accessible in your instance methods on the prototype.
this works
var BoxUtility = function() {
this.boxList = Array.prototype.pop.apply(arguments);
Object.defineProperties(this, {
totalArea: {
get: function(){
var x = 0;
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});};
var y = new BoxUtility(boxArray);
alert(y.totalArea)
This is simple way to pass array as argument in constructer and declare function prototype for public access.
function BoxUtility(boxArray) {
this.boxArray = boxArray;
this.len = boxArray.length;
}
Color.prototype.getAverage = function () {
var sum = 0;
for(let i = 0;i<this.len;i++){
sum+=this.boxArray[i];
}
return parseInt(sum);
};
var red = new BoxUtility(boxArray);
alert(red.getAverage());