ExcelVBAゲームプログラミング?

初心者でもきっとできる!
Excelさえ持っていれば特別なソフトは不要!
すぐにでも始められる簡単ゲームプログラミング!
今すぐ始めよう!

サンプルやゲームのダウンロードができる別館も好評運営中です。
ご意見やご質問、ゲームの感想等は掲示板までお気軽に。是非、皆さんの声を聞かせてください。運営、開発の励みになります。



各種ダウンロードはコチラ ↓ 意見・感想・質問はコチラ ↓
影倉庫 Shadow warehouse サポート掲示板
ブログの全体像はコチラ ↓ リンクのページはコチラ ↓
サイトマップ 自分本位なリンク


スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。






Chapter.61 [ カードゲームで使えるめくり効果 ]

■プロパティを活用した演出

ユーザーフォーム上に配置できる様々なコントロールたち。それらの多くは、非常に多彩なプロパティを持っています。これらのプロパティを変化させることで、ユーザーにとって扱いやすいインターフェイスを作ったり、安定したプログラムを作成することができるようになります。

ですが、プロパティを活用することで、ゲームの演出面が強化される場合もあります。

今まで扱ってきた、アニメーション処理やシューティングゲームの処理でも、イメージコントロールのBackStyleプロパティをうまく利用したキャラクターの表示などを行ってきましたね。
これも、プロパティの成せる技です。

今回は、イメージコントロールが持っているプロパティのうち、PictureSizeModeというプロパティにフォーカスを当ててみたいと思います。


■PictureSizeModeプロパティ

コントロールに画像を表示する際、その表示方法にPictureSizeModeが影響を与えます。
PictureSizeModeは、画像の大きさとコントロールの大きさが一致していない場合に、画像を伸縮させて表示させるか、あるいはそのままの大きさを維持して表示させるか、それを管理します。
シューティングゲームの中でも、このプロパティを使った部分がありましたね(Chapter54を参照)。

このプロパティをうまく活用することで、カードがめくれるような演出を行うことができます。早速、その詳細を見てみましょう。

まずは、ユーザーフォーム上にイメージコントロールを3つ配置します。このイメージコントロールがカードの役割を果たします。
このうち、1つはカードそのものを表し名前が『card』です。残りの2つは原画の役割を果たします。名前は『back』と『front』としておきます。

350.gif

カードの表面と裏面の両方に相当する画像をロードしておき、適宜名前を変更します。
カードそのものを表すcardPictureSizeModeプロパティを変更してfmPictureSizeModeStretchに設定しておきましょう。
コマンドボタンを追加して、これでユーザーフォームの準備は完了です。

あとでコードが記述しやすいように、各コントロールの名前を変更しておくのを忘れずにやっておきましょうね。


■考え方とコードの記述

カードがめくれるような演出を行うためには、どのようにコードを記述すればいいのでしょうか。人間の視点に立って考えてみましょう。

カードが視線に対して直角に存在する場合には、次のようになりますね。

351.gif

カードが視点に対して直角になっているので、カードがそのまま見えるだけです。
そして、カードがめくれていく途中の段階では、こんな風になりますね。

352.gif

視点から見たカードの幅は、めくれていく中でだんだん狭くなっていきます。
完全に視線と水平になったとき、カードはほとんど見えなくなり、今度はだんだん幅が広がっていきます。
完全にめくり終わると、カードは再び視線に対して直角に戻ります。

ここで重要なのは、めくれていく中で、はじめは『 幅が狭くなっていき 』裏返ると『 幅が広くなっていく 』ということです。
イメージコントロールの幅が、狭くなる⇒広くなる、という具合に連続して処理できれば、カードのめくれる動作を実現できるのです。

それでは実際にコードを見てみます。

'API宣言と変数及び定数の宣言
Public Declare Function GetTickCount Lib "kernel32" () As Long
Public Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMillsecounds As Long)

Public Stime As Long
Public Fronts As Boolean

Public Const Card_Left As Single = 72
Public Const Card_Width As Single = 90


Sub Turn()

    Dim Before As Boolean
    Dim Flg As Boolean
    
    Before = True
    
    With UserForm1.card
        Do Until Flg
            Stime = GetTickCount
            If Before Then
                .Width = .Width - 4
                If .Width < 5 Then
                    Before = False
                    If Fronts Then
                        .Picture = UserForm1.back.Picture
                        Fronts = False
                    Else
                        .Picture = UserForm1.front.Picture
                        Fronts = True
                    End If
                End If
            Else
                .Width = .Width + 4
                If .Width > Card_Width Then
                    .Width = Card_Width
                    Flg = True
                End If
            End If
            .Left = Card_Left + (Card_Width - .Width) / 2 '①
            DoEvents
            Do
                Sleep 1
            Loop Until GetTickCount - Stime > 10
        Loop
    End With
        
End Sub


'標準モジュールここまで
'ここからはフォームモジュール

Private Sub CommandButton1_Click()

    CommandButton1.Enabled = False
    
    Turn
    
    CommandButton1.Enabled = True

End Sub

Private Sub UserForm_Initialize()

    Me.Height = 215

    With card
        .Top = 18
        .Left = Card_Left
    End With

    Fronts = False

End Sub

それでは最初から見ていきます。

まずは、APIの宣言と変数及び定数の宣言です。
APIはSleep関数とGetTickCount関数の2種類です。これはループ処理中の同期を取るために使います。今までのゲーム作成などでも使ってきたAPIなので、ここでは詳しい説明はしません。

次に変数ですが、これも2つ、Publicを使って宣言しています。
Stimeは同期処理のために使います。一方、Frontsはカードが今現在表向きなのか、それとも裏向きなのか、それを管理するために使います。

定数も2つです。こちらは必ずしも定義しなくてもいいのですが、後からコードを修正するときの手間を考えて宣言しています。カードの横位置(Left)と幅(Width)の規定値を設定しています。

その下、Turnという名前のプロシージャが、実際にカードのめくれる動作を処理するプロシージャです。
このプロシージャがユーザーフォーム上のコマンドボタンから呼び出されると、ユーザーフォーム上のカードが裏返ります。

そして、このプロシージャの中でも変数を宣言していますね。こちらも2つ宣言されています。Beforeという変数は、今現在の状態が、めくり作業の前半か後半かを管理します。しかしなぜ、前半と後半を分けて処理しなければいけないのでしょう。
先ほども書いたように、カードがめくれていく過程では、始めはカードの幅が狭くなっていきます。しかし後半はカードの幅が広がっていくようになります。今現在カードの幅を狭めるべきなのか、もしくは広げるべきなのか、これを変数Beforeで判断して処理するわけです。

もうひとつの変数Flgは、ループ処理から抜けるためのフラグの役割を担います。


さて、実際の処理の中身です。
変数Beforeが、今カードがどのような状態かを管理するのでしたね。まずはプロシージャの開始と同時に、この変数にTrueを代入しておきます。変数BeforeTrueのときには、めくり動作の前半だというわけです。

もし、めくり動作の前半ならば、カードを表すイメージコントロールの幅、つまりWidthをマイナスして狭くしていきます。一定の幅まで狭まったら、今度は変数BeforeFalseを設定して、カードがめくれたあとの動作に移ります。このときにカードの画像を同時に切り替えているのがポイントです。
カードがめくれたあとは、逆に幅を広げていきます。ここでも、一定の幅まで広がったら、ループ処理を抜けるようにしておきます。

今回は①で示す部分が最も難解な部分になると思います。
ここでは、カードの横位置(Left)を設定しています。定数をうまく利用することで、できる限り簡単に処理できるようにしています。

本来のカードの横位置がCard_Leftです。止まっているときのカードの横位置ですね。そしてCard_Widthが本来のカードの幅です。
めくり動作中には、カードの幅が常に変更され続けますよね。これをただ単に幅の変更だけにしてしまうと、横位置が変更されないので左に寄っていってしまいます。

353.gif

    ▼

354.gif

    ▼

355.gif

どうですか? ただ横幅(Width)を変更するだけでは、幅が狭くなっていくだけなので左に寄っていってしまうのです。

