ラベル ゲーム開発 の投稿を表示しています。 すべての投稿を表示
ラベル ゲーム開発 の投稿を表示しています。 すべての投稿を表示

2014年12月22日月曜日

Unityオブジェクトの子要素を取得する

プレファブはsensya>housin>anaの入れ子の親子関係になっています。
pXXはゲームオブジェクトです。

子要素の取得

        p1 = getJittai (presen);//一つのプレファブから二つの戦車の実態を作成
        p2 = getJittai (presen);
        //p1a = GameObject.Find ("Ana");これだとどちらの戦車の砲身だかわからない
        p1a = p1.transform.FindChild ("Housin").transform.FindChild("Ana").gameObject;


    }
//プレファブから実体を作成して画面に配置
    public GameObject getJittai(GameObject prefab){
        GameObject gameObj = Instantiate (prefabas GameObject;
        Transform tran = gameObj.transform;
        tran.position = this.transform.position;
        return gameObj;
    }

親要素の取得は以下です。
gameObject.transform.parent.gameObject
親は一つしかないので名前を指定する必要はありません。

2014年12月16日火曜日

移動に合わせてキャラクターの向きを8方向に変えるサンプル

矢印キー入力でプレイヤーの向きを変える方法。
右矢印キーと下矢印キーを同時押しすることで斜め右下に向きを変えます。
計算式はラジアン*180/円周率です。

以下サンプルソース

public void Update()  
//矢印キーでの移動
Vector3 vc1 = new Vector3 (Input.GetAxisRaw("Horizontal"), 0Input.GetAxisRaw ("Vertical"));
//角度を算出
  float kakudo = Mathf.Atan2(Input.GetAxisRaw("Horizontal"),Input.GetAxisRaw("Vertical"))*180/Mathf.PI;
//移動        transform.rigidbody.velocity = vc1;
//向きを変える
        transform.rotation = Quaternion.Euler (0kakudo0);

2014年10月23日木曜日

Unityボタンでのジャンプ力の調整と空中での移動

アクションゲーム用のジャンプ制御を改良してみました。

  • ジャンプボタンを押しっぱなしでジャンプ力が増します。
  • 空中で左右へ移動できます
  • 二段ジャンプはできません。
  • 横移動して落下中もジャンプはできません。

接地判定は以下の記事を参考にしてください。
キャラクターコントロールクラスと地面判定の記事はこちら

以下がサンプルソースです。
public float speed =   9.0f;
public float jumpspeed = 5.0f;
private float JAMP_SPEED = 6.5f;
public float gravity = 9.0f;
private Vector3 idou =  new Vector3();
public void Start()
{
//kyo.jimen = false;//地面判定は自作しないと
}
public void Update()
{
//地面判定
if (kyo.jimen) { idou = new Vector3 (Input.GetAxis ("Horizontal"), 0, Input.GetAxisRaw ("Vertical"));
idou = transform.TransformDirection (idou);
idou *= speed;
if (Input.GetButton ("Jump")) {
idou.y = jumpspeed;
}

} else {//空中でも移動
idou.x = Input.GetAxis ("Horizontal") * speed;
if (Input.GetButton ("Jump")) {
jumpspeed= jumpspeed/2;
idou.y += jumpspeed;
}
}
idou.y -= gravity * Time.deltaTime;

rigidbody.velocity = idou;//直接加速度を設定すつ
}
//地面判定
void OnCollisionEnter(Collision collision)
{
kyo.jimen = true;
jumpspeed = JAMP_SPEED;

}
void OnCollisionExit(Collision collision)
{
kyo.jimen = false;
}

やっつけ仕事ですみません。操作性はゲームの要なので、まだまだ改良していく予定です。
シフトや論理演算を使うなど処理速度を改善できればと思います。

2014年10月19日日曜日

ゲームエンジンの比較まとめ

ゲームエンジン

自分はゲームエンジンにUnityを選びました。
理由は以下のとおりです。
  1. 情報量の多さ
  2. 統合開発環境
  3. マルチプラットフォーム
  4. 利用できる言語
  5. ネイティブプログラムの組み込み
 Unityは利用者数が多く、ほかのゲームエンジンの10倍以上の人口です。
そのため日本語の情報も多く、アセットストアを通じてプログラムや3Dモデルの開発者も数多くいます。
 アセットストアを通すことで様々な部品を利用することができ、素材を集めるのが楽になります。
 個人で3Dゲームを開発するならばUnity一択かもしれません。

2014年10月18日土曜日

Unity オブジェクトを移動させる方法色々

オブジェクトの移動にはtransform.positionを使う方法がありますが他にも


があります。

velocityはオブジェクトの速度を設定します。
AddForceはオブジェクトに力を加えます。
動かしてみると分かりますがvelocityは速度を直接指定しているので摩擦がかからずに一定速度になります。一方AddForceは地面では摩擦で動きが遅いですが、ジャンプさせると加速し続けます。

具体的な使用方法は以下のサンプルソースを参考にしてください。
リジットボディも必要です。
using UnityEngine;
using System.Collections;

public class Sousa : MonoBehaviour {

public float speed =   9.0f;
public float jumpspeed = 9.0f;
public float gravity = 20.0f;
private bool jimen = false;

private Vector3 idou =  new Vector3();

public void Start()
{
jimen = true;//地面判定は自作しないと
}

public void Update()
{
if (jimen)
{
idou = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxisRaw("Vertical"));
idou = transform.TransformDirection (idou);
idou *= speed;

if(Input.GetButton ( "Jump"))
{
idou.y = jumpspeed;
}
}
idou.y -= gravity * Time.deltaTime;
//transform.rigidbody.AddForce(moveDirection);//力を加えて移動
rigidbody.velocity = idou;//直接加速度を設定すつ


}
}

