Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Subjunctive
Sep 12, 2006

✨sparkle and shine✨

a slime posted:

Javascript newbie here, playing with Emscripten. The C code I'm compiling to Javascript is pretty small, a few dozen lines, but it's a lot of integer math that depends on overflows and etc and I'm too lazy to port it myself. Emscripten, with all of the options for size optimization, still dumps ~180K of boilerplate stuff in the output, most of which appears to be unused. My translated C code ends up being about !K of this.

You can think of that stuff as libc, sort of. JS doesn't do dynamic linking the same way, and most projects that get transpiled are big enough that it's not a huge overhead. It'd be possible for emscripten to only emit the transitive closure of referenced utility functions, which might be a fun project.

Can you strip it textually, if big chunks are unused? Otherwise you could post-process to only pull in the pieces you need, if it's a really big deal.

Jabor posted:

What minifier are you using? If running it through Closure Compiler breaks it then that sounds like a bug in one of the two projects that you should report.

IMO, unless specifically documented otherwise, any minifier that changes the behavior of a script has a bug, so I'd start there.

Edit: are you using the --minify option on emscripten? I think the boilerplate should probably always be minified, but maybe not.

Subjunctive fucked around with this message at 14:31 on Jun 4, 2014

Adbot
ADBOT LOVES YOU

a slime
Apr 11, 2005

I was using UglifyJS, maybe I should try another minifier.

Subjunctive posted:

IMO, unless specifically documented otherwise, any minifier that changes the behavior of a script has a bug, so I'd start there.

Edit: are you using the --minify option on emscripten? I think the boilerplate should probably always be minified, but maybe not.

Yeah, this only minifies the translated code, and does nothing to the boilerplate. Seems really weird to me, which is why I thought I might be missing something.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

a slime posted:

Yeah, this only minifies the translated code, and does nothing to the boilerplate. Seems really weird to me, which is why I thought I might be missing something.

The boilerplate not being pre-minified does sound weird. I'll ask Alon what's up.

a slime
Apr 11, 2005

I hadn't updated Emscripten in a couple of months- I just pulled the latest version and recompiled, and it minifies the boilerplate out of the box now. Still 108KB, but I'm satisfied. Thanks.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



I'm looking at redoing a bunch of our stuff using require.js. Is there a better option that does AMD module loading I should be considering?

pepito sanchez
Apr 3, 2004
I'm not mexican
So I'm at the stage of my Simon game where I have to make the code create a random array (done, easy) and use that array to display a sequence of four (or more, later on) buttons on the screen. I'm trying to use setInterval and clearInterval for this procedure after learning a for loop simply can't have delays in it how I need them. Right now, my code doesn't trigger the event at all when it's supposed to.

http://jsfiddle.net/r87Pf/

The focus and issue with me is this:

code:
function randFour() {
    var num = Math.floor(Math.random() * 4) + 1;
    return num;
}
function beginner() {
    alert("Welcome to the game!");
    for(i = 0; i <=3; i++) {
        game.sequence[i] = randFour();
    }
     game.difficulty = 4;
     game.speed = 2000;
     buttonsShown(game.difficulty, game.sequence, game.speed);
}
function buttonsShow(difficulty, sequence, speed){
    sequence[sequence.length]++;
    var go = $this.setInterval( function() {if (difficulty < 0) {
                  $("#c"+sequence[sequence.length]+"i").attr("src", "imgs/"+sequence[sequence.length]+".png");
              $("#snd"+sequence[sequence.length])[0].play();

      difficulty--;
      sequence[sequence.length]++;
    };      
    setTimeout(function(){
        $("#c"+sequence+"i").attr("src", "imgs/d"+sequence[sequence.length]+".png");
      }));
    if (difficulty === 0) {
        clearInterval(go);
    }
        player1Turn();
    }
}
Sorry for being such a newbie. I do see the errors in my IDE. I just messed around with it a lot trying to resolve the issue and it kept getting worse. I hate having to re-write code over and over again, but that's been the case.

v1nce
Sep 19, 2004

Plant your brassicas in may and cover them in mulch.
Your indentation isn't really helping you either, it took me a while to realise setTimeout is within setInterval. If your IDE supports it, I'd suggest running this through a code formatter before you post it in future, just for ease of reading.

