Minggu, 06 Juli 2014

Javascript Sourcecode My Smallest Billiard Game

Here is the source code. Feel free to use and modify.
This is a html, so you can copy to a note pad, save as html and play it.

Jumat, 21 Maret 2014

Handling Events to Cut Working-time

This is the class to handle events in K

/**
 *
 * @author mi_kuncoro@yahoo.co.id
 * @include k.js
*/
if (!K) alert("You must include k.js in HTMLElement");
/*
 * Mouse position
 * Only updated when eventManager mouse active
*/
K.mouseX = 0;
K.mouseY = 0;
/*
 * Enter Frame Event Handler
 * Set by your own function
*/
K.FrameManager = function(f_callback)
{
var _active = false;
var _id = null;
var _nFrame = 0;
this.active = false;
this.getFrameElapsed = function() {
return _nFrame;
};
this.callback = f_callback;
this.update = function() {
_nFrame++;
this.callback(_nFrame);
if (_active == true) {
_id = window.requestAnimationFrame(
function(e){
FM.update();
}
);
}
};
this.activate = function() {
if (_active == true) return;
_active = this.active = true;
window.FM = this;
this.update();
};
this.deactivate = function() {
if (_active == false) return;
_active = this.active = false;
if (_id) window.cancelAnimationFrame(_id);
window.FM = null;
};
};
/*
 * class
*/
K.EventListener = function(etype, fcall, odispatcher) {
this.name = "el_" + K.incrementCounter().toString();
this.dispatcher = odispatcher;
this.event = null;
this.eventType = etype;
this.eventCallback = fcall;
this.broadcastEvent = function(e) {
this.event = e;
this.eventCallback(e);
};
this.dispose = function() {
this.dispatcher = null;
};
};
/*
 * class
 * uses to manage events inside the platform
*/
K.EventManager = function()
{
var _active = false;
var _listeners = {
keydown : [],
keyup : [],
mousedown : [],
mousemove : [],
mouseup : [],
click : [],
accel : [],
enterFrame : []
};
var broadcastEvent = function(a, e) {
for (var i = 0; i < a.length; i++) {
a[i].broadcastEvent(e);
}
};
var _fm = new K.FrameManager(
function() {
broadcastEvent(_listeners.enterFrame, {eventType:"enterFrame"});
}
);
var inputDevices = {
keyboard: {active:false, lastInput:0 },
mouse: {active:false, lastInput:0 },
touch: { active:false, lastInput:0 },
accel: {active:false, lastInput:0 },
enterFrame:_fm
};
this.handleCustomEvent = function(e, t) {
broadcastEvent(_listeners[t], e);
};
this.handleKeyboard = function(e, t) {
inputDevices.keyboard.lastInput = e;
broadcastEvent(_listeners[t], e);
};
var _oUnderPoint = [];
var sortByOrder = function(a, b) {
if (a.dispatcher.order < b.dispatcher.order) return -1;
if (a.dispatcher.order > b.dispatcher.order) return 1;
return 0;
};
this.getObjectUnderPoint = function() {
return _oUnderPoint;
};
this.handleMouse = function(e, t) {
var xx = K.mouseX = e.offsetX;
var yy = K.mouseY = e.offsetY;
inputDevices.mouse.lastInput = e;
var a = _listeners[t];
_oUnderPoint.length = 0;
for (var i = 0; i < a.length; i++) {
if (a[i].dispatcher.hitTestPoint(xx, yy)) _oUnderPoint.push(a[i]);
}
if (_oUnderPoint.length > 0) {
_oUnderPoint.sort(sortByOrder);
_oUnderPoint.pop().broadcastEvent(e);
}
};
this.activate = function(inputType) {
if (inputDevices[inputType].active == true) return
inputDevices[inputType].active = true;
switch (inputType) {
case "enterFrame":
_fm.activate();
break;
case "keyboard":
document.addEventListener("keydown", function(e){ e.preventDefault(); K.eventManager.handleKeyboard(e, "keydown"); });
document.addEventListener("keyup", function(e){ e.preventDefault(); K.eventManager.handleKeyboard(e, "keyup"); });
break;
case "mouse":
var c = K.getCanvas();
c.addEventListener("click", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "click"); });
c.addEventListener("mousedown", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mousedown");});
c.addEventListener("mousemove", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mousemove");});
c.addEventListener("mouseup", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mouseup");});
break;
case "touch":
// not supported without pluggin
break;
case "accel":
// not supported without pluggin
break;
}
};
this.deactivate = function(inputType) {
if (inputDevices[inputType].active == false) return;
inputDevices[inputType].active = false;
switch (inputType) {
case "enterFrame":
_fm.deactivate();
break;
case "keyboard":
document.removeEventListener("keydown", function(e){ e.preventDefault(); K.eventManager.handleKeyboard(e, "keydown"); });
document.removeEventListener("keyup", function(e){ e.preventDefault(); K.eventManager.handleKeyboard(e, "keyup"); });
break;
case "mouse":
var c = K.getCanvas();
c.removeEventListener("click", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "click"); });
c.removeEventListener("mousedown", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mousedown"); });
c.removeEventListener("mousemove", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mousemove"); });
c.removeEventListener("mouseup", function(e){ e.preventDefault(); K.eventManager.handleMouse(e, "mouseup"); });
break;
case "touch":
// not supported without pluggin
break;
case "accel":
// not supported without pluggin
break;
}
};
this.addEventListener = function(el) {
if (!_listeners[el.eventType]) _listeners[el.eventType] = [];
_listeners[el.eventType].push(el);
};
this.removeEventListener = function(el) {
var a = _listeners[el.eventType];
var idx = -1;
for (var i = 0; i < a.length; i++) {
if (a[i].name == el.name) {
idx = i;
break;
}
}
if (i < 0) return;
_listeners[el.eventType].splice(idx, 1);
el.dispose();
};
};
/*
 * EventManager instance of K
*/
K.eventManager = new K.EventManager();
/*
 * class
 * Every interactive Object must have it to enable EventManager manage rhe events
*/
K.EventDispatcher = function(o)
{
this.owner = o;
this.eventListeners = {
keydown:null,
keyup:null,
click:null,
mousedown:null,
mousemove:null,
mouseup:null,
accel:null,
enterFrame:null
};
};
K.EventDispatcher.prototype =
{
constructor:K.EventDispatcher,
dispatchEvent:function(e) {
if (!e.eventType) {
alert("an event must has eventType ");
return;
}
e.dispatcher = this.owner;
K.eventManager.handleCustomEvent(e, e.eventType);
},
eventListeners:null,
owner:null,
addEventListener:function(eventType, eventCallback) {
var o = new K.EventListener(eventType, eventCallback, this.owner);
K.eventManager.addEventListener(o);
this.eventListeners[eventType] = o;
},
removeEventListener:function(eventType) {
var o = this.eventListeners[eventType];
K.eventManager.removeEventListener(o);
this.eventListeners[eventType] = null;
}
};

Header of K Engine

/**
 * ...
 * @author mi_kuncoro@yahoo.co.id
 * platform's main
 */

var K = {
version:"2.0",
counter:0,
incrementCounter:function() {
K.counter++;
return K.counter;
},
cloneObject:function(v){
var ret = {};
for (var i in v){
var g = v.__lookupGetter__(i), s = v.__lookupSetter__(i);
if ( g || s ) {
if ( g ) ret.__defineGetter__(i, g);
if ( s ) ret.__defineSetter__(i, s);
} else
ret[i] = v[i];
}
return ret;
},
extendObject:function(a, b){
for ( var i in b ) {
var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
if ( g || s ) {
if ( g ) a.__defineGetter__(i, g);
if ( s ) a.__defineSetter__(i, s);
} else
a[i] = b[i];
}
return a;
}
};

Geometry to Support K.Display

This is the code:

/**
 *
 * @author mi_kuncoro@yahoo.co.id
 * @include k.js
 *
 */
if (!K) alert("You must include k.js in HTMLElement");
/*
 One degree in radian
*/
K.P1 = Math.PI / 180;
/*
 * Convert radian to degree
*/
K.toDegree = function(n) {
return n * K.P1;
};
/*
 * Convert degree to radian
*/
K.toRadian = function(n) {
return n / K.P1
};

/*
** Point 2D
*/
K.Point = function(xx, yy) {
this.x = xx || 0;
this.y = yy || 0;
};
K.Point.prototype = {
constructor:K.Point,
x:0, y:0,
toAngle:function() { return Math.atan2(this.y, this.x); },
angleTo:function(x, y) { return Math.atan2(y - this.y, x - this.x); },
getLength:function() { return Math.sqrt(this.x * this.x + this.y * this.y); },
add:function(x, y) { this.x += x; this.y += y; return this; },
clone:function() { return new Point(this.x, this.y); },
dispose:function() {},
distanceTo:function(x, y) {
var dx = x - this.x;
var dy = y - this.y;
return Math.sqrt(dx * dx + dy * dy);
},
subtract:function(x, y) { this.x -= x; this.y -= y; return this; },
multiply:function(v) { this.x *= v; this.y *= v; return this; },
normalize:function() {
var d = this.length;
if (d > 0 || d != 1){
this.x /= d;
this.y /= d;
}
return this;
},
toString:function() {
return "[Point (x="+this.x+" y="+this.y+")]";
}
};
K.Point.addPoint = function(p1, p2) {
return new K.Point(p1.x + p2.x, p1.y + p2.y);
};
K.Point.anglePoint = function(p1, p2) {
var dx = p1.x - p1.x;
var dy = p2.y - p1.y;
return Math.atan2(dy, dx);
};
K.Point.clonePoint = function(p) {
return new K.Point(p.x, p.y);
};
K.Point.distancePoint = function(p1, p2) {
var dx = p1.x - p1.x;
var dy = p2.y - p1.y;
return Math.sqrt(dx * dx + dy * dy);
};
K.Point.multiplyPoint = function(p, n) {
return new K.Point(p.x * n, p.y * n);
};
K.Point.normalizePoint = function(p) {
var d = Math.sqrt(p.x * p.x + p.y * p.y);
if (d > 1)
{
p.x /= d;
p.y /= d;
}
};
K.Point.subtractPoint = function(p1, p2) {
return new K.Point(p1.x - p2.x, p1.y - p2.y);
};

/*
 * Rectangle
*/
K.Rectangle = function(xx, yy, ww, hh, offsetx, offsety){
this.x = xx || 0;
this.y = yy || 0;
this.width = ww || 0;
this.height = hh || 0;
this.offsetX = offsetx || 0;
this.offsetY = offsety || 0;
};
K.Rectangle.prototype = {
constructor:K.Rectangle,
x:0, y:0, width:0, height:0, offsetX:0, offsetY:0,
getLeft:function() { return this.x; },
getTop:function() { return this.y; },
getRight:function() { return this.x + this.width; },
getBottom:function() { return this.y + this.height; },
getTopLeft:function() { return {x:this.x, y:this.y}; },
getBottomRight:function() { return {x:this.x + this.width, y:this.y + this.height}; },
clone:function() {
var ret = new K.Rectangle(this.x, this.y, this.width, this.height);
ret.offsetX = this.offsetX;
ret.offsetY = this.offsetY;
return ret;
},
containsPoint:function(xx, yy) {
if (xx < this.x) return false;
if (yy < this.y) return false;
if (xx > this.right) return false;
if (yy > this.bottom) return false;
return true;
},
containsRect:function(v){
if (v.x < this.x) return false;
if (v.y < this.y) return false;
if (v.right > this.right) return false;
if (v.bottom > this.bottom) return false;
return true;
},
dispose:function() {},
intersects:function(v) {
if (v.x > this.right) return false;
if (v.y > this.bottom) return false;
if (v.right < this.x) return false;
if (v.bottom < this.y) return false;
return true;
},
intersections:function(v){
var ret = new K.Rectangle(
Math.max(this.x, v.x),
Math.max(this.y, v.y),
0, 0);
ret.width = Math.min(this.right, v.right) - ret.x;
ret.height = Math.min(this.bottom, v.bottom) - ret.y;
return ret;
},
toString:function() {
return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]";
}
};

