前の記事の内容を修正して、スライドにまとめてみた。

スライド

boku2d(仮)という自作のライブラリを使ってナビゲーション部分を実装した。
このエンジンも判定に含めてくれるとうれしいなぁ。

メインのコードは以下のような感じ。

コピペっぽいところがあるのはご愛嬌。
(時間的に少し焦ってた)

var LoadImages = function(images) {
	for (var i in images) {
		if ($.isArray(images[i])) {
			LoadImages(images[i]);
		} else {
			var image = new Image();
			image.src = images[i];
		}
	}
};
 
Boku2D.Model.defaults.viscosity = 100;
Boku2D.Model.defaults.elastic = 1000;
 
Boku2D.Object = {};
 
// 壁
Boku2D.Object.ground = Boku2D.Model();
Boku2D.Object.ground.prototype.fixed = true;
Boku2D.Object.ground.prototype.gravity = new Boku2D.Vec();
 
// 固定物体
Boku2D.Object.fixed = Boku2D.Model();
Boku2D.Object.fixed.prototype.fixed = true;
Boku2D.Object.fixed.prototype.gravity = new Boku2D.Vec();
 
// 浮遊物体
Boku2D.Object.floating = Boku2D.Model();
Boku2D.Object.floating.prototype.gravity = new Boku2D.Vec();
Boku2D.Object.floating.prototype.elastic = 10;
Boku2D.Object.floating.prototype.viscosity = 1;
 
// 移動用土管
Boku2D.Object.navi = Boku2D.Model();
Boku2D.Object.navi.prototype.fixed = true;
Boku2D.Object.navi.prototype.gravity = new Boku2D.Vec();
Boku2D.Object.navi.prototype.updateContact = function(contact, manifold) {
	if (manifold.opponent.type === 'controll' &&
		manifold.direction.y > 0 &&
		Boku2D.keyPress[40]) {
		this.world.navi = this;
	}
};
 
// 雲
Boku2D.Object.cloud = Boku2D.Model();
Boku2D.Object.cloud.prototype.elastic = 2;
Boku2D.Object.cloud.prototype.viscosity = 1;
Boku2D.Object.cloud.prototype.fixed = true;
Boku2D.Object.cloud.prototype.gravity = new Boku2D.Vec();
Boku2D.Object.cloud.prototype.createContact = function(contact, manifold) {
	if (manifold.direction.y < 0) {
		var manifolds = contact.manifolds;
		for (var i=0,l=manifolds.length;i<l;i++) {
			manifolds[i].direction.x = 0;
			manifolds[i].direction.y = 0;
		}
	}
};
 
// 敵のジャンプや移動
Boku2D.Object.kame = Boku2D.Model();
Boku2D.Object.kame.prototype.elastic = 2;
Boku2D.Object.kame.prototype.viscosity = 1;
Boku2D.Object.kame.prototype.fixedSpeed = new Boku2D.Vec(-10, 0);
Boku2D.Object.kame.prototype.images = {
	stop : '/image/masao/kame/left.gif',
	left : ['/image/masao/kame/left.gif', '/image/masao/kame/left2.gif'],
	right : ['/image/masao/kame/right.gif', '/image/masao/kame/right2.gif'],
	treadedLeft : '/image/masao/kame/tleft.gif',
	treadedRight : '/image/masao/kame/tright.gif'
};
Boku2D.Object.kame.prototype.init = function(time) {
	if (this.fixedSpeed) {
		this.speed = this.fixedSpeed.copy();
	}
	LoadImages(this.images);
};
Boku2D.Object.kame.prototype.beforeStep = function(time) {
	if (this.fixedSpeed) {
		this.applyForce({
			x: this.force.x * -1,
			y: 0
		});
	}
 
	if (this.treaded && --this.life < 0) {
		this.world.destroyObject(this);
		$(this.elem).remove();
	}
};
Boku2D.Object.kame.prototype.createContact = function(contact, manifold) {
	if (this.fixedSpeed && manifold.direction.x * this.speed.x < 0) {
		this.speed.x *= -1;
	}
	if (manifold.opponent.type === 'controll' &&
		manifold.direction.y > 0) {
		this.treaded = true;
		this.life = 10;
		this.images = {
			stop: this.images.treadedLeft
		};
	}
};
 