Also comment your code. I know you're a newbie, but it's a habit you want to get into asap.
code:
/**
 * Generate a random number from 1 to 4
 * @return int
 */
function randFour() { }

/**
 * Begin a new game, in Beginner difficulty
 */
function beginner() { }

/**
 * @param int Difficulty (1-4)
 * @param []  Sequence to light buttons
 * @param int Duration of button visibility, in ms.
 */
function buttonsShow(difficulty, sequence, speed) {}
buttonShow is the source of your despair, and it looks like you're trying to use setInterval to light each button in order, then use setTimeout on each to hide them thereafter.
Both setInterval and setTimeout are expecting a delay after the associated function, so there's one issue.
You'll probably kick yourself, but jQuery also has a $.delay() function, so you can actually do something like .show().delay.hide() instead of messing with setTimeout.

You also don't want the player to get their turn (player1Turn()) to hit buttons until the sequence is finished. In your current code, that looks like it'll happen almost immediately.. but again, the tabbing makes it hard for me to work out exactly what you were intending to happen.

If it were me, I'd do something like:
code:

/**
 * @var {}  Game mode data
 */ 
var gameMode = {
    speed: null,
    difficulty: null,
    sequence: null,
};

/**
 * Generate a random button sequence, to the length specified
 * Note: This used to be randFour(), but now generates the full sequence
 * @param int Length of sequence to generate
 * @param []  Array containing button sequence
 */
function generateSequence( length )
{
    var sequence = new Array();
    for (var i=0; i<length; i++) {
        sequence[i] = Math.floor(Math.random() * 4) + 1;
    }
}

/**
 * Start a game in beginner mode
 * Note: This used to be beginner(), but can replace medium() and difficult() too
 * @param string  Game difficulty
 */
function startGame( difficulty ) {

    // Welcome message
    alert('Welcome to the game!');
    
    // Set the difficulty so we can get it later
    gameMode.difficulty = difficulty;

    // Create sequence from difficulty
    switch (difficulty) {
        case 'beginner':
            sequenceLength = 4;
            gameMode.speed = 2000;
            break;
        case 'medium':
            sequenceLength = 6;
            gameMode.speed = 1000;
            break;
        case 'difficult':
        default:
            sequenceLength = 10;
            gameMode.speed = 500;
            break;
    }

    // Generate sequence
    gameMode.sequence = generateSequence(sequenceLength);

    // Play the button sequence
    // Execute "player1Turn" on completion of the sequence.
    // Note: We're padding playButtonSequence a function, which will be used as a callback.
    playButtonSequence(gameMode.sequence, function() {
        player1Turn();
    });
}

/**
 * Play the given sequence until it is empty.
 * Run the Callback function when there are no more sequence items to execute.
 * Note: used to be called buttonsShow
 * @param []        Array of buttons to play as a sequence
 * @param function  Callback function to run when sequence is complete.
 */
function playButtonSequence( sequence, callback )
{
    // If we've no more sequences to play, run the callback.
    if (sequence.length < 1) {
        callback();

        // Don't run any more code.
        return;
    }

    // Get the button number by taking the first element off the sequence array
    var button = sequence.shift();

    // Play the audio cue
    $("#snd"+button)[0].play();

    // 1. Highlight button
    // 2. delay 
    // 3. dismiss button
    // 4. call next button
    $("#c"+button+"i")
        .attr("src", "imgs/"+button+".png")
        .delay(gameMode.speed)
        .attr("src", "imgs/d"+button+".png");  
        .show(0, function() {
            // Note: show() is used simply so we can run a callback.
            // Things like delay() aren't blocking, so we have to run the function off the back of this sequence.

            // This will run this function again, but as we used .shift() on sequence, it'll be one element lighter.
            // We keep doing this until sequence is empty, and then the callback will be executed.
            playButtonSequence( sequence, callback );
        });
}
I haven't run this code even once, and it obviously doesn't play a full game of Simon. All it will do is generate a sequence based off the difficulty, and try to play the buttons in the sequence order, and then run player1Turn() after the sequence is done playing.

I leave it to you to figure out where this fits into your code, and how it needs to be modified so your game is actually playable.

