font-family:Geogrotesque,Helvetica; color:#fff; background-color:#3F3F3F; }
body { font-family:Geogrotesque, Helvetica; font-size:12pt; }
h1 { position:fixed; top:0; right:0; margin:0; padding:0; font-size:3em; color:#000; opacity:0.25; z-index:100; }
+h2, h3, h4, h5 { margin:0; margin-bottom:0.5em; }
ul, ol, li { list-style: none ! important; margin:0; padding:0; }
.rounded { border-radius:1em; -moz-border-radius:1em; -webkit-border-radius:1em; }
+.box {
+ padding:0.5em; background-color:rgba(0,0,0, 0.1); color:#787878;
+ border-radius:1em; -moz-border-radius:1em; -webkit-border-radius:1em; }
-#viewport { position:relative; top:1em; width:500px; height:500px; margin:0 auto; overflow:hidden;
- /* outline:1px solid #aaa; */ }
+#controls { position:fixed; top:1em; left:1em; width:250px; }
+ #controls > div { position:relative; }
+ #controls label { position:relative; width:30%; display:inline-block; }
+ #controls input { position:absolute; width:40%; top:0; right:0; text-align:center;
+ border:0; background-color:rgba(0,0,0, 0.1) ! important; color:#5c5c5c; }
-#howto { position:fixed; top:3em; right:1em; color:#BFBFBF; }
-
-#info { position:fixed; bottom:10px; right:10px; padding:0.5em; background-color:rgba(0,0,0, 0.1); color:#787878; }
+#viewport { position:relative; top:1em; width:500px; height:500px; margin:0 auto; overflow:hidden; }
+#info { position:fixed; bottom:10px; right:1em; }
#info #state { font-weight:bold; }
#info label { display:block; float:left; width:3em; margin-right:0.5em; color:#787878; }
#info input { border:0; background-color:transparent; min-width:5em; width:5em; color:#5c5c5c; }
#info .sep { opacity:0.1; background-color:#999; margin:5px 0; height:1px; }
#info .fps-sparkline { width:100%; height:1.5em; margin-top:0.5em; }
+
+#howto { position:fixed; top:3em; right:1em; color:#BFBFBF; }
+
<link rel="stylesheet" href="css/lttl.css" type="text/css" media="screen">
</head>
<body class="lttl tanks">
+ <h1>The Littlest Battletank</h1>
-<div id="viewport"></div>
-
-<h1>The Littlest Battletank</h1>
-
-<div id="controls">
- <label for="nbullets">Num Bullets</label> <input id="nbullets" name="nbullets" value="15" type="text">
+<div id="controls" class="box">
+ <h3>config</h3>
+ <div><label for="bullets">bullets</label> <input id="bullets" name="bullets" value="10" type="text"></div>
</div>
-<ul id="info" class="rounded">
+<div id="viewport"></div>
+<ul id="info" class="box">
<li id="state"></li>
<li><div class="fps-sparkline"></div></li>
- <li><label for="fps">fps</label> <input id="fps" name="fps" value="" type="text"></li>
- <li><label for="frame">frame</label> <input id="frame" name="frame" value="" type="text"></li>
+ <li><label for="info_fps" >fps</label> <input id="info_fps" name="fps" value="" type="text"></li>
+ <li><label for="info_frame" >frame</label> <input id="info_frame" name="frame" value="" type="text"></li>
<li><div class="sep"></div></li>
- <li><label for="objects">objects</label> <input id="objects" name="objects" value="" type="text"></li>
- <li><label for="units">units</label> <input id="units" name="units" value="" type="text"></li>
- <li><label for="bullets">bullets</label> <input id="bullets" name="bullets" value="" type="text"></li>
+ <li><label for="info_objects">objects</label> <input id="info_objects" name="objects" value="" type="text"></li>
+ <li><label for="info_units" >units</label> <input id="info_units" name="units" value="" type="text"></li>
+ <li><label for="info_bullets">bullets</label> <input id="info_bullets" name="bullets" value="" type="text"></li>
</ul>
<div id="scripts">
- <!--[if IE]><script type="text/javascript" src="lib/excanvas.min.js"></script><![endif]-->
<?php require "tanks.php"; Tanks::writeTags( Tanks::ALL_SCRIPTS ); ?>
</div>
function y_dump($expose=false) {
global $y_files;
+ header('Content-type: application/javascript; charset=UTF-8');
if (!$expose)
dump_file("./_intro.js");
foreach ($y_files as $f)
// Show definition points
if ( this.drawDefinitionPoints ) {
- this.point(p1.x,p1.y, 'rgba(69,150,255,0.4)');
- this.point(p2.x,p2.y, 'rgba(69,150,255,0.4)');
+ this.point(p1.x,p1.y, 'rgba(46,98,201, 0.4)');
+ this.point(p2.x,p2.y, 'rgba(69,150,255, 0.4)');
}
},
Game = new Y.Class('Game', {
+ showOverlay : true,
init : function init(viewport){
this.loop = new EventLoop(this, FRAME_RATE);
this.addEventListener('tick', this.tick);
},
- showOverlay : false,
+
+ draw : function draw(){
+ this.root.draw();
+ this.pathmap.removeOverlay(this.viewport);
+ if (this.showOverlay)
+ this.pathmap.overlay(this.viewport);
+ },
/**
* Main Event Loop.
SQUARETH = REF_SIZE * SECONDTH
this.units.invoke('act');
-
- this.root.draw();
-
// XXX: Collect the dead
- // this.grid.removeOverlay(this.el);
- // if (this.showOverlay) this.grid.overlay(this.el);
+ this.draw();
}
});
function setupUI(){
spark = LBT.loop.spark = new FpsSparkline(LBT.loop, '.fps-sparkline', 0,0);
+ btank = new Tank(0);
+ btank.act = function(){ return this; };
+ LBT.addUnit(btank, 0,0);
+ LBT.pathmap.removeBlocker(btank);
+ btank.shape.hide();
+
LBT.root.draw();
// Start button (click or return key)
$(document).bind('keydown', 'return', toggleGame);
$(document).bind('keydown', 'ctrl+o', toggleOverlay);
- var bullets = new Y.YArray();
-
- $('#nbullets').bind('blur', function(){
- var n = parseInt($('#nbullets').val());
-
- if ( isNaN(n) || n === bullets.size() ) return;
-
- while (n < bullets.size()) {
- var i = Math.round(rand(0, bullets.size()-1));
- bullets.remove( bullets.attr(i).remove() );
- }
-
- while (n > bullets.size())
- bullets.push(spawnBullet());
+ $('#bullets').bind('blur', function(evt){
+ var n = parseInt($('#bullets').val() || 0);
+ updateBullets(n);
});
- $('#nbullets').blur();
+ $('#bullets').blur();
- // Draw grid, initial units
LBT.root.draw();
-
setInterval(updateInfo, 1000);
- // updateInfo();
- toggleGame();
+ // Start the simulation!
+ // toggleGame();
+ updateInfo();
+
// Fix grid-size on resize
// $(window).bind('resize', resizeGame);
}
-function rand(a,b){ return a + Math.random()*(b-a); }
-function randOpenLoc(){
- do {
- var x = rand(0,COLUMNS*REF_SIZE)
- , y = rand(0,ROWS*REF_SIZE);
- } while ( LBT.pathmap.get(x,y, x+6,y+6).size() );
- return new math.Vec(x,y);
-}
+var BULLETS = new Y.YArray();
function spawnBullet(x,y, atX,atY){
if (x === undefined && y === undefined) {
atY = rand(0,ROWS*REF_SIZE);
} while ( atX === x && atY === y);
- T.setLocation(x,y);
- var p = T.fireProjectile(atX,atY);
- // console.log('spawnBullet(',x,y, atX,atY,') -->', p);
- return p;
+ btank.setLocation(x,y);
+ return btank.fireProjectile(atX,atY);
}
+function updateBullets(n){
+ if ( !Y.isNumber(n) || isNaN(n) || n === BULLETS.size() ) return;
+
+ while (n < BULLETS.size()) {
+ var i = Math.round(rand(0, BULLETS.size()-1));
+ BULLETS.remove( BULLETS.attr(i).remove() );
+ }
+
+ while (n > BULLETS.size())
+ BULLETS.push(spawnBullet());
+}
+
+function rand(a,b){ return a + Math.random()*(b-a); }
+function randOpenLoc(){
+ do {
+ var x = rand(0,COLUMNS*REF_SIZE)
+ , y = rand(0,ROWS*REF_SIZE);
+ } while ( LBT.pathmap.get(x,y, x+6,y+6).size() );
+ return new math.Vec(x,y);
+}
+
+
// Update performance info periodically
function updateInfo(){
}
}
+// function initUki(){
+// uki({ view:'Box', rect:'0 0 250 500', anchor:'top width', className:'box', childViews:[
+// { view:'Box', rect:'8 8 250 0', anchor:'top width height', childViews:[
+// { view:'HFlow', rect:'250 25', anchor:'width', childViews:[
+// { view:'Label', rect:'200 25', anchor:'top left', text:'Bullets' },
+// { view:'TextField', rect:'50 25', anchor:'top right', name:'bullets', value:'10', background:'' }
+// ]}
+// ]}
+// ]})
+// .attachTo(
+// $('<div/>').css({
+// 'position':'relative',
+// 'width':'100%',
+// 'top':0, 'left':0
+// }).appendTo('#controls')[0], '0 0');
+// // .attachTo(window, '10 10');
+// }
new Wall(3*sq,6*sq, 1*sq,1*sq)
);
- T = new Tank(0);
- LBT.addUnit(T, 1,2);
-
- LBT.pathmap.removeBlocker(T);
- T.shape.hide();
-
- // T.fireProjectile(5*sq,5*sq);
- // T.fireProjectile(1*sq,3*sq);
- // T.fireProjectile(6*sq,1.5*sq);
- // T.fireProjectile(0.5*sq,0.5*sq);
- //
- // T.setLocation(3*sq,3*sq);
- // T.fireProjectile(1*sq,1*sq);
-
+ T = LBT.addUnit(new Tank(0), 1,2);
P = new Player(LBT, T);
setupUI();
-
- // T.setLocation(1*sq,2*sq);
}
},
moveByAngle : function moveByAngle(theta, v){
- var x = this.x + v*Math.sin(theta)
- , y = this.y + v*Math.cos(theta);
+ var x = this.x + v*Math.cos(theta)
+ , y = this.y + v*Math.sin(theta);
return new Loc(x,y);
},
dirToAngle : function dirToAngle(dir){
switch (dir) {
case Loc.RIGHT: return 0;
- case Loc.UP: return HALF_PI;
+ case Loc.UP: return PI_AND_HALF;
case Loc.LEFT: return PI;
- case Loc.DOWN: return PI_AND_HALF;
+ case Loc.DOWN: return HALF_PI;
default: throw new Error("wtf direction is "+dir+"??");
}
},
attemptMove : function attemptMove(obj, trj, to){
- var wall, blocker, what, bb = obj.boundingBox
+ var wall, blocker, what
+ , clamp = math.clamp
+ , bb = obj.boundingBox
, maxW = this.width, maxH = this.height
, w = bb.width, h = bb.height
, x1 = to.x, y1 = to.y
, x2 = x1+w, y2 = y1+h
;
- // Check for collision with the walls
- // if (x1 < 0 || x2 > maxW || y1 < 0 || y2 > maxH){
- // blocker = this.game.level;
- // what = 'LevelWall on the ';
- //
- // if (x1 < 0) {
- // what = 'left';
- // wall = this.walls.left;
- // to = trj.pointAtX(0);
- //
- // } else if (x2 > maxW) {
- // what = 'right';
- // wall = this.walls.right;
- // to = trj.pointAtX(maxW-w);
- //
- // } else if (y1 < 0) {
- // what = 'top';
- // wall = this.walls.top;
- // to = trj.pointAtY(0);
- //
- // } else if (y2 > maxH) {
- // what = 'bottom';
- // wall = this.walls.bottom;
- // to = trj.pointAtY(maxH-h);
- // }
- //
- // }
-
// Check for pathmap collisions
var blockers = this.get(x1,y1, x2,y2).remove(obj);
if (blockers.size() > 1){
}
}
+ to.setXY(
+ clamp(to.x, 2,maxW-2),
+ clamp(to.y, 2,maxH-2) );
+
what += ' at '+wall;
return { 'ok':!wall, 'to':to, 'wall':wall, 'blocker':blocker, 'what':what };
},
, h = this.height *SCALE
, canvas = $('.overlay', gridEl)[0];
- if (!canvas)
+ if (!canvas) {
canvas = $('<canvas class="overlay" style="position:absolute"/>').prependTo(gridEl)[0];
-
- $(canvas).width(w).height(h);
- canvas.width = w;
- canvas.height = h;
+ $(canvas).width(w).height(h);
+ canvas.width = w;
+ canvas.height = h;
+ }
var ctx = canvas.getContext('2d');
ctx.scale(SCALE, SCALE);
// Clear the canvas
ctx.beginPath();
- ctx.fillStyle = 'rgba(0,0,0,0)';
- ctx.lineWidth = 0;
- ctx.fillRect(this.x,this.y, w,h);
+ // ctx.fillStyle = 'rgba(0,0,0,0)';
+ // ctx.lineWidth = 0;
+ ctx.clearRect(this.x,this.y, w,h);
ctx.closePath();
+ ctx.fillStyle = 'rgba(255,255,255,0.1)';
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = 'rgba(255,255,255,0.2)';
+
+
// Draw regions
this.reduce(function(acc, value, r, tree){
if ( acc[r.id] ) return acc;
acc[r.id] = r;
ctx.beginPath();
- ctx.fillStyle = 'rgba(255,255,255,0.1)';
- ctx.lineWidth = 1;
- ctx.strokeStyle = 'rgba(255,255,255,0.2)';
+ // ctx.fillStyle = 'rgba(255,255,255,0.1)';
+ // ctx.lineWidth = 1;
+ // ctx.strokeStyle = 'rgba(255,255,255,0.2)';
ctx.rect(r.x1,r.y1, r.width,r.height);
ctx.fill();
ctx.stroke();
Bullet = new Y.Class('Bullet', Thing, {
+ traceTrajectories : true,
+
/**
* @param {tanks.Unit} owner
createCooldowns : Y.op.nop,
+
+ setLocation : function setLocation(x,y){
+ var loc = this.loc;
+ if (loc && loc.x === x && loc.y === y)
+ return loc;
+
+ loc = this.loc = new Loc(x,y);
+
+ if (this.shape) this.shape.position(x,y);
+ var w2 = this.width/2, h2 = this.height/2;
+ this.boundingBox = new Loc.Rect(x-w2,y-h2, x+w2,y+h2);
+
+ return this;
+ },
+
// setLocation : function setLocation(x,y){
// var trj = this.trajectory;
// this.trajectory = new math.Line(x,y, trj.x2,trj.y2, trj.tdist);
if (this.tline) this.tline.remove();
if (this.shape) this.shape.remove();
+ if (this.traceTrajectories) {
var t = this.trajectory;
- this.tline = Line.fromPoints(t.x1,t.y1, t.x2,t.y2)
- .attr('drawDefinitionPoints', true)
- .stroke('rgba(255,246,174, 0.05)')
- .appendTo( parent );
+ this.tline = Line.fromPoints(t.x1,t.y1, t.x2,t.y2)
+ .attr('drawDefinitionPoints', true)
+ .stroke('rgba(255,246,174, 0.05)')
+ .appendTo( parent );
+ }
this.shape = new Circle(3)
- .position(this.loc.x, this.loc.y)
+ .position(this.loc.x+6, this.loc.y+6)
.fill('#EC5B38')
.appendTo( parent );
Tank = new Y.Class('Tank', Thing, {
projectile : Bullet,
- blocking: false,
+ blocking : true,
// Bounding box size
width : REF_SIZE*0.7,
this.game = game;
this.tank = tank;
tank.act = this.act; // Override tank actions with player control
+ tank.move = this.move;
$(window)
.bind('keydown', this.keydown)
for (var key in Action.moveDirFromKey)
if ( active.has(key) ) {
this.move( Action.moveDirFromKey[key] );
- return this;
+ return this.tank;
}
- return this;
+ return this.tank;
},
move : function move(dir){
var tank = this.tank
- , toLoc = tank.loc.moveByAngle(dir, (tank.stats.move * SQUARETH));
+ , toLoc = tank.loc.moveByDir(dir, (tank.stats.move * SQUARETH));
this.game.moveAgentTo(tank, toLoc.x, toLoc.y);
}
"lib/jquery.sparkline.min.js",
"lib/jquery.hotkeys.js",
- // "http://static.ukijs.org/pkg/0.3.8/uki.js",
- // "http://static.ukijs.org/pkg/0.3.8/uki-more.js",
+ // "lib/uki/uki.dev.js",
+ // "lib/uki/uki-theamless.dev.js",
+ // "lib/uki/uki-more.dev.js",
+ // "lib/uki/uki-theme/aristo.js",
"src/lessly/future.js",