entityjs 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +1 -1
  2. data/lib/entityjs/config.rb +4 -4
  3. data/lib/entityjs/dirc.rb +2 -2
  4. data/lib/entityjs/page.rb +7 -1
  5. data/lib/entityjs/version.rb +1 -1
  6. data/public/qunit/qunit.entity.js +27 -12
  7. data/spec/javascripts/src/core/comp_spec.js +11 -0
  8. data/spec/javascripts/src/core/entity_spec.js +88 -5
  9. data/spec/javascripts/src/core/query_spec.js +196 -15
  10. data/spec/javascripts/src/cycle/drawlist_spec.js +36 -0
  11. data/spec/javascripts/src/cycle/tween_spec.js +1 -1
  12. data/spec/javascripts/src/cycle/wait_spec.js +31 -0
  13. data/spec/javascripts/src/{cycle → display}/draw_spec.js +25 -9
  14. data/spec/javascripts/src/display/sprite_spec.js +18 -0
  15. data/spec/javascripts/src/display/text_spec.js +8 -0
  16. data/spec/javascripts/src/input/mouse_spec.js +24 -36
  17. data/spec/javascripts/src/math/bisect_spec.js +4 -4
  18. data/spec/javascripts/src/math/distance_spec.js +11 -0
  19. data/spec/javascripts/src/math/iso_spec.js +131 -0
  20. data/spec/javascripts/src/math/point_spec.js +3 -3
  21. data/spec/javascripts/src/{util → math}/random_spec.js +0 -0
  22. data/spec/javascripts/src/math/range_spec.js +9 -0
  23. data/spec/javascripts/src/math/tile_spec.js +22 -7
  24. data/spec/javascripts/src/pattern/automap_spec.js +2 -2
  25. data/spec/javascripts/src/pattern/flicker_spec.js +34 -22
  26. data/spec/javascripts/src/pattern/pathfind_spec.js +55 -0
  27. data/src/core/comp.js +16 -16
  28. data/src/core/entity.js +52 -51
  29. data/src/core/load.js +5 -5
  30. data/src/core/query.js +214 -74
  31. data/src/core/system.js +16 -6
  32. data/src/cycle/drawlist.js +79 -0
  33. data/src/cycle/tween.js +7 -20
  34. data/src/cycle/wait.js +10 -19
  35. data/src/{cycle → display}/draw.js +24 -34
  36. data/src/display/image.js +1 -1
  37. data/src/display/screen.js +3 -3
  38. data/src/display/sprite.js +3 -3
  39. data/src/display/text.js +3 -1
  40. data/src/input/mouse.js +35 -12
  41. data/src/math/bisect.js +11 -10
  42. data/src/math/distance.js +7 -0
  43. data/src/math/iso.js +147 -0
  44. data/src/math/point.js +1 -5
  45. data/src/math/random.js +21 -0
  46. data/src/math/range.js +14 -0
  47. data/src/math/tile.js +40 -27
  48. data/src/pattern/automap.js +12 -11
  49. data/src/pattern/flicker.js +87 -135
  50. data/src/pattern/pathfind.js +168 -0
  51. data/src/pattern/timestep.js +4 -1
  52. data/src/util/polyfill.js +1 -1
  53. data/templates/isometric/assets/images/isotiles.png +0 -0
  54. data/templates/isometric/config.yml +22 -0
  55. data/templates/isometric/readme.txt +79 -0
  56. data/templates/isometric/scripts/displays/cursor.js +34 -0
  57. data/templates/isometric/scripts/displays/isoimage.js +32 -0
  58. data/templates/isometric/scripts/init.js +7 -0
  59. data/templates/isometric/scripts/levels/level.js +55 -0
  60. data/templates/isometric/scripts/levels/level1.js +11 -0
  61. data/templates/isometric/scripts/scenes/home.js +10 -0
  62. data/templates/isometric/scripts/scenes/load.js +11 -0
  63. data/templates/isometric/tests/scenes/load_test.js +15 -0
  64. metadata +42 -21
  65. data/src/net/socket.js +0 -52
  66. data/src/util/random.js +0 -24
