ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

子供に、ゲーム「制作者の意図まで理解させ」る。。すげー(@_@!)マネージャーの悲哀とか?

2006-12-27 18:31:03 | Weblog

ここの
「ゲームが暴力を助長。"倒された者の家族の気持ち"などを考えさせるゲームリテラシー教育を」…専門家
http://blog.livedoor.jp/dqnplus/archives/885694.html

なんだけど、いや、途中までは、よくある話で、面白くないんだけど。。

こんな文があるのよ(以下斜体は上記記事より引用)

倒された者の家族はどんな気持ちか-など、「ゲームに描かれていないもの」を考えることで、暴力は「ゲームの中のもの」と理解させることは可能だという。

ゲームリテラシー教育とは、子供にゲームに描かれていない背景、制作者の意図まで理解させ、子供がゲームにコントロールされないように教えることだ。


ゲームの「制作者の意図まで理解させ」るんだって(@_@!)
えーっとえーっと、じゃあ、

どうしてここのグラフィックが荒いかというと、
ここを細かくしてしまうと、グラフィックの
処理スピードが間に合わなくなってしまうので、
荒くしてる
とか。。。

どうして、こーいう画面割なの?
とかいったら、いや、こういう開発ツールをつくってしまっているので、
それ以外の画面だとシステムつくりなおさないといけないのよ
とか。。。。

どーして、暴力シーンが多いの?
っていったら、いや、企画の何々さんが、そー言うのが好きで、
さらにこの前ヒットしたんで、
冒険したくない上の連中は、またもや、おなじものを作って
2匹目のどじょうをねらってるわけ。

いや、もっと、リズムゲーとか、つくりたいんだよ、つくりたいんだけど、
上が認めてくれないのさー、アクションモノのほうが、あたるだろー。
ほら、それに、グラフィックエンジンも作っちゃってるわけで、
さらにデザイナーも抱えちゃってるわけで。。

。。。とか、そーいうもんだよねえ。。
「制作者」の意図って、
よーするに、マネージャーの悲哀とか。。

うーん、たしかに、そーすれば、暴力シーンも、押さえられるかもしれませんね。
つまり、暴力シーンが多いのは、そういうのを買う人が多いからであって、
みんなが、オシャレ魔女に夢中になれば、そっちのゲームが増えると。。

そこまで考えたら、ゲームに左右されることもなくなるかもしれません。。




 それと、

 「ゲームに描かれていないもの」を考える。。。

 って、仕様書とか? 企画書とか。。

 このプラットホームだと、ユーザーがこれくらいいそうだから、
 この程度の開発費をペイさせるには。。
 やっぱ、グラフィックはさておき、
 このプラットフォームで行きましょうとか?


 たしかに、そこまで考えたら、

「ゲームに描かれていないもの」を考えることで、暴力は「ゲームの中のもの」と理解させることは可能

 かもしれない。つまり、ゲームメーカーは、採算をとることが必要なんであって、
 ゲームの企画者やマネージャーの多くは別に暴力が好きなわけじゃない。
 (もっと売れる分野があったら、そっちのほうが好きだ)
 →下のほうの人には、個人的に好きという人は、もちろんいると思いますが、
  上に行けばいくほど、それより、採算を重視すると思います。

 つまり、暴力シーンは、売れるからゲームの中でやってるわけであって、
 売れなくなって、たとえば、美少女萌え萌え系が、はやれば、
 すぐに、そっちのほうをつくる。。

 っていう現実を知ってしまえば、夢も希望もなくなって、
 子供はゲームしなくなるかも。。

 それが良いか悪いかは別として、
 そこまでいけば、世の中、すごいことになるかもしんない。。

幼稚園でも早すぎることはありません

 うーん、そこまでの現実を知ってしまうことは、幼稚園でも早くないのか。。
 そーすると、その子たちは、小学生になったら、株でもやりだすだろうな。。




 って、ウィリアムのいたずら、なにか、勘違いしてる??
 文字通りによむと、そうやって読めてしまうんだけど。。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

仕様書からプログラムソースを生成する方法(Excelの仕様書編 その25:イベント追加 ソース)

2006-12-27 17:38:37 | Weblog

 シリーズ仕様書からプログラムソースを生成する方法の続きです。
字数の関係で、以下、いきなりですが、ソースです
Public Const gamen_teigi_str_gyo As Integer = 5