pepito sanchez
Apr 3, 2004
I'm not mexican
It's a good start for me, and sorry for the lack of comments. I really appreciate you taking the time. I'll work it our tomorrow for sure.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

So I'm at the stage of my Simon game where I have to make the code create a random array (done, easy) and use that array to display a sequence of four (or more, later on) buttons on the screen. I'm trying to use setInterval and clearInterval for this procedure after learning a for loop simply can't have delays in it how I need them. Right now, my code doesn't trigger the event at all when it's supposed to.

You don't really explain what your problem is.
What are you trying to user setInterval and clearInterval for?
What do you need delays for and what do you mean by "a loop simply can't have delays in it how I need them?"
What is "the event" that is supposed to trigger?

pepito sanchez
Apr 3, 2004
I'm not mexican
Sorry. I'll try to be clearer. Originally I was trying to use a for loop to show the random Simon sequence, then learned that a for loop will simply go through it. There was no way to add a delay between each "flash" of a button when I added simple if statements in my for loop. They all simply flashed at once. All I knew for certain was that there were random buttons being flashed each time, so I at least had part of it done. I was seriously struggling finding a method to delay between button flashes, and found out the easiest way to do this would be to somehow use setInterval in an if statement to flash a random button (using game.speede for the delay, depending on the game's difficulty setting), decrease an outside variable after each pass of the setInterval (in this case game.difficulty), and use clearInterval if the outside variable reached a given number. I'm probably doing this the hard way, but I could find no other way. I'm trying to implement some of v1nce's advice right now.

I don't know how much this is going to screw up my code later on, since I have to give the sequence, then move onto player one's turn, then player two's, and compare everyone's arrays to find out who won, tied, lost, etc.

pepito sanchez
Apr 3, 2004
I'm not mexican
Well, right now implementing the callback function, it plays eight sounds when it's supposed to play four, and no colors change. I don't think callback() is the way for me. Even reading about it online I don't think I understand how that works. I'm going to try and implement the example our teacher gave us, using intervals and clearinterval.

He gave us a fiddle to take as an example: http://jsfiddle.net/Lv4bz/2/

The code might be longer, much longer, but at least I'll be able to understand it and document it.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

Sorry. I'll try to be clearer. Originally I was trying to use a for loop to show the random Simon sequence, then learned that a for loop will simply go through it. There was no way to add a delay between each "flash" of a button when I added simple if statements in my for loop. They all simply flashed at once. All I knew for certain was that there were random buttons being flashed each time, so I at least had part of it done. I was seriously struggling finding a method to delay between button flashes, and found out the easiest way to do this would be to somehow use setInterval in an if statement to flash a random button (using game.speede for the delay, depending on the game's difficulty setting), decrease an outside variable after each pass of the setInterval (in this case game.difficulty), and use clearInterval if the outside variable reached a given number. I'm probably doing this the hard way, but I could find no other way. I'm trying to implement some of v1nce's advice right now.

I don't know how much this is going to screw up my code later on, since I have to give the sequence, then move onto player one's turn, then player two's, and compare everyone's arrays to find out who won, tied, lost, etc.

You cannot have a delay in the middle of a loop, but you can have a function that flashes a random button. Or one that flashes the next button from a previously randomized sequence.
Both setTimeout and setInterval take a function as their first argument.

In general, if you have a problem in JavaScript, you often have to make more functions.

Here is a "sequence" method:
JavaScript code:
var sequence = [];

var sequence_length = 5;

for (var i = 0; i < sequence_length; i++) {
	sequence.push(Math.floor(Math.random() * 4));
}
var interval_id;

var flasher = function () {
	var button_to_flash = sequence.pop();
	
	if (button_to_flash !== undefined) {
		var button = $('#button' + button_to_flash);
		
		//actually flash button here
		console.log('would flash #button' + button_to_flash);
	} else {
		clearInterval(interval_id);
	}
}

var flash_speed = 500;

interval_id = setInterval(flasher, flash_speed);

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

I don't think callback() is the way for me. Even reading about it online I don't think I understand how that works.

Callbacks are just functions. That's it.

You can assign a function to a variable in Javascript. You can then call those variables like functions.

