entityjs 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +49 -0
  4. data/Rakefile +1 -0
  5. data/bin/entityjs +14 -0
  6. data/build/build_debug.bat +1 -0
  7. data/build/build_min.bat +1 -0
  8. data/build/config.php +64 -0
  9. data/build/debug.php +48 -0
  10. data/build/files.php +74 -0
  11. data/build/jsmin.php +376 -0
  12. data/build/min.php +50 -0
  13. data/changelog.txt +53 -0
  14. data/entityjs.gemspec +25 -0
  15. data/examples/keys/arrow.png +0 -0
  16. data/examples/keys/keys.html +59 -0
  17. data/examples/keys/keys.js +148 -0
  18. data/examples/mouse/mouse.html +58 -0
  19. data/examples/mouse/mouse.js +60 -0
  20. data/examples/scenes/home.png +0 -0
  21. data/examples/scenes/scenes.html +55 -0
  22. data/examples/scenes/scenes.js +134 -0
  23. data/examples/scenes/win.png +0 -0
  24. data/examples/sounds/sound1.mp3 +0 -0
  25. data/examples/sounds/sound1.ogg +0 -0
  26. data/examples/sounds/sounds.html +56 -0
  27. data/examples/sounds/sounds.js +44 -0
  28. data/examples/style/background.png +0 -0
  29. data/examples/style/sheet.css +762 -0
  30. data/examples/tiles/tiles.html +56 -0
  31. data/examples/tiles/tiles.js +85 -0
  32. data/examples/tiles/tiles.png +0 -0
  33. data/lib/blank/config.js +4 -0
  34. data/lib/blank/config.yml +21 -0
  35. data/lib/blank/home.js +11 -0
  36. data/lib/blank/init.js +7 -0
  37. data/lib/blank/load.js +21 -0
  38. data/lib/blank/play.html +29 -0
  39. data/lib/entity.debug.js +52 -0
  40. data/lib/entity.min.js +184 -0
  41. data/lib/entityjs/command.rb +37 -0
  42. data/lib/entityjs/comp.rb +11 -0
  43. data/lib/entityjs/game.rb +93 -0
  44. data/lib/entityjs/min.rb +11 -0
  45. data/lib/entityjs/refresh.rb +14 -0
  46. data/lib/entityjs/version.rb +3 -0
  47. data/lib/entityjs.rb +6 -0
  48. data/license.txt +1 -0
  49. data/spec/lib/entityjs/game_spec.rb +11 -0
  50. data/spec/spec_helper.rb +3 -0
  51. data/src/entityjs/core/component.js +306 -0
  52. data/src/entityjs/core/entity.js +516 -0
  53. data/src/entityjs/core/load.js +224 -0
  54. data/src/entityjs/core/query.js +410 -0
  55. data/src/entityjs/core/re.js +70 -0
  56. data/src/entityjs/core/system.js +125 -0
  57. data/src/entityjs/cycle/draw.js +185 -0
  58. data/src/entityjs/cycle/ticker.js +27 -0
  59. data/src/entityjs/cycle/tween.js +61 -0
  60. data/src/entityjs/cycle/update.js +86 -0
  61. data/src/entityjs/cycle/wait.js +22 -0
  62. data/src/entityjs/cycle/worker.js +9 -0
  63. data/src/entityjs/display/anchor.js +53 -0
  64. data/src/entityjs/display/bitfont.js +93 -0
  65. data/src/entityjs/display/bitmap.js +37 -0
  66. data/src/entityjs/display/circle.js +30 -0
  67. data/src/entityjs/display/font.js +41 -0
  68. data/src/entityjs/display/group.js +63 -0
  69. data/src/entityjs/display/rect.js +19 -0
  70. data/src/entityjs/display/screen.js +46 -0
  71. data/src/entityjs/display/sprite.js +37 -0
  72. data/src/entityjs/input/keyboard.js +150 -0
  73. data/src/entityjs/input/mouse.js +123 -0
  74. data/src/entityjs/input/pressed.js +81 -0
  75. data/src/entityjs/input/touch.js +28 -0
  76. data/src/entityjs/math/bind.js +76 -0
  77. data/src/entityjs/math/bisect.js +69 -0
  78. data/src/entityjs/math/body.js +39 -0
  79. data/src/entityjs/math/drag.js +39 -0
  80. data/src/entityjs/math/hitmap.js +165 -0
  81. data/src/entityjs/math/hittest.js +26 -0
  82. data/src/entityjs/math/physics.js +142 -0
  83. data/src/entityjs/math/point.js +57 -0
  84. data/src/entityjs/math/tile.js +91 -0
  85. data/src/entityjs/media/channel.js +93 -0
  86. data/src/entityjs/media/playlist.js +5 -0
  87. data/src/entityjs/media/sound.js +110 -0
  88. data/src/entityjs/net/socket.js +52 -0
  89. data/src/entityjs/pattern/arraymap.js +89 -0
  90. data/src/entityjs/pattern/flicker.js +214 -0
  91. data/src/entityjs/pattern/timestep.js +34 -0
  92. data/src/entityjs/save/database.js +7 -0
  93. data/src/entityjs/save/storage.js +57 -0
  94. data/src/entityjs/util/log.js +25 -0
  95. data/src/entityjs/util/polyfill.js +25 -0
  96. data/src/entityjs/util/random.js +38 -0
  97. data/src/entityjs/util/scene.js +101 -0
  98. data/src/entityjs/util/sheet.js +51 -0
  99. data/src/entityjs/util/support.js +132 -0
  100. metadata +156 -0