'//=========================//
'//     前処理              //
'//=========================//
Sub initAppData()
    Dim gyo As Integer
    Dim pathdir As String
    Dim i As Integer
    Dim j As Integer
    Dim gamenSu As Integer
    Dim sagyoShname As String
    Dim sagyoSh As Worksheet
    Dim shname() As String
    
    gyo = Sheets("作業一覧").Range("A65536").End(xlUp).Row
    If (gyo >= 5) Then
        Sheets("作業一覧").Range("A5:C" & CStr(gyo)).Clear
    End If
    
    '// 値の初期設定
    pathdir = ActiveWorkbook.Path 
    gyo = 5
    
    '// 主処理:作業一覧の書き出し
    gamenSu = 0
    For i = 1 To Sheets.Count

            '■ 画面一覧の場合
        If (Sheets(i).Range("B1") = "画面一覧") Then
                
                '// アプリ用ソース書き出し
            Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥app_c.txt"
            Sheets("作業一覧").Cells(gyo, 2) = Sheets(i).Name
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(i).Range("B2") & ".c"
            gyo = gyo + 1
            
                '// アプリ用ヘッダー書き出し
            Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥app_h.txt"
            Sheets("作業一覧").Cells(gyo, 2) = Sheets(i).Name
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(i).Range("B2") & ".h"
            gyo = gyo + 1
            
                '// バージョン用書き出し
            Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥version_h.txt"
            Sheets("作業一覧").Cells(gyo, 2) = Sheets(i).Name
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥version.h"
            gyo = gyo + 1
        End If

            '■ 各画面定義の場合
        If (Sheets(i).Range("B1") = "画面定義") Then
                
                '// 新規画面用にシート名保存
            ReDim Preserve shname(gamenSu + 1)
            shname(gamenSu) = Sheets(i).Name
            sagyoShname = "@" & Sheets(i).Name
            gamenSu = gamenSu + 1
            
                '// 画面用ソース書き出し
            If (Sheets(i).Cells(gamen_teigi_str_gyo, 1) = "") Then
                Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_c.txt"
            Else
                Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_b_c.txt"
            End If
            Sheets("作業一覧").Cells(gyo, 2) = sagyoShname
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(i).Range("D2") & ".c"
            gyo = gyo + 1
            
                '// 画面用ヘッダ書き出し
            If (Sheets(i).Cells(gamen_teigi_str_gyo, 1) = "") Then
                Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_h.txt"
            Else
                Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_b_h.txt"
            End If
            Sheets("作業一覧").Cells(gyo, 2) = sagyoShname
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(i).Range("D2") & ".h"
            gyo = gyo + 1
        End If
    
    Next
    
    '// 主処理2:作業用画面定義の作成
    For i = 0 To gamenSu - 1
        Set sagyoSh = Sheets.Add()
        sagyoShname = "@" & shname(i)
        sagyoSh.Name = sagyoShname
        Call makeSagyoSheet(sagyoShname, shname(i))
        Set sagyoSh = Nothing
    Next
    
    '// 主処理3:画面イベント処理の作成
    For i = 0 To gamenSu - 1
        sagyoShname = "@" & shname(i)
        j = 5
        Do While (Sheets(sagyoShname).Cells(j, 13) <> "")
            Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_event_h.txt"
            Sheets("作業一覧").Cells(gyo, 2) = "@" & Sheets(sagyoShname).Cells(j, 13)
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(sagyoShname).Cells(j, 13) & ".h"
            gyo = gyo + 1
            Sheets("作業一覧").Cells(gyo, 1) = pathdir & "¥gamen_event_c.txt"
            Sheets("作業一覧").Cells(gyo, 2) = "@" & Sheets(sagyoShname).Cells(j, 13)
            Sheets("作業一覧").Cells(gyo, 3) = pathdir & "¥" & Sheets(sagyoShname).Cells(j, 13) & ".c"
            gyo = gyo + 1
            j = j + 1
        Loop
    Next
    
End Sub

'//=========================//
'//     後処理              //
'//=========================//
Sub freeAppData()
    Dim sagyoShname As String
    Dim sagyoSh As Worksheet
    Dim shname() As String
    Dim i As Integer
    Dim j As Integer
    
    '// 主処理1:作業用画面定義の取得
    j = 0
    For i = 1 To Sheets.Count
        If (Left(Sheets(i).Name, 1) = "@") Then
                '// 新規画面用にシート名保存
            ReDim Preserve shname(j + 1)
            shname(j) = Sheets(i).Name
            j = j + 1
        End If
    Next
    
    '// 主処理2:作業用画面定義の削除
    Application.DisplayAlerts = False
    For i = 0 To j - 1
        Sheets(shname(i)).Delete
    Next
    Application.DisplayAlerts = True

