前の記事の内容を修正して、スライドにまとめてみた。
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に収まるはず。