@@ -0,0 +1,165 @@
1
+ /*
2
+
3
+ The hitmap component is used for collision detection in a tile-based game.
4
+ This can be sent to a physics entity and it will recieve checks if it hits
5
+ a tile.
6
+
7
+ Creating this signal system will allow other developers to easily implement
8
+ their own hit collision system.
9
+ */
10
+ re.c('hitmap')
11
+ .require('arraymap')
12
+ .extend({
13
+
14
+ hitValue:1,
15
+
16
+ checkAxisX:function(value, x, y, vx, vy){
17
+
18
+ return value == this.hitValue;
19
+
20
+ },
21
+
22
+ checkAxisY:function(value, x, y, vx, vy){
23
+ return value == this.hitValue;
24
+ },
25
+
26
+ checkHit:function(posX, posY, velX, velY, bodX, bodY, padX, padY){
27
+ if(arguments.length == 1){
28
+ var velX = posX.velX;
29
+ var velY = posX.velY;
30
+
31
+ var bodX = posX.bodX;
32
+ var bodY = posX.bodY;
33
+
34
+ var padX = posX.padX;
35
+ var padY = posX.padY;
36
+
37
+ var posY = posX.posY;
38
+ posX = posX.posX;
39
+ }
40
+
41
+ var res = {
42
+ posX:posX,
43
+ posY:posY,
44
+ tarX:-1,
45
+ tarY:-1
46
+ };
47
+
48
+ var step = ~~(Math.max(Math.abs(velX), Math.abs(velY)) / ((re.tile.sizeX + re.tile.sizeY) * 0.5) + 0.5);
49
+
50
+ if(step > 1) {
51
+ var sx = velX / step;
52
+ var sy = velY / step;
53
+
54
+ for(var i=0; i<step && (sx || sy); i++) {
55
+
56
+ this.hitmap_step(res, posX, posY, sx, sy, bodX, bodY, padY, padY);
57
+
58
+ if(res.hitX) {
59
+ sx = 0;
60
+ }
61
+
62
+ if(res.hitY) {
63
+ sy = 0;
64
+ }
65
+ }
66
+
67
+ } else {
68
+
69
+ this.hitmap_step(res, posX, posY, velX, velY, bodX, bodY, padX, padY);
70
+
71
+ }
72
+
73
+ return res;
74
+ }
75
+
76
+ })
77
+ .namespace({
78
+
79
+ /*
80
+ TODO:
81
+ refactor
82
+ possibly utilize entity methods for more robust calculations.
83
+ */
84
+ step:function(res, x, y, vx, vy, width, height, padx, pady){
85
+
86
+ res.posX += vx;
87
+ res.posY += vy;
88
+
89
+ var t, ty, tx;
90
+
91
+ if(vx) {
92
+
93
+ t = re.tile.sizeX;
94
+
95
+ var offsetx = (vx > 0 ? width - padx : padx);
96
+
97
+ var firsty = Math.floor((y + pady)/ t);
98
+ var lasty = Math.ceil((y + height - pady) / t);
99
+
100
+ tx = Math.floor((x + vx + offsetx) / t);
101
+
102
+ var offx = (vx < 0 ? t : 0);
103
+ //is inside
104
+ if(tx >= 0 && tx < this.lengthX && lasty >= 0 && firsty < this.lengthY) {
105
+
106
+ for(ty = firsty; ty<lasty; ty++){
107
+
108
+ if(this.map[ty]){
109
+
110
+ //signal
111
+ this.signal('hit', this.map[ty][tx], tx, ty);
112
+
113
+ if(this.checkAxisX(this.map[ty][tx], x, y, vx, vy)) {
114
+ res.hitX = true;
115
+ res.posX = tx * t + offx - offsetx;
116
+ res.tarX = tx * t;
117
+ res.tarY = ty * t;
118
+ break;
119
+ }
120
+ }
121
+
122
+ }
123
+
124
+ }
125
+
126
+ }
127
+
128
+ if(vy) {
129
+ t = re.tile.sizeY;
130
+
131
+ var offsety = (vy > 0 ? height -pady : pady);
132
+
133
+ var firstx = Math.floor((res.posX + padx) / t);
134
+ var lastx = Math.ceil((res.posX + width - padx) / t);
135
+ ty = Math.floor((y + vy + offsety) / t);
136
+
137
+ var offy = (vy < 0 ? t : 0);
138
+ // Still inside this collision map?
139
+ if(ty >= 0 && ty < this.lengthY && lastx >= 0 && firstx< this.lengthX) {
140
+
141
+ for(tx = firstx; tx<lastx; tx++) {
142
+
143
+ if(this.map[ty]){
144
+
145
+ this.signal('hit', this.map[ty][tx], tx, ty);
146
+
147
+ if(this.checkAxisY(this.map[ty][tx], x, y, vx, vy)) {
148
+ res.hitY = true;
149
+ res.posY = ty * t + offy - offsety;
150
+ res.tarX = tx * t;
151
+ res.tarY = ty * t;
152
+ break;
153
+ }
154
+ }
155
+
156
+ }
157
+ }
158
+
159
+
160
+
161
+ }
162
+
163
+ }
164
+
165
+ });
@@ -0,0 +1,26 @@
1
+ re.c('hittest')
2
+ .inherit({
3
+
4
+ posX:0,
5
+ posY:0,
6
+
7
+ sizeX:0,
8
+ sizeY:0,
9
+
10
+ /*
11
+ checks if the two targets intersect with each other.
12
+
13
+ k.touches(x, y, width, height);
14
+
15
+ */
16
+ touches:function(x, y, w, h){
17
+ return !
18
+ (
19
+ x > this.posX + this.sizeX ||
20
+ x + w < this.posX ||
21
+ y > this.posY + this.sizeY ||
22
+ y + h < this.posY
23
+ );
24
+ }
25
+
26
+ });
@@ -0,0 +1,142 @@
1
+ /*
2
+ The Physics component adds new physical and time calculated variables to an entity.
3
+
4
+ These variables will give the entity a more fluid movement in 2d space.
5
+
6
+ Warning - this component is not delta time safe. It assumes a fixed timestep.
7
+ */
8
+ re.physics = re.c('physics')
9
+ .require('update')
10
+ .global({
11
+ graX:0,
12
+ graY:0,
13
+
14
+ //velocity lower than this will be rounded down
15
+ minVel:0.01
16
+ })
17
+ .inherit({
18
+
19
+ posX:0,
20
+ posY:0,
21
+
22
+ velX:0,
23
+ velY:0,
24
+
25
+ velMaxX:100,
26
+ velMaxY:100,
27
+
28
+ friX:0.9,
29
+ friY:0.4,
30
+
31
+ accX:0,
32
+ accY:0,
33
+
34
+ resX:0,
35
+ resY:0,
36
+
37
+ masX:1,
38
+ masY:1,
39
+
40
+ padX:0,
41
+ padY:0,
42
+
43
+ bodX:1,
44
+ bodY:1
45
+
46
+ })
47
+ .namespace({
48
+
49
+ update:function(t){
50
+
51
+ this.velX = this.force(this.velX, this.accX, this.friX, this.graX, this.masX, this.velMaxX);
52
+ this.velY = this.force(this.velY, this.accY, this.friY, this.graY, this.masY, this.velMaxY);
53
+
54
+ //check collisions and get result
55
+ if(this.hitmap){
56
+
57
+ this.aftermath(this.hitmap.checkHit(this));
58
+
59
+ } else {
60
+
61
+ this.aftermath(this.posX + this.velX, this.posY + this.velY);
62
+ }
63
+
64
+ }
65
+
66
+ })
67
+ .extend({
68
+
69
+ aftermath:function(posx, posy, hitx, hity, tarx, tary){
70
+
71
+ if(arguments.length == 1){
72
+ hitx = posx.hitX;
73
+ hity = posx.hitY;
74
+
75
+ tarx = posx.tarX;
76
+ tary = posx.tarY;
77
+
78
+ posy = posx.posY;
79
+ posx = posx.posX;
80
+ }
81
+
82
+ this.posX = posx;
83
+ this.posY = posy;
84
+
85
+ this.signal('aftermath', hitx, hity, tarx, tary);
86
+
87
+ if(hitx){
88
+ this.velX = this.forceRes(this.velX, this.resX);
89
+ }
90
+
91
+ if(hity){
92
+ this.velY = this.forceRes(this.velY, this.resY);
93
+ }
94
+
95
+ },
96
+
97
+ forceRes:function(vel, res){
98
+ return vel * -res;
99
+ },
100
+
101
+ forceGra:function(gra, mas){
102
+ return gra * mas;
103
+ },
104
+
105
+ forceVel:function(vel, acc, fri){
106
+ return (vel + acc) * fri;
107
+
108
+ },
109
+
110
+ force:function(vel, acc, fri, gra, mas, max){
111
+
112
+ var v = this.forceVel(vel, acc, fri) + this.forceGra(gra, mas);
113
+
114
+ v = Math.min(max, Math.max(-max, v));
115
+
116
+ if(Math.abs(v) < re.physics.minVel){
117
+ v = 0;
118
+ }
119
+
120
+ return v;
121
+ },
122
+
123
+ isIdle:function(){
124
+ return (this.velY == 0 && this.velX == 0 && this.accX == 0 && this.accY == 0);
125
+ }
126
+
127
+ })
128
+ .init(function(c){
129
+
130
+ //setup defaults
131
+ this.hitmap = re.hitmap;
132
+
133
+ this.graX = c.graX;
134
+ this.graY = c.graY;
135
+
136
+ this.addSignal('update', this.physics_update);
137
+ })
138
+ .dispose(function(){
139
+
140
+ this.removeSignal('update', this.physics_update);
141
+
142
+ });
@@ -0,0 +1,57 @@
1
+ /*
2
+ The point component extends an entity that has a 2d position in space.
3
+ This can be used for 2d calculations or most commonly 2d sprite positioning.
4
+
5
+ */
6
+
7
+ re.c('point')
8
+ .inherit({
9
+
10
+ posX:0,
11
+ posY:0
12
+
13
+ })
14
+ .extend({
15
+
16
+ setPos:function(x, y){
17
+
18
+ if(arguments.length == 1){
19
+ if(x.y)
20
+ this.posY = x.posY;
21
+
22
+ if(x.x)
23
+ this.posX = x.posX;
24
+
25
+ } else {
26
+
27
+ this.posX = x;
28
+ this.posY = y;
29
+
30
+ }
31
+
32
+ return this;
33
+ },
34
+
35
+ setPosX:function(x){
36
+ this.posX = x;
37
+ return this;
38
+ },
39
+
40
+ setPosY:function(y){
41
+ this.posY = y;
42
+ return this;
43
+ },
44
+
45
+ distanceTo:function(x, y){
46
+ if(arguments.length == 1){
47
+ y = x.posY;
48
+ x = x.posX;
49
+ }
50
+ var kx, ky;
51
+ kx = x-this.posX>>31;
52
+ ky = y-this.posY>>31;
53
+
54
+ return Math.round(((x-this.posX ^kx)-kx)+((y-this.posY^ky)-ky));
55
+ }
56
+
57
+ });
@@ -0,0 +1,91 @@
1
+ /*
2
+ The tile component adds tile positioning functions and helper functions for tile based games.
3
+ */
4
+ re.tile = re.c('tile')
5
+ .global({
6
+ sizeX:40,
7
+ sizeY:40,
8
+
9
+ roundX:function(x, size){
10
+ if(arguments.length == 1){
11
+ size = re.tile.sizeX;
12
+ }
13
+ return re.tile.roundTileX(x) * size;
14
+ },
15
+
16
+ roundY:function(y, size){
17
+ if(arguments.length == 1){
18
+ size = re.tile.sizeY;
19
+ }
20
+ return re.tile.roundTileY(y) * size;
21
+ },
22
+
23
+ roundTileX:function(x, size){
24
+ if(arguments.length == 1){
25
+ size = re.tile.sizeX;
26
+ }
27
+ return Math.round((x - size*0.5)/size);
28
+ },
29
+
30
+ roundTileY:function(y, size){
31
+ if(arguments.length == 1){
32
+ size = re.tile.sizeY;
33
+ }
34
+ return Math.round((y - size * 0.5)/size);
35
+ }
36
+
37
+ })
38
+ .inherit({
39
+
40
+ posX:0,
41
+ posY:0
42
+
43
+ })
44
+ .init(function(){
45
+
46
+ if(!this.sizeX)
47
+ this.sizeX = re.tile.sizeX;
48
+
49
+ if(!this.sizeY)
50
+ this.sizeY = re.tile.sizeY;
51
+
52
+ })
53
+ .extend({
54
+
55
+ setTileFromPoint:function(x, y){
56
+ this.posX = re.tile.roundX(x);
57
+ this.posY = re.tile.roundY(y);
58
+
59
+ return this;
60
+ },
61
+
62
+ setTile:function(xt, yt){
63
+ this.setTileX(xt);
64
+ this.setTileY(yt);
65
+
66
+ return this;
67
+ },
68
+
69
+ setTileX:function(value){
70
+ this.posX = Math.floor(value * this.sizeX);
71
+
72
+ return this;
73
+ },
74
+
75
+ getTileX:function(){
76
+ return Math.floor(this.posX / this.sizeX);
77
+ },
78
+
79
+ setTileY:function(value){
80
+
81
+ this.posY = Math.floor(value * this.sizeY);
82
+
83
+ return this;
84
+ },
85
+
86
+ getTileY:function(){
87
+
88
+ return Math.floor(this.posY / this.sizeY);
89
+ }
90
+
91
+ });
@@ -0,0 +1,93 @@
1
+ /*
2
+ The channel component allows you to play a sound component more than
3
+ once at the sametime. This is useful for shooting or fast games.
4
+
5
+ //create a new channel
6
+ re.e('channel attack.sfx')
7
+ .play()
8
+ .play()
9
+ .play();
10
+
11
+ //extension sfx is created for every
12
+ //sound loaded regards of type
13
+
14
+ //TODO
15
+
16
+ //add more channels
17
+
18
+ //cloning glitch fix
19
+ document.body.appendChild(s);
20
+
21
+ s.addEventListener('canplaythrough', function(e){
22
+
23
+ //multiple channels will allow the sound to be played more at the sametime.
24
+ //this will load the sound multiple times sadly FIX
25
+ for(var i=0; i<re.load.maxChannels-1; i++){
26
+ channels.push(s.cloneNode(true));
27
+ }
28
+
29
+ if(that._p){
30
+ that._p.call(that, that.current, that.total, a);
31
+ }
32
+
33
+ if(that.current >= that.total){
34
+
35
+ if(that._s){
36
+ that._s.call(that, that.assets);
37
+ }
38
+
39
+ }
40
+
41
+ }, false);
42
+ *//*
43
+ re.channel = re.c('channel')
44
+ .require('sound')
45
+ .inherit({
46
+ volume:1,
47
+ max:3
48
+ })
49
+ .extend({
50
+
51
+ play:function(loop){
52
+ if(!this.channels || !re.sound.enabled) return this;
53
+
54
+ var c;
55
+ for(var i=0; i<this.channels.length; i++){
56
+
57
+ c = this.channels[i];
58
+ if(c.ended || !c.currentTime){
59
+ //play new channel
60
+ c.play();
61
+ break;
62
+ } else if(i == this.channels[i].length-1){
63
+ c.currentTime = 0;
64
+ c.play();
65
+ }
66
+
67
+ }
68
+
69
+ if(loop){
70
+
71
+ var l = 0;
72
+
73
+ c.addEventListener('ended', function(){
74
+
75
+ if(loop == -1 || l >= loop){
76
+ this.currentTime = 0;
77
+ l++;
78
+ }
79
+
80
+ }, false);
81
+
82
+ }
83
+
84
+ return this;
85
+ },
86
+
87
+ stop:function(){
88
+
89
+ //stop all channels
90
+
91
+ }
92
+
93
+ });*/
@@ -0,0 +1,5 @@
1
+ /*
2
+ The playlist component allows you to play background music during a game.
3
+ It has methods for adding tracks and playing through them.
4
+ */
5
+ re.c('playlist');
@@ -0,0 +1,110 @@
1
+ /*
2
+ The sound component utilizes the new HTML5 to play sound effects in the web browser.
3
+ It is reccommended to load two sound codecs OGG and AAC because not every browser supports
4
+ all sound codecs at this time.
5
+
6
+ //load a sound
7
+ re.load('run.ogg run.aac');
8
+ //BAD this will load both sounds. Even if the browser might not support one
9
+
10
+ //GOOD. load just one codec of the sound
11
+ var codec;
12
+ if(re.support('ogg')){
13
+ codec = 'ogg';
14
+ } else if(re.support('aac')){
15
+ codec = 'aac';
16
+ }
17
+
18
+ re.load('run.'+codec');
19
+
20
+ //create sound
21
+ re.e('sound run.'+codec);
22
+
23
+ //that is a pain, so a helper method has been created
24
+ re('sound run.'+re.support('ogg', 'aac'));
25
+
26
+ Its reccomended to save the supported codec somewhere globaly
27
+ //like so...
28
+ re.codec = re.support('ogg', 'aac');
29
+
30
+ re.load('run.'+re.codec);
31
+
32
+ re.e('run.'+re.codec);
33
+
34
+ WARNING: Because the sound component has generic
35
+ method names stop, play, watchout for overwrites.
36
+
37
+ Sound Tip
38
+ //find all sounds in game and play them all!
39
+ re('sound').method('play');
40
+
41
+
42
+ */
43
+ re.sound = re.c('sound')
44
+ .global({
45
+
46
+ enabled:true
47
+
48
+ })
49
+ .namespace({
50
+
51
+ hasEvent:false,
52
+ loops:0
53
+
54
+ })
55
+ .extend({
56
+
57
+ play:function(loop){
58
+ if(!this.sound || !re.sound.enabled) return this;
59
+
60
+ var c = this.sound;
61
+ var that = this;
62
+
63
+ c.currentTime = 0;
64
+
65
+ c.play();
66
+
67
+ if(loop){
68
+
69
+ this.sound_loops = 0;
70
+
71
+ if(!this.sound_hasEvent){
72
+ this.sound_hasEvent = true;
73
+
74
+ c.addEventListener('ended', function(){
75
+
76
+ that.signal('sounded', that.sound_loops, loop);
77
+
78
+ if(loop == -1 || that.sound_loops < loop){
79
+ c.currentTime = 0;
80
+ that.sound_loops++;
81
+ }
82
+
83
+ }, false);
84
+ }
85
+
86
+ }
87
+
88
+ return this;
89
+ },
90
+
91
+ resume:function(){
92
+ this.sound.play();
93
+ return this;
94
+ },
95
+
96
+ pause:function(){
97
+ this.sound.pause();
98
+
99
+ return this;
100
+ },
101
+
102
+ currentTime:function(){
103
+ return this.sound.currentTime;
104
+ },
105
+
106
+ ended:function(){
107
+ return this.sound.ended;
108
+ }
109
+
110
+ });