JavaScript code:
var number = 0;

var some_function = function() {
	console.log('hello from some_function: ' + number);
	number++;
}

some_function();

var another_variable = some_function;

another_variable();

var function_that_takes_a_callback = function(callback) {
	console.log('calling callback');
	callback();
}

function_that_takes_a_callback(some_function);

function_that_takes_a_callback(another_variable);

pepito sanchez
Apr 3, 2004
I'm not mexican
I've got it to work with a simple setTimeout. Now does shift() actually make the variable gameMode.sequence shorter? If so I'll have to store it at the beginning in some other variable for later comparison with player input.

code:
function startGame(difficulty) {

    // Welcome message
    alert('Welcome to the game!');

    // Set the difficulty so we can get it later
    gameMode.difficulty = difficulty;

    // Create sequence from difficulty
    switch (difficulty) {
        case 'basic':
            sequenceLength = 4;
            gameMode.speed = 2000;
            break;
        case 'inter':
            sequenceLength = 6;
            gameMode.speed = 1000;
            break;
        case 'advanced':
        default:
            sequenceLength = 10;
            gameMode.speed = 500;
            break;
    }

    function generateSequence(length) {
        var sequence = [];
        for (var i = 0; i < length; i++) {
            sequence[i] = Math.floor(Math.random() * 4) + 1;
        }
        return sequence;
    }

    // Generate sequence
    gameMode.sequence = generateSequence(sequenceLength);

    // Play the button sequence
    // Execute "player1Turn" on completion of the sequence.
    playButtonSequence(gameMode.sequence);
}

function playButtonSequence(sequence) {
    if (sequence.length < 1) {
        player1Turn();
    }
    //shift() is something I haven't used before. But it does run through the received sequence array correctly.
    var button = sequence.shift();

    //make the random button change color, and play the corresponding sound.
    $("#c" + button + "i").attr("src", "imgs/" + button + ".png");
    $("#snd" + button)[0].play();
    //make it change back after gameMode.speed. And go through the function again. It stops when sequence.length < 1. 
    //That's my fear. If it's changed permanently I'll have to store gameMode.sequence somewhere else for array comparison
    //reasons later on.
    setTimeout(function() {
        $("#c" + button + "i").attr("src", "imgs/d" + button + ".png");
        playButtonSequence(sequence);
    }, gameMode.speed);
}

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
You could also just save your current position in the sequence into another variable.
JavaScript code:
var sequence = [0,3,2,3,1];
var position = 0;

var blink_button = function () {
	$('#button' + sequence[position]).whatever();
	position++;
}
But yes, shift() removes the first element of the array and returns it.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

Let's say I wanted to make a tile-based level editor in Javascript - is there a way to read/write local files in Javascript without having some server-backend that handles uploading and downloading files?

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

Bob Morales posted:

Let's say I wanted to make a tile-based level editor in Javascript - is there a way to read/write local files in Javascript without having some server-backend that handles uploading and downloading files?

Nope. Client JavaScript cannot access the filesystem directly in a standard browser implementation. You can have a formal 'upload' and 'download', but that's user driven.

MrMoo
Sep 14, 2000

Reading OK - FileReader API, writing requires a round-trip.

Also, there is AppCache and IndexedDB which may be of use.

Tres Burritos
Sep 3, 2009

You could read the file in, change it around and then re-save it as something else.

pepito sanchez
Apr 3, 2004
I'm not mexican
Something strange happens in my game now. I set it to move onto player 2's turn once player 1 reaches the array length javascript generates. Now this was an issue, because shift() made the generated array zero, so it just went straight from "Player 1's turn!" to "Player 2's turn!" I tried to resolve this by making the sequence its own seperate variable, and oddly now it doesn't matter how many buttons I push, the player's generated array (based on what buttons he pushes) never meets the new seperate array.

code:
    function generateSequence(length) {
        var sequence = [];
        for (var i = 0; i < length; i++) {
            sequence[i] = Math.floor(Math.random() * 4) + 1;
        }
        return sequence;
    }

    // Generate sequence
    gameMode.sequence = generateSequence(sequenceLength);
    // Make my global var storedSequence the generated sequence for later use.
    storedSequence = gameMode.sequence;

    // Play the button sequence
    // Execute "player1Turn" on completion of the sequence.
    playButtonSequence(gameMode.sequence);
}