End Sub


'//=========================//
'//  作業用シート書き出し   //
'//=========================//
Sub makeSagyoSheet(shname As String, motoname As String)
    Dim sakiSheet As Worksheet
    Dim motoSheet As Worksheet
    Dim lastGyo As Integer
    Dim i As Integer
    Dim j As Integer
    Dim sts As Integer
    Dim strMenuGyo As Integer
    Dim strEventGyo As Integer
    
    '// 元、先シートと最後の行を求める
    Set sakiSheet = Sheets(shname)
    Set motoSheet = Sheets(motoname)
    lastGyo = motoSheet.Range("A65536").End(xlUp).Row
    
    sts = 0
    For i = 1 To lastGyo
        Select Case sts
        Case 0:
            If (motoSheet.Cells(i, 1) = "メニュー一覧") Then
                sts = 1
                strMenuGyo = i
                For j = 1 To 4
                    sakiSheet.Cells(i - strMenuGyo + 3, j + 14) = motoSheet.Cells(i, j)
                Next
            ElseIf (motoSheet.Cells(i, 1) = "イベント一覧") Then
                sts = 2
                strEventGyo = i
                Call makeEventList(sakiSheet, motoSheet, strEventGyo, i)
            Else
                For j = 1 To 12
                    sakiSheet.Cells(i, j) = motoSheet.Cells(i, j)
                Next
            End If
        Case 1:
            If (motoSheet.Cells(i, 1) = "イベント一覧") Then
                sts = 2
                strEventGyo = i
                Call makeEventList(sakiSheet, motoSheet, strEventGyo, i)
            Else
                For j = 1 To 4
                    sakiSheet.Cells(i - strMenuGyo + 3, j + 14) = motoSheet.Cells(i, j)
                Next
            End If
        Case 2:
            Call makeEventList(sakiSheet, motoSheet, strEventGyo, i)
        End Select
    Next

    '//あとしまつ
    Set sakiSheet = Nothing
    Set motoSheet = Nothing
    
End Sub

'//=========================//
'//  イベント一覧書き出し   //
'//=========================//
Sub makeEventList(sakiSheet As Worksheet, motoSheet As Worksheet, _
                strEventGyo As Integer, gyo As Integer)
    Dim j As Integer
    Dim i As Integer
    Dim ecName As String
    Dim eventName As String
    Dim eGyo As Integer
    Dim eventSheet As Worksheet
    Dim eWriteGyo As Integer
    
    i = gyo
    For j = 1 To 6
        If (motoSheet.Cells(i, 2) <> "") And _
        (j >= 3) And (j <= 4) And _
        (motoSheet.Cells(i, j) = "") Then
           sakiSheet.Cells(i - strEventGyo + 3, j + 19) = 0
        Else
            sakiSheet.Cells(i - strEventGyo + 3, j + 19) = motoSheet.Cells(i, j)
        End If
    Next
    
    '// イベントモードの設定
    sakiSheet.Cells(i - strEventGyo + 3, 26) = _
        getEventMode(motoSheet.Cells(i, 2), motoSheet.Cells(i, 3), motoSheet.Cells(i, 4))
                
    '// イベントがわかんない行(イベント種類がない)は、ここで終わり
    If (sakiSheet.Cells(i - strEventGyo + 3, 26) = "") Then
        Exit Sub
    End If
                
    '// イベントクラスとメソッド取得
    ecName = motoSheet.Cells(i, 5)
    eventName = motoSheet.Cells(i, 6)
    eGyo = 5
    Do While (sakiSheet.Cells(eGyo, 13) <> "")
        If (sakiSheet.Cells(eGyo, 13) = ecName) Then
            Exit Do
        End If
        eGyo = eGyo + 1
    Loop
    
    '// イベントシートの取得(なければ追加)
    If (sakiSheet.Cells(eGyo, 13) = "") Then
        sakiSheet.Cells(eGyo, 13) = ecName
        Set eventSheet = makeEventSheet(ecName, motoSheet.Range("D2"))
    Else
        Set eventSheet = Sheets(CStr("@" & ecName))
    End If
   
    '// イベントの書き出し
    eWriteGyo = eventSheet.Range("A65536").End(xlUp).Row + 1
    eventSheet.Cells(eWriteGyo, 1) = eWriteGyo - 4
    eventSheet.Cells(eWriteGyo, 2) = eventName
    Set eventSheet = Nothing
    
End Sub