/*
 * Matrix 2D
*/
K.Matrix = function(a, b, c, d, e, f) {
this.a = a || 1; this.b = b || 0; this.e = e || 0;
this.c = c || 0; this.d = d || 1; this.f = f || 0;
};
K.Matrix.prototype = {
constructor:K.Matrix,
a:1, b:0, c:0, d:1, e:0, f:0,
setValues:function (aa, bb, cc, dd, ee, ff) {
this.a = aa;
this.b = bb;
this.c = cc;
this.d = dd;
this.e = ee;
this.f = ff;
return this;
},
rotate:function (rads) {
var nCos = Math.cos(rads);
var nSin = Math.sin(rads);
var tmp = this.a;
this.a = nCos * tmp - nSin * this.b;
this.b = nSin * tmp + nCos * this.b;
tmp = this.c;
this.c = nCos * tmp - nSin * this.d;
this.d = nSin * tmp + nCos * this.d;
tmp = this.e;
this.e = nCos * tmp - nSin * this.f;
this.f = nSin * tmp + nCos * this.f;

return this;
},
scale:function (sx, sy) {
this.a *= sx;
this.b *= sy;
this.c *= sx;
this.d *= sy;
this.e *= sx;
this.f *= sy;
return this;
},
translate:function (dx, dy) {
this.e += this.a * dx + this.c * dy;
this.f += this.b * dx + this.d * dy;
return this;
},
prependRotation:function(rads){
var nCos = Math.cos(rads);
var nSin = Math.sin(rads);
var tmp = this.a;
this.a = nCos * tmp - nSin * this.b;
this.b = nSin * tmp + nCos * this.b;
tmp = this.c;
this.c = nCos * tmp - nSin * this.d;
this.d = nSin * tmp + nCos * this.d;
return this;
},
prependTranslation:function (dx, dy) {
this.e += dx;
this.f += dy;
return this;
},
prependScale:function (sx, sy) {
this.a *= sx;
this.b *= sy;
this.c *= sx;
this.d *= sy;
return this;
},
multiply:function(m){
var tmp = this.a;
this.a = tmp * m.a + this.b * m.c;
this.b = tmp * m.b + this.b * m.d;
tmp = this.c;
this.c = tmp * m.a + this.d * m.c;
this.d = tmp * m.b + this.d * m.d;
tmp = this.e;
this.e = tmp * m.a + this.f * m.c + m.e;
this.f = tmp * m.b + this.f * m.d + m.f;
return this;
},
transformPoint:function(xx, yy){
return {
x : xx * this.a + yy * this.c + this.e,
y : xx * this.b + yy * this.d + this.f
};
},
transformRectangle:function(rect) {
var tl = this.transformPoint(rect.x, rect.y);
var br = this.transformPoint(rect.x + rect.width, rect.y + rect.height);
var xx = Math.min(tl.x, br.x);
var yy = Math.min(tl.y, br.y);
var ww = Math.abs(br.x - tl.x);
var hh = Math.abs(br.y - tl.y);
return new Rectangle(xx, yy, ww, hh);
},
invert:function () {
var det = this.determinant();
if (det !== 0) {
var old = {
a: this.a,
b: this.b,
c: this.c,
d: this.d,
e: this.e,
f: this.f
};
this.a = old.d / det;
this.b = -old.b / det;
this.c = -old.c / det;
this.d = old.a / det;
this.e = (old.c * old.f - old.e * old.d) / det;
this.f = (old.e * old.b - old.a * old.f) / det;
}
return this;
},
clone:function(){
return new K.Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
},
determinant:function(){
return this.a * this.d - this.b * this.c;
},
dispose:function(){},
equal:function(m){
return
this.a == m.a && this.b == m.b && this.c == m.c &&
this.d == m.d && this.e == m.e && this.f == m.f;
},
identity:function(){
this.a = this.d = this.i = 1;
this.b = this.c = this.e = this.f = this.g = this.h = 0;
},
isIdentity:function () {
return this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.e === 0 && this.f === 0;
},
isInvertible:function () {
return this.determinant() !== 0;
}
};