// マリリ
Boku2D.Object.mariri = Boku2D.Model();
Boku2D.Object.mariri.prototype.elastic = 2;
Boku2D.Object.mariri.prototype.viscosity = 1;
Boku2D.Object.mariri.prototype.randForce = new Boku2D.Vec(100, 0);
Boku2D.Object.mariri.prototype.randJump = new Boku2D.Vec(0, -300);
Boku2D.Object.mariri.prototype.images = {
	stop : '/image/masao/mariri/stop.gif',
	upLeft : '/image/masao/mariri/jleft.gif',
	upRight : '/image/masao/mariri/jright.gif',
	downLeft : '/image/masao/mariri/dleft.gif',
	downRight : '/image/masao/mariri/dright.gif',
	treadedLeft : '/image/masao/mariri/tleft.gif',
	treadedRight : '/image/masao/mariri/tright.gif'
};
Boku2D.Object.mariri.prototype.init = function(time) {
	LoadImages(this.images);
};
Boku2D.Object.mariri.prototype.beforeStep = function(time) {
	if (this.randForce) {
		this.applyForce(this.randForce.multiply(Math.random()-0.5));
	}
	if (this.randJump && Math.random() < 0.1 && this.canJump()) {
		this.applyForce(this.randJump);
	}
 
	if (this.treaded && --this.life < 0) {
		this.world.destroyObject(this);
		$(this.elem).remove();
	}
};
Boku2D.Object.mariri.prototype.createContact = function(contact, manifold) {
	if (manifold.opponent.type === 'controll' &&
		manifold.direction.y > 0) {
		this.treaded = true;
		this.life = 10;
		this.images = {
			stop: this.images.treadedRight
		};
	}
};
 
// ポッピー
Boku2D.Object.poppi = Boku2D.Model();
Boku2D.Object.poppi.prototype.elastic = 2;
Boku2D.Object.poppi.prototype.viscosity = 1;
Boku2D.Object.poppi.prototype.fixedSpeed = new Boku2D.Vec(-10, 0);
Boku2D.Object.poppi.prototype.gravity = new Boku2D.Vec(0, 0);
Boku2D.Object.poppi.prototype.images = {
	stop : '/image/masao/poppi/left.gif',
	left : ['/image/masao/poppi/left.gif', '/image/masao/poppi/left2.gif'],
	right : ['/image/masao/poppi/right.gif', '/image/masao/poppi/right2.gif'],
	treadedLeft : '/image/masao/poppi/tleft.gif',
	treadedRight : '/image/masao/poppi/tright.gif'
};
Boku2D.Object.poppi.prototype.init = function(time) {
	if (this.fixedSpeed) {
		this.speed = this.fixedSpeed.copy();
	}
	LoadImages(this.images);
};
Boku2D.Object.poppi.prototype.beforeStep = function(time) {
	if (this.fixedSpeed) {
		this.applyForce({
			x: this.force.x * -1,
			y: 0
		});
	}
 
	if (this.treaded && --this.life < 0) {
		this.world.destroyObject(this);
		$(this.elem).remove();
	}
};
Boku2D.Object.poppi.prototype.createContact = function(contact, manifold) {
	if (this.fixedSpeed && manifold.direction.x * this.speed.x < 0) {
		this.speed.x *= -1;
	}
	if (manifold.opponent.type === 'controll' &&
		manifold.direction.y > 0) {
		this.treaded = true;
		this.life = 10;
		this.images = {
			stop: this.images.treadedLeft
		};
	}
};
 
// 正男
Boku2D.Object.controll = Boku2D.Model();
Boku2D.Object.controll.prototype.viscosity = 1;
Boku2D.Object.controll.prototype.elastic = 10;
Boku2D.Object.controll.prototype.type = 'controll';
Boku2D.Object.controll.prototype.controll = {
	37: new Boku2D.Vec(-50, 0),
	39: new Boku2D.Vec(50, 0)
};
Boku2D.Object.controll.prototype.jump = new Boku2D.Vec(0, -800);
Boku2D.Object.controll.prototype.gravity = new Boku2D.Vec(0, 30);
Boku2D.Object.controll.prototype.maxSpeed = new Boku2D.Vec(30, 1000);
Boku2D.Object.controll.prototype.images = {
	stop : '/image/masao/stop.gif',
	left : ['/image/masao/left.gif', '/image/masao/left.gif', '/image/masao/left.gif',
		'/image/masao/left2.gif', '/image/masao/left2.gif', '/image/masao/left2.gif'],
	right : ['/image/masao/right.gif', '/image/masao/right.gif', '/image/masao/right.gif',
		'/image/masao/right2.gif', '/image/masao/right2.gif', '/image/masao/right2.gif'],
	upRight : '/image/masao/uright.gif',
	upLeft : '/image/masao/uleft.gif',
	downRight : '/image/masao/dright.gif',
	downLeft : '/image/masao/dleft.gif'
	// brakeRight : '/image/masao/bright.gif',
	// brakeLeft : '/image/masao/bleft.gif'
};
Boku2D.Object.controll.prototype.init = function(time) {
	LoadImages(this.images);
};
Boku2D.Object.controll.prototype.beforeStep = function(time) {
	if (this.jump && Boku2D.keyPress[38] && this.canJump()) {
		// ジャンプ時の高さを一定に
		this.applyForce({
			x: 0,
			y: this.force.y * -1
		});
		this.applyForce(this.jump);
	}
 
	if (-this.maxSpeed.x < this.speed.x && this.speed.x < this.maxSpeed.x) {
		for (var key in this.controll) {
			if (Boku2D.keyPress[key]) {
				var force = this.controll[key];
				this.applyForce(force);
			}
		}
	}
 
	// 横向きに空気抵抗
	this.applyForce({
		x: this.speed.x * -1,
		y: 0
	});
};
 