'//=========================//
'//  イベントモード決定    //
'//=========================//
Function getEventMode(eCode As String, wParam As String, dwParam As String) As String
    
    If (InStr(eCode, "EVT") = 0) Then
        getEventMode = ""
        Exit Function
    End If
    
    If (dwParam = "") Then
        If (wParam = "") Then
            getEventMode = "IEVENTLIST_KIND_ECODE"
        Else
            getEventMode = "IEVENTLIST_KIND_WPARAM"
        End If
    Else
        getEventMode = "IEVENTLIST_KIND_DWPARAM"
    End If
End Function
'//=========================//
'//  イベントシート作成    //
'//=========================//
Function makeEventSheet(ecName As String, gamenName As String) As Worksheet
    Dim sagyoSh As Worksheet
    Set sagyoSh = Sheets.Add()
    sagyoSh.Name = "@" & ecName
    sagyoSh.Range("A1") = "イベントクラス名"
    sagyoSh.Range("B1") = ecName
    sagyoSh.Range("C1") = StrConv(ecName, vbUpperCase)
    sagyoSh.Range("A2") = "画面名"
    sagyoSh.Range("B2") = gamenName
    sagyoSh.Range("A4") = "イベント一覧"
    Set makeEventSheet = sagyoSh
End Function


(上記 < > ¥ は、本当は半角)
字数いっぱいなので説明は次回

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

単体テストを省略できるという理論的根拠と、その条件

2006-12-27 16:18:23 | 開発ネタ

 ちょっと全然別のことを考えていたときに、なぜか、思いついたので。。
メモメモ。




 よく、開発のときに、単体テストを線表上はあるけど、時間がなくて省略することがある。
 このとき、省略しても、うまくいくケースとうまくいかないケースが、経験的にある。
 (単純に、人の問題とか、そういうのではない気もする)。

 この条件って、なに?っていうのが、大体分かっているんだけど、それって、理論的に
説明できてなかったんだけど、いま、「そうだよね」と思ったので。。メモ。




もともと、単体テストを省略しないでやろうと思った時点では、
単体テストで
・単体テストの仕様書(どのように行うか)
・とその結果(エビデンスを含む)
を提出するつもりでいる。

さて、最近、プログラムを開発するときは、昔のように、
・コーディングシートに書いて
・パンチして
・一気にコンパイルして確認する
ということは、まずしない。

ふつう、
・トップダウンにつくっていって、
・ダミーモジュール(スタブ)を作成し
・ダミーモジュールを呼び出す形で確認を取り
・OKだったら、今度はそのダミーモジュールを作っていく
というように、テストファーストの手法で、多分組んでいると思う。




この場合、コーディングが全部終わった時点で(JUNITを使っていれば、
ダミーモジュールがなくなって、すべて実装し、緑色になった時点で)、
テスト仕様書は1ページも書いていないけど、実質単体テストまで完了
している。
完了していないと、プログラムは、実装できないので。。

 ところが、テスト仕様書とそのエビデンスはまったく書いていないので、
テストは、まったく、していないことになっている。
 なので、ここから仕様書を書かなければならないが、しかし、ここで
書いてしまってもムダになる可能性は大きい。
 というのも、この時点では結合テストをしていない。
 結合テストの結果によっては、プログラムは変わり、そしたら、単体テスト
やりなおしになる。
 ということは、先に結合をやって、安全なことを確かめたほうがいい。

 ってなると、単体テストを省略し、結合を先にやったほうがいいことになる。

 この場合、単体テストは省略しても、品質に問題ないことになる。




 という場合、じゃあ、これが成立する条件は?と考えると

・トップダウンで作っていき、分からないところにスタブを入れていく
・で、トンドンスタブを奥ふかくまでつくり、スタブの部分がなくなるようにする
・すべてのテストはOKとなっている(JUNITで緑になる)

っていうことになると。。スタートの時点の問題になる。
初めの時点で、入力データと出力データに対するダミーデータがそろっていて、
そのダミーデータがすべてのケース分、存在すること。

 まず、データがないとテストできないのでX
 で、正常形だけあっても、異常系でおかしくなるかもしれないのでX
 正常、異常、すべてのケース分の入出力データがあれば、それをもとに、テストファーストで
テストできる。




 ここで問題なのは、この「正常、異常、すべてのケース分の入出力データ」を
確認しないといけないのは、構造設計レベルである(単体のプログラムではない。
単体プログラムはそれが呼び出されるプログラムとのインターフェースの整合性
まではわからない。コレが分かるのは、構造設計)。

 つまりよく、プログラムの出来が悪いと、単体を作ってるプログラマが馬鹿だからとか