2014年7月13日日曜日

Unity failed to create 2D texture

7年前のvistaPCでUnityの環境構築をしてみました。

インストールはEXEを実行するだけなので簡単です。
Android用のAPKファイルをビルドするにも触ってればできてしまいます。
タッチイベントのテストは実機が必要です。unityリモートアプリを入れてつなげばOKです。

環境構築は楽勝かと思いきやアセットストアが表示されない

さっそくエラーが発生。
・以下コンソール
failed to create 2D texture
allocation 0x00000000 already registered @ C:/BuildAgent/work/d63dfc6385190b60/Runtime/GfxDevice/d3d11/TexturesD3D11.cpp:l466 size 6291456; now calling from C:/BuildAgent/work/d63dfc6385190b60/Runtime/GfxDevice/d3d11/TexturesD3D11.cpp:l466 size 3145728?

ダイレクトエックスの不具合だというのが見て取れますが、
ネットで検索をかけても解決方法が見つからない。
海外のQAを見る限りでは.Netフレームワークの更新だとか、DX11をインストールしなおすとかいろいろ出てきます。
自分は何となくUnityウインドウ上部DX11 on DX9をいう表示が気になって何を意味しているかを調べてみました。

解決策
グラボが対応しているDirect Xのバージョンで起動してみる。
以下起動パラメーター。
 -force-d3d9
 -force-d3d10
 -force-d3d11

とりあえずこれでアセットをダウンロードできます。
ブラウザからだと「Unityで開く」はなぜか使えません。
旧型GPUやVista環境だと苦労するかも?


2013年8月18日日曜日

スマホゲーム開発の注意点

ゲーム開発コスト

スマホのゲーム開発の注意点はUIかもしれない。
スマホにソフトウエアコントローラを実装してみましたがいまいちです。
文字入力のフリック入力やスワイプ入力のような新しい入力方法が現れるかも。
とはいえ物理入力装置がないだけでゲームジャンルが限られてしまいます。
磁気センサーなど各センサーを利用して、任天堂のような開拓が必要かもしれません。

