objects in an array alerted randomly - javascript

I have built this code using javascript that makes a few objects called monster. I then put those monsters in an array and finally am trying to call one of thous monsters to the console randomly. Unfortunately it displays in my console log as undefined. Any advice on how to get a random monster in the console log every time I refresh the page?
function Monster(type, level, mAttack, mAgility, mHP) {
this.type = type;
this.level = level;
this.mAttack = mAttack;
this.mAgility = mAgility;
this.mHP = mHP;
}
Monster.prototype.logInfo = function() {
console.log("I am a : ", this.type);
console.log("I am level : ", this.level);
console.log("I have the attack of : ", this.mAttack);
console.log("I have the agility : ", this.mAgility);
console.log("I have the health : ", this.mHP);
}
var troll = new Monster("troll", 1, 10, 10, 10);
var skeleton = new Monster("skeleton", 1, 10, 10, 10);
var slime = new Monster("slime", 1, 10, 10);
var boar = new Monster("boat", 1, 10, 10);
var monsterList = new Array();
monsterList[0] = troll;
monsterList[1] = skeleton;
monsterList[3] = slime;
monsterList[4] = boar;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);

You create a function but never call it. Therefor monsterSummoner is never set.
// THIS IS NEVER CALLED
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
console.log(monsterSummoner);
Try this instead. Notice that now that the function is called the value is set.
var monsterSummoner;
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
}
summonRandomMonster();
console.log(monsterSummoner);

You're close... Change your last four lines as follows -
var monsterList = [troll,skeleton,slime,boar];
var summonRandomMonster = function (){
monsterSummoner = monsterList[Math.floor(Math.random() * monsterList.length)];
console.log(monsterSummoner);
}
for (var i = 0; i < 100; i++) {
summonRandomMonster();
}

There are atleast two problems in this code. The variable "monsterSummoner" is not defined, and the function "summonRandomMonster" is not called.

Related

How to make this function do this in an interval

I'm trying to get the first function, to run repeatedly. Like it does in the second function. Where should I take a look?
(function printLetterByLetter() {
var i = 0;
var destination = "comment";
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
var typewriter = function () {
document.getElementById(destination).innerHTML += message.charAt(i);
i++;
if (i > message.length) {
clearInterval(typespeed);
}
}
var speed = 60;
var typespeed = setInterval(typewriter, speed)
}());
(function printLetterByLetter() {
var destination = "comment";
var frequency = 1000;
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var RandomCommentTimer = setInterval(function () {
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
}, frequency)
}());
So what i'm trying to do is to make one function/module that types out a random comment at a set speed(first function). And after a set time the comment will disappear and a new comment will be typed out(second function). And like the second function this will go on.
So far I haven't made it work myself so I thought: let's see if anyone can help me on stackoverflow.
If anyone can give a tip on where to take a look, that is also most welcome.
You could set and alter the function parameters outside of the function then access them inside. Caveat is that you can't put var in front when setting them. Not putting var in front makes it accessible outside of the current scope.
destination = "comment";
frequency = 6000;
(function printLetterByLetter() {
//now you have access to destination and frequency as they are defined before the function is called
var RandomComment = [
"Did you choose that outfit?"
, "I like trains."];
var RandomCommentTimer = setInterval(function () {
var message = RandomComment[Math.floor(Math.random() * RandomComment.length)];
document.getElementById(destination).innerHTML = message;
}, frequency)
}());

HTML canvas measureText().width is too big