function playButtonSequence(sequence) {
    if (sequence.length < 1) {
        player1Turn();
    }

    var button = sequence.shift();

    $("#c" + button + "i").attr("src", "imgs/" + button + ".png");
    $("#snd" + button)[0].play();

    setTimeout(function() {
        $("#c" + button + "i").attr("src", "imgs/d" + button + ".png");
        playButtonSequence(sequence);
    }, gameMode.speed);
}

function player1Turn() {
    player1.active = true;
    alert("Es turno del jugador uno!");
	// just a bunch of code that makes the buttons light up when player clicks on them, and add to player's sequence var.
    $("#c1i").on("click", function() {
        redButton();
        player1.sequence[player1.sequence.length] = 1;
    });
    $("#c2i").on("click", function() {
        yellowButton();
        player1.sequence[player1.sequence.length] = 2;
    });
    $("#c3i").on("click", function() {
        blueButton();
        player1.sequence[player1.sequence.length] = 3;
    });
    $("#c4i").on("click", function() {
        greenButton();
        player1.sequence[player1.sequence.length] = 4;
    });
	// Check and see if player's array matches gameMode.sequence when it was first generated.
    if (player1.sequence.length === storedSequence) {
        player2turn();
    }
}

function player2turn() {
    player2.active = true;
    // I never get to this alert message.
    alert("Es turno del jugador dos!");
		// just a bunch of code that makes the buttons light up when player clicks on them, and add to player's sequence var.

    $("#c1i").on("click", function() {
        redButton();
        player2.sequence[player2.sequence.length] = 1;
    });
    $("#c2i").on("click", function() {
        yellowButton();
        player2.sequence[player2.sequence.length] = 2;
    });
    $("#c3i").on("click", function() {
        blueButton();
        player2.sequence[player2.sequence.length] = 3;
    });
    $("#c4i").on("click", function() {
        greenButton();
        player2.sequence[player2.sequence.length] = 4;
    });
    if (player2.sequence.length === storedSequence.length) {
        gameEnd();
    }
}
I've tried to make the separate array holder inside the gameMode object and its own variable, but each ends up with the same issue. It never enters player2turn(). I do need some way of storing that array separately for later.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
if (player1.sequence.length === storedSequence)

You compare the length of player1.sequence with the array storedSequence. (Not storedsequence.length)

pepito sanchez
Apr 3, 2004
I'm not mexican
:blush:

That's why I post these problems here instead of Stackoverflow.

Thanks for pointing out the obvious, Wheany.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
One code-quality issue: player1Turn() is (in practice) identical to player2turn(). You could pass the player object as a parameter.

Also you always add another event handler in both functions, so soon every time you click #c1i, you will call redButton() several times.

pepito sanchez
Apr 3, 2004
I'm not mexican
Well I fixed up the code, but it still keeps on going, allowing me to press on infinite buttons and never going into player 2's turn, even when player1.sequence.length === storedSequence.length. Any idea what could be causing this issue?

edit: http://jsfiddle.net/ZA724/

Posting all of that code would be pointless. Sorry for the lack of comments. Most of the code underneath player1Turn is for later use. I kept on coding since I assumed the issue was fixed.

edit2: Don't understand what you mean by that? I mean, I need them as separate object to compare them later on, and to make a table based on their individual statistics. In other words, their individual variables have to be stored indefinetely. The very last part of the project is all about creating a table ordered highest to lowest based on points (score).

pepito sanchez fucked around with this message at 18:22 on Jun 8, 2014

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

Well I fixed up the code, but it still keeps on going, allowing me to press on infinite buttons and never going into player 2's turn, even when player1.sequence.length === storedSequence.length. Any idea what could be causing this issue?

When you execute player1Turn(), it will add the event handlers to the buttons, then compare player1.seequence.length to storedSequence.length.

When you press a button, an entry is added to player1.sequence, but its length is never compared to storedSequence.length.

quote:

