Inventories and Items

Modifying classes and code

We now need to update some of our existing code and classes. Firstly, we'll add the parameter itemStack to the Tile object:

	this.itemStack	= null;

Modifying the Character class

Each Character will have its own inventory. To the Character class, we'll add the inventory property, which will have an Inventory object with 3 slots:

	this.inventory = new Inventory(3);

The Character class will have a new pickUp method for picking up items the character is standing on. This method will firstly check that the character is not currently moving, by ensuring the x, y properties of the tileFrom, tileTo parameters are the same. If they are not, we won't allow the character to try and pick up yet, so we'll return false:

Character.prototype.pickUp = function()
{
	if(this.tileTo[0]!=this.tileFrom[0] ||
		this.tileTo[1]!=this.tileFrom[1])
	{
		return false;
	}

We'll now get a reference to the PlacedItemStack on the tile on which the character is standing in the is variable:

	var is = mapTileData.map[toIndex(this.tileFrom[0],
				this.tileFrom[1])].itemStack;

If the is variable is not null, we'll add the item stack to the characters inventory and store the result of the addItems method to the remains variable.

	if(is!=null)
	{
		var remains = this.inventory.addItems(is.type, is.qty);

If the characters invetory was filled before collecting all the items here, the value of remains will be greater than 0 - in this case we'll just update the qty of the PlacedItemStack, is, to the number of remaining items.

Otherwise, we'll clear the reference to the PlacedItemStack for the current tile, as the stack has been "picked up". After, we can close the else/if block and the method itself, after returning true to show we collected some items (or at least attempted to do so).

		if(remains) { is.qty = remains; }
		else
		{
			mapTileData.map[toIndex(this.tileFrom[0],
				this.tileFrom[1])].itemStack = null;
		}
	}
	
	return true;
};

onload item placement

To place some example items on our map, we'll add a bit of code to the window.onload event handler. This will just create a couple of lines of the star item, one horizontally and one vertically. At each loop iteration, we just create a new PlacedItemStack object with the itemTypes id 1, and the qty 1. We then place the stack at an x, y position determined by our loops.

	for(var i = 3; i < 8; i++)
	{
		var ps = new PlacedItemStack(1, 1); ps.placeAt(i, 1);
	}
	for(var i = 3; i < 8; i++)
	{
		var ps = new PlacedItemStack(1, 1); ps.placeAt(3, i);
	}

Drawing items & Inventory

To draw items to the map, we'll add the following code inside our nested y, x drawing loops. After the if(z==0) { ... } section used to draw floor tiles, we'll add an else if statement to check the z value is 1, and if so we'll get a reference is to the itemStack property of the current tile.

If is is not null, we'll draw the sprite for the corresponding itemTypes entry here:

			else if(z==1)
			{
				var is = mapTileData.map[toIndex(x,y)].itemStack;
				if(is!=null)
				{
					var sprite = itemTypes[is.type].sprite;
					
					ctx.drawImage(tileset,
						sprite[0].x, sprite[0].y,
						sprite[0].w, sprite[0].h,
						viewport.offset[0] + (x*tileW) + itemTypes[is.type].offset[0],
						viewport.offset[1] + (y*tileH) + itemTypes[is.type].offset[1],
						sprite[0].w, sprite[0].h);
				}
			}

After the nested drawing loops, we'll draw the player inventory. We'll set the text alignment to the right, then loop over all the possible spaces in the players inventory, and draw a filled rectangle at the bottom-left (moving right for each successive inventory slot) for each iteration:

	ctx.textAlign = "right";
	
	for(var i = 0; i < player.inventory.spaces; i++)
	{
		ctx.fillStyle = "#ddccaa";
		ctx.fillRect(10 + (i * 50), 350,
			40, 40);

If there's an entry in the players inventory at the specified offset, we'll get a reference to the itemTypes entry for this stack, and its sprite, and draw the sprite here:

		if(typeof player.inventory.stacks[i]!='undefined')
		{
			var it = itemTypes[player.inventory.stacks[i].type];
			var sprite = it.sprite;
					
			ctx.drawImage(tileset,
				sprite[0].x, sprite[0].y,
				sprite[0].w, sprite[0].h,
				10 + (i * 50) + it.offset[0],
				350 + it.offset[1],
				sprite[0].w, sprite[0].h);

If the qty of the stack at this point in the inventory is more than one, we'll show the quantity at the bottom-right of this inventory icon:

			if(player.inventory.stacks[i].qty>1)
			{
				ctx.fillStyle = "#000000";
				ctx.fillText("" + player.inventory.stacks[i].qty,
					10 + (i*50) + 38,
					350 + 38);
			}

We'll then close the if statement and the loop. After the loop has completed, we'll reset the text alignment to the left.

		}
	}
	ctx.textAlign = "left";
Page loaded in 0.011 second(s).