I try to find out the width of a text in a html canvas.
I'm using the measureText method but it gives me a value the is more than double as expected. I generate the Text by using the toSting method. If I just hard code the return from toSting into measureText it works fine...
console.log("--->width "+this.ctx.measureText("-100").width);
returns 22
console.log(labels[i]);
returns "-100"
console.log("->width "+this.ctx.measureText(labels[i]).width);
returns 48
Any ideas why?
thanks for help!
Here is the whole code: https://jsfiddle.net/falkinator/Lze1rnm5/4/
function createGraph(){
this.canvas = document.getElementById("graph");
this.ctx = this.canvas.getContext("2d");
this.options={};
this.datasets=[];
this.options.fontSize=11;
this.ctx.font=this.options.fontSize+"px Arial";
this.ctx.textAlign="left";
this.ctx.textBaseline="middle";
this.datasetLength=500;
this.dataset=function(options){
/*this.strokeColor=options.strokeColor;
this.signalName=options.signalName;
this.signalMin=options.signalMin;
this.signalMax=options.signalMax;
this.signalUnit=options.signalUnit;*/
this.data=[];
this.min;
this.max;
};
this.buildYLabels = function(scaleMin, scaleMax){
var labels = [];
var maxLabelWidth=0;
console.log("--->width "+this.ctx.measureText("-100").width);
for(i=10;i>=0;i--){
labels.push((scaleMin+((scaleMax-scaleMin)/10)*i).toString());
console.log((scaleMin+((scaleMax-scaleMin)/10)*i).toString());
console.log("->width "+this.ctx.measureText(labels[i]).width);
if(maxLabelWidth<this.ctx.measureText(labels[i]).width){
maxLabelWidth=this.ctx.measureText(labels[i]).width;
}
}
return {labels: labels,
maxLabelWidth: maxLabelWidth};
};
this.buildXLabels = function(x){
};
this.draw = function (){
var _this=this;
each(this.datasets,function(dataset, index){
//plot data
if(index>0)return;
//draw scale
var canvasHeight = _this.canvas.height;
console.log("canvas height="+canvasHeight);
var yLabels = _this.buildYLabels(-100, 500);
var currX = _this.options.fontSize/2;
var scaleHeight = canvasHeight-_this.options.fontSize*1.5;
var maxLabelWidth=yLabels.maxLabelWidth;
console.log(yLabels.maxLabelWidth);
each(yLabels.labels,function(label, index){
_this.ctx.fillText(label,0,currX);
console.log(label);
currX+=(scaleHeight/10);
});
_this.ctx.beginPath();
_this.ctx.moveTo(maxLabelWidth,0);
_this.ctx.lineTo(maxLabelWidth,canvasHeight);
_this.ctx.stroke();
});
};
this.addSignal = function(){
var dataset = new this.dataset({});
this.datasets.push(dataset);
};
this.pushData = function(data){
var _this=this;
if(data.length!=this.datasets.length){
console.error("the number of pushed data is diffrent to the number of datasets!");
return;
}
each(data,function(data, index){
_this.datasets[index].data.push(data);
if(_this.datasets[index].data.length>_this.datasetLength){
_this.datasets[index].data.shift();
}
});
};
this.calculateScaling = function(dataset){
var range = dataset.max - dataset.min;
var decStep = Math.pow(10,Math.floor(Math.log10(range)));
var scaleMin = roundTo(dataset.min/*+(decStep*10)/2*/, decStep);
var scaleMax = roundTo(dataset.max/*+(decStep*10)/2*/, decStep);
var scaleStep = (scaleMax - scaleMin)/10;
};
var minx=-34, maxx=424;
var range = maxx - minx;
var decStep = Math.pow(10, Math.floor(Math.log10(range)));
var scaleMin = roundTo(minx-(decStep/2), decStep);
var scaleMax = roundTo(maxx+(decStep/2), decStep);
var scaleStep = (scaleMax - scaleMin)/10;
console.log(this.buildYLabels(scaleMin,scaleMax));
console.log("range="+range);
console.log("log="+Math.floor(Math.log10(range)));
console.log("scaleStep="+scaleStep);
console.log("decStep="+decStep);
console.log("scaleMin="+scaleMin);
console.log("scaleMax="+scaleMax);
}
graph = new createGraph();
graph.addSignal();
graph.addSignal();
graph.addSignal();
graph.pushData([1,2,3]);
graph.pushData([1,2,3]);
graph.draw();
function each(array, callback){
console.log(callback);
for(i in array){
callback(array[i], i);
}
}
function roundTo(num, to){
return Math.round(num/to)*to;
}
<canvas id="graph"></canvas>
In your code that generates the labels, the loop index i is going from 10 to 0. Each time though the loop you are pushing a new label to the array (i.e. labels[0], labels[1], ...) but you are attempting to measure the labels using the loop index i (i.e. labels[10], labels[9], ...). Thus, the first few measurments are of the text "undefined".
Change...
console.log("->width "+this.ctx.measureText(labels[i]).width);
if(maxLabelWidth<this.ctx.measureText(labels[i]).width){
maxLabelWidth=this.ctx.measureText(labels[i]).width;
to...
console.log("->width "+this.ctx.measureText(labels[labels.length-1]).width);
if(maxLabelWidth<this.ctx.measureText(labels[labels.length-1]).width){
maxLabelWidth=this.ctx.measureText(labels[labels.length-1]).width;

Change properties of a class from time to time

I have two functions. In the first one I increase a variable by adding 100 to it and I put a setInterval so the funcion repeats itself after some time. The other function is a class, a contrusctor to create an object. I want this.x_origen to get increased by adding aumento to it after some time and repeat it. However what I'm getting here is that the first function increases aument and then it finishes and then the second function starts. How can I solve this?
var aument = 0;
function aumento(){
aument = aument + 100;
return aument;
}
setInterval(function () {aumento()}, 1000/50);
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
this.x_origen = x_origen_in + aumento();
this.y_origen = y_origen_in;
this.x_final = x_final_in + aumento();
this.y_final = y_final_in;
this.estado = mi_estado;
this.velocidad = mi_velocidad;
this.id_elemento = mi_id;
this.DESPLAZAR_LADRILLO = desplazar_ladrillo;
this.F0 = f0;
this.F2 = f2;
this.crear_ladrillo = crear_ladrillo;
this.obtener_x_origen_ladrillo = obtener_x_origen_ladrillo;
this.obtener_y_origen_ladrillo = obtener_y_origen_ladrillo;
this.obtener_x_final_ladrillo = obtener_x_final_ladrillo;
this.obtener_y_final_ladrillo = obtener_y_final_ladrillo;
}
An example on how to wait for the initial call:
function brick (x_origen_in){
this.x_origen = x_origen_in;
}
function aumento(brick){
console.log(brick.x_origen);
brick.x_origen += 100;
setTimeout(aumento.bind(this, brick), 500);
}
var brick = new brick(100);
aumento(brick);
http://jsfiddle.net/x6c08u39/
You can use Object.defineProperty to dynamically generate the value whenever it is accessed.
First, lets simplify the auto-incrementing of aument:
var aument = 0;
function aumento(){
aument += 100;
}
// The first argument for setInterval is the function to execute
// No need to figure out the interval value at runtime as there are no dynamic values
setInterval(aumento, 20); // 1000/50 === 20
Now lets make an object that will have a the correct value:
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
Object.defineProperty(this, 'x_origen', {
get: function () { return x_origen_in + aument; }
});
// Other stuff
// ...
}
A quick test:
> aument
34100
> var obj = new create_class_brick(23);
undefined
> obj.x_origen
161523
> obj.x_origen
167223
> obj.x_origen
172423

Javascript for loop doesn't work (adding numbers to a total)

I am using Jasmine for JS testing, and unfortunately I can't get the following test to pass.
it('should know the total game score', function() {
frame1 = new Frame;
frame2 = new Frame;
game = new Game;
frame1.score(3, 4);
frame2.score(5, 5);
expect(game.totalScore()).toEqual(17)
});
The error message I get is as follows: Error: Expected 0 to equal 17.
The code is as follows:
function Game() {
this.scorecard = []
};
Game.prototype.add = function(frame) {
this.scorecard.push(frame)
};
// Why is this not working!!???
Game.prototype.totalScore = function() {
total = 0;
for(i = 0; i < this.scorecard.length; i++)
{
total +=this.scorecard[i].rollOne + this.scorecard[i].rollTwo;
}
return total;
};
function Frame() {};
Frame.prototype.score = function(first_roll, second_roll) {
this.rollOne = first_roll;
this.rollTwo = second_roll;
return this
};
Frame.prototype.isStrike = function() {
return (this.rollOne === 10);
};
Frame.prototype.isSpare = function() {
return (this.rollOne + this.rollTwo === 10) && (this.rollOne !== 10)
};
Adding the numbers together manually seems to work e.g. total = game.scorecard[0].rollOne + this.scorecard[0].rollTwo , but the for loop (even though it looks correct) doesn't seem to work. Any help would be greatly appreciated :)
I am not pretty sure, but it seems that you are not calling the "Add" method, so no data is added to the scorecard.
You have to add the Frames to your game i guess
it('should know the total game score', function () {
frame1 = new Frame;
frame2 = new Frame;
game = new Game;
// those lines are missing
game.add(frame1);
game.add(frame2);
frame1.score(3, 4);
frame2.score(5, 5);
expect(17).toEqual(game.totalScore())
});
otherwise, the scorecard-array is empty and the total score is therefore equal to 0.
missing (so no data is added to the scorecard.)
game.Add(frame1);
game.Add(frame2);

JS mini-game in grid, browser frozen after first replication