edit2: Don't understand what you mean by that? I mean, I need them as separate object to compare them later on, and to make a table based on their individual statistics. In other words, their individual variables have to be stored indefinetely. The very last part of the project is all about creating a table ordered highest to lowest based on points (score).

I mean that you could have player1 = {sequence: []} and player2 = {sequence:[]}

Then have a function that takes a player as a parameter:

JavaScript code:
var player1 = {sequence: [], points: 0};
var player2 = {sequence: [], points: 0};

// now there is no duplicated code, and any bugs you make you only have to fix once
var doThingWithPlayer = function (player) {
	player.sequence.push("an entry");
	player.points++;
	
	if(player.sequence.length > 10) {
		console.log('that sure is a long sequence');
	}
}

doThingWithPlayer(player1);

doThingWithPlayer(player2);

pepito sanchez
Apr 3, 2004
I'm not mexican
Isn't that what I've done? Apart from having the functions take the objects as parameters, which isn't currently my issue (I think?).

It still doesn't really tell me how storedSequence isn't ever really stored, or compared correctly to the player objects sequence variables.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





MrMoo posted:

Reading OK - FileReader API, writing requires a round-trip.

Also, there is AppCache and IndexedDB which may be of use.

It's not recommended to use AppCache. Completely unusable. http://alistapart.com/article/application-cache-is-a-douchebag

Strong Sauce fucked around with this message at 20:07 on Jun 8, 2014

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

It still doesn't really tell me how storedSequence isn't ever really stored, or compared correctly to the player objects sequence variables.

When you call player1Turn, these are the steps it takes through the function:


When you click "#c1i", this is what is run:


In other words, in player1Turn:
you set player1.active to true
you show an alert
you add a click handler to each of those elements [ .on("click", function (){}); ]
then the sequence length is compared. It is not true, so player2Turn() is not called.

After that, when you click a button, the function you gave as an argument to .on() gets called, so
The function redButton() is called.
player1.sequence gets lengthened.

pepito sanchez
Apr 3, 2004
I'm not mexican
Yet adding a else { player1Turn() }, which should re-run the function doesn't do a thing to help. Do I have to add yet another seperate counter in order to let the function run until the desired length is completed?

edit: Yeah I never get the alert message again, so it doesn't enter the function again.

pepito sanchez fucked around with this message at 21:58 on Jun 8, 2014

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

Yet adding a else { player1Turn() }, which should re-run the function doesn't do a thing to help. Do I have to add yet another seperate counter in order to let the function run until the desired length is completed?

If you run player1Turn() again in the else branch, you will just add another click handler to each element and also you will cause an infinite loop which will cause a stack overflow.

What you need to do is compare the length of the sequence while inside the click handlers.

pepito sanchez
Apr 3, 2004
I'm not mexican
You mean like this?

code:
function player1Turn() {
    player1.active = true;
    alert("Es turno del jugador uno!");
    $("#c1i").on("click", function() {
        redButton();
        player1.sequence[player1.sequence.length] = 1;
            if (player1.sequence.length === storedSequence.length) {
        player2Turn();
            }
    });
    $("#c2i").on("click", function() {
        yellowButton();
        player1.sequence[player1.sequence.length] = 2;
            if (player1.sequence.length === storedSequence.length) {
        player2Turn();
            }
    });
    $("#c3i").on("click", function() {
        blueButton();
        player1.sequence[player1.sequence.length] = 3;
            if (player1.sequence.length === storedSequence.length) {
        player2Turn();
            }
    });
    $("#c4i").on("click", function() {
        greenButton();
        player1.sequence[player1.sequence.length] = 4;
            if (player1.sequence.length === storedSequence.length) {
        player2Turn();
            }
    });
}
It still gives me the same problem.

MrMoo
Sep 14, 2000

Strong Sauce posted:

It's not recommended to use AppCache. Completely unusable. http://alistapart.com/article/application-cache-is-a-douchebag

You just have to not be dumb, read the follow up article http://flailingmonkey.com/application-cache-not-a-douchebag. Using AppCache in an iframe works pretty well.

Blakles
Mar 10, 2008

I have lived a great deal among grown-ups. I have seen them intimately, close at hand. And that hasnt much improved my opinion of them.
I didn't see an Angular thread, but I'm hoping someone can help me figure this out in here.