@@ -0,0 +1,7 @@
1
+ re.distance = function(x1, y1, x2, y2) {
2
+ var kx, ky;
3
+ kx = x2 - x1;
4
+ ky = y2 - y1;
5
+
6
+ return Math.sqrt(kx*kx + ky*ky);
7
+ };
data/src/math/iso.js ADDED
@@ -0,0 +1,147 @@
1
+ re.iso = re.c('iso')
2
+ .statics({
3
+ sizeX:30,
4
+ sizeY:30,
5
+ sizeZ:30,
6
+
7
+ /*
8
+ Converts an x position into the closest iso x position.
9
+ */
10
+ toPosX:function(x, y){
11
+ var isox = this.toIsoX(x, y);
12
+ var isoy = this.toIsoY(x, y);
13
+
14
+ return (isox - isoy) * this.sizeX;
15
+ },
16
+
17
+ toPosY:function(x, y){
18
+ var isox = this.toIsoX(x, y);
19
+ var isoy = this.toIsoY(x, y);
20
+
21
+ return (isox + isoy) * this.sizeY * 0.5;
22
+ },
23
+
24
+ toPos:function(x, y){
25
+ if(re.is(x,'object')){
26
+ y = x.posY || x.y;
27
+ x = x.posX || x.x;
28
+ }
29
+
30
+ return {posX:this.toPosX(x, y), posY:this.toPosY(x, y)};
31
+ },
32
+
33
+ toIsoX:function(x, y){
34
+ var ym = (2*y - x) * 0.5;
35
+ var xm = x + ym;
36
+
37
+ return Math.round(xm / this.sizeX)-1;
38
+ },
39
+
40
+ toIsoY:function(x, y){
41
+ var ym = (2*y - x) * 0.5;
42
+
43
+ return Math.round(ym / this.sizeY);
44
+ },
45
+
46
+ toIso:function(x, y){
47
+ if(re.is(x, 'object')){
48
+ y = x.posY || x.y;
49
+ x = x.posX || x.x;
50
+ }
51
+ return {isoX:this.toIsoX(x,y), isoY:this.toIsoY(x, y)};
52
+ }
53
+
54
+ })
55
+ .defaults({
56
+ posX:0,
57
+ posY:0,
58
+ posZ:0
59
+ })
60
+ .defines({
61
+
62
+ /*
63
+ Moves the iso entity to the given isometric position.
64
+
65
+ examples:
66
+
67
+ e.iso(1, 0, 0);
68
+
69
+ e.iso(otherIso);
70
+
71
+ e.iso({x:1, y:1, z:2});
72
+ */
73
+ iso:function(x, y, z){
74
+ if(re.is(x,'object')){
75
+ z = x.z
76
+ if(re.is(x.posZ)){
77
+ z = x.posZ / re.iso.sizeZ;
78
+ }
79
+ y = x.y;
80
+
81
+ //copy attributes
82
+ if(re.is(x.posX) && re.is(x.posY)){
83
+ this.posX = x.posX;
84
+ this.posY = x.posY;
85
+ if(x.posZ){
86
+ this.posZ = x.posZ;
87
+ }
88
+ return this;
89
+ }
90
+
91
+ x = x.x;
92
+
93
+ }
94
+
95
+ //convert to screen space
96
+ x = (re.is(x)) ? x : this.isoX();
97
+ x *= re.iso.sizeX;
98
+
99
+ //posY handles a lot of transformations, its safest to recalculate it
100
+ y = (re.is(y)) ? y : this.isoY();
101
+ y *= re.iso.sizeY;
102
+
103
+ z = (re.is(z)) ? z : this.isoZ();
104
+ z *= re.iso.sizeZ;
105
+
106
+ //all values should be in screen space from here
107
+ this.posX = x - y;
108
+ this.posY = (x + y) * 0.5 - z;
109
+ this.posZ = z;
110
+
111
+ return this;
112
+ },
113
+
114
+ isoX:function(value){
115
+ if(re.is(value)){
116
+
117
+ return this.iso(value);
118
+ }
119
+
120
+ return (this.posX + (2*(this.posY+this.posZ) - this.posX) * 0.5) / re.iso.sizeX;
121
+ },
122
+
123
+ isoY:function(value){
124
+ if(re.is(value)){
125
+
126
+ return this.iso({y:value});
127
+ }
128
+
129
+ return ((2*(this.posY+this.posZ) - this.posX) * 0.5) / re.iso.sizeY;
130
+ },
131
+
132
+ isoZ:function(value){
133
+ if(re.is(value)){
134
+
135
+ return this.iso({z:value});
136
+ }
137
+
138
+ return this.posZ / re.iso.sizeZ;
139
+ },
140
+
141
+ //returns true if the current iso position is directly on top of a tile.
142
+ onIso:function(){
143
+ var total = this.isoX() + this.isoY() + this.isoZ();
144
+ return (total|0) == total;
145
+ }
146
+
147
+ });
data/src/math/point.js CHANGED
@@ -30,11 +30,7 @@ re.c('point')
30
30
  y = x.posY || x.y;