The Display (object) Class

This is the code in my K.Display class

/**
 * ...
 * @author mi_kuncoro@yahoo.co.id
 * @include k.js
 * @include events.js
 * @include geom.js
*/
(function(){
if (!K) {
alert("You must include k.js");
K = {};
} else {
var s = ""
if (!K.Point)  s += "You must include geom.js";
if (!K.EventDispatcher)  s += "You must include events.js";
if (s.length > 0) console.log(s);
}
});
/*
 * Base class for display object
 * - by default has an EventDispatcher
*/
K.Display = function()
{
this.name = "instance_" + K.incrementCounter().toString();
this.x = 0;
this.y = 0;
this.rotation = 0;
this.matrix = new K.Matrix();
this.children = [];
this.eventDispatcher = new K.EventDispatcher(this);
this.order = 1;
};
K.Display.prototype = {
constructor:K.Display,
name:String="",
eventDispatcher:null,
data:null,
x:0,
y:0,
z:0,
width:1,
height:1,
rotation:0,
scaleX:1,
scaleY:1,
order:1,
orderLevel:1,
canvasX:0,
canvasY:0,
canvas:null,
context:null,
getContext:function() {
if (this.context == null) {
if (this.canvas == null) {
this.canvas = document.createElement("canvas");
this.canvas.width = this.width;
this.canvas.height = this.height;
}
else if (this.canvas.width <= 1) {
this.canvas.width = this.width;
this.canvas.height = this.height;
}
this.context = this.canvas.getContext("2d");
}
return this.context;
},
backgroundColor:null,
children:[],
addChild:function(o){
o.parent = this;
o.orderLevel = this.orderLevel + 1;
o.order = (this.children.length + 1) * o.orderLevel + this.order;
this.children.push(o);
},
removeChildAt:function(i) {
this.children.splice(i, 1);
},
removeChild:function(o) {
this.removeChildAt(this.chidren.indexOf(o));
},
sortByOrder:function(a, b) {
if (a.dispatcher.order < b.dispatcher.order) return -1;
if (a.dispatcher.order > b.dispatcher.order) return 1;
return 0;
},
arrangeChildOrder:function() {
for (var i = 0; i < this.children.length; i++) {
this.children[i].order = (i + 1) * o.orderLevel + this.order;
}
},
swapChildren:function(a, b) {
var ai = this.children.indexOf(a);
var bi = this.children.indexOf(b);
this.children[ai] = b;
this.children[bi] = a;
a.order = (bi + 1) * a.orderLevel + this.order;
b.order = (ai + 1) * b.orderLevel + this.order;
},
parent:null,
matrix:null,
setSize:function(ww, hh) {
this.width = ww;
this.height = hh;
if (this.canvas) {
//this.canvas = document.createElement("canvas");
this.canvas.width = ww;
this.canvas.height = hh;
this.context = this.canvas.getContext("2d");
}
},
globalToLocal:function(xx, yy) {
var m = this.matrix.clone().invert();
return m.transformPoint(xx, yy);
},
localToGlobal:function(xx, yy) {
return this.matrix.transformPoint(xx, yy);
},
hitTestPoint:function(xx, yy) {
if (this.canvas ) {
if (this.canvas.width > 1) {
var p = this.globalToLocal(xx, yy);
var d = this.context.getImageData(p.x-this.canvasX, p.y-this.canvasY, 1, 1).data;
if (d[3] >= 1) return true;
}
}
if (this.children.length > 0) {
var ret = false;
for (var i = 0; i < this.children.length; i++) {
if (this.children[i].hitTestPoint(xx, yy) == true) {
ret = true;
break;
}
}
return ret;
}
return false;
},
paint:function(c) {
var m = this.matrix;
m.identity();
if (this.scaleX != 1 || this.scaleY != 1) m.prependScale(this.scaleX, this.scaleY);
if (this.rotation != 0) m.prependRotation(this.rotation);
m.prependTranslation(this.x, this.y);
if (this.parent) m.multiply(this.parent.matrix);
var tc = this.canvas;
if (tc && tc.width > 1) {
c.save();
c.setTransform(m.a, m.b, m.c, m.d, m.e, m.f);
c.drawImage(tc, 0, 0, tc.width, tc.height, this.canvasX, this.canvasY, tc.width, tc.height);
c.restore();
}
if (this.children.length > 0) {
for (var i = 0; i < this.children.length; i++) {
this.children[i].paint(c);
}
}
}
};

/*
** Stage
*/
K.Stage = function() {
this.name = "stage";
this.x = 0;
this.y = 0;
this.rotation = 0;
this.matrix = new K.Matrix();
this.children = [];
this.eventDispatcher = new K.EventDispatcher(this);
this.order = 1;
this.level = 0;
};
K.Stage.prototype = K.cloneObject(K.Display.prototype);
K.Stage.prototype.constructor = K.Stage;
K.Stage.prototype.paint = function() {
var c = this.context;
c.fillStyle = this.backgroundColor;
c.fillRect(0, 0, this.canvas.width, this.canvas.height);
if (this.children.length > 0) {
for (var i = 0; i < this.children.length; i++) {
this.children[i].paint(c);
}
}
};

K.stage = new K.Stage();
K.getCanvas = function() {
return K.stage.canvas;
};
K.setCanvas = function(cvs) {
K.stage.canvas = cvs;
K.stage.context = cvs.getContext("2d");
K.stage.width = cvs.width;
K.stage.height = cvs.height;
};
K.getContext = function() {
return K.stage.getContext();
};
/*
 * class to hold SpriteSheet sheet data
*/
K.SpriteSheet = function()
{
this.animations = {};
this.frames = [];
this.image = null;
this.maxWidth = 100;
this.maxHeight = 100;
this.addAnimation = function(animName, start, end, loop, next) {
this.animations[animname] = {name:animName, start:start, end:end, loop:loop, next:next};
};
this.addFrame = function(xx, yy, ww, hh, offsetx, offsety) {
frames.push({x:xx, y:yy, width:ww, height:hh, offsetX:offsetx, offsety:offsety});
};
this.dispose = function() {
this.image = null;
this.animations = null;
this.frames.length = 0;
};
/*
* this drawing ignoring offset values.
* uses to draw frame at K.Display.context
*/
this.drawFrame = function(frameIndex, context) {
var f = this.frames[f];
context.clearRect(0, 0, this.maxWidth, this.maxHeight);
context.drawImage(this.image, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
};
};

Simple platform to short learning time

SHORT LEARNING

Using some platforms available in internet is good, but sometimes it takes longer time to learn and too complex. So I decide to make myself in a simple way.
Here the example:

Display.hitTestPoint by pixel
Parameters: x and y position to test
Return true if color transparancy >= 1



Please try click an object
?

Look how simple to make application as the following html code

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>K HitTextPoint</title>
<script src="kunjs/k.js"></script>
<script src="kunjs/geom.js"></script>
<script src="kunjs/events.js"></script>
<script src="kunjs/display.js"></script>
</head>
<body>
Display.hitTestPoint by pixel
<br />
Parameters: x and y position to test
<br />
Return true if color transparancy >= 1
<hr />
<canvas id="maincanvas" width="400" height="400"></canvas>
<hr />
<div id="otherdiv">?</div>
<script>
/**
 *
 * @author mi_kuncoro@yahoo.co.id
 * include k.js
*/
(function(){
// Get the main canvas in html
var canvas = document.getElementById("maincanvas");
// assign it to the engine
K.setCanvas(canvas);
// You also can scale the canvas:
//K.canvas.style.width = 600 + "px";
//K.canvas.style.height = 600 + "px";
// Set the background color:
K.stage.backgroundColor = "#000000";
// Create some display-objects
var d = new K.Display(5, 5, 2);
d.x = 200;
d.y = 200;
// You have to carefully define the size to make your drawing fit,
// thought you can change it later by setSize()
d.width = 100;
d.height = 30;
// If you want to centerize or offset it:
d.canvasX = -50;
d.canvasY = -15;
// Now draw something:
var c = d.getContext();
c.fillStyle = "#3333ff";
c.fillRect(0, 0, 50, 30);
c.fillStyle = "#ff0000";
c.fillRect(50, 0, 50, 30);

var d2 = new K.Display(5, 5, 2);
d2.x = 100;
d2.y = 0;
d2.width = 50;
d2.height = 50;
d2.canvasX = -25;
d2.canvasY = -25;
c = d2.getContext();
c.strokeStyle = "#cccccc";
c.fillStyle = "#eeff00";
c.fillRect(0, 0, d2.width, d2.height);
c.strokeRect(0, 0, d2.width, d2.height);

var d3 = new K.Display(5, 5, 2);
d3.x = 150;
d3.y = 150;
d3.width = 100;
d3.height = 100;
d3.canvasX = 0;
d3.canvasY = 0;
c = d3.getContext();
c.strokeStyle = "#00ff00";
c.fillStyle = "#55ff66";
c.beginPath();
c.arc(50, 50, 40, Math.PI, false);
c.stroke();
c.fill();
// The click event will check mouse position based on it's pixel (not rectangle).
// Transparency below 1 will be ignored
var od = document.getElementById("otherdiv");
d.eventDispatcher.addEventListener( "click", function(e) { od.innerHTML = "Click d "; } );
d3.eventDispatcher.addEventListener("click", function(e) { od.innerHTML = "Click d3"; });
// Test hierarchie by adding a display object to another:
d.addChild(d2);
// Now add to stage the first level display-objects
K.stage.addChild(d);
K.stage.addChild(d3);

var s = 1; // scale value
var ds = 0.1; // delta scale

var step = function (e)
{
// add rotation:
d.rotation += K.P1;
d2.rotation -= K.P1 * 5;
d3.rotation += K.P1 * 2;
// scaling:
s += ds;
if (s < 0.6 || s > 1.5) {
ds *= -1;
s += ds;
}
d2.scaleX = d2.scaleY = s;
// draw everything just by painting the stage:
K.stage.paint();
};

K.stage.eventDispatcher.addEventListener("enterFrame", step);
// Events, including ENTER_FRAME, are fully controlled,
// so we have to activate device event monitor as necessary:
K.eventManager.activate("enterFrame");
K.eventManager.activate("mouse");

}());
</script>
</body>
</html>

Next post, I will open the engine/platform behind it.