Large Display Size Middle Display Size Small Display Size
There is no canvas.

2017 年 10月 の日記


模様: 止める, 小さい四角形, ライン, 小さい★, バブル〇, ゴースト, なると

2017/10/13(金)

iPod Shuffleを購入しました。
以下はAmazonに投稿したレビューです。

私は掃除と皿洗いが嫌いですが、音楽聴きながらだと念入りに皿洗いする事に気づき、早速この商品を購入しました。
(※コンロに火を付け料理しながらのヘッドホン使用は危険だと思うのでご注意を)
(※レビューは長いです)

●付属のイヤホンで聴いて:
高音質だと思いました。

●気に入っているカナル(耳の穴に埋没)型のイヤホンで聴いて:
同じく、高音質だと思いました。
当然ですがカナル型らしく密閉感がプラスされます。
…良い音だ…楽しめそう。

●気に入っていないカナル型のイヤホンで聴いて:
購入後不満でポイしていたイヤホンですが、とくに不満のない音質で聴けています。
そんなことがあるのかと、不満を感じたときに聴いていた再生装置(PC)にそのイヤホンをつなげて再度聞くとやはり不満な音質です。
iPodにつなげるとその不満がやわらぐようです。
同じ曲データと同じヘッドホンでも、どんな装置で再生するかで音質が変わるんだなぁと思いました。iPodは良い再生装置かなと思います。
第一世代のiPodも同様の耳をいたわるような良い音質だったので、(私は第2,3世代は知りませんが)一貫してよい音質を維持しているんだなとiPodの良さを再確認できました。

以下、私の導入に合わせた気になる事柄です:
行頭の◎○△は良しあしを示しています。

△「容量は2GBのみなのか?」と購入後ですが調べたら2GBのみでした。
○パッケージが小さくクリアなボックスに入っていて、昔あった「G4キューブ」というMacを思い出しました。Appleは結局G4キューブが好きだったのかな..
△説明書に書かれている通り、PCに接続してiTunesを起動。
説明書に「iTunesの画面に指示が表示されたら、..」と書いてありますが しばらく何も表示されず、困惑し始めたところで表示されました。
△「それに従って設定します」とあるので、いざ設定しようと思ったら画面が消えて、曲のライブラリの画面に戻ってしまいました。
まだ何も設定していないのに...。まぁいいけどね。

△続いて「バッテリーを充電しながらコンテンツを同期します」とあるので、曲やプレイリストをあれこれデバイス(iPod)へ移動。
その最中、Windowsのメッセージで、「このドライブで問題が見つかりました。」、「iPod(G:)をスキャンして修復しますか?」という確認画面が繰り返し表示される。
ネットを調べるとよくある症状らしく、結局のところその確認画面は「スキャンしないで続行」でやりすごすのが良いみたいです。

◎Windowsのエクスプローラーの「PC」の画面で容量を見るとすでに1GB以上消費していて「この程度の曲数か..」と思いましたが、曲数を増やすには以下のようにします。
1. iPodをPCに接続
2. iTunes(Win版Ver12.7)の画面の左上のほう「<」、「>」、「♪ミュージック」の次にiPodのデバイスのマークが(しばらくすると)出るのでそれをクリック。
3. 表示された オプション の ビットレートの高い曲を次の形式に変換:128kbps AAC にチェックを入れる。
(AACとは MP3の改良版。MP3よりも上手にCDデータをカットする。AAと続くのでAppleかと思いますがAdvanced Audio Codingだそうです)
すると次からiPodに転送される曲は変換されてiPodに入ります。256kbpsの状態で保存した場合と比べて単純に半分の容量になるそうです。
音質は上記で「…良い音だ…楽しめそう。」と書いたときの状態が128kbpsだったので問題ないかなと思います。
曲数は現在、527曲 / 20時間8分 で1.32GB使用。「そんなに入った?」という感じです。(ゲームBGMがほとんどなので1曲あたり1:30くらいですが)

