3
\$\begingroup\$

I would like to implement an object for my spritesheets in Javascript.

I'm very new to this language and game-developement so I dont really know how to do it.

My guess is I set spritesize to 16, use that to divide as many times as it fits on the spritesheet and store this value as "spritesheet". Then a for(i=0;i<spritesheet.length;i++) loop running saving the number of sprites.

Then tile = new Image(); and tile.src = spritesheet[i] to store the individual sprites based on their coordinates on the spritesheet.

My problem is how could I loop trough the spritesheet and make an array of that? The result should be similar to:

sprite.sprites = Array(
"0",
"1"
);

If possible this would be done with one single object that i only access once, and the tile array would be stored for later reference.

I couldn't find anything similar searching for "javascript spritesheet".

Edit 2: I've come a long bit since I first posted this question and this is what I've come up with so far:

function Sprite(){
    this.size = 16;
    this.spritesheet = new Image();
    this.spritesheet.src = 'spritesheet.png';
    this.spriteCount = this.spritesheet.height / this.spritesheet.width;
    this.spriteIndex = 0;
    var sprites = new Array();

    for(i=0;i<this.spriteCount;i++){
    sprites.push(this.spriteIndex); // Could insert pretty much whatever I want
    this.spriteIndex++;
    alert('spriteIndex # ' + sprites[i] + ' pushed');
    }
}
var sprite = new Sprite();

The alert method is only for testing, it alerts from 0 and up giving me usable X and Y values for the drawing (when multiplyed by size). If anyone has improvements please let me know.

Edit 3: I still have some trouble with the array. How would i access the index of it? For example the first sprite should give me sprite.sprites[0] second sprite sprite.sprites[1].

\$\endgroup\$
3
  • 1
    \$\begingroup\$ You are currently throwing away your sprites array, you have to use this.sprites instead of just sprites to be able to access it outside the function. \$\endgroup\$ Commented Mar 18, 2012 at 20:48
  • \$\begingroup\$ Oh and this.spriteCount = this.spritesheet.height / this.spritesheet.width; doesn't make a lot of sense, it would only work for a single column sprite sheet of square sprites. And by the way, imageelement.height and width only work when the image is loaded. As soon as you hit the internet with lag your code will fail at that point as the image isn't loaded when you ask for it's dimensions. You could wait for it's onload event to fire, but it would be a lot simpler to just pass the values along with the url. \$\endgroup\$ Commented Mar 18, 2012 at 20:55
  • \$\begingroup\$ Oh oops! Thats why i couldn't access it, I knew I missed something. With the map I'm using currently I can do sprites using just spriteSize, and dropping the whole function. I also thought of the problem on more than single columns, but if it comes to that it is an easy fix, i used that for quick testing. \$\endgroup\$ Commented Mar 18, 2012 at 21:19

4 Answers 4

5
\$\begingroup\$

This is a little different than your object-based approach, but here is the code I'm using to preload tiles from a spritesheet into canvas elements:

  tileSize = 16;
  sprites1x1Image = new Image();
  sprites1x1Image.src = 'images/sprites-1x1.png';
  sprites1x1Image.onload = function() {

  sprites1x1 = [];
  var names1x1 = [
  'character1', 'character2', 'obstacle1', 'obstacle2'
  ];
  for (var i=0, iLimit=names1x1.length; i<iLimit; i++) {
   sprites1x1[names1x1[i]+'Canvas'] = document.createElement('canvas');
   sprites1x1[names1x1[i]+'Canvas'].width = tileSize;
   sprites1x1[names1x1[i]+'Canvas'].height = tileSize;
   sprites1x1[names1x1[i]+'Context'] = sprites1x1[names1x1[i]+'Canvas'].getContext('2d');
   sprites1x1[names1x1[i]+'Context'].drawImage(sprites1x1Image, 0, tileSize*i, tileSize, tileSize, 0, 0, tileSize, tileSize);
  }

Then I can draw sprites onto a canvas like so:

  context.drawImage(sprites1x1['character1Canvas'], x, y);
\$\endgroup\$
1
  • \$\begingroup\$ This is not what Im after, Im looking for a more flexible way, that takes any spritesheet, and based on the tile size just splits it into sprite coordinates. This is because I will be using different spritesheets. \$\endgroup\$ Commented Mar 18, 2012 at 16:40
1
\$\begingroup\$

As far as I understand your intentions you can't do what you are looking to do, an img element doesn't take offset coordinates.

There are many tricks in the book for spritesheets, the simplest is to use set the background of a div element as that can be offset using the background-position CSS property, like so: background-position:-32px -16px;. And yes, the values have to be negative for the spritesheet trick. You should be able to shorthand it all into the CSS attribute background like so: -32px -16px url("images/sprites-1x1.png")

\$\endgroup\$
5
  • \$\begingroup\$ I was also going to say something about using stylesheets to reference the sub-image, so plus 1. Also that if you want to reference a sprite by index in code, just dynamically calculate the offset and set the css offsets directly rather than via hard-coded CSS. \$\endgroup\$
    – Tim Holt
    Commented Mar 18, 2012 at 17:40
  • \$\begingroup\$ Im not after CSS spritesheets, I know how to do that, I want a javascript function to generate an array. So I can use i*size on x,y position. I know it can be done, just need to figure out how. I'll post the answer once I got it done. \$\endgroup\$ Commented Mar 18, 2012 at 17:52
  • \$\begingroup\$ @hustlerinc It seems to me like you are mostly architecture astronauting. You can't pack everything in a slick interface, you'll never get anything done if everything has to be that perfect. \$\endgroup\$ Commented Mar 18, 2012 at 21:01
  • \$\begingroup\$ I'm not looking for perfection, just want to be able to reuse one the object independent of the sheet size. Basically I want a spritesheet object thats useable on the fly, so that if I add sprites to the sheet I dont have to edit the code. \$\endgroup\$ Commented Mar 18, 2012 at 21:36
  • \$\begingroup\$ @hustlerinc To me it seems like you are wasting a lot of time making some tool that might be a minute benefit on a few future occasions. Don't lose your scope, reusability and neatly packed functions have 0 end user value. If those features ain't saving you a lot of time they are net costs. \$\endgroup\$ Commented Mar 19, 2012 at 15:12
1
\$\begingroup\$

When I first posted this question I didn't know drawImage(); had an imageposition function. After playing around with it I came up with a solution that only needs the sprite size. The simplicity is beautiful, and I feel retarded for not thinking of it before.

Since I'm using numbers ranging from 0 and up in my map i just take that number, multiply it by spritesize and voila, spritesheets Y position on the fly.

I'll post the code in case someone needs this in the future:

// First I load the Image
sprite = new Image();
sprite.src = 'img/spritesheet.png';
// Define sprite size
spriteSize = 16;
// Draw on map, tileIndex is the number i store in the map array
ctx.drawImage(sprite, 0, tileIndex * spriteSize, spriteSize, spriteSize, tileX, tileY, spriteSize, spriteSize);
// And the map looks like this but bigger
var map = Array([0,0,0,1,1],[1,1,0,1,0]);

This can absolutely be improved but for my current project it is perfect.

\$\endgroup\$
0
\$\begingroup\$

you can use spritely, it does all the job for you... Only that you need is a image with your drawings with the same size, and it does cuts of the objects for you. Spritely it's a Jquery based plugin and have a lot of options... http://www.spritely.net/download/

\$\endgroup\$
1
  • \$\begingroup\$ Yeah I've seen that, but i prefer not using external libraries for this. It's relatively simple to do. \$\endgroup\$ Commented Mar 18, 2012 at 19:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .