-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWWS.js
697 lines (591 loc) · 17.1 KB
/
WWS.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
/*
JavaScript&HTML5 ゲーム開発用システム
開発 ワールドワイドソフトウェア有限会社
(使用条件)
本ソースコードの著作権は開発元にあります。
利用されたい方はメールにてお問い合わせ下さい。
[email protected] ワールドワイドソフトウェア 廣瀬
*/
// ---------- グローバル変数 ----------
var SYS_VER = "Ver.20201111";
var DEBUG = false;
//端末の種類
var deviceType = 0;
var PT_PC = 0;
var PT_iOS = 1;
var PT_Android = 2;
var PT_Kindle = 3;
//処理の進行を管理
//main_idxの値↓
//0: 初期化
//1: セーブできない警告
//2: メイン処理
var main_idx = 0;
var main_tmr = 0;
var stop_flg = 0;//メイン処理の一時停止
var NUA = navigator.userAgent;//機種判定
var supportTouch = 'ontouchend' in document;//タッチイベントが使えるか?
if(DEBUG) {//★★★開発中
log(NUA);
log(supportTouch);
}
// ---------- 描画面(キャンバス) ----------
//サウンドの定義
var SOUND_ON = true;//サウンドを出力するか
//キャンバスの初期サイズ
var CWIDTH = 800;//幅
var CHEIGHT = 600;//高さ
//フレームレート
var FPS = 30;//1秒間に何回処理を行うか ( frames per second )
//ローカルストレージ
var LS_KEYNAME = "SAVEDATA";//keyName 任意に変更可
//保存できるか判定し、できない場合に警告を出す 具体的には iOS Safari プライベートブラウズがON(保存できない)状態に警告を出す
var CHECK_LS = false;
//キー入力用
var K_ENTER = 13;
var K_SPACE = 32;
var K_LEFT = 37;
var K_UP = 38;
var K_RIGHT = 39;
var K_DOWN = 40;
var K_a = 65;
var K_z = 90;
// ---------- 描画面(キャンバス) ----------
var winW, winH;
var bakW, bakH;
var SCALE = 1.0;//スケール値設定+タップ位置計算用
var cvs = document.getElementById("canvas");
var bg = cvs.getContext("2d");
function initCanvas() {//キャンバス初期設定
winW = window.innerWidth;
winH = window.innerHeight;
bakW = winW;
bakH = winH;
if( winH < winW*CHEIGHT/CWIDTH ) {
winW = int(winH*CWIDTH/CHEIGHT);
}
else {
winH = int(CHEIGHT*winW/CWIDTH);
}
cvs.width = winW;
cvs.height = winH;
SCALE = winW / CWIDTH;
bg.scale(SCALE, SCALE);
bg.textAlign = "center"; //┬文字列のセンタリング表示用に必要な値を指定
bg.textBaseline = "middle";//┘
// cvs.focus();//キー入力を拾えるようにフォーカスを当てる
}
function canvasSize(w, h) {//■ユーザー用関数
CWIDTH = w;
CHEIGHT = h;
initCanvas();
}
// ---------- 各種の関数 ----------
function eID(id) {
return document.getElementById(id);
}
function log(str) {
console.log(str);
}
function int(val) {//整数を返す=小数点以下を切り捨て
// return Math.floor(val);//マイナスの場合 -0.1 → -1となるので注意
return parseInt(val);//こちらはプラスもマイナスも小数部分を切り捨てる
}
function str(val) {//数を文字列に変換
return String(val);
}
function rnd(max) {//乱数
return int(Math.random()*max);
}
function abs(val) {//絶対値
return Math.abs(val);
}
function sin(a) {//三角関数
return Math.sin(Math.PI*2*a/360);
}
function cos(a) {
return Math.cos(Math.PI*2*a/360);
}
function tan(a) {
return Math.tan(Math.PI*2*a/360);
}
function getDis(x1, y1, x2, y2) {//2点間の距離
return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
function digit0(val, leng) {
var s = "0000000000000000" + val;
return s.substring( s.length-leng, s.length );
}
function setFPS(val) {//フレームレートの設定
FPS = val;
}
//一様乱数 線形合同法で発生させる乱数
var rndseed = 13;
//種をセットする
function setRSeed(val) {
rndseed = val;
}
//乱数を生成
function rndLCM(max) {
rndseed = (rndseed*109 + 1021) % 65536;
return rndseed%max;
}
// ---------- キー入力 ----------
window.addEventListener("keydown", onKey);
window.addEventListener("keyup", offKey);
var inkey = 0;
var key = new Array(256);
function clrKey() {
inkey = 0;
for(var i = 0; i < 256; i++) key[i] = 0;
}
function onKey(e) {
if(snd_init == 0) loadSoundSPhone();//【重要】サウンドの読み込み
inkey = e.keyCode;
key[e.keyCode]++;
//log(inkey);
}
function offKey(e) {
inkey = 0;
key[e.keyCode] = 0;
}
// ---------- マウス入力 ----------
var tapX = 0;
var tapY = 0;
var tapC = 0;
function mouseDown(e) {
e.preventDefault();//キャンバスの選択/スクロール等を抑制する
var rect = e.target.getBoundingClientRect();
tapX = e.clientX-rect.left;
tapY = e.clientY-rect.top;
tapC = 1;
transformXY();
if(snd_init == 0) loadSoundSPhone();//【重要】サウンドの読み込み
}
function mouseMove(e) {
e.preventDefault();
var rect = e.target.getBoundingClientRect();
tapX = e.clientX-rect.left;
tapY = e.clientY-rect.top;
transformXY();
}
function mouseUp(e) { tapC = 0; }
function mouseOut(e) { tapC = 0; }
// ---------- タップ入力 ----------
function touchStart(e) {
e.preventDefault();//キャンバスの選択/スクロール等を抑制する
var rect = e.target.getBoundingClientRect();
tapX = e.touches[0].clientX-rect.left;
tapY = e.touches[0].clientY-rect.top;
tapC = 1;
transformXY();
if(snd_init == 0) loadSoundSPhone();//【重要】サウンドの読み込み
}
function touchMove(e) {
e.preventDefault();
var rect = e.target.getBoundingClientRect();
tapX = e.touches[0].clientX-rect.left;
tapY = e.touches[0].clientY-rect.top;
transformXY();
}
function touchEnd(e) {
e.preventDefault();
tapC = 0;//※マウス操作ではmouseOutがこれになる
}
function touchCancel(e) {
tapX = -1;
tapY = -1;
tapC = 0;
}
function transformXY() {//実座標→仮想座標への変換
tapX = int(tapX/SCALE);
tapY = int(tapY/SCALE);
}
// ---------- 加速度センサー ----------
var acX = 0, acY = 0, acZ = 0;
//window.ondevicemotion = deviceMotion;//★★★旧
window.addEventListener("devicemotion", deviceMotion);
function deviceMotion(e) {
var aIG = e.accelerationIncludingGravity;
acX = int(aIG.x);
acY = int(aIG.y);
acZ = int(aIG.z);
if(deviceType == PT_Android) {//Android と iOS で正負が逆になる
acX = -acX;
acY = -acY;
acZ = -acZ;
}
}
// ---------- 画像読み込み ----------
var img = new Array(256);
var img_loaded = new Array(256);
function loadImg(n, filename) {
// log("画像"+n+" "+filename+" 読込開始");
img_loaded[n] = false;//読み込み開始
img[n] = new Image();
img[n].onload = function() {
// log("画像"+n+" "+filename+" 読込完了");
img_loaded[n] = true;
}
img[n].src = filename;
}
// ---------- サウンド制御 ----------
var snd_init = 0;//サウンドファイルを読み込んだか(スマートフォン対策)
var soundfile = new Array(256);
var isBgm = -1;
var bgmNo = 0;
var wait_se = 0;
var seNo = -1;
var soundloaded = 0;//いくつファイルを読み込んだか
var sf_name = new Array(256);
function loadSoundSPhone() {//スマートフォンでサウンドファイルを読み込む
for(var i = 0; i < soundloaded; i++) {
try {
soundfile[i] = new Audio(sf_name[i]);
soundfile[i].load();
// log("サウンド読み込みSP"+i);
} catch(e) {}
}
snd_init = 2;//スマホでサウンドを読み込んだ
}
function loadSound(n, filename) {
// if(deviceType == PT_PC) {
// try {
// soundfile[n] = new Audio(filename);
// soundfile[n].load();
// log("サウンド読み込みPC"+n);
// } catch(e) {}
// snd_init = 1;//パソコンでサウンドを読み込んだ
// }
// else {
sf_name[n] = filename;
// }
soundloaded++;
}
function playSE(n) {
if(SOUND_ON == false) return;
if(isBgm == 2) return;
if(wait_se == 0) {
seNo = n;
soundfile[n].currentTime = 0;
soundfile[n].loop = false;
soundfile[n].play();
wait_se = 3;//ブラウザに負荷をかけないため連続して流さないようにする
}
}
function playBgm(n) {
if(SOUND_ON == false) return;
log("BGM"+n+"出力");
bgmNo = n;
soundfile[n].loop = true;
soundfile[n].play();
isBgm = 1;//BGM流れている
}
function pauseBgm() {
soundfile[bgmNo].pause();
isBgm = 0;//BGM停止している
}
function stopBgm() {
soundfile[bgmNo].pause();
soundfile[bgmNo].currentTime = 0;
isBgm = 0;//BGM停止している
}
function rateSnd(rate) {//曲の速度
soundfile[bgmNo].playbackRate = rate;
}
//ブラウザを隠した時に音を一時停止する処理
document.addEventListener("visibilitychange", vcProc);
function vcProc() {
log("visibilitychange");
if(document.visibilityState == "hidden") {
stop_flg = 1;
if(isBgm == 1) {
pauseBgm();
isBgm = 2;//BGM再出力待ち
}
}
else if(document.visibilityState == "visible") {
stop_flg = 0;
if(isBgm == 2) playBgm(bgmNo);
}
}
// ---------- ローカルストレージ ----------
//【開発メモ】
//ローカルストレージへのアクセスができない状態(具体的にはSafariでプライベートブラウズになっている時) try catch が入っていないとフリーズする
//7 C:\Users\ユーザ名\AppData\Local\Google\Chrome\User Data\Default\Local Storage
//
function saveLS(kno, val) {
try {
localStorage.setItem(LS_KEYNAME+kno, val);
}
catch(e) {}
}
function loadLS(kno) {//文字列、数値をそのまま保存し、元の状態(型)で読み込めるようにしてある
var val = null;
try {
val = localStorage.getItem(LS_KEYNAME+kno);
}
catch(e) {}
if(val == null) return val;
if(val == "") return val;
if(isNaN(val) == true) return val;
//↑以上、文字列
return Number(val);
}
function clrLS(kno) {
localStorage.removeItem(LS_KEYNAME+kno);
}
function clrAllLS() {
localStorage.clear();
}
// ---------- 描画1 図形 ----------
function setAlp(per) {
bg.globalAlpha = per/100;//【メモ】HTML5は0.0~1.0の値で指定
}
function colorRGB(cr, cg, cb) {
cr = int(cr);//【開発メモ】少数を渡すとおかしくなるので整数にしておく
cg = int(cg);
cb = int(cb);
return ("rgb("+cr+","+cg+","+cb+")");
}
var line_width = 1;
function lineW(wid) {//線の太さを指定
line_width = wid;//バックアップ
bg.lineWidth = wid;
bg.lineCap = "round";//線の先端を丸める指定
bg.lineJoin = "round";//線の接続部分を丸める指定
}
function line(x0, y0, x1, y1, col) {//線
bg.strokeStyle = col;
bg.beginPath();
bg.moveTo(x0, y0);
bg.lineTo(x1, y1);
bg.stroke();
}
function fill(col) {//キャンバス全体の塗り潰し
bg.fillStyle = col;
bg.fillRect(0, 0, CWIDTH, CHEIGHT);
}
function fRect(x, y, w, h, col) {//矩形(塗り潰し)
bg.fillStyle = col;
bg.fillRect(x, y, w, h);
}
function sRect(x, y, w, h, col) {//矩形(線)
bg.strokeStyle = col;
bg.strokeRect(x, y, w, h);
}
function fCir(x, y, r, col) {//円(塗り潰し)
bg.fillStyle = col;
bg.beginPath();
bg.arc(x, y, r, 0, Math.PI*2, false);
bg.closePath();
bg.fill();
}
function sCir(x, y, r, col) {//円(線)
bg.strokeStyle = col;
bg.beginPath();
bg.arc(x, y, r, 0, Math.PI*2, false);
bg.closePath();
bg.stroke();
}
function fTri(x0, y0, x1, y1, x2, y2, col) {//三角(塗り潰し)
bg.fillStyle = col;
bg.beginPath();
bg.moveTo(x0, y0);
bg.lineTo(x1, y1);
bg.lineTo(x2, y2);
bg.closePath();
bg.fill();
}
function sTri(x0, y0, x1, y1, x2, y2, col) {//三角(線)
bg.strokeStyle = col;
bg.beginPath();
bg.moveTo(x0, y0);
bg.lineTo(x1, y1);
bg.lineTo(x2, y2);
bg.closePath();
bg.stroke();
}
function fPol(xy, col) {//多角形(塗り潰し)
bg.fillStyle = col;
bg.beginPath();
bg.moveTo(xy[0], xy[1]);
for(var i=2; i<xy.length; i+=2) bg.lineTo(xy[i], xy[i+1]);
bg.closePath();
bg.fill();
}
function sPol(xy, col) {//多角形(線)
bg.strokeStyle = col;
bg.beginPath();
bg.moveTo(xy[0], xy[1]);
for(var i=2; i<xy.length; i+=2) bg.lineTo(xy[i], xy[i+1]);
bg.closePath();
bg.stroke();
}
// ---------- 描画2 画像 ----------
function drawImg(n, x, y) {
if(img_loaded[n] == true) bg.drawImage(img[n], x, y);
}
function drawImgLR(n, x, y) {//左右反転
if(img_loaded[n] == true) {
var w = img[n].width;
var h = img[n].height;
bg.save();
bg.translate(x+w/2, y+h/2);
bg.scale(-1, 1);
bg.drawImage(img[n], -w/2, -h/2);
bg.restore();
}
}
function drawImgC(n, x, y) {//センタリング表示
if(img_loaded[n] == true) bg.drawImage(img[n], x-int(img[n].width/2), y-int(img[n].height/2));
}
function drawImgS(n, x, y, w, h) {//拡大縮小
if(img_loaded[n] == true) bg.drawImage(img[n], x, y, w, h);
}
function drawImgTS(n, sx, sy, sw, sh, cx, cy, cw, ch) {//切り出し+拡大縮小
if(img_loaded[n] == true) bg.drawImage(img[n], sx, sy, sw, sh, cx, cy, cw, ch);
}
function drawImgR(n, x, y, ang) {//回転
if(img_loaded[n] == true) {
var w = img[n].width;
var h = img[n].height;
bg.save();
bg.translate(x, y);
bg.rotate(Math.PI*ang/180);
bg.drawImage(img[n], -w/2, -h/2);
bg.restore();
}
}
// ---------- 描画3 文字 ----------
function fText(str, x, y, siz, col) {
bg.font = int(siz) + "px bold monospace";//等幅フォントを指定
bg.fillStyle = "black";
bg.fillText(str, x+1, y+1);
bg.fillStyle = col;
bg.fillText(str, x, y);
}
function fTextN(str, x, y, h, siz, col) {
var i;
var sn = str.split("\n");//改行を区切り文字とした一次元配列を生成
bg.font = int(siz) + "px bold monospace";//等幅フォントを指定
if(sn.length == 1) {
h = 0;
}
else {
y = y - int(h/2);
h = int(h/(sn.length-1));
}
for(i = 0; i < sn.length; i++) {
bg.fillStyle = "black";
bg.fillText(sn[i], x+1, y+h*i+1);
bg.fillStyle = col;
bg.fillText(sn[i], x, y+h*i);
}
}
function mTextWidth(str) {//文字列のキャンバス上の幅を返す
return bg.measureText(str).width;
}
// ---------- 日時の取得 ----------
var year, month, date, day, hour, min, sec;
function getDate() {
var D = new Date();
year = D.getFullYear(); //西暦を取得
month = D.getMonth(); //月を取得 1月は0
date = D.getDate(); //日を取得
day = D.getDay(); //曜日を取得 日曜は0
hour = D.getHours(); //時間を取得
min = D.getMinutes(); //分を取得
sec = D.getSeconds(); //秒を取得
}
// ---------- リアルタイム処理 ----------
function wwsSysMain() {
// var stime = new Date().getTime();
var stime = Date.now();
//ブラウザのサイズが変化したか?(スマホなら持ち方を変えたか 縦持ち⇔横持ち)
if(bakW != window.innerWidth || bakH != window.innerHeight) {
initCanvas();
lineW(line_width);
}
main_tmr ++;
switch(main_idx) {
case 0://初期化
setup();
clrKey();
main_idx = 2;
//iOS Safari プライベートブラウズがON(保存できない)か判定
if(CHECK_LS == true) {
try {localStorage.setItem("_save_test", "testdata"); } catch(e) { main_idx = 1; }
}
break;
case 1://ローカルストレージの警告
var x = int(CWIDTH/2);
var y = int(CHEIGHT/6);
var fs = int(CHEIGHT/16);
fill("black");
fText("※セーブデータが保存されません※", x, y/2, fs, "yellow");
fTextN("iOS端末をお使いの場合は\nSafariのプライベートブラウズ\nをオフにして起動して下さい。", x, y*2, y, fs, "yellow");
fTextN("その他の機種(ブラウザ)では\nローカルストレージへの保存を\n許可する設定にして下さい。", x, y*4, y, fs, "yellow");
fText("このまま続けるには画面をタップ", x, y*5.5, fs, "lime");
if(tapC != 0) main_idx = 2;
break;
case 2://メイン処理
if(stop_flg == 0) {
mainloop();
}
else {
clrKey();
main_tmr--;
}
if(wait_se > 0) wait_se--;
break;
}
var ptime = Date.now() - stime;
if(ptime < 0) ptime = 0;
if(ptime > int(1000/FPS)) ptime = int(1000/FPS);
if(DEBUG) {//★★★デバッグ
var i, x = 240, y;
fText("処理時間="+(ptime), x, 50, 16, "lime");
fText("deviceType="+deviceType, x, 100, 16, "yellow");
fText("isBgm="+isBgm+"("+bgmNo+")", x, 150, 16, "yellow");
fText("winW="+winW+" winH="+winH+" SCALE="+SCALE, x, 200, 16, "yellow");
fText(main_idx+":"+main_tmr+"("+tapX+","+tapY+")"+tapC, x, 250, 16, "cyan");
fText("加速度 "+acX + " : " + acY + " : " + acZ, x, 300, 16, "pink");
for(i = 0; i < 256; i++) {
x = i%16;
y = int(i/16);
fText(key[i], 15+30*x, 15+30*y, 12, "white");
}
}
setTimeout("wwsSysMain()", int(1000/FPS)-ptime);
}
// ---------- 起動処理 ----------
//window.onload = function() {}
window.addEventListener("load", wwsSysInit);
function wwsSysInit() {
initCanvas();
if( NUA.indexOf('Android') > 0 ) {
deviceType = PT_Android;
}
else if( NUA.indexOf('iPhone') > 0 || NUA.indexOf('iPod') > 0 || NUA.indexOf('iPad') > 0 ) {
deviceType = PT_iOS;
window.scrollTo(0,1);//iPhoneのURLバーを消す位置に
}
else if( NUA.indexOf('Silk') > 0 ) {
deviceType = PT_Kindle;
}
//イベントリスナー(タップ判定)
if(supportTouch == true) {
cvs.addEventListener("touchstart", touchStart);
cvs.addEventListener("touchmove", touchMove);
cvs.addEventListener("touchend", touchEnd);
cvs.addEventListener("touchcancel", touchCancel);
}
else {
cvs.addEventListener("mousedown", mouseDown);
cvs.addEventListener("mousemove", mouseMove);
cvs.addEventListener("mouseup", mouseUp);
cvs.addEventListener("mouseout", mouseOut);
}
wwsSysMain();//リアルタイム処理を開始
}