△iTunesのフォルダ構造をそのままiPodに入れたい。
ネットを調べましたができないらしいです。iPod内ではフォルダを作ることができません。
(iTunesのファイルメニューの新規>プレイリストフォルダ のコマンドがグレーアウトしています)
べたっと曲を一緒くたに入れて、曲には作曲者などいろいろな情報があるのでスマートプレイリストなどを活用するのが普通のようです。

◎説明書に「少なくとも3時間は充電」とありますが1時間か2時間くらいで、とりあえずちょっと聴くには十分に充電されました。

〇再生ボタンを長押しするとカシャッと鳴る。
そのあとボタン操作するとできません。ホールド機能らしいです。

◎”1枚のアルミニウムから削りだして製造された筺体” (Wikipediaの「iPod shuffle」ページより)
再生ボタンを長押ししてホールドしてからならば、衣服にはさむクリップの操作時に 誤操作を防止できてGOODです。
小さいのにファッション性がとてもに高いと感じます。人前に出るときこれを付けていればポイント高いのでは?

掃除と皿洗いのときだけ使うにはもったいないですね。


2017/10/9(月)

新しい形のJavaScriptアニメ

JavaScript のプログラムで行の末尾に //anm:数値 と記入すると、その行を実行した後、数値の秒数(ms)だけプログラムを停止するというプログラムのサンプルです。

普通に JavaScript を書いてアニメしたいと思ったら、その行の末尾に //anm:数値 と記入すればアニメになります。かつてない新しいスタイルの JavaScript プログラミングを体験できると思います。

たとえば以下のように記述するとキャラが 1000ms(1秒) ごとに 16 ドット右に動くアニメになります。1行目の getElementById() の行と2行目の変数への代入の行は行末にアニメの指定がないので時間待ちせずに実行されます。

sprite = document.getElementById( "sprite" );
x = 100;
sprite.style.left = x + 16 * 0; //anm:1000
sprite.style.left = x + 16 * 1; //anm:1000
sprite.style.left = x + 16 * 2; //anm:1000
sprite.style.left = x + 16 * 3; //anm:1000
sprite.style.left = x + 16 * 4; //anm:1000

これを実際に動かすとこうなります。

新しいウィンドウで実行

これを for文 で書くとこうなります。

sprite = document.getElementById( "sprite" );
x = 100;
for( i = 0; i < 5; i++ ) {
    sprite.style.left = x + 16 * i; //anm:1000
}

動かすと同じ動作をします。

新しいウィンドウで実行

まだ開発途中のものについて、これ以降たくさん説明を続けて読みにくいと思いますが、結構いいものだと思っているので、気ままに書いてしまいます。

使い方の概要