単体テストやってないからとかいったり、ITレベルで落ちると、単体テスト以下だろうとか
言う人が、非常に多くいるが、本質的な問題は、構造設計における、インターフェース設計の
甘さと事象の読みの甘さ、あと、PG担当者に対するPGの進め方の指示ミスであることが多い。

 このように、本質的な問題は解決されず、PG側に責任転嫁し、まわりもこの事象を
見抜けないため、この問題は何度も繰り返し、起こっている。




 っていうことは、分かりきっていることなんで、どうでもいいんだけど、
せっかく思いついたことがまとまったんで、一応書いておいて見た。

  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

仕様書からプログラムソースを生成する方法(Excelの仕様書編 その24:イベント追加 マクロ仕様)

2006-12-27 15:13:44 | ケータイ

 BREWの画面部分のプログラムをExcelの仕様書から自動生成するという、シリーズ仕様書からプログラムソースを生成する方法の続きです。

 前回までで、雛形サンプルの公開をしました。
 なので、今度は雛形サンプルを読んで、ソースを出力する、マクロを作成すればOK!ってことになります。

 で、そのマクロなのですが、今回は、どういうものを作るかについて説明します。




■概要
 今回は、画面ソースと画面用イベント用ソースを書き出します。
 ところが、画面と画面用イベントは、1対1に対応しません。
 画面1個にたいして、イベント用のソースを分けてもかまわないし、
 逆のことも言えるわけです。

 ということで、コレを解決するために
   画面定義から、画面用の作業シートと、イベント用の作業シート
 を別々に作成することにしました。
 (なお、作業用シートは作業開始時に作成され、終了時に削除されます)

 以下、作業シートごとに、説明します。




■画面用作業シート
 画面用作業シートは、1画面に1つできます。
 シート名は、日本語の画面名に@を付けたものです。
 こんな感じのシートです

(全体を入れるため、縮小し、一部の桁の幅を縮小しています)
画面、メニュー、イベントが、横に並んでいます。
なお、M桁に、この画面で使うイベントクラスが並んでいます。
本来ここではないのですが、バグのためか、Z桁以上が入れられないので、
むりやり、ここに突っ込みました。




■画面イベント用作業シート
 画面イベント用作業シートは、1イベントクラスに1つできます。
 シート名は、イベントクラス名に@を付けたものです。
 こんな感じのシートです

(全体を入れるため、一部の桁の幅を拡大しています)
イベント関連の内容が並んでいます。

P.S いまのこの方式だと2つの画面から、同じ画面イベントファイルを参照する場合、
  ヘッダファイルに1つしかかなないので、困ってしまいます。
  参照される画面用に、たとえばG桁5行目あたりから書けばいいのですが、
  それ以外にもやることがあって、複雑になってしまうので、今回は省略します。



■各シートと、書き出すファイルとの関係
上記のシートと、書き出すファイルの関係は以下のとおりです

<<1アプリ1つ>>
・アプリ用ソース(アプリ名.c)=>画面一覧シート
・アプリ用ヘッダ(アプリ名.h)=>画面一覧シート
・バージョンファイル(version.h)=>画面一覧シート

<<画面分できる>>
・画面用ソース(画面名.c)=>画面用作業シート(@画面名.c)
・画面用ヘッダ(画面名.h)=>画面用作業シート(@画面名.h)

<<イベントクラス分できる>>
・画面イベント用ソース(イベントクラス名.c)
        =>画面イベント用作業シート(@イベントクラス名.c)
・画面イベント用ヘッダ(イベントクラス名.h)
        =>画面イベント用作業シート(@イベントクラス名.h)

なお、この内容は、作業一覧シートに書き出されます。




■マクロの概要
 マクロは、前処理のinitAppDataと後処理のFreeAppDataのところを作成します。
 
●前処理のinitAppDataの内容
(1)作業一覧シートをクリア
(2)シートに対して、以下の処理をする
    (あ)シートが画面一覧だったら、
      アプリ用ソース、ヘッダ、バージョンファイルの書き出し指示を
      作業一覧シートに書き出す

    (い)シートが画面定義だったら
      画面名を保持し、画面用ソース、ヘッダの書き出し指示を
      作業一覧シートに書き出す
    
(3)保持しておいた画面名をもとに、画面用作業シートを作成する
      この中で、イベントがあれば、
        画面イベント用作業シートも作成する

(4)保持しておいた画面名をもとに、画面用作業シートを検索し
   画面イベント用作業シートを書き出す




実際のマクロのソースは、次回のこのシリーズで書きます。


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする