ページ 1 / 1
ブラウザーゲーム作成について
Posted: 2011年3月24日(木) 13:22
by MoNoQLoREATOR
どうも、スレ立てるまでもない質問http://dixq.net/forum/viewtopic.php?f=81&t=7494にて質問させて頂いていた者です。長くなると思い、トピックを立てさせていただきました。
kimuchi さんが書きました:過度なファイルアクセスをするとそのファイルが壊れてしまう可能性があります。
アクセス速度も考えるとやはりデータベースを使ったほうが良さそうですが・・・
ひとつ質問なんですが、
サーバーはレンタルのものでしょうか?
サーバーはレンタルのものです。
データベースを使うと、具体的に何がどのように便利なのですか?
データベースというのは実態があるのではなく考え方の1つだと思っていたのですが違うのですか?
今私が考えているシステムは次の通りです。
↓以下ブラウザがデータを操作するときのシステム↓
・ユーザー1人につき1つのシリアルナンバーを振り、ユーザー全体としてのデータにはそれを用いてアクセスする
・村のデータは座標を用いてアクセスする
・ユーザーのアカウントが作成されたとき、または新しく村が作成されたとき、
その情報をランダムなファイル名で保存する
・データをアクセスしたいときはシリアルナンバー又は座標が
示すフォルダ内の全てのファイル名を取得する方法でファイル名を取得する。
↑以上ブラウザがデータを操作するときのシステム↑
↓以下ユーザーがデータを閲覧するときのシステム↓
・ログイン時に使用されたユーザーID、パスワードURLにくっつけて閲覧ページにアクセス
↑以上ユーザーがデータを閲覧するときのシステム↑
ユーザーIDパスワード.phpを開くと、そこにはシリアルナンバー、座標が記録されているが、これはデータを記録しておくためのファイルではなく閲覧ページ。共通の処理の部分はPHPのrequireを使って読み込む。
わかりにくい説明ですね。
しかしこの方法では、誰もログインしなかった場合いつまで経っても情報が更新されません。もっとも、今のところ当事者(攻撃側、防御側など)がログインしなかったら不都合が起きるという場面は予想されないので、まあいいかなと思っています。ちゃんとしたブラウザーゲームでは、どのような使用になっているのでしょうか。一度、ソースコードを解読してみようとしましたが気力が続きませんでした。
Re: ブラウザーゲーム作成について
Posted: 2011年3月24日(木) 18:42
by Ciel
それだけ情報を読み書きするのであれば、データーベースを使うことをおススメします。
データーベースを使うと一つ一つファイルを読み書きする必要がなくなるし、
データの読み書きもすごい楽です。
ファイルでも可能ですが、面倒だし不具合も起こりやすいと思います。
PHPの経験はあるとのことですが、データーベースは扱ったことないのですか?
普通データーベースを扱っていれば、その利便性は理解できると思うのですが。。
Re: ブラウザーゲーム作成について
Posted: 2011年3月24日(木) 23:32
by kimuchi
データベースを使うと、具体的に何がどのように便利なのですか?
データベースというのは実態があるのではなく考え方の1つだと思っていたのですが違うのですか?
語弊があったかもしれません。ここで言ったデータベースとは基本概念ではなく、
MySQLなどのRDBMSを指したものです。
利点についてはCielさんが仰って下さったので割愛します。
・ユーザー1人につき1つのシリアルナンバーを振り、ユーザー全体としてのデータにはそれを用いてアクセスする
・村のデータは座標を用いてアクセスする
・ユーザーのアカウントが作成されたとき、または新しく村が作成されたとき、
その情報をランダムなファイル名で保存する
・データをアクセスしたいときはシリアルナンバー又は座標が
示すフォルダ内の全てのファイル名を取得する方法でファイル名を取得する。
こういった処理を扱うのは、RDBMSの十八番といえるでしょう。
上の中で「その情報をランダムなファイル名で保存する」だけはテキストファイル仕様での明確なデメリットになるかもしれません。
これはランダムといえど万が一ファイル名が被った場合にデータを上書きしてしまいますし、
防ごうと思えば、ディレクトリ内を検索して一致しないことを確認する必要があるので確実に処理が重くなります。
ここまで書きましたが、レンタルサーバーがRDBMS使用不可であれば使えません・・・
↓以下ユーザーがデータを閲覧するときのシステム↓
・ログイン時に使用されたユーザーID、パスワードURLにくっつけて閲覧ページにアクセス
↑以上ユーザーがデータを閲覧するときのシステム↑
ユーザーIDパスワード.phpを開くと、そこにはシリアルナンバー、座標が記録されているが、これはデータを記録しておくためのファイルではなく閲覧ページ。共通の処理の部分はPHPのrequireを使って読み込む。
この辺りの部分でJavaScriptからのリクエスト(Ajax)を使って、PHPにアクセス→情報を操作・取得・表示
の流れの方がゲームのFPS的に早くなると思います。(非同期通信を使える)
トラビアンについてこちらも(勝手に)調べてみました。
オンラインゲームの区分でもMMOというものに入るようです。
ゲーム内時間の管理は基本的にサーバーの常駐ソフトが行うようです。
つまり、ログイン時以外の時間経過などを再現するのはレンタルサーバー使用、及びPHPのみでは困難でしょう。
Re: ブラウザーゲーム作成について
Posted: 2011年3月25日(金) 22:33
by MoNoQLoREATOR
1つのフォルダの中にランダムな名前のファイルを1つだけつくるので、名前がかぶるような問題は発生しません。
XAMPをダウンロードした際に、MySQLも付いてきたので、とりあえずそれを勉強してみようと思います。
Ajaxについても、これから勉強します。
なにかWEB上でお勧めの講座サイトがあったらぜひ教えてください。
サーバー常駐ソフト・・・ということは、自分のパソコンをサーバーにするとかしないと無理なんでしょうか?
ソフトを常に起動させておけるサーバーが必要ってことですよね?レンタルサーバーでは聞いた事がないです。
Re: ブラウザーゲーム作成について
Posted: 2011年3月26日(土) 00:45
by kimuchi
サーバー常駐ソフト・・・ということは、自分のパソコンをサーバーにするとかしないと無理なんでしょうか?
ソフトを常に起動させておけるサーバーが必要ってことですよね?レンタルサーバーでは聞いた事がないです。
有償ではいくつかあるみたいですが、無償となると無いようですね。
Ajaxは技術自体幅があるものでもないので習得は容易だと思います。
データベースの管理や設定のほうがおそらく大変だと思います。(個人的にですが)
以下、私がお世話になったサイトです。
おすすめ学習サイト
http://www.ajaxtower.jp/ini/
http://www.dbonline.jp/mysql/
Re: ブラウザーゲーム作成について
Posted: 2011年3月26日(土) 09:02
by MoNoQLoREATOR
返信ありがとうございます。
Ajaxとデータベースを同時に使う事はできるのでしょうか?
Ajaxは基本JavaScriptなので、JavaScriptではデータベースにアクセスできないと思うのですが・・・。
Re: ブラウザーゲーム作成について
Posted: 2011年3月26日(土) 20:08
by kimuchi
おそらくAjaxを利用して直接データベースにアクセスするのは無理だと思います。
検索すれば出てくると思いますが、Ajaxでサーバープログラム(PHP)を呼び出して、
間接的にデータベースを操作することになります。
具体的には、
Ajaxからのリクエスト(情報をPHPに送る)
→ PHPで情報を取得($_POST[]などを利用)
→ PHPでMySQLを操作(mysql_関数群を利用)
→ 必要があればAjax(クライアント)に情報を返す(echoする)
→ 受け取った情報を処理する
と、このような流れになると思います。
Re: ブラウザーゲーム作成について
Posted: 2011年3月27日(日) 12:11
by MoNoQLoREATOR
ということは書き込みもできそうですね。
kakikomi.open("POST", "kakikomi.php");
kakikomi.send(書き込みたい内容);
とすればデータを送れ・・・ますよね?
受け取るとき、
$_POST[ここ]
には何を書けばよいのでしょうか?
別の話になるのですが
ファイルから読み込んだデータをsplitで分割しようとしたら
Uncaught TypeError: Object #<XMLHttpRequest> has no method 'split'
というエラーが出てしまいました。どうすれば解決できますか?
Re: ブラウザーゲーム作成について
Posted: 2011年3月27日(日) 20:40
by kimuchi
kakikomi.open("POST", "kakikomi.php");
kakikomi.send(書き込みたい内容);
とすればデータを送れ・・・ますよね?
受け取るとき、
$_POST[ここ]
には何を書けばよいのでしょうか?
「ここ」にはキーを書きます。
「書き込みたい内容」には、(「ここ」で書いたキー)=(キーに対応する情報)を書きます。
クッキーを扱ったことがあれば感覚が分かるのではないでしょうか。
コード:
//Ajax
kakikomi.send("data01=0&data02=hoge"); //複数の指定は「&」で繋ぐ
コード:
//PHP
$data01 = $_POST["data01"];
$data02 = $_POST["data02"];
こうすることで、PHP側の「$data01」には"0"が、「$data02」には"hoge"が格納されます。
ファイルから読み込んだデータをsplitで分割しようとしたら
Uncaught TypeError: Object #<XMLHttpRequest> has no method 'split'
というエラーが出てしまいました。どうすれば解決できますか?
上の「kakikomi」をお借りすると、
array = kakikomi.responseText.split(",");
のように書きます。(「responseText」はPHP等からの情報をテキスト形式で格納しているプロパティ)
エラーを見る限りですが、
array = kakikomi.split(",");
このようにされていませんか?
Re: ブラウザーゲーム作成について
Posted: 2011年3月27日(日) 22:05
by MoNoQLoREATOR
おお~。ありがとうございます。
kakikomi の件は・・・仰るとおり
array = kakikomi.split
という風にやっていました。
Re: ブラウザーゲーム作成について
Posted: 2011年3月28日(月) 21:04
by MoNoQLoREATOR
ブラウザーゲームではないのですが、Ajaxを使ってニコニコ動画のようなコメント機能を実装しようとしています。
kimuchiさんが以前作ってくださったサンプルをベースに、そこにコメント保存機能をつける作戦です。
しかし、動きませんでした。エラーは出ず、実行しても何も表示されません。下にソースコードを張りますので、おかしな部分があったら教えてください。
コード:
<html>
<head>
<style type="text/css"><!--
* {
overflow-x: hidden;
}
span {
font-size: 80px;
white-space: nowrap;
position: absolute;
color: yellow;
font-weight: bold;
}
--></style>
<script type="text/javascript"><!--
var fileCom; //ファイルから読み込んだコメント文を記憶させておく
var fileComNum; //ファイルから読み込んだ「コメント数」を記憶させておく
var fileComSize; //ファイルから読み込んだ「コメントサイズ」を記憶させておく
var commentNum; //コメント数を記憶させておく(ユーザーがコメントした時コメント数が増えるため)
var intComSize = new Array(); //一つ一つのコメント文のコメントサイズを記憶させておく
var commentSpeed = 4;
//ファイル読み込み
function setup(){
//↓IEとそれ以外でオブジェクトの生成方法を変えている↓
if (window.XMLHttpRequest){
fileCom = new XMLHttpRequest();
fileComNum = new XMLHttpRequest();
fileComSize = new XMLHttpRequest();
}else{
if (window.ActiveXObject){
fileCom = new ActiveXObject("Microsoft.XMLHTTP");
fileComNum = new ActiveXObject("Microsoft.XMLHTTP");
fileComSize = new ActiveXObject("Microsoft.XMLHTTP");
}else{
fileCom = null;
fileComNum = null;
fileComSize = null;
}
}
//↑IEとそれ以外でオブジェクトの生成方法を変えている↑
fileCom.onreadystatechange = checkStatus;
fileComNum.onreadystatechange = checkStatus;
fileComSize.onreadystatechange = checkStatus;
fileCom.open("GET", "fileCom.txt", true);
fileComNum.open("GET", "fileComNum.txt", true);
fileComSize.open("GET", "fileComSize.txt", true);
fileCom.send(null);
fileComNum.send(null);
fileComSize.send(null);
}
//ファイル読み込み後の処理
function checkStatus(){
var winSize;//ウインドウの幅を記憶しておく
var element;//オブジェクト用
if (fileCom.readyState == 4 && fileCom.status == 200 &&
fileComNum.readyState == 4 && fileComNum.status == 200 &&
fileComSize.readyState == 4 && fileComSize.status == 200){
var cutedCom = fileCom.responseText.split("\r\n"); //文字列を改行で分割
commentNum = Number(fileComNum.responseText); //コメント数を数値で取得
//コメントの大きさの情報を改行で分割
var strSize = fileComSize.responseText.split("\r\n");
if(window.innerWidth){
winSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
winSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
element = document.createElement("span"); //要素(タグ)の追加
element.style.top = (Math.floor( Math.random()*400 +100))+"px"; //y座標初期値を設定
element.style.left = winSize+"px"; //x座標初期値を設定
//コメントの数だけ繰り返す
for(var i=0;i<commentNum;i++){
intComSize[i] = Number(strSize[i]); //コメントサイズを数値で取得
element.style.fontSize = intComSize[i]+"px";//コメントサイズ設定
element.setAttribute("id","comment"+i);//要素の属性設定(属性名,設定値)
var str = document.createTextNode(cutedCom[i]); //代入する要素の値
element.appendChild(str); //要素に値を代入
document.body.appendChild(element); //このページで最後に生成した要素を追加
}
//0.03秒ごとにmove()を呼び出す
setInterval("move()",30);
}
}
function move()
{
var ele; //オブジェクト用
var nawWinSize; //ウインドウの幅を記録させておく
if(window.innerWidth){
nawWinSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
nawWinSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
//コメントの数だけ繰り返す
for(i=0; i<commentNum; i++){
ele = document.getElementById("comment"+i); //"comment"+i のIDのオブジェクトデータを渡す
ele.style.left -= commentSpeed; //コメントを左に移動させる
//画面を通り過ぎたら
if(eleX < (-1)*ele.innerText.length*intComSize[i]){
ele.style.left = nowWinSize; //新しいx座標初期値を設定
ele.style.top = Math.floor( Math.random()*1100 ); //新しいy座標初期値を設定
}
}
}
--></script>
</head>
<body onload="setup()"></body></html>
Re: ブラウザーゲーム作成について
Posted: 2011年3月28日(月) 23:07
by kimuchi
とりあえず動くようにバグフィックスしてみました。
>1行目
IEでは!DOCTYPE宣言がないと「document.documentElement.clientWidth」の値が0になるようです。
以下を足しました。
コード:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
>82行目~
コード:
element = document.createElement("span"); //要素(タグ)の追加
element.style.top = (Math.floor( Math.random()*400 +100))+"px"; //y座標初期値を設定
element.style.left = winSize+"px"; //x座標初期値を設定
//コメントの数だけ繰り返す
for(var i=0;i<commentNum;i++){
intComSize[i] = Number(strSize[i]); //コメントサイズを数値で取得
element.style.fontSize = intComSize[i]+"px";//コメントサイズ設定
element.setAttribute("id","comment"+i);//要素の属性設定(属性名,設定値)
var str = document.createTextNode(cutedCom[i]); //代入する要素の値
element.appendChild(str); //要素に値を代入
document.body.appendChild(element); //このページで最後に生成した要素を追加
}
この状態では要素作成部がループの外に出ているため一つしかコメントが生成されません。
以下のようにループに入れる必要があります。
コード:
//コメントの数だけ繰り返す
for(var i=0;i<commentNum;i++){
intComSize[i] = Number(strSize[i]); //コメントサイズを数値で取得
element = document.createElement("span"); //要素(タグ)の追加
element.style.top = (Math.floor( Math.random()*400 +100))+"px"; //y座標初期値を設定
element.style.left = winSize+"px"; //x座標初期値を設定
element.style.fontSize = intComSize[i]+"px";//コメントサイズ設定
element.setAttribute("id","comment"+i);//要素の属性設定(属性名,設定値)
var str = document.createTextNode(cutedCom[i]); //代入する要素の値
element.appendChild(str); //要素に値を代入
document.body.appendChild(element); //このページで最後に生成した要素を追加
}
>104行目~
コード:
var ele; //オブジェクト用
var nawWinSize; //ウインドウの幅を記録させておく
if(window.innerWidth){
nawWinSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
nawWinSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
//コメントの数だけ繰り返す
for(i=0; i<commentNum; i++){
ele = document.getElementById("comment"+i); //"comment"+i のIDのオブジェクトデータを渡す
ele.style.left -= commentSpeed; //コメントを左に移動させる
//画面を通り過ぎたら
if(eleX < (-1)*ele.innerText.length*intComSize[i]){
ele.style.left = nowWinSize; //新しいx座標初期値を設定
ele.style.top = Math.floor( Math.random()*1100 ); //新しいy座標初期値を設定
}
}
118行目:
styleプロパティの値はテキストなので数値演算できません。おそらくうっかりだと思いますが。
121行目:
比較の式がおかしいです。
eleはHTMLオブジェクトですが、(-1)*ele.innerText.length*intComSize
は数値です。
nawWinSize → nowWinSize へ統一。
以上を踏まえて以下、変更。
コード:
function move()
{
var ele; //オブジェクト用
var nowWinSize; //ウインドウの幅を記録させておく
if(window.innerWidth){
nowWinSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
nowWinSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
//コメントの数だけ繰り返す
for(i=0; i<commentNum; i++){
ele = document.getElementById("comment"+i); //"comment"+i のIDのオブジェクトデータを渡す
var wPos = eval(ele.style.left.replace(/px/,""));
ele.style.left = wPos-commentSpeed+"px"; //コメントを左に移動させる
//画面を通り過ぎたら
if(wPos < (-1)*ele.innerText.length*intComSize[i]){
ele.style.left = nowWinSize; //新しいx座標初期値を設定
ele.style.top = Math.floor( Math.random()*1100 ); //新しいy座標初期値を設定
}
}
一応全文を貼っておきます。
► スポイラーを表示
コード:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css"><!--
* {
overflow-x: hidden;
}
span {
font-size: 80px;
white-space: nowrap;
position: absolute;
color: yellow;
font-weight: bold;
}
--></style>
<script type="text/javascript"><!--
var fileCom; //ファイルから読み込んだコメント文を記憶させておく
var fileComNum; //ファイルから読み込んだ「コメント数」を記憶させておく
var fileComSize; //ファイルから読み込んだ「コメントサイズ」を記憶させておく
var commentNum; //コメント数を記憶させておく(ユーザーがコメントした時コメント数が増えるため)
var intComSize = new Array(); //一つ一つのコメント文のコメントサイズを記憶させておく
var commentSpeed = 4;
//ファイル読み込み
function setup(){
//↓IEとそれ以外でオブジェクトの生成方法を変えている↓
if (window.XMLHttpRequest){
fileCom = new XMLHttpRequest();
fileComNum = new XMLHttpRequest();
fileComSize = new XMLHttpRequest();
}else{
if (window.ActiveXObject){
fileCom = new ActiveXObject("Microsoft.XMLHTTP");
fileComNum = new ActiveXObject("Microsoft.XMLHTTP");
fileComSize = new ActiveXObject("Microsoft.XMLHTTP");
}else{
fileCom = null;
fileComNum = null;
fileComSize = null;
}
}
//↑IEとそれ以外でオブジェクトの生成方法を変えている↑
fileCom.onreadystatechange = checkStatus;
fileComNum.onreadystatechange = checkStatus;
fileComSize.onreadystatechange = checkStatus;
fileCom.open("GET", "fileCom.txt", true);
fileComNum.open("GET", "fileComNum.txt", true);
fileComSize.open("GET", "fileComSize.txt", true);
fileCom.send(null);
fileComNum.send(null);
fileComSize.send(null);
}
//ファイル読み込み後の処理
function checkStatus(){
var winSize;//ウインドウの幅を記憶しておく
var element;//オブジェクト用
if (fileCom.readyState == 4 && fileCom.status == 200 &&
fileComNum.readyState == 4 && fileComNum.status == 200 &&
fileComSize.readyState == 4 && fileComSize.status == 200){
var cutedCom = fileCom.responseText.split("\r\n"); //文字列を改行で分割
commentNum = Number(fileComNum.responseText); //コメント数を数値で取得
//コメントの大きさの情報を改行で分割
var strSize = fileComSize.responseText.split("\r\n");
if(window.innerWidth){
winSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
winSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
//コメントの数だけ繰り返す
for(var i=0;i<commentNum;i++){
intComSize[i] = Number(strSize[i]); //コメントサイズを数値で取得
element = document.createElement("span"); //要素(タグ)の追加
element.style.top = (Math.floor( Math.random()*400 +100))+"px"; //y座標初期値を設定
element.style.left = winSize+"px"; //x座標初期値を設定
element.style.fontSize = intComSize[i]+"px";//コメントサイズ設定
element.setAttribute("id","comment"+i);//要素の属性設定(属性名,設定値)
var str = document.createTextNode(cutedCom[i]); //代入する要素の値
element.appendChild(str); //要素に値を代入
document.body.appendChild(element); //このページで最後に生成した要素を追加
}
//0.03秒ごとにmove()を呼び出す
setInterval("move()",30);
}
}
function move()
{
var ele; //オブジェクト用
var nowWinSize; //ウインドウの幅を記録させておく
if(window.innerWidth){
nowWinSize = window.innerWidth; //ウインドウの幅を取得
} else if(document.documentElement.clientWidth){
nowWinSize = document.documentElement.clientWidth; //ウインドウの描画可能領域の取得
}
//コメントの数だけ繰り返す
for(i=0; i<commentNum; i++){
ele = document.getElementById("comment"+i); //"comment"+i のIDのオブジェクトデータを渡す
var wPos = eval(ele.style.left.replace(/px/,""));
ele.style.left = wPos-commentSpeed+"px"; //コメントを左に移動させる
//画面を通り過ぎたら
if(wPos < (-1)*ele.innerText.length*intComSize[i]){
ele.style.left = nowWinSize; //新しいx座標初期値を設定
ele.style.top = Math.floor( Math.random()*1100 ); //新しいy座標初期値を設定
}
}
}
--></script>
</head>
<body onload="setup()">
</body>
</html>
※バグとは関係ない話ですが、
コメントをsplitで取得したときに、
配列の長さ=コメント数となるのでコメント数をは保存しなくても良い気がします。
おかしな点があれば、遠慮なくご指摘お願いします。
Re: ブラウザーゲーム作成について
Posted: 2011年3月29日(火) 10:01
by MoNoQLoREATOR
私はelementは一時的なデータの入れ物にすぎず、document.body.appendChild(element);の部分でデータを渡して実体を生成しているのかと思っていましたが、違うのですか?elementがグローバル変数でないところを見ると、変数が存在し続ける必要はないようですし。(=実体は別の場所にあり、データはそこに保存される)
element.setAttribute("id","comment"+i);
で識別するためのIDを付与して、別の場所で操作するときは
document.getElementById("comment"+i);
を使っているところを見ると、
document.body.appendChild()//実体を生成し、そこに引数の示すデータを保存する
↓
.setAttribute()であらかじめ決めておいた識別番号のようなものを
var hennsuu = document.getElementById()
の引数に指定して、変数のアドレスを取得して、その後はそのアドレスを使ってその変数を操作する。
(この場合のhennsuuはポインタの役割をしているのでは?)
説明できたかどうかわかりませんが、私は上記のように考えました。
つまり、
var hennsuu = document.createElement()がいくつ宣言されているかは関係なく、
.setAttribute()によって、個々を識別できるようになっていることと、
その数だけdocument.body.appendChild()が呼び出されていることが重要なのではないかということです。
Re: ブラウザーゲーム作成について
Posted: 2011年3月29日(火) 10:44
by MoNoQLoREATOR
実際にやってみましたが、本当ですね。コメントの数だけオブジェクトを生成する必要があるようです。
それはさておき、修正すべき点を修正したら動きました。本当にありがとうございました。
あとはコメント保存機能をつけて完成です。これもAjaxを使って書いてみようと思います。
Re: ブラウザーゲーム作成について
Posted: 2011年3月29日(火) 22:54
by kimuchi
私はelementは一時的なデータの入れ物にすぎず、document.body.appendChild(element);の部分でデータを渡して実体を生成しているのかと思っていましたが、違うのですか?elementがグローバル変数でないところを見ると、変数が存在し続ける必要はないようですし。(=実体は別の場所にあり、データはそこに保存される)
element.setAttribute("id","comment"+i);
で識別するためのIDを付与して、別の場所で操作するときは
document.getElementById("comment"+i);
を使っているところを見ると、
document.body.appendChild()//実体を生成し、そこに引数の示すデータを保存する
↓
.setAttribute()であらかじめ決めておいた識別番号のようなものを
var hennsuu = document.getElementById()
の引数に指定して、変数のアドレスを取得して、その後はそのアドレスを使ってその変数を操作する。
(この場合のhennsuuはポインタの役割をしているのでは?)
Javascriptで扱う関数、配列などが全てオブジェクトで構成されているのはご存知ですよね。
また変数には数値や文字列などを扱う「普通の変数」(関数の引数などはコピーになる)
とメモリの何処かで構成されているオブジェクトを指し示す「参照型の変数」があります。
(これらはキャストなどによって明確に区別されるものではなく、代入されたデータによって変わります。)
参照型はC言語で言うポインタのようなものです。
ここでの、「document.createElement」関数は、
メモリ上にHTMLオブジェクト(ノード)を
作成し、「element」変数はそれを指す「参照型の変数」としての役割を持っています。
つまり、「document.createElement」関数が実行されたときにはオブジェクトの実体は存在しますが、
画面には反映されていないのです。
そこで、「appendChild」を使うことによって、DOMツリーへノードが追加され、実際に画面へ
反映されます。
つまり、MoNoQLoREATORさんの仰るようにオブジェクトの実体は別の場所に保存され、参照型変数はそれを指し示すものですが、HTMLオブジェクトは少々ややこしくて、DOMツリーへノードとして追加されないと画面に反映されないのです。おそらく別の体系なんでしょうね。
「setAttribute()」であらかじめ決めておいた識別番号のようなものを~
というのはどうなんでしょうね。
てっきり、ノードを全部検索してプロパティが一致したときにそれを返すものだと思ってたんですが・・・
これは良く分からないです。
「hennsuu」がポインタのような役割をしているのは確かです。
var hennsuu = document.createElement()がいくつ宣言されているかは関係なく、
.setAttribute()によって、個々を識別できるようになっていることと、
その数だけdocument.body.appendChild()が呼び出されていることが重要なのではないかということです。
「element」が参照型の変数である以上実体はひとつです。
「setAttribute()」によって属性が付加される対象は「element」の指すオブジェクトが変わらない限り同じままです。つまり、結局はひとつのノードに対して属性の更新が行われるだけになります。
上でも申し上げたのでくどいですが「appendChild」はノードの反映しか行わないので、既に反映されたノードに対して何度行っても意味がありません。
またまた、おかしな点ございましたらご指摘お願いします。
間違っているかもしれないので。
※蛇足
「document.getElementById()」等のメソッドは既に反映されたノードが対象で、
「setAttribute()」等のメソッドは反映の有無を問いません。
逆に「createTextNode()」等のメソッドは反映前のノードしか効果がない、など色々と仕様がありますね。