2013年8月12日月曜日

ソフトウエアゲームコントローラーのサンプル

アクションゲームでは見えないコントローラーを作ってみましたが、RPGなどではボタンの表示が必要です。

ゲーム開発コントロールサンプル画像

今回はレイアウトファイルでコントローラーを作成してみました。

この場合はクリックイベントではなく、タッチイベントを使用します。

サーフェースビューでコントローラーを作成しても良いのですが、
一部GUIにスクロール機能を付けたかったため手抜きをしました。
できるだけコードは書きたくないので。。


ボタンを大きくすると、どうしてもゲーム画面が小さくなってしまいます。
しかし、綺麗なグラフィックを売りにするつもりはありませんので、
操作性を重視してコントローラーを大きめにしています。


サンプルソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/lay1"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:orientation="vertical" >

        <com.example.gametest2.GameView
            android:id="@+id/gameView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/lay_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="20"
        android:orientation="vertical" >

        <MultiAutoCompleteTextView
            android:id="@+id/multiAutoCompleteTextView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:text="MultiAutoCompleteTextView" >

            <requestFocus />
        </MultiAutoCompleteTextView>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/lay2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >

        <ScrollView
            android:id="@+id/scr1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/sute"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Status" />

            <Button
                android:id="@+id/aitemu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:layout_weight="1"
                android:text="Tool" />

            <Button
                android:id="@+id/sukiru"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="8dp"
                android:layout_weight="1"
                android:text="Skill" />

            <Button
                android:id="@+id/sisutemu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="System" />

        </LinearLayout>
        </ScrollView>

        <LinearLayout
            android:id="@+id/lay_jyuji"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal" >

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="0.50"
                android:orientation="vertical" >

                <Button
                    android:id="@+id/jyuuji7"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="○" />

                <Button
                    android:id="@+id/jyuuji4"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="←" />

                <Button
                    android:id="@+id/jyuuji1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="○" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="0.50"
                android:orientation="vertical" >

                <Button
                    android:id="@+id/jyuuji8"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="↑" />

                <Button
                    android:id="@+id/jyuuji5"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="□" />

                <Button
                    android:id="@+id/jyuuji2"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="↓" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="0.50"
                android:orientation="vertical" >

                <Button
                    android:id="@+id/jyuuji9"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="○" />

                <Button
                    android:id="@+id/jyuuji6"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="→" />

                <Button
                    android:id="@+id/jyuuji3"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="○" />

            </LinearLayout>

            <LinearLayout
                android:id="@+id/lay_atk"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="15dp"
                android:orientation="vertical" >

                <Button
                    android:id="@+id/houkou"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="⇔" />

                <Button
                    android:id="@+id/kougeki"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="ATK" />
                
                <!--Android 縦方向に均等に  -->
            </LinearLayout>
        </LinearLayout>



    </LinearLayout>

</LinearLayout>



2013年6月23日日曜日

ANDROIDのゲーム開発について

以前、アクションゲームのサンプルを作成して公開しましたが、まだ色々と修正が必要なようです。
アクションゲームサンプルの記事はこちら

ゲームには最低二つのスレッドがあります。
・ボタン入力用のスレッド
・描画処理用のスレッド

サンプルではボタン入力用のスレッドから直接キャラクターを動かしてしまっています。
ボタン入力用のスレッドはソフトウエアゲームコントローラ機能の処理行い、それに応じて共通資源のフラグを立てるだけにするほうがよさそうです。

描画処理用のスレッドは60fpsで描画されるように動作しています。
内部的な処理速度に偏りがあっても時間内に処理できれば速度は均一になります。
各計算を処理後に描画処理行います。

ゲームコントローラーについて

タッチパネルで操作しやすいソフトウエアコントローラーが必要。
画面解像度によって感度を調節する必要があり。
アクションゲームは物理コントローラー並みの扱いやすさが必要。

カメラアングルについて

各キャラクターの位置から適切なアングルを計算、または固定。

