ruby2d 0.2.1 → 0.3.0
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.
- checksums.yaml +4 -4
- data/assets/README.md +1 -0
- data/assets/opal.js +19532 -0
- data/assets/simple2d.js +1180 -0
- data/assets/template.html +18 -0
- data/bin/ruby2d +161 -46
- data/ext/ruby2d/extconf.rb +17 -8
- data/ext/ruby2d/ruby2d-opal.rb +219 -0
- data/ext/ruby2d/ruby2d.c +665 -154
- data/lib/ruby2d.rb +7 -4
- data/lib/ruby2d/application.rb +14 -2
- data/lib/ruby2d/color.rb +56 -33
- data/lib/ruby2d/dsl.rb +21 -12
- data/lib/ruby2d/exceptions.rb +2 -3
- data/lib/ruby2d/image.rb +22 -9
- data/lib/ruby2d/music.rb +17 -0
- data/lib/ruby2d/quad.rb +24 -15
- data/lib/ruby2d/rectangle.rb +2 -5
- data/lib/ruby2d/sound.rb +6 -9
- data/lib/ruby2d/sprite.rb +91 -0
- data/lib/ruby2d/square.rb +2 -5
- data/lib/ruby2d/text.rb +19 -23
- data/lib/ruby2d/triangle.rb +29 -15
- data/lib/ruby2d/version.rb +1 -1
- data/lib/ruby2d/window.rb +121 -67
- metadata +27 -7
data/assets/simple2d.js
ADDED
@@ -0,0 +1,1180 @@
|
|
1
|
+
// Simple2D.js — v0.1.0, built 03-01-2017
|
2
|
+
|
3
|
+
// start.js - Open the anonymous function defining the Simple 2D module
|
4
|
+
|
5
|
+
(function(undefined) {
|
6
|
+
|
7
|
+
// Check if Simple 2D is already loaded
|
8
|
+
if (typeof(this.S2D) !== 'undefined') {
|
9
|
+
console.warn("Simple 2D already loaded! Loading twice may cause problems.");
|
10
|
+
return this.S2D;
|
11
|
+
}
|
12
|
+
|
13
|
+
// Create the Simple 2D module
|
14
|
+
var S2D = this.S2D = {};
|
15
|
+
|
16
|
+
// ... Simple 2D library starts here ...
|
17
|
+
|
18
|
+
|
19
|
+
// simple2d.js
|
20
|
+
|
21
|
+
// Simple 2D OpenGL namespace
|
22
|
+
S2D.GL = {};
|
23
|
+
|
24
|
+
// Simple 2D definitions
|
25
|
+
Object.defineProperty(S2D, "KEYDOWN", { value: 1 });
|
26
|
+
Object.defineProperty(S2D, "KEY", { value: 2 });
|
27
|
+
Object.defineProperty(S2D, "KEYUP", { value: 3 });
|
28
|
+
|
29
|
+
// Viewport scaling modes
|
30
|
+
Object.defineProperty(S2D, "FIXED", { value: 1 });
|
31
|
+
Object.defineProperty(S2D, "SCALE", { value: 2 });
|
32
|
+
Object.defineProperty(S2D, "STRETCH", { value: 3 });
|
33
|
+
|
34
|
+
// Color
|
35
|
+
S2D.Color = {
|
36
|
+
r: 1.0,
|
37
|
+
g: 1.0,
|
38
|
+
b: 1.0,
|
39
|
+
a: 1.0
|
40
|
+
};
|
41
|
+
|
42
|
+
// Window
|
43
|
+
S2D.Window = {
|
44
|
+
title: null,
|
45
|
+
width: null,
|
46
|
+
height: null,
|
47
|
+
orig_width: null,
|
48
|
+
orig_height: null,
|
49
|
+
viewport: {
|
50
|
+
width: null,
|
51
|
+
height: null,
|
52
|
+
mode: null
|
53
|
+
},
|
54
|
+
pixel_ratio: null,
|
55
|
+
update: null,
|
56
|
+
render: null,
|
57
|
+
mouse: {
|
58
|
+
x: 0,
|
59
|
+
y: 0
|
60
|
+
},
|
61
|
+
on_key: null,
|
62
|
+
on_mouse: null,
|
63
|
+
element: null, // The HTML element to append the canvas
|
64
|
+
canvas: null,
|
65
|
+
background: null,
|
66
|
+
frames: 0,
|
67
|
+
close: false
|
68
|
+
};
|
69
|
+
|
70
|
+
// Image
|
71
|
+
S2D.Image = {
|
72
|
+
texture: null,
|
73
|
+
data: null,
|
74
|
+
color: null,
|
75
|
+
x: 0,
|
76
|
+
y: 0,
|
77
|
+
width: null,
|
78
|
+
height: null,
|
79
|
+
orig_width: null,
|
80
|
+
orig_height: null
|
81
|
+
};
|
82
|
+
|
83
|
+
// Sprite
|
84
|
+
S2D.Sprite = {
|
85
|
+
img: null,
|
86
|
+
x: 0,
|
87
|
+
y: 0,
|
88
|
+
width: null,
|
89
|
+
height: null,
|
90
|
+
tx1: null,
|
91
|
+
ty1: null,
|
92
|
+
tx2: null,
|
93
|
+
ty2: null,
|
94
|
+
tx3: null,
|
95
|
+
ty3: null,
|
96
|
+
tx4: null,
|
97
|
+
ty4: null
|
98
|
+
};
|
99
|
+
|
100
|
+
// Text
|
101
|
+
S2D.Text = {
|
102
|
+
texture: null,
|
103
|
+
data: null,
|
104
|
+
color: null,
|
105
|
+
x: 0,
|
106
|
+
y: 0,
|
107
|
+
width: null,
|
108
|
+
height: null,
|
109
|
+
font: null,
|
110
|
+
size: null,
|
111
|
+
msg: null
|
112
|
+
};
|
113
|
+
|
114
|
+
// Sound
|
115
|
+
S2D.Sound = {
|
116
|
+
data: null
|
117
|
+
};
|
118
|
+
|
119
|
+
// Music
|
120
|
+
S2D.Music = {
|
121
|
+
data: null
|
122
|
+
};
|
123
|
+
|
124
|
+
// Global current music playing
|
125
|
+
S2D.current_music = null;
|
126
|
+
|
127
|
+
// Collection of keys currently pressed
|
128
|
+
S2D.keys_down = [];
|
129
|
+
|
130
|
+
// On keyboard starting at top row, left to right
|
131
|
+
S2D.key_map = {
|
132
|
+
27: "Escape",
|
133
|
+
|
134
|
+
192: "`",
|
135
|
+
189: "-",
|
136
|
+
187: "=",
|
137
|
+
8: "Backspace",
|
138
|
+
|
139
|
+
9: "Tab",
|
140
|
+
219: "[",
|
141
|
+
221: "]",
|
142
|
+
220: "\\",
|
143
|
+
|
144
|
+
20: "CapsLock",
|
145
|
+
186: ";",
|
146
|
+
222: "'",
|
147
|
+
13: "Return",
|
148
|
+
|
149
|
+
16: "Shift",
|
150
|
+
188: ",",
|
151
|
+
190: ".",
|
152
|
+
191: "/",
|
153
|
+
|
154
|
+
17: "Ctrl",
|
155
|
+
18: "Option",
|
156
|
+
91: "Left Command",
|
157
|
+
32: "Space",
|
158
|
+
93: "Right Command",
|
159
|
+
37: "Left",
|
160
|
+
38: "Up",
|
161
|
+
39: "Right",
|
162
|
+
40: "Down"
|
163
|
+
};
|
164
|
+
|
165
|
+
// Web-specific helpers
|
166
|
+
|
167
|
+
// Looks up a key from a given keycode
|
168
|
+
S2D.GetKey = function(keycode) {
|
169
|
+
if (typeof(keycode) == "string") {
|
170
|
+
return keycode;
|
171
|
+
} else if (S2D.key_map[keycode]) {
|
172
|
+
return S2D.key_map[keycode];
|
173
|
+
} else {
|
174
|
+
return String.fromCharCode(keycode);
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
// Trim transparent pixels from canvas
|
179
|
+
// Adapted from: https://gist.github.com/remy/784508
|
180
|
+
S2D.TrimCanvas = function(c) {
|
181
|
+
var ctx = c.getContext('2d'),
|
182
|
+
copy = document.createElement('canvas').getContext('2d'),
|
183
|
+
pixels = ctx.getImageData(0, 0, c.width, c.height),
|
184
|
+
l = pixels.data.length,
|
185
|
+
i,
|
186
|
+
bound = {
|
187
|
+
top: null,
|
188
|
+
left: null,
|
189
|
+
right: null,
|
190
|
+
bottom: null
|
191
|
+
},
|
192
|
+
x, y;
|
193
|
+
|
194
|
+
for (i = 0; i < l; i += 4) {
|
195
|
+
if (pixels.data[i+3] !== 0) {
|
196
|
+
x = (i / 4) % c.width;
|
197
|
+
y = ~~((i / 4) / c.width);
|
198
|
+
|
199
|
+
if (bound.top === null) {
|
200
|
+
bound.top = y;
|
201
|
+
}
|
202
|
+
|
203
|
+
if (bound.left === null) {
|
204
|
+
bound.left = x;
|
205
|
+
} else if (x < bound.left) {
|
206
|
+
bound.left = x;
|
207
|
+
}
|
208
|
+
|
209
|
+
if (bound.right === null) {
|
210
|
+
bound.right = x;
|
211
|
+
} else if (bound.right < x) {
|
212
|
+
bound.right = x;
|
213
|
+
}
|
214
|
+
|
215
|
+
if (bound.bottom === null) {
|
216
|
+
bound.bottom = y;
|
217
|
+
} else if (bound.bottom < y) {
|
218
|
+
bound.bottom = y;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
var trimHeight = bound.bottom - bound.top,
|
224
|
+
trimWidth = bound.right - bound.left,
|
225
|
+
trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
|
226
|
+
|
227
|
+
copy.canvas.width = trimWidth;
|
228
|
+
copy.canvas.height = trimHeight;
|
229
|
+
copy.putImageData(trimmed, 0, 0);
|
230
|
+
|
231
|
+
// open new window with trimmed image:
|
232
|
+
return copy.canvas;
|
233
|
+
};
|
234
|
+
|
235
|
+
|
236
|
+
// shapes.js
|
237
|
+
|
238
|
+
/*
|
239
|
+
* Draw a triangle
|
240
|
+
*/
|
241
|
+
S2D.DrawTriangle = function(x1, y1, c1r, c1g, c1b, c1a,
|
242
|
+
x2, y2, c2r, c2g, c2b, c2a,
|
243
|
+
x3, y3, c3r, c3g, c3b, c3a) {
|
244
|
+
|
245
|
+
S2D.GL.DrawTriangle(x1, y1, c1r, c1g, c1b, c1a,
|
246
|
+
x2, y2, c2r, c2g, c2b, c2a,
|
247
|
+
x3, y3, c3r, c3g, c3b, c3a);
|
248
|
+
};
|
249
|
+
|
250
|
+
|
251
|
+
/*
|
252
|
+
* Draw a quad, using two triangles
|
253
|
+
*/
|
254
|
+
S2D.DrawQuad = function(x1, y1,
|
255
|
+
c1r, c1g, c1b, c1a,
|
256
|
+
x2, y2,
|
257
|
+
c2r, c2g, c2b, c2a,
|
258
|
+
x3, y3,
|
259
|
+
c3r, c3g, c3b, c3a,
|
260
|
+
x4, y4,
|
261
|
+
c4r, c4g, c4b, c4a) {
|
262
|
+
|
263
|
+
S2D.GL.DrawTriangle(x1, y1, c1r, c1g, c1b, c1a,
|
264
|
+
x2, y2, c2r, c2g, c2b, c2a,
|
265
|
+
x3, y3, c3r, c3g, c3b, c3a);
|
266
|
+
|
267
|
+
S2D.GL.DrawTriangle(x3, y3, c3r, c3g, c3b, c3a,
|
268
|
+
x4, y4, c4r, c4g, c4b, c4a,
|
269
|
+
x1, y1, c1r, c1g, c1b, c1a);
|
270
|
+
};
|
271
|
+
|
272
|
+
|
273
|
+
// image.js
|
274
|
+
|
275
|
+
/*
|
276
|
+
* Create an image
|
277
|
+
* Params: path = image file path
|
278
|
+
*/
|
279
|
+
S2D.CreateImage = function(path, loadedCallback) {
|
280
|
+
|
281
|
+
// TODO: Check if image file exists
|
282
|
+
|
283
|
+
// Create image object
|
284
|
+
var img = Object.create(S2D.Image);
|
285
|
+
img.data = new Image();
|
286
|
+
img.color = Object.create(S2D.Color);
|
287
|
+
|
288
|
+
img.data.onload = function() {
|
289
|
+
img.texture = S2D.GL.CreateTexture(this);
|
290
|
+
if (!img.width) img.width = this.width;
|
291
|
+
if (!img.height) img.height = this.height;
|
292
|
+
if (loadedCallback) loadedCallback();
|
293
|
+
};
|
294
|
+
|
295
|
+
// Causes image to be loaded
|
296
|
+
img.data.src = path;
|
297
|
+
|
298
|
+
return img;
|
299
|
+
};
|
300
|
+
|
301
|
+
|
302
|
+
/*
|
303
|
+
* Draw an image
|
304
|
+
*/
|
305
|
+
S2D.DrawImage = function(img) {
|
306
|
+
if (!img) return;
|
307
|
+
S2D.GL.DrawImage(img);
|
308
|
+
};
|
309
|
+
|
310
|
+
|
311
|
+
// sprite.js
|
312
|
+
|
313
|
+
/*
|
314
|
+
* Create a sprite, given an image file path
|
315
|
+
*/
|
316
|
+
S2D.CreateSprite = function(path) {
|
317
|
+
|
318
|
+
// TODO: Check if sprite image file exists
|
319
|
+
|
320
|
+
var spr = Object.create(S2D.Sprite);
|
321
|
+
spr.img = S2D.CreateImage(path, function() {
|
322
|
+
spr.width = spr.img.width;
|
323
|
+
spr.height = spr.img.height;
|
324
|
+
});
|
325
|
+
|
326
|
+
spr.tx1 = 0.0;
|
327
|
+
spr.ty1 = 0.0;
|
328
|
+
spr.tx2 = 1.0;
|
329
|
+
spr.ty2 = 0.0;
|
330
|
+
spr.tx3 = 1.0;
|
331
|
+
spr.ty3 = 1.0;
|
332
|
+
spr.tx4 = 0.0;
|
333
|
+
spr.ty4 = 1.0;
|
334
|
+
|
335
|
+
return spr;
|
336
|
+
};
|
337
|
+
|
338
|
+
|
339
|
+
/*
|
340
|
+
* Clip a sprite
|
341
|
+
*/
|
342
|
+
S2D.ClipSprite = function(spr, x, y, w, h) {
|
343
|
+
if (!spr) return;
|
344
|
+
|
345
|
+
// Calculate ratios
|
346
|
+
// rw = ratio width; rh = ratio height
|
347
|
+
var rw = w / spr.img.width;
|
348
|
+
var rh = h / spr.img.height;
|
349
|
+
|
350
|
+
// Apply ratios to x, y coordinates
|
351
|
+
// cx = crop x coord; cy = crop y coord
|
352
|
+
var cx = x * rw;
|
353
|
+
var cy = y * rh;
|
354
|
+
|
355
|
+
// Convert given width, height to doubles
|
356
|
+
// cw = crop width; ch = crop height
|
357
|
+
var cw = w;
|
358
|
+
var ch = h;
|
359
|
+
|
360
|
+
// Apply ratio to texture width and height
|
361
|
+
// tw = texture width; th = texture height
|
362
|
+
var tw = rw * w;
|
363
|
+
var th = rh * h;
|
364
|
+
|
365
|
+
// Calculate and store sprite texture values
|
366
|
+
|
367
|
+
spr.tx1 = cx / cw;
|
368
|
+
spr.ty1 = cy / ch;
|
369
|
+
|
370
|
+
spr.tx2 = (cx + tw) / cw;
|
371
|
+
spr.ty2 = cy / ch;
|
372
|
+
|
373
|
+
spr.tx3 = (cx + tw) / cw;
|
374
|
+
spr.ty3 = (cy + th) / ch;
|
375
|
+
|
376
|
+
spr.tx4 = cx / cw;
|
377
|
+
spr.ty4 = (cy + th) / ch;
|
378
|
+
|
379
|
+
// Store the sprite width and height
|
380
|
+
spr.width = w;
|
381
|
+
spr.height = h;
|
382
|
+
};
|
383
|
+
|
384
|
+
|
385
|
+
/*
|
386
|
+
* Draw a sprite
|
387
|
+
*/
|
388
|
+
S2D.DrawSprite = function(spr) {
|
389
|
+
if (!spr) return;
|
390
|
+
S2D.GL.DrawSprite(spr);
|
391
|
+
};
|
392
|
+
|
393
|
+
|
394
|
+
// text.js
|
395
|
+
|
396
|
+
/*
|
397
|
+
* Create text, given a font file path, the message, and size
|
398
|
+
*/
|
399
|
+
S2D.CreateText = function(font, msg, size) {
|
400
|
+
|
401
|
+
// Create image object
|
402
|
+
var txt = Object.create(S2D.Text);
|
403
|
+
txt.color = Object.create(S2D.Color);
|
404
|
+
txt.font = font;
|
405
|
+
txt.msg = msg;
|
406
|
+
txt.size = size;
|
407
|
+
|
408
|
+
return txt;
|
409
|
+
};
|
410
|
+
|
411
|
+
|
412
|
+
/*
|
413
|
+
* Sets the text message
|
414
|
+
*/
|
415
|
+
S2D.SetText = function(txt, msg) {
|
416
|
+
if (msg == "") return; // no need to create a texture
|
417
|
+
|
418
|
+
S2D.GL.FreeTexture(txt.texture);
|
419
|
+
|
420
|
+
// Create a canvas element to make a texture
|
421
|
+
var ctx = document.createElement("canvas").getContext("2d");
|
422
|
+
|
423
|
+
// TODO: Width and height should probably be variable, based on
|
424
|
+
// `ctx.measureText(msg).width` or something.
|
425
|
+
var w = 1000;
|
426
|
+
var h = 1000;
|
427
|
+
|
428
|
+
// Double size of font for high DPI
|
429
|
+
var size = txt.size * 2;
|
430
|
+
|
431
|
+
// Set context attributes and draw text
|
432
|
+
ctx.canvas.width = w;
|
433
|
+
ctx.canvas.height = h;
|
434
|
+
ctx.font = `${size}px ${txt.font}`;
|
435
|
+
ctx.textAlign = "right";
|
436
|
+
ctx.textBaseline = "bottom";
|
437
|
+
ctx.fillStyle = "white";
|
438
|
+
ctx.fillText(msg, w, h);
|
439
|
+
|
440
|
+
txt.data = S2D.TrimCanvas(ctx.canvas); // trim the transparent pixels
|
441
|
+
txt.texture = S2D.GL.CreateTexture(txt.data);
|
442
|
+
txt.width = txt.data.width / 2; // half size of texture for high DPI
|
443
|
+
txt.height = txt.data.height / 2;
|
444
|
+
};
|
445
|
+
|
446
|
+
|
447
|
+
/*
|
448
|
+
* Draw text
|
449
|
+
*/
|
450
|
+
S2D.DrawText = function(txt) {
|
451
|
+
if (!txt) return;
|
452
|
+
|
453
|
+
if (!txt.texture) {
|
454
|
+
S2D.SetText(txt, txt.msg);
|
455
|
+
}
|
456
|
+
|
457
|
+
S2D.GL.DrawText(txt);
|
458
|
+
};
|
459
|
+
|
460
|
+
|
461
|
+
// sound.js
|
462
|
+
|
463
|
+
/*
|
464
|
+
* Create a sound, given an audio file path
|
465
|
+
*/
|
466
|
+
S2D.CreateSound = function(path) {
|
467
|
+
|
468
|
+
// TODO: Check if audio file exists
|
469
|
+
|
470
|
+
var sound = Object.create(S2D.Sound);
|
471
|
+
sound.data = new Audio(path);
|
472
|
+
|
473
|
+
return sound;
|
474
|
+
};
|
475
|
+
|
476
|
+
|
477
|
+
/*
|
478
|
+
* Play the sound
|
479
|
+
*/
|
480
|
+
S2D.PlaySound = function(sound) {
|
481
|
+
// Clone sound and play so audio can overlap
|
482
|
+
sound.data.cloneNode(true).play();
|
483
|
+
};
|
484
|
+
|
485
|
+
|
486
|
+
// music.js
|
487
|
+
|
488
|
+
/*
|
489
|
+
* Create the music, given an audio file path
|
490
|
+
*/
|
491
|
+
S2D.CreateMusic = function(path) {
|
492
|
+
|
493
|
+
// TODO: Check if audio file exists
|
494
|
+
|
495
|
+
var music = Object.create(S2D.Music);
|
496
|
+
music.data = new Audio(path);
|
497
|
+
|
498
|
+
return music;
|
499
|
+
};
|
500
|
+
|
501
|
+
|
502
|
+
/*
|
503
|
+
* Play the music
|
504
|
+
*/
|
505
|
+
S2D.PlayMusic = function(music, loop) {
|
506
|
+
S2D.StopMusic();
|
507
|
+
music.data.loop = loop;
|
508
|
+
S2D.current_music = music.data;
|
509
|
+
S2D.current_music.play();
|
510
|
+
};
|
511
|
+
|
512
|
+
|
513
|
+
/*
|
514
|
+
* Pause the playing music
|
515
|
+
*/
|
516
|
+
S2D.PauseMusic = function() {
|
517
|
+
if (!S2D.current_music) return;
|
518
|
+
S2D.current_music.pause();
|
519
|
+
};
|
520
|
+
|
521
|
+
|
522
|
+
/*
|
523
|
+
* Resume the current music
|
524
|
+
*/
|
525
|
+
S2D.ResumeMusic = function() {
|
526
|
+
if (!S2D.current_music) return;
|
527
|
+
S2D.current_music.play();
|
528
|
+
};
|
529
|
+
|
530
|
+
|
531
|
+
/*
|
532
|
+
* Stops the playing music; interrupts fader effects
|
533
|
+
*/
|
534
|
+
S2D.StopMusic = function() {
|
535
|
+
if (!S2D.current_music) return;
|
536
|
+
S2D.current_music.pause();
|
537
|
+
S2D.current_music.currentTime = 0;
|
538
|
+
};
|
539
|
+
|
540
|
+
|
541
|
+
/*
|
542
|
+
* Fade out the playing music
|
543
|
+
*/
|
544
|
+
S2D.FadeOutMusic = function(ms) {
|
545
|
+
if (!S2D.current_music) return;
|
546
|
+
|
547
|
+
if (S2D.current_music.paused) {
|
548
|
+
S2D.StopMusic();
|
549
|
+
return;
|
550
|
+
}
|
551
|
+
|
552
|
+
var fadeAudio = setInterval(function () {
|
553
|
+
if (S2D.current_music.volume >= 0.05) {
|
554
|
+
S2D.current_music.volume -= 0.05;
|
555
|
+
} else {
|
556
|
+
S2D.StopMusic();
|
557
|
+
S2D.current_music.volume = 1.0;
|
558
|
+
clearInterval(fadeAudio);
|
559
|
+
}
|
560
|
+
|
561
|
+
}, ms / 20);
|
562
|
+
};
|
563
|
+
|
564
|
+
|
565
|
+
// input.js
|
566
|
+
|
567
|
+
/*
|
568
|
+
* Get the mouse coordinates relative to the viewport
|
569
|
+
*/
|
570
|
+
S2D.GetMouseOnViewport = function(win, wx, wy) {
|
571
|
+
|
572
|
+
var scale; // viewport scale factor
|
573
|
+
var w, h; // width and height of scaled viewport
|
574
|
+
var x, y; // mouse positions to be returned
|
575
|
+
|
576
|
+
switch (win.viewport.mode) {
|
577
|
+
|
578
|
+
case S2D.FIXED:
|
579
|
+
x = wx / (win.orig_width / win.viewport.width);
|
580
|
+
y = wy / (win.orig_height / win.viewport.height);
|
581
|
+
break;
|
582
|
+
|
583
|
+
case S2D.SCALE:
|
584
|
+
var o = S2D.GL.GetViewportScale(win);
|
585
|
+
x = wx * 1 / o.scale - (win.width - o.w) / (2.0 * o.scale);
|
586
|
+
y = wy * 1 / o.scale - (win.height - o.h) / (2.0 * o.scale);
|
587
|
+
break;
|
588
|
+
|
589
|
+
case S2D.STRETCH:
|
590
|
+
x = wx * win.viewport.width / win.width;
|
591
|
+
y = wy * win.viewport.height / win.height;
|
592
|
+
break;
|
593
|
+
}
|
594
|
+
|
595
|
+
return {
|
596
|
+
x: x,
|
597
|
+
y: y
|
598
|
+
};
|
599
|
+
};
|
600
|
+
|
601
|
+
|
602
|
+
// window.js
|
603
|
+
|
604
|
+
/*
|
605
|
+
* Create a window
|
606
|
+
*/
|
607
|
+
S2D.CreateWindow = function(title, width, height, update, render, element, opts) {
|
608
|
+
|
609
|
+
var win = Object.create(S2D.Window);
|
610
|
+
|
611
|
+
win.title = title;
|
612
|
+
win.width = width;
|
613
|
+
win.height = height;
|
614
|
+
win.orig_width = width;
|
615
|
+
win.orig_height = height;
|
616
|
+
win.viewport.width = width;
|
617
|
+
win.viewport.height = height;
|
618
|
+
win.viewport.mode = S2D.SCALE;
|
619
|
+
win.update = update;
|
620
|
+
win.render = render;
|
621
|
+
win.background = Object.create(S2D.Color);
|
622
|
+
win.background.r = 0;
|
623
|
+
win.background.g = 0;
|
624
|
+
win.background.b = 0;
|
625
|
+
win.background.a = 1;
|
626
|
+
|
627
|
+
// `element` can be an ID string (e.g. "#game") or an actual DOM element
|
628
|
+
if (typeof(element) == 'string') {
|
629
|
+
win.element = document.getElementById(element);
|
630
|
+
} else {
|
631
|
+
win.element = element;
|
632
|
+
}
|
633
|
+
|
634
|
+
return win;
|
635
|
+
};
|
636
|
+
|
637
|
+
|
638
|
+
/*
|
639
|
+
* Show the window
|
640
|
+
*/
|
641
|
+
S2D.Show = function(win) {
|
642
|
+
|
643
|
+
// Create the canvas element
|
644
|
+
|
645
|
+
var el = document.createElement('canvas');
|
646
|
+
win.element.appendChild(el);
|
647
|
+
|
648
|
+
el.setAttribute('width', win.width);
|
649
|
+
el.setAttribute('height', win.height);
|
650
|
+
el.innerHTML = "Your browser doesn't appear to support" +
|
651
|
+
"the <code><canvas></code> element.";
|
652
|
+
|
653
|
+
win.canvas = el;
|
654
|
+
|
655
|
+
// Detect and set up canvas for high DPI
|
656
|
+
|
657
|
+
win.canvas.style.width = win.width + "px";
|
658
|
+
win.canvas.style.height = win.height + "px";
|
659
|
+
|
660
|
+
var ratio = window.devicePixelRatio ||
|
661
|
+
window.webkitDevicePixelRatio ||
|
662
|
+
window.mozDevicePixelRatio ||
|
663
|
+
window.opDevicePixelRatio || 1;
|
664
|
+
|
665
|
+
win.canvas.width = win.width * devicePixelRatio;
|
666
|
+
win.canvas.height = win.height * devicePixelRatio;
|
667
|
+
win.pixel_ratio = ratio;
|
668
|
+
|
669
|
+
// Initialize WebGL
|
670
|
+
S2D.GL.Init(win);
|
671
|
+
|
672
|
+
S2D.onkeydown = function(e) {
|
673
|
+
var key = S2D.GetKey(e.keyCode);
|
674
|
+
if (!S2D.keys_down.includes(key)) {
|
675
|
+
S2D.keys_down.push(key);
|
676
|
+
if (win.on_key) win.on_key(S2D.KEYDOWN, key);
|
677
|
+
}
|
678
|
+
};
|
679
|
+
document.addEventListener("keydown", S2D.onkeydown);
|
680
|
+
|
681
|
+
S2D.onkeyup = function(e) {
|
682
|
+
var key = S2D.GetKey(e.keyCode);
|
683
|
+
var i = S2D.keys_down.indexOf(key);
|
684
|
+
if (i > -1) S2D.keys_down.splice(i, 1);
|
685
|
+
if (win.on_key) win.on_key(S2D.KEYUP, key);
|
686
|
+
};
|
687
|
+
document.addEventListener("keyup", S2D.onkeyup);
|
688
|
+
|
689
|
+
// Clear keys down list when focus is lost
|
690
|
+
window.addEventListener("blur", function functionName() {
|
691
|
+
var e = {};
|
692
|
+
S2D.keys_down.slice().forEach(function(key) {
|
693
|
+
e.keyCode = key;
|
694
|
+
S2D.onkeyup(e);
|
695
|
+
});
|
696
|
+
});
|
697
|
+
|
698
|
+
S2D.onmousedown = function(e) {
|
699
|
+
var x = e.pageX - win.canvas.offsetLeft;
|
700
|
+
var y = e.pageY - win.canvas.offsetTop;
|
701
|
+
var o = S2D.GetMouseOnViewport(win, x, y);
|
702
|
+
if (win.on_mouse) win.on_mouse(o.x, o.y);
|
703
|
+
};
|
704
|
+
document.addEventListener("mousedown", S2D.onmousedown);
|
705
|
+
|
706
|
+
// Get and store mouse position
|
707
|
+
S2D.onmousemove = function(e) {
|
708
|
+
var x = e.pageX - win.canvas.offsetLeft;
|
709
|
+
var y = e.pageY - win.canvas.offsetTop;
|
710
|
+
var o = S2D.GetMouseOnViewport(win, x, y);
|
711
|
+
win.mouse.x = o.x;
|
712
|
+
win.mouse.y = o.y;
|
713
|
+
};
|
714
|
+
document.addEventListener("mousemove", S2D.onmousemove);
|
715
|
+
|
716
|
+
// Main loop
|
717
|
+
|
718
|
+
var req; // the animation frame request
|
719
|
+
var start_ms = new Date();
|
720
|
+
var end_ms = new Date();
|
721
|
+
var elapsed_ms;
|
722
|
+
|
723
|
+
function mainLoop(win) {
|
724
|
+
|
725
|
+
if (win.close) {
|
726
|
+
cancelAnimationFrame(req);
|
727
|
+
return;
|
728
|
+
}
|
729
|
+
|
730
|
+
S2D.GL.Clear(win.background);
|
731
|
+
|
732
|
+
// Update frame counter
|
733
|
+
win.frames++;
|
734
|
+
|
735
|
+
// Calculate and store FPS
|
736
|
+
end_ms = new Date();
|
737
|
+
elapsed_ms = end_ms.getTime() - start_ms.getTime();
|
738
|
+
win.fps = win.frames / (elapsed_ms / 1000.0);
|
739
|
+
|
740
|
+
// Detect keys held down
|
741
|
+
S2D.keys_down.forEach(function(key) {
|
742
|
+
if (win.on_key) win.on_key(S2D.KEY, key);
|
743
|
+
});
|
744
|
+
|
745
|
+
if (win.update) win.update();
|
746
|
+
if (win.render) win.render();
|
747
|
+
|
748
|
+
requestAnimationFrame(function() { mainLoop(win); });
|
749
|
+
}
|
750
|
+
|
751
|
+
req = requestAnimationFrame(function() { mainLoop(win); });
|
752
|
+
};
|
753
|
+
|
754
|
+
|
755
|
+
/*
|
756
|
+
* Close the window
|
757
|
+
*/
|
758
|
+
S2D.Close = function(win) {
|
759
|
+
win.close = true;
|
760
|
+
// win.canvas.remove();
|
761
|
+
};
|
762
|
+
|
763
|
+
|
764
|
+
// gl.js
|
765
|
+
|
766
|
+
var gl = null, // The WebGL context
|
767
|
+
canvas, // The HTML canvas element
|
768
|
+
indices = [0, 1, 2, 2, 3, 0],
|
769
|
+
// Triangle shader
|
770
|
+
shaderProgram,
|
771
|
+
positionLocation,
|
772
|
+
colorLocation,
|
773
|
+
// Texture shader
|
774
|
+
texShaderProgram,
|
775
|
+
texPositionLocation,
|
776
|
+
texColorLocation,
|
777
|
+
texCoordLocation,
|
778
|
+
samplerLocation;
|
779
|
+
|
780
|
+
var orthoMatrix = [
|
781
|
+
0, 0, 0, 0,
|
782
|
+
0, 0, 0, 0,
|
783
|
+
0, 0, 0, 0,
|
784
|
+
-1.0, 1.0, -1.0, 1.0
|
785
|
+
];
|
786
|
+
|
787
|
+
|
788
|
+
/*
|
789
|
+
* Initialize WebGL
|
790
|
+
*/
|
791
|
+
S2D.GL.Init = function(win) {
|
792
|
+
|
793
|
+
// Initialize the GL context
|
794
|
+
try {
|
795
|
+
// Try to grab the standard context. If it fails, fallback to experimental.
|
796
|
+
gl = win.canvas.getContext("webgl") || win.canvas.getContext("experimental-webgl");
|
797
|
+
} catch(e) {
|
798
|
+
console.log("GL error caught");
|
799
|
+
}
|
800
|
+
|
801
|
+
// If we don't have a GL context, give up now
|
802
|
+
if (!gl) {
|
803
|
+
console.error("Unable to initialize WebGL. Your browser may not support it.");
|
804
|
+
return null;
|
805
|
+
}
|
806
|
+
|
807
|
+
S2D.GL.WebGLInit();
|
808
|
+
S2D.GL.SetViewport(win);
|
809
|
+
};
|
810
|
+
|
811
|
+
|
812
|
+
/*
|
813
|
+
* Initialize WebGL
|
814
|
+
*/
|
815
|
+
S2D.GL.WebGLInit = function() {
|
816
|
+
|
817
|
+
// Enable transparency
|
818
|
+
gl.enable(gl.BLEND);
|
819
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
820
|
+
|
821
|
+
// Vertex shader source string
|
822
|
+
var vertexSource = `
|
823
|
+
uniform mat4 u_matrix;
|
824
|
+
attribute vec4 a_position;
|
825
|
+
attribute vec4 a_color;
|
826
|
+
attribute vec2 a_texcoord;
|
827
|
+
varying vec4 v_color;
|
828
|
+
varying vec2 v_texcoord;
|
829
|
+
void main(void) {
|
830
|
+
v_color = a_color;
|
831
|
+
v_texcoord = a_texcoord;
|
832
|
+
gl_Position = u_matrix * a_position;
|
833
|
+
}`;
|
834
|
+
|
835
|
+
// Fragment shader source string
|
836
|
+
var fragmentSource = `
|
837
|
+
precision mediump float;
|
838
|
+
varying vec4 v_color;
|
839
|
+
void main(void) {
|
840
|
+
gl_FragColor = v_color;
|
841
|
+
}`;
|
842
|
+
|
843
|
+
// Fragment shader source string for textures
|
844
|
+
var texFragmentSource = `
|
845
|
+
precision mediump float;
|
846
|
+
varying vec4 v_color;
|
847
|
+
varying vec2 v_texcoord;
|
848
|
+
uniform sampler2D s_texture;
|
849
|
+
void main(void) {
|
850
|
+
gl_FragColor = texture2D(s_texture, v_texcoord) * v_color;
|
851
|
+
}`;
|
852
|
+
|
853
|
+
// Load the vertex and fragment shaders
|
854
|
+
var vertexShader = S2D.GL.LoadShader( gl.VERTEX_SHADER, vertexSource, "Vertex");
|
855
|
+
var fragmentShader = S2D.GL.LoadShader(gl.FRAGMENT_SHADER, fragmentSource, "Fragment");
|
856
|
+
var texFragmentShader = S2D.GL.LoadShader(gl.FRAGMENT_SHADER, texFragmentSource, "Texture Fragment");
|
857
|
+
|
858
|
+
// Triangle Shader //
|
859
|
+
|
860
|
+
// Create the texture shader program object
|
861
|
+
shaderProgram = gl.createProgram();
|
862
|
+
|
863
|
+
// Attach the shader objects to the program object
|
864
|
+
gl.attachShader(shaderProgram, vertexShader);
|
865
|
+
gl.attachShader(shaderProgram, fragmentShader);
|
866
|
+
|
867
|
+
// Link the shader program
|
868
|
+
gl.linkProgram(shaderProgram);
|
869
|
+
|
870
|
+
// Check if linked
|
871
|
+
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
872
|
+
console.error("Unable to initialize the shader program.");
|
873
|
+
}
|
874
|
+
|
875
|
+
// Get the attribute locations
|
876
|
+
positionLocation = gl.getAttribLocation(shaderProgram, "a_position");
|
877
|
+
colorLocation = gl.getAttribLocation(shaderProgram, "a_color");
|
878
|
+
|
879
|
+
// Texture Shader //
|
880
|
+
|
881
|
+
// Create the texture shader program object
|
882
|
+
texShaderProgram = gl.createProgram();
|
883
|
+
|
884
|
+
// Attach the shader objects to the program object
|
885
|
+
gl.attachShader(texShaderProgram, vertexShader);
|
886
|
+
gl.attachShader(texShaderProgram, texFragmentShader);
|
887
|
+
|
888
|
+
// Link the shader program
|
889
|
+
gl.linkProgram(texShaderProgram);
|
890
|
+
|
891
|
+
// Check if linked
|
892
|
+
if (!gl.getProgramParameter(texShaderProgram, gl.LINK_STATUS)) {
|
893
|
+
console.error("Unable to initialize the texture shader program.");
|
894
|
+
}
|
895
|
+
|
896
|
+
// Get the attribute locations
|
897
|
+
texPositionLocation = gl.getAttribLocation(texShaderProgram, "a_position");
|
898
|
+
texColorLocation = gl.getAttribLocation(texShaderProgram, "a_color");
|
899
|
+
texCoordLocation = gl.getAttribLocation(texShaderProgram, "a_texcoord");
|
900
|
+
|
901
|
+
// Get the sampler location
|
902
|
+
samplerLocation = gl.getUniformLocation(texShaderProgram, "s_texture");
|
903
|
+
};
|
904
|
+
|
905
|
+
|
906
|
+
/*
|
907
|
+
* Creates a shader object, loads shader string, and compiles.
|
908
|
+
*/
|
909
|
+
S2D.GL.LoadShader = function(type, shaderSrc, shaderName) {
|
910
|
+
|
911
|
+
var shader = gl.createShader(type);
|
912
|
+
|
913
|
+
gl.shaderSource(shader, shaderSrc);
|
914
|
+
gl.compileShader(shader);
|
915
|
+
|
916
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
917
|
+
console.error("Error compiling shader \"" + shaderName + "\":\n" + gl.getShaderInfoLog(shader));
|
918
|
+
return null;
|
919
|
+
}
|
920
|
+
|
921
|
+
return shader;
|
922
|
+
};
|
923
|
+
|
924
|
+
|
925
|
+
/*
|
926
|
+
* Calculate the viewport's scaled width and height
|
927
|
+
*/
|
928
|
+
S2D.GL.GetViewportScale = function(win) {
|
929
|
+
|
930
|
+
var s = Math.min(
|
931
|
+
win.width / win.viewport.width,
|
932
|
+
win.height / win.viewport.height
|
933
|
+
);
|
934
|
+
|
935
|
+
var w = win.viewport.width * s;
|
936
|
+
var h = win.viewport.height * s;
|
937
|
+
|
938
|
+
return {
|
939
|
+
w: w,
|
940
|
+
h: h,
|
941
|
+
scale: s
|
942
|
+
};
|
943
|
+
};
|
944
|
+
|
945
|
+
|
946
|
+
/*
|
947
|
+
* Sets the viewport and matrix projection
|
948
|
+
*/
|
949
|
+
S2D.GL.SetViewport = function(win) {
|
950
|
+
|
951
|
+
var ortho_w = win.viewport.width;
|
952
|
+
var ortho_h = win.viewport.height;
|
953
|
+
var x, y, w, h; // calculated GL viewport values
|
954
|
+
|
955
|
+
x = 0; y = 0; w = win.width; h = win.height;
|
956
|
+
|
957
|
+
switch (win.viewport.mode) {
|
958
|
+
|
959
|
+
case S2D.FIXED:
|
960
|
+
w = win.orig_width;
|
961
|
+
h = win.orig_height;
|
962
|
+
y = win.height - h;
|
963
|
+
break;
|
964
|
+
|
965
|
+
case S2D.SCALE:
|
966
|
+
var o = S2D.GL.GetViewportScale(win);
|
967
|
+
// Center the viewport
|
968
|
+
x = win.width / 2.0 - o.w/2.0;
|
969
|
+
y = win.height / 2.0 - o.h/2.0;
|
970
|
+
break;
|
971
|
+
|
972
|
+
case S2D.STRETCH:
|
973
|
+
break;
|
974
|
+
}
|
975
|
+
|
976
|
+
gl.viewport(
|
977
|
+
x * win.pixel_ratio,
|
978
|
+
y * win.pixel_ratio,
|
979
|
+
w * win.pixel_ratio,
|
980
|
+
h * win.pixel_ratio
|
981
|
+
);
|
982
|
+
|
983
|
+
orthoMatrix[0] = 2.0 / ortho_w;
|
984
|
+
orthoMatrix[5] = -2.0 / ortho_h;
|
985
|
+
|
986
|
+
gl.useProgram(shaderProgram);
|
987
|
+
|
988
|
+
gl.uniformMatrix4fv(
|
989
|
+
gl.getUniformLocation(shaderProgram, "u_matrix"),
|
990
|
+
false, new Float32Array(orthoMatrix)
|
991
|
+
);
|
992
|
+
|
993
|
+
gl.useProgram(texShaderProgram);
|
994
|
+
|
995
|
+
gl.uniformMatrix4fv(
|
996
|
+
gl.getUniformLocation(texShaderProgram, "u_matrix"),
|
997
|
+
false, new Float32Array(orthoMatrix)
|
998
|
+
);
|
999
|
+
};
|
1000
|
+
|
1001
|
+
|
1002
|
+
/*
|
1003
|
+
* Clear buffers to given color values
|
1004
|
+
*/
|
1005
|
+
S2D.GL.Clear = function(clr) {
|
1006
|
+
gl.clearColor(clr.r, clr.g, clr.b, clr.a);
|
1007
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
1008
|
+
};
|
1009
|
+
|
1010
|
+
|
1011
|
+
/*
|
1012
|
+
* Creates a texture for rendering
|
1013
|
+
*/
|
1014
|
+
S2D.GL.CreateTexture = function(data) {
|
1015
|
+
|
1016
|
+
var texture = gl.createTexture();
|
1017
|
+
|
1018
|
+
// Bind the named texture to a texturing target
|
1019
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
1020
|
+
|
1021
|
+
// Specifies the 2D texture image
|
1022
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
1023
|
+
|
1024
|
+
// Set the filtering mode
|
1025
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
1026
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
1027
|
+
|
1028
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
1029
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
1030
|
+
|
1031
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
1032
|
+
|
1033
|
+
return texture;
|
1034
|
+
};
|
1035
|
+
|
1036
|
+
|
1037
|
+
/*
|
1038
|
+
* Free a texture
|
1039
|
+
*/
|
1040
|
+
S2D.GL.FreeTexture = function(texture) {
|
1041
|
+
gl.deleteTexture(texture);
|
1042
|
+
};
|
1043
|
+
|
1044
|
+
|
1045
|
+
/*
|
1046
|
+
* Draw triangle
|
1047
|
+
*/
|
1048
|
+
S2D.GL.DrawTriangle = function(x1, y1, c1r, c1g, c1b, c1a,
|
1049
|
+
x2, y2, c2r, c2g, c2b, c2a,
|
1050
|
+
x3, y3, c3r, c3g, c3b, c3a) {
|
1051
|
+
|
1052
|
+
var vertices = [
|
1053
|
+
x1, y1, 0.0,
|
1054
|
+
x2, y2, 0.0,
|
1055
|
+
x3, y3, 0.0
|
1056
|
+
];
|
1057
|
+
|
1058
|
+
var colors = [
|
1059
|
+
c1r, c1g, c1b, c1a,
|
1060
|
+
c2r, c2g, c2b, c2a,
|
1061
|
+
c3r, c3g, c3b, c3a
|
1062
|
+
];
|
1063
|
+
|
1064
|
+
gl.useProgram(shaderProgram);
|
1065
|
+
|
1066
|
+
// Vertex
|
1067
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
1068
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
1069
|
+
|
1070
|
+
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
|
1071
|
+
gl.enableVertexAttribArray(positionLocation);
|
1072
|
+
|
1073
|
+
// Colors
|
1074
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
1075
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
1076
|
+
|
1077
|
+
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
|
1078
|
+
gl.enableVertexAttribArray(colorLocation);
|
1079
|
+
|
1080
|
+
// Draw
|
1081
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
1082
|
+
};
|
1083
|
+
|
1084
|
+
|
1085
|
+
/*
|
1086
|
+
* Draw a texture
|
1087
|
+
*/
|
1088
|
+
S2D.GL.DrawTexture = function(x, y, w, h,
|
1089
|
+
r, g, b, a,
|
1090
|
+
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4,
|
1091
|
+
texture) {
|
1092
|
+
|
1093
|
+
var vertices =
|
1094
|
+
// x, y coords | x, y texture coords
|
1095
|
+
[ x, y, 0.0, tx1, ty1,
|
1096
|
+
x + w, y, 0.0, tx2, ty2,
|
1097
|
+
x + w, y + h, 0.0, tx3, ty3,
|
1098
|
+
x, y + h, 0.0, tx4, ty4 ];
|
1099
|
+
|
1100
|
+
var colors = [
|
1101
|
+
r, g, b, a,
|
1102
|
+
r, g, b, a,
|
1103
|
+
r, g, b, a,
|
1104
|
+
r, g, b, a
|
1105
|
+
];
|
1106
|
+
|
1107
|
+
gl.useProgram(texShaderProgram);
|
1108
|
+
|
1109
|
+
// Vertex
|
1110
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
1111
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
1112
|
+
|
1113
|
+
gl.vertexAttribPointer(texPositionLocation, 3, gl.FLOAT, false, 5*4, 0);
|
1114
|
+
gl.enableVertexAttribArray(texPositionLocation);
|
1115
|
+
|
1116
|
+
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 5*4, 3*4);
|
1117
|
+
gl.enableVertexAttribArray(texCoordLocation);
|
1118
|
+
|
1119
|
+
// Colors
|
1120
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
1121
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
1122
|
+
|
1123
|
+
gl.vertexAttribPointer(texColorLocation, 4, gl.FLOAT, false, 0, 0);
|
1124
|
+
gl.enableVertexAttribArray(texColorLocation);
|
1125
|
+
|
1126
|
+
gl.activeTexture(gl.TEXTURE0);
|
1127
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
1128
|
+
|
1129
|
+
gl.uniform1i(samplerLocation, 0);
|
1130
|
+
|
1131
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
|
1132
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
|
1133
|
+
|
1134
|
+
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
|
1135
|
+
};
|
1136
|
+
|
1137
|
+
|
1138
|
+
/*
|
1139
|
+
* Draw image
|
1140
|
+
*/
|
1141
|
+
S2D.GL.DrawImage = function(img) {
|
1142
|
+
S2D.GL.DrawTexture(
|
1143
|
+
img.x, img.y, img.width, img.height,
|
1144
|
+
img.color.r, img.color.g, img.color.b, img.color.a,
|
1145
|
+
0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
|
1146
|
+
img.texture
|
1147
|
+
);
|
1148
|
+
};
|
1149
|
+
|
1150
|
+
|
1151
|
+
/*
|
1152
|
+
* Draw sprite
|
1153
|
+
*/
|
1154
|
+
S2D.GL.DrawSprite = function(spr) {
|
1155
|
+
S2D.GL.DrawTexture(
|
1156
|
+
spr.x, spr.y, spr.width, spr.height,
|
1157
|
+
spr.img.color.r, spr.img.color.g, spr.img.color.b, spr.img.color.a,
|
1158
|
+
spr.tx1, spr.ty1, spr.tx2, spr.ty2, spr.tx3, spr.ty3, spr.tx4, spr.ty4,
|
1159
|
+
spr.img.texture
|
1160
|
+
);
|
1161
|
+
};
|
1162
|
+
|
1163
|
+
|
1164
|
+
/*
|
1165
|
+
* Draw text
|
1166
|
+
*/
|
1167
|
+
S2D.GL.DrawText = function(txt) {
|
1168
|
+
S2D.GL.DrawTexture(
|
1169
|
+
txt.x, txt.y, txt.width, txt.height,
|
1170
|
+
txt.color.r, txt.color.g, txt.color.b, txt.color.a,
|
1171
|
+
0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
|
1172
|
+
txt.texture
|
1173
|
+
);
|
1174
|
+
};
|
1175
|
+
|
1176
|
+
|
1177
|
+
// end.js - Close the anonymous function defining the Simple 2D module
|
1178
|
+
|
1179
|
+
// Call anonymous and the Simple 2D module to the global scope
|
1180
|
+
}).call(this);
|