I have an webpage in Angular where I'm trying to simply load in videos from my YouTube channel using their v3 API. Right now they only allow you to return a maximum of 50 results at a time, but I need to get all of them. In order to do that I basically have to make separate API calls with a "nextPageToken" parameter added to the URL that is sent with the previous call's results. My problem is that I can't seem to get the nextPageToken being sent to my factory call to be the correct one. It always stays at the same value which is the value it is set to after the first call.

Any help on this is greatly appreciated. Thanks!

code:
// controller
App.controller('videosController', function ($scope, $rootScope, videosFactory, $window, $http) {
	var videos;
	var pageToken;
	videosFactory.getAllVideos(function (results) {
		videos = results.items;
		pageToken = results.nextPageToken;
		var videoCount = 50;
		while (results.pageInfo.totalResults > videoCount) {
			videosFactory.getNextVideos(pageToken, function (nextResults) {
				videos.push(nextResults.items);
				pageToken = nextResults.nextPageToken;
				console.log(pageToken);
			});
			videoCount += 50;
		}
		$scope.allVideos = videos;
	});
});

//factory
App.factory('videosFactory', function ($http) {
	return{
		getAllVideos: function (callback) {
			$http.get('https://www.googleapis.com/youtube/v3/search?key={myKey}&channelId={myChannelId}&part=snippet,id&order=date&maxResults=50').success(callback);
		},
		getNextVideos: function (pageToken, callback) {
			console.log("in factory: "+pageToken);
			$http.get('https://www.googleapis.com/youtube/v3/search?key={myKey}&channelId={myChannelId}&part=snippet,id&order=date&maxResults=50&pageToken='+pageToken).success(callback);
		}
	};
});

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

pepito sanchez posted:

You mean like this?

JavaScript code:
function() {
    redButton();
    player1.sequence[player1.sequence.length] = 1;
    if (player1.sequence.length === storedSequence.length) {
        player2Turn();
    }
}
Yes. That is the correct logic, but player2Turn does the wrong thing:
When player2Turn gets run, it will add another click handler to all those elements. So when you click on an element after player2Turn has run, first the player1 sequence gets lengthened, then player2.

You should set up your click handlers only once, (init function could be a good place for that), then maybe save the currently active player in some variable, then you can access the currently active player from inside the click handler.

So for example:
JavaScript code:
var player1 = {name: null,
    points: 0,
    gamesWon: 0,
    gamesLost: 0,
    gamesTied: 0,
    sequence: null,
    correct: false
};
var player2 = {name: null,
    points: 0,
    gamesWon: 0,
    gamesLost: 0,
    gamesTied: 0,
    sequence: null,
    correct: false
};

var currentlyActivePlayer = player1;

pepito sanchez
Apr 3, 2004
I'm not mexican
It just never goes back into the function. I've tried using a simple if statement, and a while wouldn't work because that would create an infinite loop which locks the script up. It goes through the function once, stores nothing, returns nothing, and compares nothing. I can see how the logic is wrong, yet I don't know how to make it so it constantly searches for player1's input.

edit: And this just makes it go straight from player1's turn to player2's turn.

code:
function player1Turn() {
    alert("Es turno del jugador uno!");
    var counter = 0;
    if (counter < storedSequence.length) {
        $("#c1i").on("click", function() {
            redButton();
            player1.sequence[player1.sequence.length] = 1;
            counter++;
        });
        $("#c2i").on("click", function() {
            yellowButton();
            player1.sequence[player1.sequence.length] = 2;
            counter++;
        });
        $("#c3i").on("click", function() {
            blueButton();
            player1.sequence[player1.sequence.length] = 3;
            counter++;
        });
        $("#c4i").on("click", function() {
            greenButton();
            player1.sequence[player1.sequence.length] = 4;
            counter++;
        });
    } else {
        player2Turn();
    }
}
For reasons I don't understand. How is counter being incremented unless a player clicks on a button?

pepito sanchez fucked around with this message at 23:58 on Jun 8, 2014

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

Blakles posted:

I didn't see an Angular thread, but I'm hoping someone can help me figure this out in here.