I'm trying to create a small game that replicate neighbors cells in a grid. I use a web worker that draw replicate cells every seconds. I'm able to replicate the first second. If my initial cell is row3col3, the new replicated cells will be :
row3col2, row3col4
row2col3, row4col3
The problem is, after the first second (and the replication), the game freezes, and i'm not able to do something. Can't click on cells, etc.
EDIT : After few seconds, it go to '00:02' but Chrome crashed "Aw, Snap! Something went wrong...' [RELOAD]
EDIT 2 : After looking on the memory used, It appears I have an memory overflow, 16000 Mb ! My method is bad, so.
I know my code is not really optimised, and I think that is the problem. Unfortunatly, i'm not able to do more efficient code, so I ask some help to you guys, to give me some ways to explore.
Here the code :
var lastClicked;
var cellTab = Array();
var replicant = Array();
var newReplicant = Array();
var count = 5;
var rows = 20;
var cols = 20;
var randomRow = Math.floor((Math.random() * rows));
var randomCol = Math.floor((Math.random() * cols));
var grid = clickableGrid(rows, cols,randomRow,randomCol,cellTab, function(el,row,col,i){
console.log("You clicked on element:",el);
console.log("You clicked on row:",row);
console.log("You clicked on col:",col);
console.log("You clicked on item #:",i);
$(el).addClass('clicked');
lastClicked = el;
});
document.getElementById("game").appendChild(grid);
function clickableGrid( rows, cols, randomRow, randomCol, cellTab, callback ){
var i=0;
var grid = document.createElement('table');
grid.className = 'grid';
for (var r=0;r<rows;++r){
var tr = grid.appendChild(document.createElement('tr'));
for (var c=0;c<cols;++c){
var cell = tr.appendChild(document.createElement('td'));
$(cell).addClass('row'+r+'col'+c);
if(randomCol == c && randomRow == r)
{
storeCoordinate(r, c, replicant);
$(cell).css('background', '#000000');
}
storeCoordinate(r, c, cellTab);
cell.addEventListener('click',(function(el,r,c,i){
return function(){
callback(el,r,c,i);
}
})(cell,r,c,i),false);
}
}
return grid;
}
function storeCoordinate(xVal, yVal, array)
{
array.push({x: xVal, y: yVal});
}
function replicate(replicant)
{
for (var i = 0; i < replicant.length; i++) {
console.log(replicant);
var supRowX = replicant[i].x-1;
var supRowY = replicant[i].y;
storeCoordinate(supRowX, supRowY, newReplicant);
var subRowX = replicant[i].x+1;
var subRowY = replicant[i].y;
storeCoordinate(subRowX, subRowY, newReplicant);
var supColsX = replicant[i].x;
var supColsY = replicant[i].y-1;
storeCoordinate(supColsX, supColsY, newReplicant);
var subColsX = replicant[i].x;
var subColsY = replicant[i].y+1;
storeCoordinate(subColsX, subColsY, newReplicant);
}
}
function drawReplicant(replicant, cellTab)
{
for (var i = 0; i < replicant.length; i++) {
if($.inArray(replicant[i], cellTab))
{
$('.row'+replicant[i].x+'col'+replicant[i].y).css('background', '#000000');
}
}
}
var w = null; // initialize variable
// function to start the timer
function startTimer()
{
// First check whether Web Workers are supported
if (typeof(Worker)!=="undefined"){
// Check whether Web Worker has been created. If not, create a new Web Worker based on the Javascript file simple-timer.js
if (w==null){
w = new Worker("w.countdown.js");
}
// Update timer div with output from Web Worker
w.onmessage = function (event) {
document.getElementById("timer").innerHTML = event.data;
console.log(event.data);
replicate(replicant);
replicant = newReplicant;
drawReplicant(replicant, cellTab);
};
} else {
// Web workers are not supported by your browser
document.getElementById("timer").innerHTML = "Sorry, your browser does not support Web Workers ...";
}
}
// function to stop the timer
function stopTimer()
{
w.terminate();
timerStart = true;
w = null;
}
startTimer();
And here, the web worker :
var timerStart = true;
function myTimer(d0)
{
// get current time
var d=(new Date()).valueOf();
// calculate time difference between now and initial time
var diff = d-d0;
// calculate number of minutes
var minutes = Math.floor(diff/1000/60);
// calculate number of seconds
var seconds = Math.floor(diff/1000)-minutes*60;
var myVar = null;
// if number of minutes less than 10, add a leading "0"
minutes = minutes.toString();
if (minutes.length == 1){
minutes = "0"+minutes;
}
// if number of seconds less than 10, add a leading "0"
seconds = seconds.toString();
if (seconds.length == 1){
seconds = "0"+seconds;
}
// return output to Web Worker
postMessage(minutes+":"+seconds);
}
if (timerStart){
// get current time
var d0=(new Date()).valueOf();
// repeat myTimer(d0) every 100 ms
myVar=setInterval(function(){myTimer(d0)},1000);
// timer should not start anymore since it has been started
timerStart = false;
}
Maybe it's because I use jQuery ?

Categories

Resources