解像度について

機種によって解像度が違うので補正が必要。

ツールアプリと違い、開発コストが。。
完成するまでどのくらいかかるやら。。

2013年6月20日木曜日

アクションゲームサンプルコード


アクションゲームサンプルコード を公開します。

サンプルの実行画像

ソースとAPKはこちら


ボタンは見えませんが、画面の左半分を触るとキャラクターが左右に移動します。
画面右側を押すとジャンプします。
地面から落ちると、落ち続けます・・・・・

大雑把な雛形です。自分で設計したものなので効率的であるかはわかりません。
すべてJAVAで書かれています。
キャラクターや障害物を増やすにはデータ作成管理クラスが必要になります。
戻るボタンで終了します。

大まかな構造としては

タッチスレッドでパラメーターを変更。
・移動ならXをプラス
・ジャンプなら慣性のFをプラス

描画スレッドで位置や慣性を計算。
・障害物に触れていないなら空中
・空中なら落下



//ゲーム画面呼び出しクラス
public class MainActivity   extends Activity {
private GameView gameView;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        
gameView=new GameView(this);
setContentView(gameView);

}    
}

//画面クラス
public class GameView extends SurfaceView{
 private GameViewCallBack cb;
 private long time;

 public GameView(Context context) {
     super(context);
     SurfaceHolder holder = getHolder();
     cb = new GameViewCallBack();
     cb.setContext(context);
     holder.addCallback(cb);

 }
@Override
public boolean onTouchEvent(MotionEvent event) {


//連続タップ防止 
if(time+100<System.currentTimeMillis()){

time=System.currentTimeMillis();

float x = event.getX(); // X座標を取得
       float y = event.getY(); // Y座標を取得  
cb.setTouchPoint( x , y );



}
return true;
}
   // キーイベント発生時、呼び出されます
   @Override
   public boolean dispatchKeyEvent(KeyEvent event) {
       if (event.getAction() == KeyEvent.ACTION_UP) { // キーが離された時
           switch (event.getKeyCode()) {
           case KeyEvent.KEYCODE_HOME: 
              
               
           case KeyEvent.KEYCODE_BACK:
            cb.teisi();
            return false;
           default:
           }
       }
       return super.dispatchKeyEvent(event);
   }
}


//描画スレッド
public class GameViewCallBack implements SurfaceHolder.Callback, Runnable{

private SurfaceHolder holder = null;
private Thread thread = null;
//スレッドの管理
private boolean isAttached = true;
//コントローラー
private Controler cl;
//プレイヤー情報
private PlayCharcter pc;
//障害物
private Syougai sg;

      private float w, h;
      //中心位置
      private int   cx, cy;
private Context context;
      
      public void setContext(Context rr){
     context=rr;
      }
      
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

this.w = width;
this.h = height;
this.cx=(int)(w*0.50);
this.cy=(int)(h*0.50);
cl=new Controler(width, height);
pc =new PlayCharcter(cx,cy,context);
//左、下、幅、高さ
sg = new Syougai(50,(int) (h-100),1000,100);

}

@Override
public void surfaceCreated(SurfaceHolder holder) {

this.holder = holder;
thread = new Thread(this);
thread.start(); 
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
      isAttached = false;
      thread = null;
}

private long t1 = 0, t2 = 0; 

