Skin:
[NORMAL]
[BLUE] [DOS] [LIGHT]  / コピーするための表示 / 実行
このファイル: /home/web6047/www/cgi-bin/prj/20200515-RPG/基本的/20200620-ウィンドウ入力/20200724-新しいメモ2/simple.html
1 <html><!--ESCAPEPROCESS-->
2 <head>
3 <meta content="text/html; charset=UTF-8" http-equiv="content-type">
4 <script>console.clear();</script>
5 <script>
6 function onloadx() {
7 app = new App();
8 }
9 class App {
10 constructor() {
11 this.cc = document.getElementById( "test" ).getContext( "2d" );
12 this.cc.font = "16px monospace";
13 this.drawers = new Array();
14 this.framers = new Array();
15
16 this.chars = new Array();
17
18 this.dougus = {
19 "やくそう" : {
20 title : "やくそう",
21 "キャンプ時" : {
22 title : "どうする?",
23 items : [
24 {
25 title : "つかう",
26 },
27 {
28 title : "わたす",
29 },
30 {
31 title : "すてる",
32 },
33 ],
34 },
35 "C1時" : {
36 title : "だれに?",
37 items : this.chars,
38 },
39 },
40 "テスト" : {
41 title : "テスト",
42 },
43 };
44 this.batcoms = {
45 "たたかう" : {
46 title : "たたかう",
47 },
48 "にげる" : {
49 title : "にげる",
50 },
51 "どうぐ" : {
52 title : "どうぐ",
53 submenu : {
54 title : "",
55 items : null,
56 },
57 },
58 "じゅもん" : {
59 title : "じゅもん",
60 },
61 "ぼうぎょ" : {
62 title : "ぼうぎょ",
63 },
64 };
65
66 let char;
67
68 char = {
69 title : "C1",
70 "どうぐ" : [
71 this.dougus[ "やくそう" ],
72 this.dougus[ "やくそう" ],
73 ],
74 }
75 char.batcoms = [
76 this.batcoms[ "たたかう" ],
77 this.batcoms[ "にげる" ],
78 {
79 title : "どうぐ",
80 submenu : {
81 title : "",
82 items : char[ "どうぐ" ],
83 },
84 },
85 this.batcoms[ "ぼうぎょ" ],
86 ];
87 this.chars[ 0 ] = char;
88
89 char = {
90 title : "C2",
91 "どうぐ" : [
92 this.dougus[ "やくそう" ],
93 this.dougus[ "テスト" ],
94 ],
95 }
96 char.batcoms = [
97 this.batcoms[ "たたかう" ],
98 this.batcoms[ "じゅもん" ],
99 {
100 title : "どうぐ",
101 submenu : {
102 title : "",
103 items : char[ "どうぐ" ],
104 },
105 },
106 this.batcoms[ "ぼうぎょ" ],
107 ];
108 this.chars[ 1 ] = char;
109
110
111 this.camp = {
112 title : "キャンプ",
113 items : [
114 {
115 title : "どうぐ",
116 submenu : {
117 title : "だれの?",
118 items : this.chars,
119 },
120 bridge : {
121 title : "",
122 propertyName : "どうぐ",
123 },
124 },
125 {
126 title : "じゅもん",
127 submenu : {
128 title : "だれの?",
129 items : this.chars,
130 },
131 },
132 {
133 title : "戦闘する",
134 },
135 ],
136 }
137
138 this.timerMs = 100;
139 this.timerId = setInterval( this.frame.bind( this ), this.timerMs );
140
141 //---test
142
143 this.campEvent();
144 //this.battleEvent();
145 }
146 //---App.battleEvent
147 async battleEvent() {
148 for( let i = 0; i < this.chars.length; i++ ) {
149 let char = this.chars[ i ];
150 let menu = new Menu( 1,19,null,null, char.title, char.batcoms, this );
151 await menu.selectionProcedure();
152 menu.close();
153 }
154 }
155 //---App.campEvent
156 async campEvent() {
157 let menu = new Menu( 1,1,null,null, this.camp.title, this.camp.items, this );
158 let res = await menu.selectionProcedure();
159 console.log( "done" );
160
161 if( res == "戦闘する" ) {
162 menu.close();
163 this.battleEvent();
164 }
165 }
166 frame() {
167 for( let i = 0; i < this.framers.length; i++ ) {
168 let framer = this.framers[ i ];
169 framer.frame();
170 }
171 this.draw( this.cc );
172 }
173 //---App.draw
174 draw( cc ) {
175 cc.clearRect( 0,0, cc.canvas.width, cc.canvas.height );
176 for( let i = 0; i < this.drawers.length; i++ ) {
177 let drawer = this.drawers[ i ];
178 drawer.draw( cc );
179 }
180 }
181 }//App
182
183 /*
184 Win
185 Win> CtrlWin
186 CtrlWin> Menu
187 CtrlWin> Serif
188 */
189 class Win {
190 constructor( cx, cy, cw, ch ) {
191 this.cx = cx;
192 this.cy = cy;
193 this.cw = cw;
194 this.ch = ch;
195 this.cpadding = 0;
196 }
197 draw( cc ) {
198 let gx = this.cx * 16;
199 let gy = this.cy * 16;
200 let gw = this.cw * 16 + this.cpadding * 16 * 2;
201 let gh = this.ch * 16 + this.cpadding * 16 * 2;
202 cc.fillStyle = "white";
203 cc.fillRect( gx, gy, gw, gh );
204 cc.strokeStyle = "black";
205 cc.strokeRect( gx, gy, gw, gh );
206 }
207 }
208 class CtrlWin extends Win {
209 constructor( cx, cy, cw, ch, app ) {
210 super( cx, cy, cw, ch );
211 this.app = app;
212
213 this.keys = new Object();
214 this.tellOk = function() {} //dummy
215 }
216 activate( tellOk ) {
217 this.tellOk = tellOk;
218 this.app.drawers.push( this );
219 window.onkeydown = this.onkeydownx.bind( this );
220 window.onkeyup = this.onkeyupx.bind( this );
221 }
222 frame() {
223 for( let key in this.keys ) {
224 this.keysense( Number( key ) );
225 //check.
226 if( ! this.keys[ key ] ) delete this.keys[ key ];
227 }
228 }
229 onkeydownx( e ) {
230 this.keys[ e.which ] = true;
231 this.keytype( e.which );
232 }
233 onkeyupx( e ) {
234 this.keys[ e.which ] = false;
235 }
236 keytype( key ) {
237 }
238 keysense( key ) {
239 }
240 }
241
242 //---class Menu
243
244 class Menu extends CtrlWin {
245 constructor( cx, cy, cw, ch, title, items, app, histories ) {
246 //check. ウィンドウのサイズを自動決定
247 if( cw == null ) {
248 //半角を1文字、全角を2文字で数えるlength関数
249 //https://javascript.programmer-reference.com/javascript-han1zen2/
250 let getLen = function( str ){
251 let result = 0;
252 for( let i = 0; i < str.length; i++ ) {
253 let chr = str.charCodeAt(i);
254 if( ( chr >= 0x00 && chr < 0x81 )
255 || ( chr === 0xf8f0 )
256 || ( chr >= 0xff61 && chr < 0xffa0 )
257 || ( chr >= 0xf8f1 && chr < 0xf8f4 ) ) {
258 //半角文字の場合は1を加算
259 result += 1;
260 } else {
261 //それ以外の文字の場合は2を加算
262 result += 2;
263 }
264 }
265 //結果を返す
266 return result;
267 };
268 cw = Math.max( ...items.map( item => Math.ceil( getLen( item.title ) / 2 ) ), title.length );
269 }
270 if( ch == null ) {
271 ch = items.length + ( title ? 1 : 0 );
272 }
273 super( cx, cy, cw, ch, app );
274 this.cpadding = 1;
275 this.title = title;
276 this.items = items;
277 if( histories ) {
278 this.histories = histories;
279 } else {
280 this.histories = new Array();
281 }
282 this.histories.push( {
283 title : title,
284 menu : this,
285 } );
286 this.cursorY = 0;
287 }
288 //Menu
289 draw( cc ) {
290 super.draw( cc );
291
292 let gx = this.cx * 16;
293 let gy = this.cy * 16;
294 let gw = this.cw * 16;
295
296 let gx2 = this.cx * 16 + this.cpadding * 16;
297 let gy2 = this.cy * 16 + this.cpadding * 16;
298 let gw2 = this.cw * 16;
299 let gh2 = this.ch * 16;
300
301 if( this.title ) {
302 cc.fillStyle = "black";
303 cc.fillText( this.title, gx2, gy2 + 8 );
304 cc.fillText( this.title, gx2 + 1, gy2 + 8 );
305 gy2 += 16;
306 }
307 for( let i = 0; i < this.items.length; i ++ ) {
308 let item = this.items[ i ];
309 if( i == this.cursorY ) {
310 //カーソル位置
311 cc.fillStyle = "black";
312 cc.fillRect( gx2, gy2, gw2, 16 );
313 cc.fillStyle = "white";
314 cc.fillText( item.title, gx2, gy2 + 16 );
315 } else {
316 cc.fillStyle = "black";
317 cc.fillText( item.title, gx2, gy2 + 16 );
318 }
319 gy2 += 16;
320 }
321 }
322 //Menu
323 keytype( key ) {
324 switch( key ) {
325 case 38:
326 if( this.cursorY > 0 )
327 this.cursorY --;
328 break;
329 case 40:
330 if( this.cursorY < this.items.length - 1 )
331 this.cursorY ++;
332 break;
333 case 32:
334 let selectedItem = this.items[ this.cursorY ];
335 //これまでの選択肢(文脈)を探る
336 let context;
337 for( let i = this.histories.length - 2; i >= 0; i-- ) {
338 let history = this.histories[ i ];
339 if( selectedItem[ history.title + "時" ] ) {
340 context = history.title;
341 break;
342 }
343 }
344 //サブメニューを開くか、実行するか
345 if( selectedItem.submenu || this.bridge || selectedItem[ context + "時" ] ) {
346 //サブメニューを開く
347 let cx = this.cx + this.cw + this.cpadding * 2;
348 let cy = this.cy;
349 let title, items;
350 if( this.bridge ) {
351 //サブメニュー情報源:bridge
352 console.log( "bridge使用", this.bridge.title );
353 title = this.bridge.title;
354 items = selectedItem[ this.bridge.propertyName ];
355 } else if( selectedItem.submenu ) {
356 //サブメニュー情報源:直
357 title = selectedItem.submenu.title ? selectedItem.submenu.title : selectedItem.title;
358 items = selectedItem.submenu.items;
359 } else {
360 //サブメニュー情報源:文脈
361 console.log( "コンテキスト使用", context );
362 title = selectedItem[ context + "時" ].title;
363 items = selectedItem[ context + "時" ].items;
364 }
365 this.subMenu = new Menu( cx, cy, null, null, title, items, this.app, this.histories );
366 //check.
367 if( selectedItem.bridge ) {
368 this.subMenu.bridge = selectedItem.bridge;
369 }
370 this.subMenu.activate( this.tellOk );
371 } else {
372 //実行する
373 console.log( selectedItem.title );
374 this.tellOk( selectedItem.title );
375 }
376 break;
377 default:
378 console.log( key );
379 }
380 }
381 //Menu
382 selectionProcedure() {
383 return new Promise(
384 function( tellOk ) {
385 this.activate( tellOk );
386 }.bind( this )
387 );
388 }
389 close() {
390 for( let i = 0; i < this.histories.length; i++ ) {
391 let history = this.histories[ i ];
392 let idx = this.app.drawers.indexOf( history.menu );
393 this.app.drawers.splice( idx, 1 );
394 }
395 }
396 }//Menu
397 class Serif extends CtrlWin {
398 constructor() {
399 }
400 }
401 </script>
402 <style>
403 </style>
404 </head>
405 <body onload="onloadx()">
406 <canvas id="test" width="512" height="448" style="
407 border : solid 1px black;
408 float:left;
409 " onclick="location.reload()">
410 </canvas>
411 <div style="float:left; width:512px; padding-left:1em;">
412 <b>最初、キャンプメニュー(フィールド上のコマンド)が表示されます。</b>
413 上下:↑↓キー、決定:スペースキー、キャンセル:なし
414 どうぐ>C1>やくそう でサブメニューの動作を確認できます。
415 しかし、キャンセルがないので戻れません。ブラウザの更新ボタンを押してください。:-(
416
417 <B>「戦闘する」を選ぶと、キャンプメニューは終了し、戦闘のコマンド入力になります。</B>
418 一人目の どうぐ→やくそう→C1 でサブメニューの動作を確認できます。
419 二人分入力して終わりです。(そのまま何もできなくなります)
420 </div>
421 <script>
422 div = document.getElementsByTagName( "div" )[ 0 ];
423 div.innerHTML = div.innerHTML.replace( /\n/g, "<BR>" );
424 </script>
425 </body>
426 </html>