// タワー
Boku2D.Object.tower = Boku2D.Model();
Boku2D.Object.tower.prototype.elastic = 1;
Boku2D.Object.tower.prototype.viscosity = 2;
Boku2D.Object.tower.prototype.friction = 10;
Boku2D.Object.tower.prototype.fixed = true;
Boku2D.Object.tower.prototype.gravity = new Boku2D.Vec();
 
// キー操作
Boku2D.keyPress = {};
jQuery(document).keydown(function (e) {
	Boku2D.keyPress[e.keyCode] = true;
});
jQuery(document).keyup(function (e) {
	Boku2D.keyPress[e.keyCode] = false;
});
Boku2D.Model.defaults.canJump = function() {
	var contacts = this.contacts,
		onGround = false;
	for (var i=0,l=contacts.length;i<l;i++) {
		var contact = contacts[i],
			m0 = contact.manifolds[0],
			m1 = contact.manifolds[1];
		if ((m0.object === this && m0.direction.y < 0) ||
			(m1.object === this && m1.direction.y < 0)) {
			onGround = true;
			break;
		}
	}
	return onGround;
};
 
// 画像調整
var afterStep = Boku2D.Model.defaults.afterStep;
Boku2D.changeImage = Boku2D.Model.defaults.afterStep = function(time) {
	if (this.images) {
		var margin = 5;
 
		this.setImage('stop');
 
		if (this.speed.x < -margin) {
			this.setImage('left');
			if (this.accel.x > 0) {
				this.setImage('brakeLeft');
			}
		}
		if (this.speed.x > margin) {
			this.setImage('right');
			if (this.accel.x < 0) {
				this.setImage('brakeRight');
			}
		}
 
		if (this.speed.y < -margin) {
			this.setImage('up');
			if (this.speed.x < -margin) {
				this.setImage('upLeft');
			}
			if (this.speed.x > margin) {
				this.setImage('upRight');
			}
		}
		if (this.speed.y > margin) {
			this.setImage('down');
			if (this.speed.x < -margin) {
				this.setImage('downLeft');
			}
			if (this.speed.x > margin) {
				this.setImage('downRight');
			}
		}
 
		$(this.elem).attr('src', this.image)
	}
 
	afterStep.call(this, time);
};
Boku2D.Model.defaults.setImage = function(type) {
	if (this.images) {
		var image = this.images[type];
		if ($.isArray(image) && image.length > 0) {
			if (!image.now) {
				image.now = 0;
			}
			this.image = image[image.now++ % image.length]
		} else if (image) {
			this.image = image;
		}
	}
};
 
$(function() {
	$('#slides').slide();
});
$.fn.Boku2D = function() {
	return this.each(function() {
		var world = new Boku2D.World();
		world.initDOM($(this).get(0));
 
		$('.object', this).each(function() {
			var object = new Boku2D.Object[$(this).data('model')]();
			object.initDOM($(this).get(0));
			world.createObject(object);
		});
 
		var timer = setInterval(function () {
			world.step(0.1);
			if (world.navi) {
				$(world.navi.elem).click();
			}
		}, 13);
		$(this).data('timer', timer);
		$(this).data('world', world);
	});
};
$.fn.stopBoku2D = function() {
	return this.each(function() {
		var timer = $(this).data('timer');
		var world = $(this).data('world');
		if (world) {
			clearInterval(timer);
			world.destroy();
		}
	});
};
$.fn.startSlide = function() {
	return this.each(function() {
		$(this).show();
		var that = this;
		setTimeout(function() {
			$(that).find('.world').Boku2D();
		}, 300);
	});
};
$.fn.endSlide = function() {
	return this.each(function() {
		$(this).hide()
			.find('.world').stopBoku2D();
	});
};
$.fn.slide = function() {
	return this.each(function() {
		$('.slide', this).endSlide();
		$('.slide:first', this).startSlide();
 
		$('.next', this).bind('click', function() {
			$(this).closest('.slide').endSlide()
				.next('.slide').startSlide();
		});
		$('.prev', this).bind('click', function() {
			$(this).closest('.slide').endSlide()
				.prev('.slide').startSlide();
		});
	});
};

jQueryを除けば100KBに収まるはず。