entityjs 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ });