]> git.plutz.net Git - flarejs/blob - engine.js
shortcut functions for animation and dressing
[flarejs] / engine.js
1 var gamedata = {};
2 var gfx = {};
3
4 function Textfile(txtfile) {
5   var lines, fetch = new XMLHttpRequest();
6   fetch.open("GET", txtfile, false);
7   fetch.send();
8
9   var line, key, value, ref = this, section;
10   for (line of fetch.responseText.split('\n')) switch(true) {
11     case /^\[.*\]$/.test(line):
12       section = line.split(/[\]\[]/)[1];
13       if                     (!this[section]) this[section] = {};
14       else if (!Array.isArray(this[section])) this[section] = [this[section],{}];
15       else if ( Array.isArray(this[section])) this[section].push({});
16       ref = this[section];
17       break;
18     case /^frame=[0-9]+,[0-7](,[0-9-]+){6}$/.test(line):
19       key = line.split(/[=,]/).slice(1,3);  value = line.split(/,/).slice(-6);
20       if (!ref.frame) ref.frame = [];
21       if (!ref.frame[key[0]]) ref.frame[key[0]] = [];
22       ref.frame[key[0]][key[1]] = value;
23       break;
24     case /^layer=[0-9]+,/.test(line):
25       key = line.split(/[=,]/)[1];  value = line.split(/,/).slice(1);
26       if (!ref.layer) ref.layer = [];
27       ref.layer[key] = value;
28       break;
29     case /^duration=[0-9]+ms$/.test(line):
30       ref["duration"] = parseInt(line.split(/=|ms$/)[1]);
31       break;
32     case /^duration=[0-9]+s$/.test(line):
33       ref["duration"] = parseInt(line.split(/=|s$/)[1]) * 1000;
34       break;
35     case /^[^#].*=.+$/.test(line):
36       key = line.split(/[=]/)[0];  value = line.split(/=/).slice(1).join("=");
37       if                     (!ref[key]) ref[key] = value;
38       else if (!Array.isArray(ref[key])) ref[key] = [ref[key],value];
39       else if ( Array.isArray(ref[key])) ref[key].push(value);
40       break;
41   }
42 }
43
44 function Mob(textdef) {
45   if (! gamedata[textdef]) gamedata[textdef] = new Textfile(textdef); 
46   this.info = gamedata[textdef];
47   this.direction = 0;
48   this.position = [0, 0];
49   this.animation = "stance";
50   this.previous_animation = "";
51   this.frametime = performance.now();
52   if (! gfx[this.info.image]) {
53     gfx[this.info.image] = document.createElement("img");
54     gfx[this.info.image].setAttribute("src", this.info.image);
55   }
56
57   this.place = function(x, y) { this.position = [x, y]; return this; }
58   this.direct = function(d) { this.direction = d % 8; return this; }
59   this.animate = function(a) {
60     this.previous_animation = this.animation;
61     this.animation = a;
62     this.frametime = performance.now();
63     return this;
64   }
65
66   this.draw = function(){
67     var f, a = this.info[this.animation];
68     var frame = ( performance.now() - this.frametime ) * a.frames / a.duration | 0;
69
70     switch(a.type){
71       case "looped":
72         frame = frame % a.frames;
73         break;
74       case "play_once":
75         if ( frame >= a.frames ){
76           this.animation = this.previous_animation;
77           this.previous_animation = "";
78           this.frametime = performance.now();
79           a = this.info[this.animation];
80           frame = 0;
81         }
82         break;
83       case "back_forth":
84         frame = frame % (a.frames * 2 - 2);
85         if ( frame >= a.frames ){
86          frame = a.frames - frame % a.frames - 1;
87         }
88         break;
89       default: break;
90     }
91     f = a.frame[frame][this.direction];
92
93     canvas.drawImage(gfx[this.info.image], f[0], f[1], f[2], f[3],
94                      this.position[0] - f[4], this.position[1] - f[5],
95                      f[2], f[3]);
96   }
97
98   this.block  = function() { this.animate("block" ); return this; };
99   this.cast   = function() { this.animate("cast"  ); return this; };
100   this.die    = function() { this.animate("die"   ); return this; };
101   this.hit    = function() { this.animate("hit"   ); return this; };
102   this.run    = function() { this.animate("run"   ); return this; };
103   this.shoot  = function() { this.animate("shoot" ); return this; };
104   this.stance = function() { this.animate("stance"); return this; };
105   this.swing  = function() { this.animate("swing" ); return this; };
106 }
107
108 function Hero(gender = "female", hair = "short"){
109   this.position = [0,0]; this.direction = 0;
110   this.hair = (gender == "female")?"long":hair;
111   this.animation = "stance";
112
113   if (! gamedata["/engine/hero_layers.txt"])
114     gamedata["/engine/hero_layers.txt"] = new Textfile("/engine/hero_layers.txt"); 
115   this.limbs = {
116     head:  new Mob("/animations/avatar/"+gender+"/head_"+this.hair+".txt"),
117     chest: new Mob("/animations/avatar/"+gender+"/default_chest.txt"),
118     hands: new Mob("/animations/avatar/"+gender+"/default_hands.txt"),
119     legs : new Mob("/animations/avatar/"+gender+"/default_legs.txt"),
120     feet : new Mob("/animations/avatar/"+gender+"/default_feet.txt"),
121     main : new Mob("/animations/avatar/"+gender+"/dagger.txt"),
122     off  : new Mob("/animations/avatar/"+gender+"/shield.txt")
123   }
124
125   this.dress = function(limb, item) {
126     this.limbs[limb] = new Mob("/animations/avatar/"+gender+"/"+item+".txt")
127     this.limbs[limb].place(this.position[0], this.position[1]).direct(this.direction);
128     this.animate(this.animation);
129     return this;
130   }
131
132   this.place   = function(x,y) {
133     this.position = [x,y];
134     for (var limb in this.limbs) this.limbs[limb].place(x,y);
135     return this;
136   }
137   this.direct  = function(d)   {
138     this.direction = d;
139     for (var limb in this.limbs) this.limbs[limb].direct(d);
140     return this;
141   }
142   this.animate = function(anim){
143     this.animation = anim;
144     for (var limb in this.limbs) this.limbs[limb].animate(anim);
145     return this;
146   }
147   this.draw    = function(){
148     gamedata["/engine/hero_layers.txt"].layer[this.direction].forEach(limb => this.limbs[limb].draw());
149     return this;
150   }
151
152   this.block  = function() { this.animate("block" ); return this; };
153   this.cast   = function() { this.animate("cast"  ); return this; };
154   this.die    = function() { this.animate("die"   ); return this; };
155   this.hit    = function() { this.animate("hit"   ); return this; };
156   this.run    = function() { this.animate("run"   ); return this; };
157   this.shoot  = function() { this.animate("shoot" ); return this; };
158   this.stance = function() { this.animate("stance"); return this; };
159   this.swing  = function() { this.animate("swing" ); return this; };
160 }
161
162 canvas = document.getElementById("view").getContext("2d");
163 player = new Hero().place(240, 160).direct(5);
164
165 setInterval( function() { canvas.clearRect(0,0, 480, 320); player.draw(); }, 33.33);