31
31
  x = x.posX || x.x;
32
32
  }
33
- var kx, ky;
34
- kx = x - this.posX;
35
- ky = y - this.posY;
36
-
37
- return Math.sqrt(kx*kx + ky*ky) + 0.5 | 0;
33
+ return re.distance(this.posX, this.posY, x, y);
38
34
  }
39
35
 
40
36
  });
@@ -0,0 +1,21 @@
1
+ /*
2
+ re.random() // 0 - 1 floats
3
+ re.random(10) // 0 - 9 integer
4
+ re.random(10, 30) // 10 - 30 integer
5
+ re.random([1, 10, 40]) // 1 or 10 or 40
6
+
7
+ */
8
+ re.random = function(max, min){
9
+ var r = Math.random();
10
+ if(re.is(max, 'array')){
11
+ return max[r * max.length | 0];
12
+ }
13
+ switch(arguments.length){
14
+ case 0:
15
+ return r;
16
+ case 1:
17
+ return r * max | 0;
18
+ case 2:
19
+ return r * (max - min + 1) + min | 0;
20
+ }
21
+ };
data/src/math/range.js ADDED
@@ -0,0 +1,14 @@
1
+ /*
2
+ Returns an array of integers within the given range.
3
+
4
+ re.range(0, 2); //[0, 1]
5
+ re.range(2, 10, 2); //[2, 4, 6, 8]
6
+
7
+ */
8
+ re.range = function(start, finish, step){
9
+ var a = [];
10
+ for(var i=start||0; i<finish; i+=step||1){
11
+ a.push(i);
12
+ }
13
+ return a;
14
+ };
data/src/math/tile.js CHANGED
@@ -39,44 +39,56 @@ re.e('tile sprite tiles.png', map.length * map[0].length)
39
39
  @warning moving to negative tiles will cause rounding issues.
40
40
  Its recommended you avoid negative tile values
41
41
 
42
+ TODO: remove size vars from entity. Use global size instead
42
43
  */
43
44
  re.tile = re.c('tile')
44
45
  .statics({
45
46
  sizeX:40,
46
47
  sizeY:40,
47
48
 
48
- toX:function(x, size){
49
- size = size || this.sizeX;
50
- return this.toTileX(x, size) * size;
49
+ toPosX:function(x){
50
+ return this.toTileX(x) * this.sizeX;
51
51
  },
52
52
 
53
- toY:function(y, size){
54
- size = size || this.sizeY;
55
- return this.toTileY(y, size) * size;
53
+ toPosY:function(y){
54
+ return this.toTileY(y) * this.sizeY;
55
+ },
56
+
57
+ toPos:function(x, y){
58
+ if(re.is(x,'object')){
59
+ y = x.posY || x.y;
60
+ x = x.posX || x.x;
61
+ }
62
+
63
+ return {posX:this.toPosX(x), posY:this.toPosY(y)};
56
64
  },
57
65
 
58
66
  //converts the given coordinate to a tile position
59
- toTileX:function(x, size){
60
- size = size || this.sizeX;
61
- return (x - size * 0.5) / size + 0.5 | 0
67
+ toTileX:function(x){
68
+ return (x - this.sizeX * 0.5) / this.sizeX + 0.5 | 0
62
69
  },
63
70
 
64
- toTileY:function(y, size){
65
- size = size || this.sizeY;
66
- return (y - size * 0.5) / size + 0.5 | 0
71
+ toTileY:function(y){
72
+ return (y - this.sizeY * 0.5) / this.sizeY + 0.5 | 0
73
+ },
74
+
75
+ toTile:function(x, y){
76
+ if(re.is(x,'object')){
77
+ y = x.posY || x.y;
78
+ x = x.posX || x.x;
79
+ }
80
+
81
+ return {tileX:this.toTileX(x), tileY:this.toTileY(y)};
67
82
  }
68
83
 
69
84
  })
70
85
  .defaults({
71
86
 
72
87
  posX:0,
73
- posY:0
88
+ posY:0,
89
+ regX:0,
90
+ regY:0
74
91
 
75
- })
76
- .init(function(){
77
- this.sizeX = re.tile.sizeX;
78
- this.sizeY = re.tile.sizeY;
79
-
80
92
  })
81
93
  .defines({
82
94
 
@@ -92,25 +104,26 @@ re.tile = re.c('tile')
92
104
  },
93
105
 
94
106
  tileX:function(v){
95
- var s = this.sizeX || re.tile.sizeX;
96
- var r = this.regX || 0;
97
107
  if(re.is(v)){
98
- this.posX = (v - r) * s;
108
+ this.posX = v * this.sizeX + 0.5 | 0;
99
109
  return this;
100
110
  }
101
111
 
102
- return (this.posX - r) / s + 0.5 | 0;
112
+ return this.posX / this.sizeX + 0.5 | 0;
103
113
  },
104
114
 
105
115
  tileY:function(v){
106
- var s = this.sizeX || re.tile.sizeY;
107
- var r = this.regY || 0;
108
116
  if(re.is(v)){
109
- this.posY = (v - r)* s;
117
+ this.posY = v* this.sizeY + 0.5 | 0;
110
118
  return this;
111
119
  }
112
120
 
113
- return (this.posY - r) / s + 0.5 | 0;
121
+ return this.posY / this.sizeY + 0.5 | 0;
114
122
  }
115
123
 
116
- });
124
+ })
125
+ .init(function(){
126
+ this.sizeX = re.tile.sizeX;
127
+ this.sizeY = re.tile.sizeY;
128
+
129
+ })
@@ -18,12 +18,12 @@ var level =
18
18
  [2,3,4,5,6,4]
19
19
  ]
20
20
 
21
- //value copy
21
+ //reference copy
22
22
  map.automap(level)
23
23
 
24
24
  map.automap(0, 1) // 1
25
25
 
26
- //reference copy
26
+ //value copy
27
27
  map.automap(level, true)
28
28
 
29
29
  map.map == level //true
@@ -45,6 +45,16 @@ re.c('automap')
45
45
  if(re.is(x, 'array')){
46
46
 
47
47
  if(y){
48
+
49
+ //deep copy
50
+ for(var y=0; y<x.length; y++){
51
+ for(var k=0; k<x[0].length; k++){
52
+ this.automap(k, y, x[y][k]);
53
+ }
54
+ }
55
+
56
+ } else {
57
+
48
58
  //non-deep copy
49
59
 
50
60
  this._automap = x;
@@ -56,15 +66,6 @@ re.c('automap')
56
66
  }
57
67
 
58
68
  this.lenY = x.length;
59
-
60
- } else {
61
-
62
- //deep copy
63
- for(var y=0; y<x.length; y++){
64
- for(var k=0; k<x[0].length; k++){
65
- this.automap(k, y, x[y][k]);
66
- }
67
- }
68
69
  }
69
70
 
70
71
  return this;
@@ -1,27 +1,45 @@
1
1
  /*
2
- The flicker component calls the implemented method and sends the given information over a period of time.
2
+ The flicker component calls the implemented flick method with the given array data over a period of time.
3
3
 
4
4
  This is most popular for sprite animation.
5
5
 
6
6
  It can also be used for graduatly writing text or flashing a drawing object.
7
+
8
+ re.c('health')
9
+ .requires('flicker')
10
+ .defines({
11
+
12
+ health:100,
13
+ flick:function(health){
14
+ this.health += health;
15
+ if(this.health >= 100){
16
+ //stops flicker
17
+ return false;
18
+ }
19
+ },
20
+
21
+ regen:function(){
22
+ //adds health over a duration of 30 seconds
23
+ this.flicker(30, [5, 5, 5, 5, 5, 5]);
24
+ }
25
+
26
+ });
27
+
28
+ var e = re.e('health').attr('health', 40);
29
+
30
+ //low on health, regenerate
31
+ e.regen();
32
+
7
33
  */
8
34
  re.c('flicker')
9
35
  .requires('update timestep')
10
36
  .interfaces('flick')
11
- .init(function(){
12
-
13
- this.flicker_reels = {};
14
- this.flicker_old = {};
15
- this.flicker_reel = {};
16
-
17
- this.flicker_flickering = '';
18
-
19
- })
20
- .defines({
21
-
22
- flicker_stop:function(){
23
- var o = this.flicker_flickering;
24
- this.flicker_flickering = '';
37
+ .namespaces({
38
+ flickering:'',
39
+
40
+ stop:function(){
41
+ var o = this.flicker_id;
42
+ this.flicker_id = '';
25
43
 
26
44
  this.stepProgress = 0;
27
45
 
@@ -30,15 +48,12 @@ re.c('flicker')
30
48
  return this.trigger('flicker:finish', o);
31
49
  },
32
50
 
33
- flicker_update:function(t){
34
-
35
- this.timestep(t, function(){
36
- var c = this.flicker_reel;
37
-
51
+ change:function(){
52
+
38
53
  //check if over
39
- if(this.flicker_frame == this.flicker_reel.frames.length){
54
+ if(this.flicker_frame == this.flicker_frames.length){
40
55
 
41
- if(c.loops == -1 || --this.flicker_loops >= 1){
56
+ if(this.flicker_loops == -1 || --this.flicker_loops >= 1){
42
57
  //loop again
43
58
 
44
59
  this.flicker_frame = 0;
@@ -47,151 +62,88 @@ re.c('flicker')
47
62
  //done flickering
48
63
 
49
64
  this.flicker_stop();
50
-
51
- return;
65
+ return;
52
66
  }
53
67
  }
54
68
 
69
+ this.flicker_run();
70
+ },
71
+
72
+ run:function(){
73
+
74
+ var f = this.flicker_frame,
75
+ fs = this.flicker_frames,
76
+ l = this.flicker_loops,
77
+ val = fs[f];
78
+
79
+ var quit = this.flick(val, f, fs, l);
80
+
81
+ this.trigger('flicker:update', val, f, fs, l);
82
+
55
83
  //flick
56
- if(this.flick(c.frames[this.flicker_frame], this.flicker_flickering, this.flicker_loops) === false){
84
+ if(quit === false){
57
85
  //stop
58
86
  this.flicker();
59
87
  }
60
-
88
+
61
89
  this.flicker_frame++;
62
-
63
- });
64
-
65
- },
66
-
67
- addFlicker:function(id, loops, duration, frames){
68
-
69
- if(re.is(id, 'object')){
70
-
71
- for(var i in id){
72
-
73
- //copy formed array and insert
74
- var c = id[i].slice();
75
- //add key into array
76
- c.unshift(i);
77
-
78
- this.addFlicker.apply(this, c);
79
-
80
- }
81
-
82
- return this;
83
- }
84
-
85
- if(re.is(frames, 'string')) frames = frames.split(' ');
86
-
87
- //add
88
- this.flicker_reels[id] =
89
- {
90
- frames:frames,
91
- duration:duration,
92
- loops:loops
93
- };
94
-
95
- return this;
96
- },
97
-
98
- removeFlicker:function(id){
99
-
100
- if(re.is(id,'object')){
101
-
102
- for(var i in id){
103
-
104
- this.removeFlicker.call(this, id[i]);
105
- }
106
-
107
- return this;
108
- }
109
-
110
- //assuming this flicker isn't running
111
- delete this.flicker_reels[id];
112
-
113
- return this;
90
+ },
91
+
92
+ update:function(t){
93
+ this.timestep(t, this.flicker_change);
114
94
  },
115
95
 
96
+ })
97
+ .defines({
98
+
116
99
  /*
117
- The animate method either creates or plays an animation.
118
- Time is in milliseconds.
119
-
120
- //create sequence animation
121
- re('#player').flicker('die', 1, 200, [0, 1, 3, 3, 4, 3, 2, 1]);
122
-
123
- //play animation
124
- //can customize the animation for this call.
125
- re('#player').flicker('die', 0, 200);
126
-
127
- //stop flickering
128
- re('#player').flicker();
129
-
130
- //add multiple animations
131
- flicker({
132
- idle:[loops, duration, frames],
133
- ..
134
-
135
-
136
- });
137
-
100
+
101
+ loops defaults to 1
102
+ id default to true
103
+
138
104
  FUTURE:
139
105
  -allow backward animations
140
106
  -allow entry of an array of frames. So each counter will go to the next frame in the array
141
107
  */
142
- flicker:function(id, loops, duration, frames){
108
+ flicker:function(duration, frames, loops, id){
143
109
 
144
- if(!re.is(id) && this.flickering()){
110
+ //stop
111
+ if(!re.is(loops) && this.flickering()){
145
112
  //stop flickering
146
113
  return this.flicker_stop();
147
114
  }
148
115
 
149
- if(id == this.flicker_flickering) return;
150
-
151
- if(!this.flicker_reels[id]){
152
- return this;
153
- }
154
-
155
- //defaults
156
-
157
- //startX = loops, endX = duration in seconds
158
- //if startX equals 0, animation loops forever
159
-
160
- var r = this.flicker_reels[id];
161
-
162
- //create new reel based on custom attributes
163
- var c = this.flicker_reel;
164
- //copy from saved animation or newly given
165
- c.loops = (isNaN(loops))? r.loops : loops;
166
- c.duration = (isNaN(duration))? r.duration : duration;
167
-
168
116
  //convert to seconds
169
- if(c.duration >= 30){
170
- c.duration /= 1000;
117
+ if(duration >= 100){
118
+ duration /= 1000;
171
119
  }
172
120
 
173
- c.frames = (re.is(frames,'object'))? frames : r.frames;
174
-
121
+ this.flicker_duration = duration || 1;
122
+
123
+ frames = (re.is(frames,'array')) ? frames : [frames];
124
+
175
125
  //setup counter for loops
176
- this.flicker_loops = c.loops;
126
+ this.flicker_loops = loops || 1;
177
127
 
178
128
  this.stepProgress = 0;
179
- this.stepSize = c.duration / c.frames.length;
129
+ this.stepSize = (duration / frames.length) / re.sys.second;
180
130
 
181
- //save old frames for upon completion
182
-
131
+ this.flicker_frames = frames;
183
132
  this.flicker_frame = 0;
184
133
 
185
- //update frame then run
186
- this.flick(c.frames[this.flicker_frame++]);
187
-
188
134
  if(!this.flickering()){
189
135
  this.on('update', this.flicker_update);
190
136
  }
191
137
 
192
- this.flicker_flickering = id;
138
+ //sets flicker status
139
+ this.flicker_id = id || true;
140
+
141
+ this.trigger('flicker:start');
142
+
143
+ //update frame then run
144
+ this.flicker_run();
193
145
 
194
- return this.trigger('flicker:start');
146
+ return this;
195
147
  },
196
148
 
197
149
  /*
@@ -202,10 +154,10 @@ re.c('flicker')
202
154
  */
203
155
  flickering:function(id){
204
156
  if(id){
205
- return this.flicker_flickering == id;
157
+ return this.flicker_id == id;
206
158
  }
207
159
 
208
- return this.flicker_flickering;
160
+ return this.flicker_id;
209
161
  }
210
162
 
211
163
  });