まだ途中だし、人が使うように整えていませんが、だいたいの使い方は、

  1. 後述のソースコードで、
    //↓↓↓ 使用サンプル ↓↓↓
    //↑↑↑ 以上、使用サンプル ↑↑↑
    で囲まれた部分のみ変更する。
    それ以外のスクリプトは変更しない。
     
  2. currentSentence = new Sentence( "JavaScriptソースコード" ); と記述する。
    この "JavaScriptソースコード" の部分に前述の100msごとに16ドット動く sprite のサンプルのようなプログラムを記述します。
    ※currentSentence はグローバル変数にする。
    ※変数名は currentSentence のみ。
    ※"JavaScriptソースコード"は、以下の方法で改行付きテキストを書ける。(一般的な裏技)
    var s = ( function() {/*
    1行目
    2行目
    3行目

    */} ).toString().match( /\/\*\s([^]*?)\s*\*\// )[ 1 ];

  3. つづいて、runSentence(); を実行する。

すると、ソースコードが1行ずつ Sentence というオブジェクトになり、eval() 関数を使って順次実行されます。なお、行末に //anm:数値 のある行については setTimeout() 関数を使って遅延して実行されます。もちろん、その行の実行が終わるまでは次の行へ移りません(アニメのために必要な動き)。

プログラムの実行とソースコード

以下のソースコード(1つの HTML ファイル)は、

  1. Sentence クラスの定義、
  2. runSentence() 関数の定義、
  3. その使用サンプル

という構成になっています。

使用サンプル部分の sourcecode = ... の部分でアニメ対応された JavaScript を書いています。

実行すると、背景色がだんだんと変わり、星が動くアニメが表示されます。

新しいウィンドウで実行

長いソースコードで ごつい 感じですが、良いところは、すでに述べたように、かつてない新しいスタイルの JavaScript プログラミングを体験できるところです。アニメ処理が手軽に書けます。

プログラミングをしている人は過去に delay() 関数を探した経験があると思います。行末に //anm:50 と書くとその行が50ms遅延されて実行されますが、これは delay( 50 ); と同じ処理です。(英単語のdelayは「遅らせる」という意味です)

別の言い方をすると、アニメをしようと思って数枚の画像を切り替えるプログラムを書いたけど、少しも待たずに一気に切り替えてしまって一瞬で終わってしまった、という経験をした人がいると思いますが、そういう問題を解決するものです。

以下はアニメ指定せずに、移動を繰り返す例です。

sprite = document.getElementById( "sprite" );
x = 100;
sprite.style.left = x + 16 * 0; //anm:1000
sprite.style.left = x + 16 * 1; //anm:1000
sprite.style.left = x + 16 * 2; //anm:1000
sprite.style.left = x + 16 * 3; //anm:1000
sprite.style.left = x + 16 * 4; //anm:1000

実行すると一気に処理されて、人間の目に見えるのは最後の行の結果だけで、アニメになりません。

新しいウィンドウで実行

もちろんこの問題の解決はいろいろな方法がありますが、ここで紹介しているプログラムはJavaScriptのプログラムそのままでアニメできるというものです。


ソースコード:

<html lang="ja">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<title>untitled script</title>
<script>

var HereDocument = /\/\*\s([^]*?)\s*\*\//;
//usage:
	
var s = ( function() {/* multi line */} ).toString().match( HereDocument )[ 1 ];
function $( id ) { return document.getElementById( id ); }


//**************************
//*1. Sentence クラスの定義*
//**************************

//(ブロック構造解析)


function Sentence( arg1 ) {
/*
ソースコードを受け取り、解析した結果を収めるクラス。


たとえば、"test( 123 );" というコードは、
this.tp == null;
this.evalSTR == "test( 123 );"
this.block == null;
となり、"for( i=0; i<10; i++ ) {...}" というコードは、
this.tp == "for";
this.evalSTR == [ "i=0", "i<10", "i++" ]
this.block == [(ブロックの各行をSentenceにした配列)];
となる。

new Sentence( "ソースコード" );
	
//通常の呼び方
new Sentence( <Sentence> );
	
	
//内部での呼び方

*/

this.tp = null;
this.evalSTR = null;
this.programCounter = 0;
this.parentSentence = null;
this.isAnimate = false;
this.block = null;

//引数リストの異なるコンストラクタを同時に定義する(オーバーロード)の代わり
if( typeof arg1 === "string" ) {
//通常の利用の場合
var sourcecode = arg1;

this.setEvalSTR( "program" );
	
//ダミー
/*
あまり重要な話ではないが、イメージとして
program {
ソースコード
}
このような形となる。
javascript.htmlのrun()の内容から言ってこの"program"は評価されない。
*/

//ブロック部分を解析
var formattedSRC = this._formatSRC( sourcecode );
var lines = formattedSRC.split( /\n/ );
this.block = this._analyzeSRC( this, lines );

} else {
//内部から利用される場合
this.parentSentence = arg1;

//ブロック部分を解析
//※ブロック部分は内部(_analyzeSRC()内)で別途解析される
}



}

Sentence.prototype.setEvalSTR = function( s ) {
/*
Sentence._analyzeSRC()とSentenceコンストラクタから呼ばれる。
1行の文から情報(tp, evalSTR等)を抽出する。
*/

//check.
	
制御文について
this.tp = null;
var pos = s.indexOf( "(" );
if( pos > -1 ) {
var name = s.substr( 0, pos );
var isCTRL = [ "if", "for" ].indexOf( name );
if( isCTRL > -1 ) {
this.tp = name;
}
}

//check.
	
アニメ指定について
if( s.match( /\/\/anm:(.*)/ ) ) {
this.isAnimate = true;
this.animateTM = Number( RegExp.$1 );
}

switch( this.tp ) {
case "if":
if( s.match( /\((.*)\)/ ) ) {
this.evalSTR = RegExp.$1;
}
break;
case "for":
if( s.match( /\((.*)\)/ ) ) {
this.evalSTR = RegExp.$1.split( /;/ );
}
break;
default:
this.evalSTR = s;
}
}

Sentence.prototype._formatSRC = function( sourcecode ) {
/*
後の_analyzeSRC()の前段として、ソースコードを受け取り、整形して返す
*/


//整形のために、for文のオプションを一度退避
var forOptions = new Array();
var next = sourcecode;
sourcecode = "";
while( next.match( /(for\()(.*)(\))/m ) ) {
sourcecode
	
+= RegExp.leftContext + RegExp.$1 + "forOptions[" + forOptions.length + "]" + RegExp.$3;
forOptions.push( RegExp.$2 );
next
	
= RegExp.rightContext;
}
sourcecode += next;

//整形のために、文字列を一度退避
var stringResources = new Array();
var next = sourcecode;
sourcecode = "";
while( next.match( /".*"/ ) ) {
sourcecode
	
+= RegExp.leftContext + "stringResources[" + stringResources.length + "]";
stringResources.push( RegExp.lastMatch );
next
	
= RegExp.rightContext;
}
sourcecode += next;


//行頭のタブ除去
sourcecode = sourcecode.replace( /^\t+/gm, "" );

//解析用整備
//1行に;が2つ以上ある場合改行する
sourcecode = sourcecode.replace( /;(.+);/g, ";\n$1;\n" );

//ブロック開始、終了は単独の行にする
sourcecode = sourcecode.replace( /{/g, "\n{\n" );
sourcecode = sourcecode.replace( /}/g, "\n}\n" );

//空行除去
sourcecode = sourcecode.replace( /\n+/g, "\n" );
sourcecode = sourcecode.replace( /\n$/g, "" );

//;除去
sourcecode = sourcecode.replace( /;/g, "" );

//文字列を復帰
for( var i = 0; i < stringResources.length; i++ ) {
sourcecode = sourcecode.replace( "stringResources[" + i + "]", stringResources[ i ] );
}

//for文のオプションを復帰
for( var i = 0; i < forOptions.length; i++ ) {
sourcecode = sourcecode.replace( "forOptions[" + i + "]", forOptions[ i ] );
}

return sourcecode;
}

Sentence.prototype._analyzeSRC = function( sentence, lines ) {
var block = new Array();
var getting = false;
var gotLines;
var nestCount;
for( var i = 0; i < lines.length; i++ ) {
var line = lines[ i ];
if( line == "{" ) {
	
//begin sub block.
//check.
	
入れ子
if( getting ) {
nestCount++;
gotLines.push( line );
continue;
}
getting = true;
gotLines = new Array();
nestCount = 0;
} else if( line == "}" ) {
	
//end sub block.
//check.
if( getting == false ) {
//エラー処理予定
//}が来るときは必ず取得中のはず
}
//check.
	
入れ子
if( nestCount > 0 ) {
nestCount--;
gotLines.push( line );
continue;
}
getting = false;
var subSentence = block.pop();
subSentence.block = this._analyzeSRC( subSentence, gotLines );
block.push( subSentence );
} else {
	
//line.
if( getting ) {
gotLines.push( line );
} else {
var subSentence = new Sentence( sentence );
subSentence.setEvalSTR( line );
subSentence.tmp = line;
block.push( subSentence );
	
	
	
}
}
}
return block;
}
//以上、ブロック構造解析


//*****************************
//*2. runSentence() 関数の定義*
//*****************************

//(ブロック構造解析後の実行関数)

function runSentence() {
/*
処理するソースコードはブロック構造により親子関係になっているので再帰処理を使えば簡潔に実行処理を記述できる。
それなのに、なぜ再帰関数を使わないのか:
処理するソースコードの任意の1文がアニメ処理になっている場合があるため。
アニメ処理を実行するには再帰的な処理を一時停止して、アニメ(時間待ち)を実行し、
停止した再帰処理へ戻る必要がある。
再帰関数を使えばコードは簡潔になるが、一時止めたり復帰したりといった柔軟な処理ができない。
そのため以下のような平坦なループで、ディレクトリ間を移動するときのような「カレント」や
「プログラムカウンタ」のような変数を用意して親子関係を再帰的(疑似的な再帰)に処理している。
「カレント」はグローバル変数で、「プログラムカウンタ」は各オブジェクトに保管されているので、
ループを出ても同じ状態から復帰できる。
*/

while( true ) {

//check.
	
平文、またはブロック末尾か
if( currentSentence.block === null || currentSentence.programCounter === currentSentence.block.length ) {

//for文ブロックの末尾の場合は
if( currentSentence.tp === "for" ) {
//for - count
eval( currentSentence.evalSTR[ 2 ] );

//for - check
if( eval( currentSentence.evalSTR[ 1 ] ) === true ) {
//続行
currentSentence.programCounter = 0;
continue;
}
}

//check.
	
全プログラム終了か
if( currentSentence.parentSentence === null ) return;

//親へ戻る
currentSentence = currentSentence.parentSentence;
continue;
}
//以上check.

//1行取得
currentSentence = currentSentence.block[ currentSentence.programCounter++ ];
currentSentence.programCounter = 0;

//1行実行
if( currentSentence.tp === "for" ) {
eval( currentSentence.evalSTR[ 0 ] );
	
//for文初期化
} else if( currentSentence.tp === "if" ) {
} else {
//平文実行
eval( currentSentence.evalSTR );
}

//アニメ指定された行の場合は一度ループを出る
if( currentSentence.isAnimate ) break;

}

//アニメ指定の指定秒後にループへ戻る
timerID = setTimeout( "runSentence()", currentSentence.animateTM );

}

//以上、ブロック構造解析後の実行関数

</script>

<script>

//*********************
//*3. その使用サンプル*
//*********************


//↓↓↓ 使用サンプル ↓↓↓

var currentSentence;

function onloadx() {

//アニメプログラムを変数へ代入
/*
アニメプログラム部分でできること:
for文
平文(変数代入や関数実行などの非制御構文)
行ごとのアニメ化指定
行末に //anm:待ち時間ms と書くとその行を実行した後、指定時間停止する(アニメ)
アニメプログラム部分でできないこと:
var文を使用した変数の使用。
つまり変数はグローバル変数のみ使える。
with文
関数定義
現在できないが将来対応する予定のもの:
if文
while文
*/
sourcecode = ( function() {/*
//アニメプログラム

//背景色
for( i = 0; i < 256; i+=10 ) {
s = "RGB(";
s += i + ",";
s += i + ",";
s += i + ")";
$( "bodyID" ).style.backgroundColor = s;
	
//anm:200
$( "bodyID" ).innerHTML = s;
}

//スプライト作成
sp = document.createElement( "div" );
document.body.appendChild( sp );
sp.innerHTML = "★";
sp.style.position = "absolute";

//横移動
for( i = 0; i < 100; i += 4 ) {
sp.style.left = i;
	
//anm:50
}

//半円移動
spX = sp.getBoundingClientRect().left
spY = sp.getBoundingClientRect().top;
centerX = spX;
centerY = spY + 100;
for( theta = 0; theta < 3.14; theta += 0.05 ) {
p = kaiten( centerX, centerY, spX, spY, theta );
sp.style.left = p.x;
sp.style.top = p.y;
	
//anm:20
}

//ジャンプ移動
spX = sp.getBoundingClientRect().left
spY = sp.getBoundingClientRect().top;
half = 100;
sy = xx( -half );
for( x = -half; x < 100; x += 2 ) {
addY = xx( x ) - sy;
sp.style.left = spX + x + half;
sp.style.top = spY + addY;
	
//anm:20
}

*/} ).toString().match( HereDocument )[ 1 ];

//ソースコードを、親子関係のオブジェクトに変換
currentSentence = new Sentence( sourcecode );

runSentence();
}

function kaiten( cx, cy, x, y, theta2 ) {
var p = new Object();
x -= cx;
y -= cy;

var theta1 = Math.atan2( y, x );
var hankei = Math.sqrt( x * x + y * y );
p.x = Math.cos( theta1 + theta2 ) * hankei;
p.y = Math.sin( theta1 + theta2 ) * hankei;

p.x += cx;
p.y += cy;
return p;
}
function xx( x ) {
y = x * x * 0.02;
return y;
}

//↑↑↑ 以上、使用サンプル ↑↑↑

</script>
</head>
<body id="bodyID" onload="onloadx(); " style="
font-size
	
:
	
1cm;
">

</body>
</html>

もとはRPGのイベントスクリプト処理

もとは RPG(Role Playing Game) のイベントスクリプトのプログラムです。

fig.
▲ドラクエ1の戦闘開始部分の再現

もともとのプログラムは9/10(日)に掲載したこのプログラムです。

左の画像リンクをクリックするとJavaScriptを実行します。


RPGのイベントスクリプトとして JavaScript を使おうとしたとき、

  • アニメの実現
  • プログラムの基本構造である「順次」のほか、「分岐」、「繰り返し」などの制御構造の実現(普通のイベントスクリプトとして必要)

この2点の解決を考えて作り始めたプログラムです。

作り始めのプログラム:

JavaScriptをRPGのイベントで使うために、

スクリプトを1行ずつ読んで eval() を使えばいい。

それを setInterval() で一定時間ごとに行えばアニメになる。

問題発生1:

変数の代入などアニメと関係のない行もアニメの1コマになってしまう。

解決:

行末に //anm:50 のように書いてある行だけ setTimeout() で実行するようにした。

プログラムした場所:

コードの解析(//anm:50の認知)については

(今回掲載したソースコード上の)

Sentence.prototype.setEvalSTR メソッド定義内

その動作(遅延させる)については

関数 runSentence() 定義内

問題発生2:

1行ずつ読んで eval() を使う方法だと、if 文や for 文などの制御構造が使えない。

解決:

制御構造を理解するプログラムを組むことにした。

プログラムした場所:

コードの解析(制御文の認知)については

Sentence.prototype.setEvalSTR メソッド定義内のほぼ全体

その動作(for文などの実行)については

関数 runSentence() 定義内の全体

問題発生3:

JavaScript では {...} によるブロック構造が多用されていて入れ子にもなっている。柔軟なスクリプトにするには必要なしくみだ。

解決:

ブロック構造を解析するプログラムを組むことにした。

プログラムした場所:

クラス Sentence の定義全体

特に、_analyzeSRC() メソッド


2017/10/8(日)

今月の右上画像(右上じゃないですが)は「拡散するアニメ」です。

模様の種類は6つで、小さい四角形, ライン, 小さい★, バブル〇, ゴースト, なると があります。


2017/10/1(日)

fig.
▲「サイドビューキャラ」

2DでShade3Dのボーンの機能と同じことをする「サイドビューキャラ」JavaScript

スカートに関節を設けることでしゃがみポーズができるようになりました。

左の画像リンクをクリックするとJavaScriptを実行します。

ファイル一式のZIPダウンロード(300KB程度)

    • 各PNGファイル
      身体の各パーツを単体のファイルで見られます。
    • javascript.html
      ソースコードを見られます。
      ブラウザで開けば、おてもとでサイドビューキャラを動かせます。
    • 画像作成用Excel.xlsx
      身体のパーツを作成したExcelファイルです。
      身体のパーツとExcelのシートが対応しており、パーツを修正したらボタン一発で画像ファイルへ保管してくれるので、いかに便利に画像編集できるかがわかります。が、他人のマクロ入りExcelファイルはセキュリティ上よろしくないので、マクロは外してテキストにしてあります。
      参考程度にご覧ください。



ページ制作 homepage6047