カードが中心を軸にして回転しているように見せるためには、常にカードの中心を求めて横位置を修正しなければいけません。①の部分のコードでは、それをやっているのです。

.Left = Card_Left + (Card_Width - .Width) / 2

本来の幅から、現在の幅を引けば、今どれくらい幅が狭まったかがわかります。もし幅が10ポイント狭まっていたなら、中心を軸に考えるので、半分の5ポイント移動させればいいことになります。少しわかりにくいかもしれませんが、よーく式を見て考えてみてくださいね。


■まとめ

カードゲームは、激しく動くアクションゲームなどと比べると、どうしても地味な印象になりがちです。カードがめくれるという単純な演出でも、その効果は非常に大きいものとなります。

今回の処理で注意しなければならないのは、コントロールのWidthプロパティを設定するときです。
コントロールの幅を表すWidthプロパティや、高さを表すHeightプロパティなど、幅を定義するプロパティにはマイナスの数値を設定できないので注意してください。
もしマイナスの数値を設定しようとすると、エラーが起きて処理が止まってしまいます。これはどんなコントロールであっても共通する仕様です。幅を表すプロパティにはマイナスの数値を設定できないと覚えておきましょう。

カードをめくる処理自体は、中心を軸にして横位置を調整する、というところさえ理解できれば、それほど難しいものではないと思います。サンプルを作成しておきましたのでそちらも参考に。


サンプルダウンロード ⇒ コチラよりダウンロードできます。(別館)



■格言

プロパティを有効に利用する
カードめくりでは中心を考えて横位置を調整


PictureSizeModeをキチンと設定しておかないとうまくいきません。
関連記事






Comment

Name
E-mail
URL
Comment
Pass  *
Secret? (管理者にだけ表示)

メールフォーム

影斬に物申すという方はこちら

名前 :
メール:
件名 :
本文 :

可能な限り要望には応えますが、必ず返信や回答ができることを、保障するものではありません。
ご了承ください。

Chapters

コンテンツ一覧


■Chapter 一覧■
    全てのChapterの一覧です。
    直接アクセスしたい方はこちらをご利用下さい。

    Chapter.1 [ 知っておくべき心得 ]
    Chapter.2 [ Excelってなんだろう ]
    Chapter.3 [ Excelの基本画面 ]
    Chapter.4 [ VBAとは? ]
    Chapter.5 [ モジュールについて ]
    Chapter.6 [ 変数 ]
    Chapter.7 [ 変数の型と宣言 ]
    Chapter.8 [ プロシージャとスコープ ]
    Chapter.9 [ ゲームつくる様々な手法 ]
    Chapter.10 [ ユーザーフォーム ]
    Chapter.11 [ プロパティウィンドウ ]
    Chapter.12 [ 乱数 ]
    Chapter.13 [ 条件分岐 ]
    Chapter.14 [ ゲーム画面のデザイン ]
    Chapter.15 [ コード記述の基本作法 ]
    Chapter.16 [ じゃんけんゲーム:1 名前をつける ]
    Chapter.17 [ じゃんけんゲーム:2 フォームの起動 ]
    Chapter.18 [ じゃんけんゲーム:3 乱数の種 ]
    Chapter.19 [ じゃんけんゲーム:4 イベント ]
    Chapter.20 [ じゃんけんゲーム:5 引数 ]
    Chapter.21 [ じゃんけんゲーム:6 役判定 ]
    Chapter.22 [ じゃんけんゲーム:7 予測と制限 ]
    Chapter.23 [ Withステートメント ]
    Chapter.24 [ 画像を表示させる ]
    Chapter.25 [ 画像表示の発展形 ]
    Chapter.26 [ 繰り返し処理 For文 ]
    Chapter.27 [ 繰り返し処理 Do~Loop文 ]
    Chapter.28 [ Exitステートメント ]
    Chapter.29 [ フォーム上の位置情報 ]
    Chapter.30 [ API基礎知識 ]
    Chapter.31 [ API補足知識 ]
    Chapter.32 [ メインループを考える ]
    Chapter.33 [ 同期処理の概念 ]
    Chapter.34 [ 移動処理その1:画面設定と考え方 ]
    Chapter.35 [ 移動処理その2:DoEvents ]
    Chapter.36 [ 移動処理その3:キー入力判定API ]
    Chapter.37 [ 条件分岐のさらなる探求 Select Case ]
    Chapter.38 [ アニメーション ]
    Chapter.39 [ 配列変数 ]
    Chapter.40 [ ゲームの初期化 ]
    Chapter.41 [ シューティングゲーム1:ゲーム設計 ]
    Chapter.42 [ シューティングゲーム2:メインプロセス ]
    Chapter.43 [ シューティングゲーム3:構造体 ]
    Chapter.44 [ シューティングゲーム4:定数 ]
    Chapter.45 [ シューティングゲーム5:プレイヤーキャラクター ]
    Chapter.46 [ シューティングゲーム6:ショットを撃つ① ]
    Chapter.47 [ シューティングゲーム7:ショットを撃つ② ]
    Chapter.48 [ シューティングゲーム8:Mod演算子の活用 ]
    Chapter.49 [ シューティングゲーム9:敵キャラクター登場 ]
    Chapter.50 [ シューティングゲーム10:衝突判定 ]
    Chapter.51 [ シューティングゲーム11:衝突の実体 ]
    Chapter.52 [ シューティングゲーム12:敵の攻撃 ]
    Chapter.53 [ シューティングゲーム13:爆発エフェクト ]
    Chapter.54 [ シューティングゲーム14:残機数表示① ]
    Chapter.55 [ シューティングゲーム15:残機数表示② ]
    Chapter.56 [ シューティングゲーム16:スコアの表示 ]
    Chapter.57 [ シューティングゲーム17:タイトル画面 ]
    Chapter.58 [ シューティングゲーム18:ボスキャラクター ]
    Chapter.59 [ シューティングゲーム19:最後の仕上げへ ]
    Chapter.60 [ シューティングゲーム20:いよいよ完成STG ]
    Chapter.61 [ カードゲームで使えるめくり効果 ]
    Chapter.62 [ ラジアンと角度 ]
    Chapter.63 [ ラジアンの活用:円運動 ]
    Chapter.64 [ ラジアンの活用:任意の角度へ移動する ]
    Chapter.65 [ APIによるサウンド再生:基礎 ]
    Chapter.66 [ APIによるサウンド再生:MIDIと多重再生 ]
    Chapter.67 [ APIによるサウンド再生:MCIコマンドとループ再生 ]
    Chapter.68 [ Function プロシージャ ]
    Chapter.69 [ 値渡しと参照渡し ]
    Chapter.70 [ デバッグ1:イミディエイトウィンドウ ]
    Chapter.71 [ デバッグ2:ローカルウィンドウ ]
    Chapter.72 [ デバッグ3:コード実行の中断 ]
    Chapter.73 [ オブジェクトってなんだ ]
    Chapter.74 [ プロパティ・メソッド・イベント ]
    Chapter.75 [ オブジェクト変数 ]
    Chapter.76 [ オブジェクトとコレクション ]
    Chapter.77 [ 特殊な繰り返し:For Each ]
    Chapter.78 [ エラー処理 ]
    Chapter.79 [ On Error と GoTo文 ]
    Chapter.80 [ Resumeステートメント ]
    Chapter.81 [ バイトとビット ]
    Chapter.82 [ ウィンドウメッセージとイベント ]
    Chapter.83 [ 文字列の基礎 ]
    Chapter.84 [ 文字列操作① ]
    Chapter.85 [ 文字列操作② ]
    Chapter.86 [ タイピングゲーム1:仕様を決める ]
    Chapter.87 [ タイピングゲーム2:キー入力検知 ]
    Chapter.88 [ タイピングゲーム3:文字列照合 ]
    Chapter.89 [ タイピングゲーム4:判定関数 ]
    Chapter.90 [ タイピングゲーム5:ゲーム画面設計 ]
    Chapter.91 [ タイピングゲーム6:問題文のソート ]
    Chapter.92 [ タイピングゲーム7:動的配列 ]
    Chapter.93 [ タイピングゲーム8:キーダウンイベント ]
    Chapter.94 [ タイピングゲーム9:正打数の表示 ]
    Chapter.95 [ タイピングゲーム10:タイムの表示 ]
    Chapter.96 [ クリックゲーム1:イベントの種類 ]
    Chapter.97 [ クリックゲーム2:画面設計 ]
    Chapter.98 [ クリックゲーム3:クリック座標検知 ]
    Chapter.99 [ クリックゲーム4:キャラクター準備 ]
    Chapter.100 [ クリックゲーム5:キャラクターの配置 ]
    Chapter.101 [ クリックゲーム6:キャラクター移動とNot演算子 ]
    Chapter.102 [ クリックゲーム7:クリックのヒット判定 ]
    Chapter.103 [ クリックゲーム8:ヒットマークエフェクト ]
    Chapter.104 [ クリックゲーム9:サウンド処理の実装 ]
    Chapter.105 [ クリックゲーム10:マウスカーソルの変更 ]
    Chapter.106 [ ブロック崩しゲーム1:仕様と概要を決める ]
    Chapter.107 [ ブロック崩しゲーム2:基本概念の確認 ]
    Chapter.108 [ ブロック崩しゲーム3:ベクトルとは ]
    Chapter.109 [ ブロック崩しゲーム4:変数や定数の宣言 ]
    Chapter.110 [ ブロック崩しゲーム5:初期化処理の実装 ]
    Chapter.111 [ ブロック崩しゲーム6:ブロックの配置 ]
    Chapter.112 [ ブロック崩しゲーム7:根幹処理とバーの処理 ]
    Chapter.113 [ ブロック崩しゲーム8:線分と線分の交差を判定 ]
    Chapter.114 [ ブロック崩しゲーム9:線分同士の交点 ]
    Chapter.115 [ ブロック崩しゲーム10:ボールの処理 ]
    Chapter.116 [ ブロック崩しゲーム11:最終調整して完成へ ]
    Chapter.117 [ テキストファイル操作基礎 ]
    Chapter.118 [ テキストファイル操作:読み込み編 ]
    Chapter.119 [ テキストファイル操作:CSV読み込み編 ]
    Chapter.120 [ テキストファイル操作:様々な読込編 ]
    Chapter.121 [ テキストファイル操作:バイナリ編 ]
    Chapter.122 [ テキストファイル操作:暗号化編 ]
    Chapter.123 [ テキストファイル操作:復号化編 ]
    Chapter.124 [ クラスモジュールとは ]
    Chapter.125 [ クラスモジュール:メソッド編 ]
    Chapter.126 [ クラスモジュール:プロパティ編 ]
    Chapter.127 [ クラスモジュール:イベント拡張編 ]
    Chapter.128 [ クラスモジュール:イベント自作編 ]
    Chapter.129 [ APIによる描画処理1:ハンドル ]
    Chapter.130 [ APIによる描画処理2:デバイスコンテキスト ]
    Chapter.131 [ APIによる描画処理3:ペン オブジェクト ]
    Chapter.132 [ APIによる描画処理4:ブラシ オブジェクト ]
    Chapter.133 [ APIによる描画処理5:図形描画準備編 ]
    Chapter.134 [ APIによる描画処理6:図形描画実践編 ]
    Chapter.135 [ APIによる描画処理7:画像描画の仕組み編 ]
    Chapter.136 [ APIによる描画処理8:ビットブロック転送編 ]
    Chapter.137 [ APIによる描画処理9:ラスタオペレーション ]
    Chapter.138 [ APIによる描画処理10:マスク描画 概念編 ]
    Chapter.139 [ APIによる描画処理11:マスク描画 実践編 ]


    コードやVBAに関する質問などはサポート掲示板(別館)までお気軽にどうぞ。




fc2 seotool Excel VBA ゲーム プログラミング 講座

Counter

twitter


Shadow BBS - 影掲示板

VBA 関連書籍



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。