2

I am currently adding extra sounds to my game. The problem is I have a shorthand if statement like "?...:..." and don't know how I can add audio to it. If it is not possible how would I make it a normal if statement without making it crash.

    b.clone().addClass(
    b.data("letter") == target.data("letter") ? "wordglow3" : "wordglow").appendTo("table").css({
        background: "transparent",
        position: "absolute",
        top: currentPos.top,
        left: currentPos.left
    })

So if "wordglow3" I want to add "hit.play()" and for "wordglow" I want to add "miss.play()"

Milo-J
  • 1,108
  • 2
  • 13
  • 26
  • What do you mean by "adding sounds"? Can you give us an example how you would do it without any conditions? – Bergi Oct 26 '12 at 09:43
  • The [ternary operator](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Conditional_Operator) makes an expression, not a statement – Bergi Oct 26 '12 at 09:44

2 Answers2

1

OK, first the obvious solution with if/else-statements:

var c = b.clone();
if ( b.data("letter") == target.data("letter") ) {
    c.addClass("wordglow3");
    hit.play();
} else {
    c.addClass("wordglow");
    miss.play();
}
c.appendTo(table).css(…);

Now, we could remove some duplicate code using variables:

var className, sound;
if ( b.data("letter") == target.data("letter") ) {
    className = "wordglow3";
    sound = hit;
} else {
    className = "wordglow";
    sound = miss;
}
b.clone().addClass(className).appendTo(table).css(…);
sound.play();

or even shorter by initialising them with the defaults:

var className, = "wordglow",
    sound = miss;
if ( b.data("letter") == target.data("letter") ) {
    className += "";
    sound = hit;
}
…

Using the ternary operator gets harder. We could use the comma operator to chain different actions in the same expression:

b.clone().addClass( b.data("letter") == target.data("letter")
  ? hit.play(), "wordglow3"
  : miss.play(), "wordglow"
).appendTo(table).css(…);

But this is ugly. A better choice would be using a variable for the condition and two ternary operators:

var success = b.data("letter") == target.data("letter");
b.clone().addClass(success ? "wordglow3" : "wordglow").appendTo(table).css(…);
(success ? hit : miss).play();

Once we've got here, you even might consider an extra data structure for your sounds and class names, to replace millions of (especially nested) if-statements with selection by key:

// global:
var sounds = { // or use an arrays
    "0": …, // miss
    "1": …  // hit
};
var classes = {
    "0": "wordglow",
    "1": "wordglow3"
};
// […]
// then, select values by casting the boolean to numeric keys:
var success = b.data("letter") == target.data("letter");
b.clone().addClass(classes[+success]).appendTo(table).css(…);
sounds[+success].play();

This makes extending your application with other cases easy, and allows an easier maintenance of used class names or sounds (in a central place) if they are used like this everywhere. Also, we've reduced two variables hit and miss to only one sounds.

Decide yourself which code snippet is best readable or most appropriate in your situation.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Which would you say is the best? @Bergi – Milo-J Oct 26 '12 at 13:21
  • "if + default variables" is best readable for beginners, "two ternary operators" even more concise and shorter (does not need variables) - my personal favourite. However, when beginning designing an application I'd always go with the last approach - I can understand that it won't integrate easily into already existing code. – Bergi Oct 26 '12 at 13:31
  • Which would you say is easiest to integrate? @Bergi – Milo-J Oct 26 '12 at 13:36
  • C'mon, I don't know your code base; so you will decide yourself which one fits best in your current code. – Bergi Oct 26 '12 at 13:39
  • Sorry I thought I had posted a fiddle. The problem is the 4th choice is the best suited but I have "}).animate" at the end and it won't seem to work @Bergi – Milo-J Oct 26 '12 at 13:44
  • Where do you have the `animate()`? Could you make a fiddle with your current code? – Bergi Oct 26 '12 at 13:46
  • Here it is http://jsfiddle.net/7Y7A5/11/ obviously because its a fiddle hit and miss will not play because they are stored locally. Watch out for the sound @Bergi – Milo-J Oct 26 '12 at 13:50
  • There's nothing wrong with solution #3: http://jsfiddle.net/7Y7A5/12/ Of course you also could put them after the longish start-animation-call. – Bergi Oct 26 '12 at 13:58
  • The thing is now the letters dont animate when clicked @Bergi – Milo-J Oct 26 '12 at 14:20
  • Why, does `.play()` raise an exception? Or is it synchronous and lasts seconds? – Bergi Oct 26 '12 at 14:22
  • OK, hadn't expected that. Then do http://jsfiddle.net/7Y7A5/13/. However, I don't think it's possible to play synchronous sounds while something else (the animation) executes. If this is really the problem, ask an extra question on how to solve that – Bergi Oct 26 '12 at 14:52
  • This wasn't the problem originally, only in your fiddles. My problem is that I want to add a sound so that when the animation hits the target it makes a sound dependent on whether it is right or wrong @Bergi – Milo-J Oct 26 '12 at 14:59
  • So the sound should play after the animation? Then move the statement into the animation's callback function – Bergi Oct 27 '12 at 12:38
  • something like if $(b.data("letter") == target.data("letter")).hasClass('wordglow3') { hitSound.play(); } else { missSound.play(); } @Bergi – Milo-J Oct 29 '12 at 08:49
  • Why not just check the `success` variable we already have? Your code relies on a class name… – Bergi Oct 29 '12 at 12:02
  • success and failure are different sounds already though. Hit and miss are different. I need them to be applied when wordglow and wordglow2 are @Bergi – Milo-J Oct 29 '12 at 12:24
  • I meant the boolean variable I introduced above, which also determines whether `wordglow3` or `wordglow` would be used. Of course you can rename it to something better. – Bergi Oct 29 '12 at 12:26
  • I see. Could you show me a fiddle with the simple if, else version you showed? @Bergi – Milo-J Oct 29 '12 at 12:31
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18728/discussion-between-milo-j-and-bergi) – Milo-J Oct 29 '12 at 15:56
0

I mean if it is not working a shorthand way, you can just try the long way:

var class_to_add = "wordglow";
if(b.data("letter") == target.data("letter"))
  class_to_add = "wordglow3";
b.clone().addClass(class_to_add).appendTo("table").css({
        background: "transparent",
        position: "absolute",
        top: currentPos.top,
        left: currentPos.left
    });
Pulkit Mittal
  • 5,916
  • 5
  • 21
  • 28
  • It works but I want to play a sound for each. So for "wordglow3" I want to play a sound called "hit" - hit.play() @Pulkit Mittal – Milo-J Oct 26 '12 at 09:54
  • You mean you wanna play audio from javascript? Then the question seems completely senseless, doesn't it? – Pulkit Mittal Oct 26 '12 at 10:04
  • Why is it senseless, if you read the question it says I want to add sound to each "wordglow" style @Pulkit Mittal – Milo-J Oct 26 '12 at 10:18