Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

1 decade ago by Gary

I've been trying to create 'building' entities to dynamically spawn across the canvas at various different heights.

Thus far I seem to be doing ok with the entity size itself, but I'm struggling with the animation sheet.

Initially I was planning to tile an image to a specific height by drawing it directly, but I found a post somewhere that suggested creating an image just taller than the maximum height of my entity and adjusting the size of the animation sheet... This sounded much easier!

What I need to do, is override the height of the animationSheet, but I seem unable to do this.

My entity looks like this:
	// Building
	EntityBuilding = ig.Entity.extend({
			size: {x:32, y:272}
		,	type: 1
		,	buildingHeight: 50
		,	buildingBlockHeight: 8
		,	animSheet: new ig.AnimationSheet('media/buildings.png', 32)

		// Collision
		,	type: ig.Entity.TYPE.A
		,	checkAgainst: ig.Entity.TYPE.BOTH
		,	collides: ig.Entity.COLLIDES.FIXED

		,	init: function(x, y, settings) {
				this.parent(x, y, settings);
				this.addAnim('idle', 1, [0]);

				// Multiply the block size by the specified building height
				this.buildingHeight = this.buildingHeight * this.buildingBlockHeight;
				this.size.y = this.buildingHeight;
				this.animSheet.height = this.buildingHeight
			}

As you can see, I'm attempting to set the height of the animSheet on init. If I send the animSheet to the console, I can see the correct height listed - but the height of the image used doesn't change.
I have some defaults for buildingHeight and the size of the entity, but these are being overwritten but my spawnEntity call. This seems to work fine for the size of the entity, but not for the animationSheet.

					// Loop for a row of buildings
					for (i=0; i < this.maxBuildings; i++) {
						// Set building settings
						var buildingSettings = {
								type: Math.floor(Math.random() * 6) + 1
							,	buildingHeight: randomFromInterval(6, this.maxBuildingHeight)
						}

						// Spawn building 
						this.spawnEntity(EntityBuilding, buildingPosition + 4, 0, buildingSettings);

						// Update building position
						buildingPosition = buildingPosition + 32;
					}

Can anyone see what I'm doing wrong?
Is there perhaps, a more sensible way to do this?

Thanks

1 decade ago by vincentpiel

a simpler approach might be to just override the draw() of your entity, and have it scale your entity.
So something like :


_initialSize :   size: {x:32, y:272},  // you need to save initial size. Private ro member.
_entityScale : 1,                           // the scale factor for this entity. Private member.
ChangeScale : function (newScale) 
{
     this._entityScale = newScale;
     this.size.x = this._initialSize.x*newScale;   this.size.y=this._initialSize.y*newScale;
},
draw : function() {
                var ctx = ig.system.context;
  		if( this.currentAnim ) {
                        ctx.save();
                        ctx.scale(ig.system.scale, ig.system.scale);
                        ctx.translate(this.pos.x - this.offset.x - ig.game._rscreen.x,
				                           this.pos.y - this.offset.y - ig.game._rscreen.y );
                        ctx.scale(this._entityScale, this._entityScale);
			this.currentAnim.draw(0,0);
                        ctx.restore();
			);
		}

// ... and in your init, you call this.ChangeScale  with the scale 
//           of your choice (<1 smaller, >1 bigger).
//  expl for a size between half size and 3 times bigger : 
//                    this.changeScale(0.5+Math.random()*2.5) ;


Another solution is to inject ig.Animation, ig.AnimationSheet and ig.Image so that they support scaling/rotation. I did it, but it needs some work.

1 decade ago by quidmonkey

I wrote a plugin for scaling Entities.

1 decade ago by Gary

Thanks for the responses guys, but I think perhaps I've not explained what I'm trying to do too well...
I don't want to scale my entity. I want to change its physical size and either tile the animation sheet to fit, or in this latest attempt merely dynamically assign the size of the animation sheet.
The idea is that the buildings will be of various different heights, but all using the same animationsheet.
What I've found is that if I create an image of a very tall building - taller than the tallest one in my game - I can specify a smaller height for my entity and in the animationsheet and it will correctly create a smaller building, only showing as much of the animationsheet as I've specified.
Where I'm coming unstuck, is passing a specific height with the spawnEntity method. It works for the physical height of the entity but has no effect on the animationsheet.

Does that make sense?

1 decade ago by Gary

Beginning to think this might not be possible... I managed to adjust the height of the animation sheet when a bomb entity collides with the building entity, but it updates the animation sheet size of every building entity at once (all different sizes), rather than just the subject of the collision. I think I've misunderstood how animation sheets work...

Does anyone have any suggestions as to how I might achieve the effect? The building entities should all be different heights, but I was hoping to use the same sprites for all of them - tiled, not stretched or scaled.
When a bomb entity hits a building entity, the height of the building should decrease. I can do this with a filled rectangle easily enough but not sprites. I could look into manually drawing the png onto the canvas after each hit, but I'd imagine that'll incur a performance hit.

Still very new to this, so possibly missing something very obvious.

1 decade ago by vincentpiel

ok, so i thought you wanted the 'same' buildings to be displayed in various sizes, but i think i get your idea now.
Just an idea : you can use an image as a texture to fill a rectangle :
http://www.w3schools.com/tags/canvas_createpattern.asp
so this, that you also combine with a scaling (to simulate buildings getting smaller with the distance) might get you to the answer.
But anyway with such a specific need for your buildings, you will have to redefine the draw() of your building entity.

(rq : IF there's a performance issue with using a fill pattern + a scale every draw(), you can still render it once in a new canvas, and then only re-draw the canvas. But have it working before making it fast ;-) )

1 decade ago by StuartTresadern

Gary, when the buildings get hit do you want to remove a tile worth of building or a fraction of a tile ?

1 decade ago by Gary

Thanks Vincent, I'll give that a go. As it happens, I don't need the buildings to scale as there's only one point of distance - however the suggestion does give me a nice idea for improving the game! ;)

Stuart: I was looking to remove a tile worth of building, or more accurately three tiles worth - however I originally gave up on the idea of tiling in favour of simply having an image larger than the specified height of the animation sheet. This worked ok and allowed me to simply specify a new height for the building when it was hit - however as stated, I can't get the animationsheet to update dynamically per building.

You mention removing a fraction of a tile however and I'd love to know how to do that!!! When a bomb entity hits I'm generating particles for the explosion - if those particles could remove tiny fragments of surrounding buildings that would be very cool. ;)

1 decade ago by StuartTresadern

You could do it all with tiles, sounds like it would work well with the plugin I created some time back :
http://impactjs.com/forums/code/dynamic-map-plugin

This helps get around the problem of having an animated map but without the Overhead of drawing all the tiles every update. If you take a look at the breakout clone http://impactjs.com/forums/code/tile-value-plugin that I created out of tiles (just to Show how it works) you will also see that I use value tiles to Keep track of the number of hits to a tile and Change the tile based on its new value. You could use the same idea to Change the building tiles to damged versions when the particles hit.

1 decade ago by Gary

Thanks Stuart, there's some interesting ideas there - I'll have to have a mess about with your plugins to see if I understand it properly. As it happens, I'd already come across your breakout clone as I was making one myself last month! Haven't gotten around to finishing it though, just using it to learn the framework... loads of fun, this. ;)

1 decade ago by Gary

Well, I've basically got it working using the texture fill method suggested by Vincent (createPattern).
Took me a while to get my head around it, but I have it working... in Chrome.
In Firefox it works fine for about 30 seconds - and then freezes the browser completely!
This seems to only happen if I'm using createPattern.
I wondered if anyone had experienced this or had any more suggestions?!

Here's a bit of code for reference:
	// Building
	EntityBuilding = ig.Entity.extend({
			size: {x:32, y:272}
		,	type: 1
		,	buildingHeight: 50
		,	buildingBlockHeight: 8
		,	tiles: new ig.Image( 'media/buildingTiles.png' )
		,	buildingTop: new ig.Image( 'media/buildingTop.png' )
		,	buildingTopScathed: new ig.Image( 'media/buildingTopScathed.png' )
		,	unscathed: 1

		// Collision
		,	type: ig.Entity.TYPE.B
		,	checkAgainst: ig.Entity.TYPE.BOTH
		,	collides: ig.Entity.COLLIDES.FIXED

		,	init: function(x, y, settings) {
				this.parent(x, y, settings);

				// Multiply the block size by the specified building height
				this.buildingHeight = this.buildingHeight * this.buildingBlockHeight;
				this.size.y = this.buildingHeight;

			}

		,	draw: function() {
		        ig.system.context.beginPath();
				ig.system.context.fillStyle = ig.system.context.createPattern(this.tiles.data, 'repeat'); // Tile
		        ig.system.context.fillRect(
		                        this.pos.x * ig.system.scale, 
		                        this.pos.y * ig.system.scale, 
		                        this.size.x * ig.system.scale, 
		                        this.size.y * ig.system.scale 
		                    );
		        ig.system.context.closePath();

				// Draw top of buildings
				if(this.unscathed) {
					this.buildingTop.draw((this.pos.x * ig.system.scale), (ig.system.height - 48) - this.size.y);
				}
				else {
					this.buildingTopScathed.draw((this.pos.x * ig.system.scale), (ig.system.height - 36) - this.size.y);
				}

				this.parent();
			}

1 decade ago by StuartTresadern

Not sure ist still the case but I always had Problems with what fill / Patterns would work with different Browsers. Also unless you can Cache the fill it can be very slow, depends on the speed of the game but you will normally find drawing Images a lot faster.
Page 1 of 1
« first « previous next › last »