@Override
public void run() {
while( isAttached ){
t1 = System.currentTimeMillis();
hyouji();
atari();
byouga();
// スリープ 60fpsの確保
t2 = System.currentTimeMillis();
if(t2 - t1 < 16){ 
try {
Thread.sleep(16 - (t2 - t1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void teisi(){
isAttached=false;
thread = null;
 
}
//コントロール
public void setTouchPoint(float x, float y) {

int tmp =cl.getTouthActionProt((int)x,(int)y);
if(tmp==100){
pc.btnAction(1);
}else{
pc.moveAction(tmp);
}
}


public void byouga(){

//描画処理を開始
Canvas canvas = holder.lockCanvas();
if(canvas==null){
return;
}
//背景
canvas.drawColor(0,PorterDuff.Mode.CLEAR );
Paint paint = new Paint();//かり

paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawRect(new RectF(sg.l, sg.t, sg.r, sg.b), paint);

pc.byouga(canvas, cx, cy);
//描画処理を終了
holder.unlockCanvasAndPost(canvas);
}
//各データの計算 キャラの状態 あたり判定
private void atari(){
//慣性移動計算 障害物への移動適応
pc.kansei();
//キャラと足場が接触 pc.y仮
if(cx>=sg.l && cx<=sg.r && pc.y>=sg.t&&cy<=sg.b){
//if(pc.x>=sg.l && pc.x<=sg.r && pc.y>=sg.t&&pc.y<=sg.b){
pc.s=0;//立ち
pc.y=sg.t;//位置補正 めり込み防止
}else{//こちらへ来ないとジャンプできない
pc.s=-1;//浮び
}

sg.sukuro(pc.x,pc.y);
}
//表示領域に存在する? hFLをたてる
private void hyouji(){
sg.hFL=true;

}

}

//コントローラーくらす
public class Controler {

private int w,h,ox=0,oy=0;
private int hidari,migi,a,j,m;
public Controler(int ww,int hh){
w=ww;
h=hh;
j= (int) (w*0.75);
a= (int) (w*0.50);
migi= (int) (w*0.25);
//hidari= (int) (w*0.75);
}
public int getTouthActionProt(int xx,int yy){
int action=0;
if(xx>=j){
action=100;
}else if(xx>=a){
action =200;
}else if(xx>=migi){
action=20;
}else{
action=-20;
}
return action;
}
}

//キャラクタークラス

public  class PlayCharcter {

private Paint paint;
//慣性 重力
private int kt=0,ky=0,kp=0,kf=0;
//座標を管理
public int x=0,y=0,w=0,h=0;//当たり判定計算用
public Bitmap gazo;
public int s=-1;//状態 0 地上 -1 空中
private Context context;
//コンストラクタ
public PlayCharcter(int xx,int yy,Context c){
paint = new Paint();
        paint.setColor(Color.WHITE);
        x=xx;//初期位置
        y=yy;       
        
       
        context =c;
        gazo = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
        
        w=gazo.getWidth();
        h=gazo.getHeight();
        
        y-=h;
        
        
}
public void byouga(Canvas canvas,int xx,int yy){
canvas.drawBitmap(gazo, xx, yy-h, null);
}
//右手操作
public void btnAction(int aa){
if(s==0){
kf=7;//ジャンプの実験
y-=3;
}
}
//左手操作
public void moveAction(int aa){
x+=aa;
}
public void kansei(){

if(s==-1){
kt=ky;
ky+=(ky-kp)+kf;
kp=kt;
kf=-1;
//慣性を適応
y-=ky;
}else{
ky=0;
kp=0;
}
}

}

//障害物くらす
public class Syougai {
public int x,y,w,h,t,b,r,l,T,B,R,L;
//表示フラグ
public boolean hFL=false;
private Paint paint;
public Syougai(int xx,int yy,int ww,int hh){
x=xx;
y=yy;
w=ww;
h=hh;
//絶対座標
T=y;
L=x;
R=x+w;
B=y+h;
t=y;
l=x;
r=x+w;
b=y+h;
paint = new Paint();
        paint.setColor(Color.GREEN);
}
//プレイヤーの移動情報を適応
public void sukuro(int xx,int yy){
t=T-yy;
l=L-xx;
r=R-xx;
b=B-yy;

}
//描画処理
public void byouga(Canvas canvas){
canvas.drawRect(new RectF(l, t, r, b), paint);
}
}

権限は必要ありません。APILEVELは9以上

アクションゲームさえ作れれば大抵のゲームは作れると思います。
設計書は再設計後に記事にします。