I do not know "The Angular", but there is a thread for all the fancy pants JS frameworks: http://forums.somethingawful.com/showthread.php?threadid=3571035

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

Strong Sauce posted:

It's not recommended to use AppCache. Completely unusable. http://alistapart.com/article/application-cache-is-a-douchebag

I wouldn't say that, at least not entirely. I use it to good effect for caching a static app, where the manifest is only changed on the release of new versions, which is what it is ideally specced for anyway. The issue is when people attempt to use it for dynamic content, which is fair enough because you can't really inspect the contents of the appcache effectively to good effect.

In the case of an editor or something like that, you would only use appcache to store the application files, never the actual user data.

Chenghiz
Feb 14, 2007

WHITE WHALE
HOLY GRAIL

Maluco Marinero posted:

I wouldn't say that, at least not entirely. I use it to good effect for caching a static app, where the manifest is only changed on the release of new versions, which is what it is ideally specced for anyway. The issue is when people attempt to use it for dynamic content, which is fair enough because you can't really inspect the contents of the appcache effectively to good effect.

In the case of an editor or something like that, you would only use appcache to store the application files, never the actual user data.

Yeah, same here. Update the appcache revision number for a new version, job's done. I haven't had any issues with it once I learned how to use it, which diveintohtml5.info was good for.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





Blakles posted:

I didn't see an Angular thread, but I'm hoping someone can help me figure this out in here.

I have an webpage in Angular where I'm trying to simply load in videos from my YouTube channel using their v3 API. Right now they only allow you to return a maximum of 50 results at a time, but I need to get all of them. In order to do that I basically have to make separate API calls with a "nextPageToken" parameter added to the URL that is sent with the previous call's results. My problem is that I can't seem to get the nextPageToken being sent to my factory call to be the correct one. It always stays at the same value which is the value it is set to after the first call.

Any help on this is greatly appreciated. Thanks!

code:
// controller
App.controller('videosController', function ($scope, $rootScope, videosFactory, $window, $http) {
	var videos;
	var pageToken;
	videosFactory.getAllVideos(function (results) {
		videos = results.items;
		pageToken = results.nextPageToken;
		var videoCount = 50;
		while (results.pageInfo.totalResults > videoCount) {
			videosFactory.getNextVideos(pageToken, function (nextResults) {
				videos.push(nextResults.items);
				pageToken = nextResults.nextPageToken;
				console.log(pageToken);
			});
			videoCount += 50;
		}
		$scope.allVideos = videos;
	});
});

//factory
App.factory('videosFactory', function ($http) {
	return{
		getAllVideos: function (callback) {
			$http.get('https://www.googleapis.com/youtube/v3/search?key={myKey}&channelId={myChannelId}&part=snippet,id&order=date&maxResults=50').success(callback);
		},
		getNextVideos: function (pageToken, callback) {
			console.log("in factory: "+pageToken);
			$http.get('https://www.googleapis.com/youtube/v3/search?key={myKey}&channelId={myChannelId}&part=snippet,id&order=date&maxResults=50&pageToken='+pageToken).success(callback);
		}
	};
});

You are not enclosing the pageToken in the getNextVideos callback which is leaking it to the last token you have.

Essentially you are doing this:

code:
for (i=0;i<5;i++) { setTimeout(function() { console.log(i) }, 200) }
Because variable i is in the scope above the executed function (in this case in the global scope), it gets changed by the looping. That is essentially what you're doing but caused by async callbacks rather than timeouts.

Edit: Actually I'm not sure if this is the problem since pageToken is passed in as a parameter.

Edit 2: Oh I see, your problem is all your calls to getNextVideos uses the same pageToken as the first parameter because your callback doesn't call right away and functions don't wait until the next iteration. So the problem is you're executing getNextVideos in parallel with the same pageToken.

Strong Sauce fucked around with this message at 01:24 on Jun 9, 2014

Adbot
ADBOT LOVES YOU

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Strong Sauce posted:

It's not recommended to use AppCache. Completely unusable. http://alistapart.com/article/application-cache-is-a-douchebag

Did you actually read that article, or did you just laugh at the introduction then close the page? It doesn't actually try to claim that AppCache is unusable; merely that it has a bunch of gotchas you have to keep in mind.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply