craftyjs/Crafty

Is there a method to address a single sprite other than the name given in the spritemap?

ogrotten opened this issue · 4 comments

I've got a spritesheet with playing cards, row = suit, col = value.

Is there a built-in function/method to call up a single sprite from the sheet by coordinate? so that say map[3,1] would be the 3 of Clubs at the sprite location 4th row, 2nd col?

The example at Sprite.sprite seems to be used to rename the sprite at that coordinate position, so I was looking for a related function to get/show a sprite.

Calling e.sprite(3, 1) should work. The sprite method is overloaded -- you can pass in either coordinates or a name.

The example is just showing two different ways of calling the method. (The first passing the exact position/dimensions in tile coordinates, the second passing a predefined sprite name.)

Thank you.

How should I refer to this when defining the element?

Crafty.e('2D, Canvas, Mouse, SpriteAnimation, Tween, Sprite, ' + (3,1))

Does not work, so I've used

Crafty.e('2D, Canvas, Mouse, SpriteAnimation, Tween, Sprite, FullDeck')

But FullDeck is only a name mapped to 0,0 coordinates map{FullDeck: [0, 0]}, which seems to work-ish but doesn't seem quite right.

Not sure if this is the source, but there winds up being a downline problem:

function go() {
  let front = true;
  let cardsuit = Math.floor(Math.random()*4);
  let cardcard = Math.floor(Math.random()*13);
  let actual = (cardcard, cardsuit);
  Crafty.e('2D, Canvas, Mouse, SpriteAnimation, Tween, Sprite, FullDeck')
  .sprite(cardcard, cardsuit)
  .reel("Flip2Back", 10, [actual ,'Back'])
  .reel("Flip2Front", 10, ['Back', actual])
  .bind('Click', function(e){
    if (front) {
      front = !front;
      this.animate('Flip2Back');
    } else {
      front = !front;
      this.animate('Flip2Front');
    }
  });
}
  1. If I go .sprite(actual) (line 7), then it fails silently, showing nothing. The display is blank, but the flip reel animates, showing the sprite defined at Back when clicked for toggle.
  2. With the code as shown, the card at the coordinate shows, and then a click shows the back. However, a 2nd click shows a blank front. It then does as the first item, showing the sprite at Back but no front when toggled.

Please advise?

let actual = (cardcard, cardsuit);

I think this is the root of your confusion here -- it looks like you're thinking of actual as a tuple, but unfortunately that's not how javascript works. You're accidentally using javascript's comma operator -- (1, 2) is an expression that returns 2. (Try logging actual, or checking its type).

If you're testing in a browser, you might want to invest some time in learning how the debugging tools work -- by stepping through the code you'll be able to see that actual wasn't of the type you thought it was. And remember that javascript isn't a completely untyped language -- you can't declare the type of a variable up front, but values have types, and you need to understand what types you're passing around.

So although conceptually you can think of a sprite's location as being identified by either a name or a tuple of coordinates, since a tuple isn't a construct in javascript, you need to pass in either a string or two separate coordinates when calling sprite:

// ok
e.sprite('name');  
// ok
e.sprite(1, 4);
// doesn't do what you want -- you're passing one argument,
// and javascript doesn't support tuples like this
let actual = (1, 4)
e.sprite( actual ); 

// Need an object to refer to multiple values together
let actual = {r: 1, c:4);
e.sprite(actual.r, actual.c);

(There are some tricks you can do by invoking apply, which can call a function with the items of an array as its arguments, but that's probably overkill in this particular case.)

But FullDeck is only a name mapped to 0,0 coordinates map{FullDeck: [0, 0]}, which seems to work-ish but doesn't seem quite right.

When you create a sprite map, under the covers Crafty generates a new component for each named sprite in the map. (You can see that each such component has the same initialization method, since they all use the same asset -- the only difference is the initial coordinate.)