リスティーゲーム制作

リスティーゲーム制作

DXライブラリを使って、C言語でゲーム作りを書いています。

趣味でゲームを制作しています。
ソースコードは公開しますが、非常に古い技術で、参考にもなりません。
低レベルの技術で、無知識を絞って作っています。

作者はアホなので、致命的なミスをしているかもしれないです。
使う人はいないと思いますが、素材、ソースコード等は自由に使って、改造もご自由に。
ソースコードにて、使用になった上で生じた損害に対して、私は一切の責任を負いません。




Amebaでブログを始めよう!
もう、12月半ば・・・・・
あ、ゲーム作りサボってます・・・・
少し息抜きで、ピグブレイブをやっています。(いつもですが・・・)

こんな感じでもできるのですよ?みたいな感じで動画アップしてみました。
ファニアスLv60、ベレッタLv60、シャルルLv50
もっと良いやり方あるかもしれないです。


戦うコックさんです。結構行けます!(仲間が助けてもらって、いるだけです)
後から気付いたのですが、ミトンレベル1でした・・・・・・


大型アップデート前です。
レベル20のときの単独モンクで、あまりうまくないです。


おまけで、過去にこんなゲームを自作していました。
Devcppで作っていました。
グラフィック、BGM、SE使わせてもらいました・・・・・



本命はシューティングRPGを作りたいのですが、技術とやる気が無いので
今は止まっています・・・

RPGつクールの素材を使っています。
同じくDevcppで作りました。



ゲーム作り・・・・
別のゲームが作りたいな・・・・

そんな気がしています。
ごめんなさいね。

万策尽きたーーー
総集編みたいですまないです。

ここまで見てくれてありがとう!

ハッチは以前出せましたが、今回は砲台です。
砲台も基本、空中の敵と変わりませんが

ただ一つ注意ですが、地形のスクロールと同じ向き
速さで移動しないと、見た目が変になりますね。

地形を歩く、移動する敵はその限りではないです。

地形がどんなスピードで、動いているかを知る必要があり
scroll.cppでスクロールの速さの変数を宣言しています。

int scroll_speed;

この変数で、ボスがてた時はスクロールを停止したり
ステージによって、スクロールのスピードを変えたり出来ます。
以前はscroll_x --;でスクロールの変数のデクリメントしていましたが、
今回は scroll_x -= scroll_speed;に変更しました。
//-------------地形スクロール-----------------------------------------------
void scroll_bg0(void) {
    for (int y = 0; y < 30; y++) {//画面y座標
        for (int x = -1; x < 41; x++) {//画面x座標
            //マップチップ表示
            DrawRotaGraph(x*20 + scroll_x+10 , y * 20+10, 1, 0, bg_graph_map1[map[y][x + scroll_i]], TRUE,FALSE);
        }
    }
    if (scroll_x < 0) {//スクロールx座標が0になったか?
        scroll_x = 20;//マップチップの大きさに初期化
        scroll_i++;//次の表示されるマップの位置更新
        if (scroll_i > 1024-41) {//ステージの終が来たらループさせるようにする
            scroll_i = 41;
        }
    }
    scroll_x -= scroll_speed;//変数の値分ス
クロールをする
}

地形のスクロールの速度と合わせて、砲台やハッチの動く方向も
同じにしなくてはいけませんので、横スクロール(いずれは上下無限ループさせるつもり)
一定の速度でしたら、単純にene->cx -= scroll_speed;で計算をしています。

ここから本題の砲台ですが、あらかじめ決まっているグラフィックを
角度に応じて、変化させているだけのものです。
敵弾も16方向にすれば、それらしく見えるのですが・・・・
面倒だったのでやめました。


砲台のコードは11,12で分けて、グラフィックを表示させ
下向きでのキャラクタは、180度グラフィックを回転させています。

//----------砲台---11の時下 12の時上------------------------------------
void enemy_type011(ENEMY_CHR *ene) {
    int kakudo;
    ene->dir = enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy);
    kakudo = abs(int(ene->dir * 180 / PI));
    ene->cx -= scroll_speed;
    if (ene->next_shot_c < 0) {
        set1_enemy(ene, 1000,ene->dir);
        ene->next_shot_c = ene->next_shot;
    }
    ene->next_shot_c--;
    if (ene->code == 11) {//下から上
        switch ((kakudo) / 22) {
        case 0:ene->anime = 48; break;
        case 1:ene->anime = 47; break;
        case 2:ene->anime = 46; break;
        case 3:ene->anime = 45; break;
        case 4:ene->anime = 44; break;
        case 5:ene->anime = 43; break;
        case 6:ene->anime = 42; break;
        case 7:ene->anime = 41; break;
        case 8:ene->anime = 40; break;
        default:ene->anime = 44; break;
        }
        sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime], 0, 0, 3);
    }
    else {//上から下
        switch ((kakudo) / 22) {
        case 0:ene->anime = 40; break;
        case 1:ene->anime = 41; break;
        case 2:ene->anime = 42; break;
        case 3:ene->anime = 43; break;
        case 4:ene->anime = 44; break;
        case 5:ene->anime = 45; break;
        case 6:ene->anime = 46; break;
        case 7:ene->anime = 47; break;
        case 8:ene->anime = 48; break;
        default:ene->anime = 44; break;
        }
        sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1,PI, enemy_graph[ene->anime], 0, 0, 3);
    }
    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -20){
        ene->code = 0;
        ene->atari = 0;
    }
}


砲台とハッチ、ハッチからの敵を出してみました。
こんな感じですが、どこかのゲームみたいですねw


地上のキャラは、地形からあまり離れず、逆にめり込まない程度にしないと大変です。
こうして地上の敵を出すときは、マップエディターで配置をエディットすると
ものすごく簡単に配置できます。

しかし配置すつ敵と、マップチップとの関連をつけなければいけません。

そういえばかなり前に、マップエディタで敵を配置させると書いたねw
僕はあまり注釈を入れないので、以前自分のプログラムも
何をしているのか、わからなくなること多々あります・・・

趣味でやっているので、まあいいか程度ですww
ブログの更新が遅れたのは、ピグブレイブでレベルを上げていたので
サボっていました。

25日に改変?されましたが、やはりバグがありますね・・・
マウスで動かないとか、かなり致命的ですが
おそらく仲間キャラの初期状態が、イベント戦で変数が自分の場所に入ってしまい
動かなくなるのかな?と勝手に思っていますが運営じゃないので分かりません。

これでも過去にビジネスソフト会社にいたので、バグ発生の時は袋小路に入ってしまった
ようになりました・・・・・思い出したくもないですw

ここまで見てくれてありがとう!








補助攻撃を作りたいと思いまして、地形に有利である
地形を這うミサイルを作りました。

どこかのシューティングゲームであるのもと、同じ機能を果たしますw

自機のミサイルを装備しているかの、構造体メンバを追加しました。
typedef struct {
    double cx;
    double cy;
    int x_graph_size;
    int y_graph_size;
    int score;
    int shot_type;
    int missile_type;
    int atk;
} MY_CHR;

今の段階では、テストでミサイルを出していますので
自機の初期化では、ミサイルが出るように、ミサイルの値を入れています

あるゲームなどで、ゲーム中ポーズをしてコマンドを入れると
フル装備になる時は、こういった変数に値を入れれば実現できますね。

アドレスもわかっていれば、チー○コードでフル装備もできますw

//--------自機の初期化-----------------------------------------------------
void init_chr(void) {
    chr.cx = 400;
    chr.cy = 300;
    chr.score = 0;
    chr.shot_type = 0;
    chr.missile_type = 20;
    chr.atk = 1;
}

ミサイルは、時期のショットと同じ配列で管理しますので
ショットの構造体メンバで、ミサイルが地形に着弾後、這うための
フラグの為の変数を追加しました。

typedef struct {
    int code;
    double cx;
    double cy;
    double cx_w;
    double cy_w;
    double x_hit_size;
    double y_hit_size;
    double gr_x_size;
    double gr_y_size;
    double dir;
    double dir_w;
    int shot_anime;
    int shot_anime_c;
    int missile_impact;
    int enemy_lockon;
    int shot_homing;
    int atk;
    } MY_SHOT;

ミサイルはミサイルで、ある程度連射するように
ショットと同じ感じで、次のミサイルが出るように別で変数を持っています。
shot.cppでの宣言。

int missile_button_on;
int missile_button_count;

ミサイルのセットと、動く部分はプロトタイプで宣言しています。

void set_missile(void);
void move_missile(MY_SHOT *sho);



ミサイルのセットも、ショットと同じで押されたボタンは、今のところショットと共通です。

//----------ショットセット--------------------------------------------------
void set_shot(void) {
    if (get_button() == 16) {
        switch (chr.shot_type){
            case 0:set_beem(); break;//ビームセット
            case 1:set_3way(); break;//3方向セット
            case 2:set_laser(); break;//レーザーセット
            case 3:set_bomb(); break;//ボムセット
            case 4:set_homing(); break;//ホーミングセット
        }
        switch (chr.missile_type){
            case 20:set_missile();break;
        }

    }
    shot_button_count--;
    missile_button_count--;
}

ミサイルはショットと同じ配列で管理しますので、配列の30番目から格納され
ショットは、最高30個までしか出せないことになります。
リスト構造を使うと、こういった制限はなくなりますね。

2連射するようになってますが、パワーアップに伴いある程度
ミサイルを出す数を増やすものいいですね。

ミサイルの攻撃の強さは5にしています。

//----------ミサイルセット--------------------------------------------------
void set_missile(void) {
    if (missile_button_count <= 0) {
        missile_button_count = 3;//連射のカウンタ初期化
        for (int i = 30; i < 32; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//ショットに空きはあるか?
                shot_init(sho, 20, chr.cx + 40, chr.cy, 15, 15,240, 0);
                sho->atk = 5;//ミサイルの威力
                break;
            }
        }
    }
}

ミサイル本体の動きですが、時期から発射されたときは、斜め前方下に
発射され、地形に到達したら、地形に沿って進み、障害物地形があると
地形は、登らずに消えてなくなります。

前回は配列の範囲が超えたら、超えないようにしていましたが
今回は範囲が超えた場合は、処理しないようにしました。

//壁に当たった時の処理
w_cx = int(sho->cx / 20);
w_cy = int(sho->cy / 20);
//配列の下限、上限以内で
if ((w_cx >= 0) && (w_cx <= 39) && (w_cy >= 0) && (w_cy <= 29)) {


一番重要なところは、下に当たり判定があるかを判断する場所です。

if (map[w_cy + 30 + 1][w_cx + scroll_i] >= 1) {

それに伴い、下に地形があるとき(着弾時後)は前に進むようにします
      sho->missile_impact = 1;
            sho->cx += 6;
            sho->dir = 0;
     }

再度地形が下にない場合は、真下に落ちるようにします。

  else {
            if (sho->missile_impact == 1) {
                sho->cy += 6;
                sho->dir = 90 * PI / 180;
            }
        }
 

全体はこんな感じになります。

//---------ミサイルの動き---------------------------------------------------
void move_missile(MY_SHOT *sho) {
    int w_cx, w_cy;
    if (sho->missile_impact == 0) {//自機から発射の状態
        sho->cx += 2;
        sho->cy += 6;
    }
    //壁に当たった時の処理
    w_cx = int(sho->cx / 20);
    w_cy = int(sho->cy / 20);
    //配列の下限、上限以内で
    if ((w_cx >= 0) && (w_cx <= 39) && (w_cy >= 0) && (w_cy <= 29)) {
        //下に壁があるか?
        if (map[w_cy + 30 + 1][w_cx + scroll_i] >= 1) {
            sho->missile_impact = 1;
            sho->cx += 6;
            sho->dir = 0;
        }
        else {
            if (sho->missile_impact == 1) {
                sho->cy += 6;
                sho->dir = 90 * PI / 180;
            }
        }
    }
    sp_set(sho->cx, sho->cy, 40, 40, 1, 1, sho->dir, chr_graph[30], 0, 0, 1);
    shot_hit(sho);
    //画面から消えたら0に戻す
    if ((sho->cx > 800) || (sho->cx < 0) || (sho->cy > 600) || (sho->cy < 0)) {
        sho->code = 0;
    }
}

本来は地形に着弾後、ミサイルの角度をなめらかに変えるといいですね。
ショットやミサイルのボタンも、コンフィグで割り当てれるように、将来的にしたいかな?

ミサイルの挙動は、グ○ディウスのノーマルミサイルと同じ感じになります。

実はこのプログラムは、以前僕が作ったグラ○ィウスもどきのものを
作って・・・作りかけでやめたのを、再度直しています。

前回のおかしな動画は、アニメキャラをボスに見立てて
遊びで作ったものです。

知らない間に1時間20分かかっていた・・・・・・
文章書くのが遅いので・・・・・


地形ができたので、今度は敵の地上物を出そうかと思いますが
別のことをするかもしれないです。

さて、ピグブレイブでもやり始めようかなw

ここまで見てくれてありがとう!
ヘッダーファイルです。shot.h

/**************************************
*                                                       *
*           自機ショットヘッダー              *
*                                                       *
*               Ver 1.11.23.13.07                  *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
**************************************/

typedef struct {
    int code;
    double cx;
    double cy;
    double cx_w;
    double cy_w;
    double x_hit_size;
    double y_hit_size;
    double gr_x_size;
    double gr_y_size;
    double dir;
    double dir_w;
    int shot_anime;
    int shot_anime_c;
    int missile_impact;
    int enemy_lockon;
    int shot_homing;
    int atk;
    } MY_SHOT;

const int SHOT_MAX = 100;



自機ショットの本体です。shot.cpp

/*************************************
*                                                       *
*           自機ショットプログラム           *
*                                                       *
*               Ver 1.11.23.13.07                  *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
**************************************/


#include <math.h>
#include <stdio.h>
#include "DxLib.h"
#include "shot.h"
#include "my_chr.h"
#include "enemy.h"



const double PI = 3.1415;
const double KAKUDO = 180;
int shot_button_on;
int shot_button_count;
int missile_button_on;
int missile_button_count;
int lasert_count;
int atari_num;
int homing_c;
int homing_enemy[10];

MY_SHOT shot[SHOT_MAX];

void set_shot(void);
void set_beem(void);
void set_3way(void);
void set_laser(void);
void set_bomb(void);
void set_homing(void);
void set_missile(void);


void move_shot(void);
void move_beem(MY_SHOT *sho);
void move_3way(MY_SHOT *sho);
void move_laser(MY_SHOT *sho);
void move_bomb(MY_SHOT *sho);
void move_homing(MY_SHOT *sho);
void move_missile(MY_SHOT *sho);


void shot_hit(MY_SHOT *sho);
void shot_init(MY_SHOT *sho,int code,double cx,double cy,double hit_x,double hit_y,double dir,int anime);
double next_shot_dir(MY_SHOT *sho, double);

extern int scroll_i;
extern int enemy_num;
extern MY_CHR chr;
extern ENEMY_CHR enemy[ENEMY_MAX];
extern unsigned short map[60][1024];
extern void sp_set(double cx, double cy, int gr_x_size, int gr_y_size, double sc_x, double sc_y, double ag, int g_han, int mir, int mo, int pr);
extern double enemy_dir(double, double, double, double);


extern int chr_graph[100];
extern int bomb_graph[8];
extern int get_button(void);
//----------ショットセット--------------------------------------------------
void set_shot(void) {
    if (get_button() == 16) {
        switch (chr.shot_type){
            case 0:set_beem(); break;//ビームセット
            case 1:set_3way(); break;//3方向セット
            case 2:set_laser(); break;//レーザーセット
            case 3:set_bomb(); break;//ボムセット
            case 4:set_homing(); break;//ホーミングセット
        }
        switch (chr.missile_type){
            case 20:set_missile();break;
        }
    }
    shot_button_count--;
    missile_button_count--;
}
//------------ビームセット----------------------------------------------------
void set_beem(void) {
    if (shot_button_count <= 0) {
        shot_button_count = 5;//連射のカウンタ初期化
        for (int i = 0; i < 10; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//ショットに空きはあるか?
                shot_init(sho, 1, chr.cx, chr.cy, 15, 10, 0, 0);
                break;
            }
        }
    }
}
//------------3方向ビームセット----------------------------------------------
void set_3way(void){
    if (shot_button_count <= 0) {
        shot_button_count = 5;
        //前方向
        for (int i = 0; i <= 9; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {
                shot_init(sho, 2, chr.cx+40, chr.cy, 10, 10,180, 0);
                break;
            }
        }
        //上方向
        for (int i = 10; i <= 19; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {
                shot_init(sho, 2, chr.cx + 40, chr.cy, 10, 10, 135, 0);
                break;
            }
        }
        //下方向
        for (int i = 20; i <= 29; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {
                shot_init(sho, 2, chr.cx + 40, chr.cy, 10, 10, 225, 0);
                break;
            }
        }
    }
}
//----------レーザーセット--------------------------------------------------
void set_laser(void) {
    if (shot_button_count <= 0) {//レーザー発射できるか?
        shot_button_count = 2;//次のレーザーのカウンタ
        for (int i = 0; i < 20; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//レーザーの空きはあるか?
                shot_init(sho, 3, chr.cx + 40, chr.cy, 20, 6, 0, 0);
                break;
            }
        }
        lasert_count++;//レーザーの長さを足している
        if (lasert_count >= 20) {//20個レーザーが出たか?
            shot_button_count = 40;//次回の発射まで40カウンタ時間を空ける
            lasert_count = 0;//レーザーの長さクリア
        }
    }
}
//----------ボムセット------------------------------------------------------
void set_bomb(void) {
    if (shot_button_count <= 0) {
        shot_button_count = 5;//連射のカウンタ初期化
        for (int i = 0; i < 5; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//ショットに空きはあるか?
                shot_init(sho, 4, chr.cx + 40, chr.cy, 15, 10, 0, 0);
                break;
            }
        }
    }
}
//----------ホーミングセット-----------------------------------------------
void set_homing(void) {
    if (shot_button_count <= 0) {
        shot_button_count = 5;//連射のカウンタ初期化
        for (int i = 0; i < 10; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//ショットに空きはあるか?
                shot_init(sho, 6, chr.cx + 40, chr.cy, 10, 10,180, 0);
                //break;
            }
        }
    }
}
//----------ミサイルセット--------------------------------------------------
void set_missile(void) {
    if (missile_button_count <= 0) {
        missile_button_count = 3;//連射のカウンタ初期化
        for (int i = 30; i < 32; i++) {
            MY_SHOT *sho = &shot[i];
            if (sho->code == 0) {//ショットに空きはあるか?
                shot_init(sho, 20, chr.cx + 40, chr.cy, 15, 15,240, 0);
                sho->atk = 5;//ミサイルの威力
                break;
            }
        }
    }

}
//----------ショット初期化--------------------------------------------------
void shot_init(MY_SHOT *sho,int code, double cx, double cy, double hit_x, double hit_y, double kakudo, int anime) {
    sho->code = code;//ショットコード入れる
    sho->cx = cx;//自機から弾が出るようにx座標セット
    sho->cy = cy;//自機から弾が出るようにy座標セット
    sho->x_hit_size = hit_x;//当たり判定x方向
    sho->y_hit_size = hit_y;//当たり判定y方向
    sho->dir= (kakudo - KAKUDO) * PI / 180;//角度
    sho->shot_anime = anime;//アニメ
    sho->shot_anime_c = 0;//アニメーションのカウンタ
    sho->missile_impact = 0;
    sho->enemy_lockon = 0;
    sho->shot_homing = 0;
    sho->atk = 1;
}
//----------beemの振り分け--------------------------------------------------
void move_shot(void){
    atari_num = 0;
    for (int i = 0; i < SHOT_MAX; i++) {
        MY_SHOT *sho = &shot[i];
        switch (sho->code) {
            case 1:move_beem(sho); break;
            case 2:move_3way(sho); break;
            case 3:move_laser(sho); break;
            case 4:
            case 5:move_bomb(sho); break;
            case 6:move_homing(sho); break;
            case 20:move_missile(sho); break;
        }
    }
}
//----------beemの動き------------------------------------------------------
void move_beem(MY_SHOT *sho) {
    sho->cx += 12;
    sp_set(sho->cx,sho->cy, 40, 40, 1, 1, 0,chr_graph[20],0 ,0, 1);
    shot_hit(sho);
    //画面から消えたら0に戻す
    if (sho->cx > 800) {
        sho->code = 0;
    }
}
//----------3wayの動き------------------------------------------------------
void move_3way(MY_SHOT *sho) {
    sho->cx += cos(sho->dir) * 12;
    sho->cy += sin(sho->dir) * 12;
    sp_set(sho->cx, sho->cy, 40, 40, 1, 1, sho->dir, chr_graph[21], 0, 0, 1);
    shot_hit(sho);
    //画面から消えたら0に戻す
    if( (sho->cx > 840) || (sho->cx <-40) || (sho->cy > 640) || (sho->cy < -40)) {
        sho->code = 0;
    }
}
//----------レーザーの動き------------------------------------------------------
void move_laser(MY_SHOT *sho) {
    sho->cx += 20;
    sho->cy = chr.cy;//自機のy座標でワインダーさせる
    sp_set(sho->cx, sho->cy, 40, 40, 1, 1, sho->dir, chr_graph[22], 0, 0, 1);
    shot_hit(sho);
    //画面から消えたら0に戻す
    if (sho->cx > 800) {
        sho->code = 0;
    }
}
//----------ボムの動き------------------------------------------------------
void move_bomb(MY_SHOT *sho) {
    if (sho->code == 4) {
        sho->cx += 10;
        sp_set(sho->cx, sho->cy, 40, 40, 1, 1, 0, chr_graph[23], 0, 0, 1);
    }
    else {
        if (sho->shot_anime_c == 0) {
            sho->x_hit_size = 15;
            sho->y_hit_size = 15;
            sho->shot_anime = 0;
        }
        if (sho->shot_anime_c == 4) {
            sho->x_hit_size = 28;
            sho->y_hit_size = 28;
            sho->shot_anime = 1;
        }
        if (sho->shot_anime_c == 8) {
            sho->x_hit_size = 32;
            sho->y_hit_size = 32;
            sho->shot_anime = 2;
        }
        if (sho->shot_anime_c == 12) {
            sho->x_hit_size = 40;
            sho->y_hit_size = 40;
            sho->shot_anime = 3;
        }
        if (sho->shot_anime_c == 16) {
            sho->shot_anime = 4;
        }
        if (sho->shot_anime_c == 20) {
            sho->shot_anime = 5;
        }
        if (sho->shot_anime_c == 24) {
            sho->shot_anime = 6;
        }
        if (sho->shot_anime_c == 28) {
            sho->shot_anime = 7;
        }
        if (sho->shot_anime_c >= 31) {
            sho->code = 0;
        }

        sp_set(sho->cx, sho->cy,128,128, 1, 1, 0, bomb_graph[sho->shot_anime], 0, 0, 1);
        sho->shot_anime_c++;
    }
    shot_hit(sho);
    //画面から消えたら0に戻す
    if (sho->cx > 800) {
        sho->code = 0;
    }
}
//---------ミサイルの動き---------------------------------------------------
void move_missile(MY_SHOT *sho) {
    int w_cx, w_cy;
    if (sho->missile_impact == 0) {//自機から発射の状態
        sho->cx += 2;
        sho->cy += 6;
    }
    //壁に当たった時の処理
    w_cx = int(sho->cx / 20);
    w_cy = int(sho->cy / 20);
    //配列の下限、上限以内で
    if ((w_cx >= 0) && (w_cx <= 39) && (w_cy >= 0) && (w_cy <= 29)) {
        //下に壁があるか?
        if (map[w_cy + 30 + 1][w_cx + scroll_i] >= 1) {
            sho->missile_impact = 1;
            sho->cx += 6;
            sho->dir = 0;
        }
        else {
            if (sho->missile_impact == 1) {
                sho->cy += 6;
                sho->dir = 90 * PI / 180;
            }
        }
    }
    sp_set(sho->cx, sho->cy, 40, 40, 1, 1, sho->dir, chr_graph[30], 0, 0, 1);
    shot_hit(sho);
    //画面から消えたら0に戻す
    if ((sho->cx > 800) || (sho->cx < 0) || (sho->cy > 600) || (sho->cy < 0)) {
        sho->code = 0;
    }
}
//----------ショットと敵、地形の当たり判定----------------------------------
void shot_hit(MY_SHOT *sho) {
    int w_cx, w_cy;
    for (int i = 0; i < ENEMY_MAX; i++) {
        ENEMY_CHR *ene = &enemy[i];
        if (ene->atari >= 1){
            if ((sho->cx - ene->x_hit_size <= ene->cx + sho->x_hit_size)
                && (sho->cx + ene->x_hit_size >= ene->cx - sho->x_hit_size)
                && (sho->cy - ene->y_hit_size <= ene->cy + sho->y_hit_size)
                && (sho->cy + ene->y_hit_size >= ene->cy - sho->y_hit_size)) {
                switch (sho->code){
                    case 1:                     //ビームの時は何もしなくてcase 2に行く
                    case 2:sho->code = 0; break;//ビーム、3方向の場合ショットを消す
                    case 3: break;              //レーザーは貫通します。
                    case 4:sho->code = 5; break;//ボムの爆発にコードを5に変える
                    case 5:break;               //爆風
                    case 6:sho->code = 0; break;//ショットを消す
                    case 20:sho->code = 0; break;//ミサイルを消す

                }
                ene->hp -= shot->atk;

                if (ene->hp <= 0) {
                    chr.score += 100;
                    if (ene->item >= 1) {
                        ene->code = 910;
                        ene->anime = 80 + (ene->item - 1);
                    }
                    else {
                        ene->code = 900;
                    }
                    ene->atari = 0;
                    ene->anime_c = 0;
                    atari_num++;
                }
            }
        }
    }
    //壁に当たった時の処理
    w_cx = int(sho->cx / 20);
    w_cy = int(sho->cy / 20);
    //配列の下限、上限以内で
    if ((w_cx >= 0) && (w_cx <= 39) && (w_cy >= 0) && (w_cy <= 29)){
        if (map[w_cy + 30][w_cx + scroll_i] >= 1) {
            switch (sho->code) {
            case 1:sho->code = 0; break;//ショットを消す
            case 2:sho->code = 0; break;//ショットを消す
            case 3:sho->code = 0; break;//ショットを消す
            case 4:sho->code = 5; break;//ボムの爆発にコードを5に変える
            case 5:break;               //爆風
            case 6:sho->code = 0; break;//ショットを消す
            case 20:sho->code = 0; break;//ミサイルを消す
            }
        }
    }
}
//----------次の敵への角度-------------------------------------------------
double next_shot_dir(MY_SHOT *sho, double kakudo) {
    if (sho->dir_w - sho->dir > PI) {
        sho->dir_w -= PI * 2;
    }
    if (sho->dir_w - sho->dir < -PI) {
        sho->dir_w += PI * 2;
    }
    if (sho->dir_w - sho->dir < 0) {
        sho->dir_w += PI / 180 * kakudo;
    }
    if (sho->dir_w - sho->dir > 0) {
        sho->dir_w -= PI / 180 * kakudo;
    }
    return sho->dir_w;
}
//--------------------------------------------------------------------------
void move_homing(MY_SHOT *sho) {
   
    if (sho->enemy_lockon == 0) {
        double min_x = 9999,w_min_x;
        double min_y = 9999, w_min_y;
        if (homing_c > 50) {
            homing_c = 0;
        }
        for (int i = homing_c; i < ENEMY_MAX; i++) {
            ENEMY_CHR *ene = &enemy[i];
            w_min_x = abs(int(chr.cx - ene->cx));
            w_min_y = abs(int(chr.cy - ene->cy));
            if (min_x > w_min_x) {
                min_x = w_min_x;
                if (min_y > w_min_y) {
                    min_y = w_min_y;
                    if (ene->atari >= 1) {
                    //if ((ene->code >= 1) && (ene->code <= 800)) {
              
                       
                            sho->shot_homing = i;
                            homing_c++;
                            sho->enemy_lockon = 1;
                            //break;
                        }
                   //}
               }
            }
        }
    }
    if (sho->enemy_lockon == 1) {
        ENEMY_CHR *ene = &enemy[sho->shot_homing];
        sp_set(ene->cx, ene->cy, 40, 40, 1, 1, 0, chr_graph[25], 0, 0, 1);
        sho->dir_w = sho->dir;
        sho->dir = enemy_dir(ene->cx, ene->cy, sho->cx, sho->cy);
        sho->dir = next_shot_dir(sho, 10);
 
    }
   
    sho->cx += cos(sho->dir) * 12;
    sho->cy += sin(sho->dir) * 12;
    sp_set(sho->cx, sho->cy, 40, 40, 1, 1, sho->dir, chr_graph[24], 0, 0, 1);
    shot_hit(sho);
    //ホーミングの効果時間
    sho->shot_anime_c++;
    if (sho->shot_anime_c >= 180) {
        sho->enemy_lockon = 2;
    }

    //画面から消えたら0に戻す
    if ((sho->cx > 840) || (sho->cx <-40) || (sho->cy > 640) || (sho->cy < -40)) {
        sho->code = 0;
       
    }
}


ヘッダーファイルです。my_chr.h
/**************************************
*                                                       *
*           自機ヘッダー                    *
*                                                       *
*               Ver1.11.23.13.07                    *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
**************************************/


typedef struct {
    double cx;
    double cy;
    int x_graph_size;
    int y_graph_size;
    int score;
    int shot_type;
    int missile_type;
    int atk;
} MY_CHR;

自機を動かすプログラムです。my_chr.cpp

/**************************************
*                                                       *
*           自機移動プログラム               *
*                                                       *
*               Ver 1.11.23.13.081                 *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
***************************************/


#include "DxLib.h"
#include "shot.h"
#include "my_chr.h"
#include "enemy.h"

MY_CHR chr;
void move_chr(void);
void init_chr(void);

extern MY_SHOT shot[SHOT_MAX];
extern ENEMY_CHR enemy[ENEMY_MAX];
extern int chr_graph[100];
extern int get_pad(void);
extern void sp_set(double cx, double cy, int gr_x_size, int gr_y_size, double sc_x, double sc_y, double ag, int g_han, int mir, int mo, int pr);
extern void num_disp(int, int, int);

//----------キャラクタを動かす--------------------------------------------------
void move_chr(void) {
    int pad_key;
    int w_cx=chr.cx;
    pad_key = get_pad();
    //上
    if (pad_key == 8) {
        chr.cy -= 6;
    }
    //下
    if (pad_key == 1) {
        chr.cy += 6;
    }
    //左
    if (pad_key == 2) {
        chr.cx -= 6;
    }
    //右
    if (pad_key == 4) {
        chr.cx += 6;
    }
    //左下
    if (pad_key == 3) {
        chr.cx -= 6 * 0.7;
        chr.cy += 6 * 0.7;
    }
    //右下
    if (pad_key == 5) {
        chr.cx += 6 * 0.7;
        chr.cy += 6 * 0.7;
    }
    //左上
    if (pad_key == 10) {
        chr.cx -= 6 * 0.7;
        chr.cy -= 6 * 0.7;
    }
    //右上
    if (pad_key == 12) {
        chr.cx += 6 * 0.7;
        chr.cy -= 6 * 0.7;
    }
    //画面からはみ出さないように
    if (chr.cx < 20) {
        chr.cx = 20;
    }
    if (chr.cy < 40) {
        chr.cy = 40;
    }
    if (chr.cx > 750) {
        chr.cx = 750;
    }
    if (chr.cy > 540) {
        chr.cy = 540;
    }
    //レーザーの時のx座標の修正
    if (chr.shot_type == 2) {
        for (int i = 0; i < 20; i++) {
            MY_SHOT *sho = &shot[i];
            sho->cx -= w_cx - int(chr.cx);
        }
    }
    //キャラクターの表示
    sp_set(chr.cx, chr.cy,40,40,1,1,0,chr_graph[0], 0, 0,  1);
    sp_set(chr.cx+40, chr.cy, 40, 40,1,1, 0, chr_graph[1], 0, 0, 1);
    sp_set(chr.cx, chr.cy,40,40, 1, 1, 0, chr_graph[12], 0, 0, 1);
  
   
    //得点
    num_disp(200,40,chr.score);
  
}


//--------自機の初期化--------------------------------------------------------
void init_chr(void) {
    chr.cx = 400;
    chr.cy = 300;
    chr.score = 0;
    chr.shot_type = 0;
    chr.missile_type = 20;
    chr.atk = 1;
}



ゲーム作りをしていると、ついつい別のことやりたくなってくるのです。
そんな過去に作ったお遊びなもの、載せていいのかなw

ゲームの基礎はグ○ディウスで作って、アニメのキャラクタを
貼り付けていますw

侵略イカ娘でテトラン。


らきすたの柊かがみで、ゴーレム。


柊つかさで、ガウ。


泉こなたで、クリスタルコア。


日下部みさおで、ゼロスフォース。


這いよれ!ニャル子さんで、イントルーダー。


また日下部みさおで、みさおステージ。(グラディウスVの1面を・・・)



こっちのほうが楽しかったりもします。
つまらないもの見せてごめんね。

ぎょぎょ!!
1週間も時間を空けていまいました。

今回は地形に当たり判定を付けてみました。
そのついでに、自機ショット、敵弾も付けました。

方法は仮想マップ方式を採用し、2次元配列の情報で
値が0の時は、当たり判定はない。

1の時は壊せる地形、2の時は壊せて復活する地形
3の時は壊せない地形で、今のところは壊せない地形のみです。
色では青、緑赤の順です。

マップエディタは、Quoyleを使っています。
適当にマップを配置しますが、レイヤー1に地形データ、レイヤー2に当たり判定と
敵キャラ出現パターンを使います。

レイヤー1が下にして、レーヤー2を上にします。
ファイルのフォーマットで、下のレイヤーが上に来るみたいです。

レイヤー1にマップを配置しました。

レイヤー2に当たり判定のある地形です。

マップチップのグラフィックが少ないものは、ここの場合斜めのグラフィックの

時は、当たり判定は置きません。


地形との当たり判定を行っている場所は、自機のショットで敵との
当たり判定の後しております。

//----------ショットと敵、地形の当たり判定----------------------------------
void shot_hit(MY_SHOT *sho) {
    int w_cx, w_cy;

    for (int i = 0; i < ENEMY_MAX; i++) {
        ENEMY_CHR *ene = &enemy[i];
        if (ene->atari >= 1){
            if ((sho->cx - ene->x_hit_size <= ene->cx + sho->x_hit_size)
                && (sho->cx + ene->x_hit_size >= ene->cx - sho->x_hit_size)
                && (sho->cy - ene->y_hit_size <= ene->cy + sho->y_hit_size)
                && (sho->cy + ene->y_hit_size >= ene->cy - sho->y_hit_size)) {
                switch (sho->code){
                    case 1:                     //ビームの時は何もしなくてcase 2に行く
                    case 2:sho->code = 0; break;//ビーム、3方向の場合ショットを消す
                    case 3: break;              //レーザーは貫通します。
                    case 4:sho->code = 5; break;//ボムの爆発にコードを5に変える
                    case 5:break;               //爆風
                    case 6:sho->code = 0; break;//ショットを消す
                }
                ene->hp -= shot->atk;

                if (ene->hp <= 0) {
                    chr.score += 100;
                    if (ene->item >= 1) {
                        ene->code = 910;
                        ene->anime = 80 + (ene->item - 1);
                    }
                    else {
                        ene->code = 900;
                    }
                    ene->atari = 0;
                    ene->anime_c = 0;
                    atari_num++;
                }
            }
        }
    }
    //壁に当たった時の処理

     w_cx = int(sho->cx / 20);
    w_cy = int(sho->cy / 20);
    //配列の下限、上限超えないように
    if (w_cx < 0) {//0より小さくしない
        w_cx = 0;
    }
    if (w_cx > 40) {//40より小さくしない
        w_cx = 0;
    }
    if (w_cy < 0) {//0より小さくしない
        w_cy = 0;
    }
    if (w_cy > 30) {//30より小さくしない
        w_cy = 0;
    }
    if (map[w_cy + 30][w_cx + scroll_i] >= 1) {
        switch (sho->code) {
        case 1:sho->code = 0; break;//ショットを消す
        case 2:sho->code = 0; break;//ショットを消す
        case 3:sho->code = 0; break;//ショットを消す
        case 4:sho->code = 5; break;//ボムの爆発にコードを5に変える
        case 5:break;               //爆風
        case 6:sho->code = 0; break;//ショットを消す
        }
    }

}

ここでは、ショットの座標を20x20単位で、大まかに当たり判定をしています
if (map[int(sho->cy / 20)+30][int(sho->cx / 20) + scroll_i] >= 1)   
 

sho->cx / 20で20ピクセルごとに、配列の添字の変化をさせています。

x座標はスクロールが進みたびに、scroll_iの値に沿ってマップの位置を見ています。
y座標は、自機のショットの座標のみです。


後は敵に当たった時みたいに、攻撃の種類ごとにしますが
多くのショットは、たいていは壁にあらると消えますね。

switch (sho->code) {
        case 1:sho->code = 0; break;//ショットを消す
        case 2:sho->code = 0; break;//ショットを消す
        case 3:sho->code = 0; break;//ショットを消す
        case 4:sho->code = 5; break;//ボムの爆発にコードを5に変える
        case 5:break;               //爆風
        case 6:sho->code = 0; break;//ショットを消す
        }

反射レーザーや、ミサイルが地表を這う場合も
地形に当たり判定があるかないかで、見てその後でそれ相当な処理をさせます。


敵弾に関しても同じく、地形がある場合消えるようにしています。

//----------敵弾------------------------------------------------------------
void enemy_type1000(ENEMY_CHR *ene) {
    int w_cx, w_cy;
    //三角関数で移動をさせる
    ene->cx += cos(ene->dir) * 3;
    ene->cy += sin(ene->dir) * 3;
   
    sp_set(ene->cx, ene->cy, 40, 40, 1, 1, 0, enemy_graph[90], 0, 0, 3);
   
    //壁に当たった時の処理

    w_cx = int(ene->cx / 20);
    w_cy = int(ene->cy / 20);
    //配列の下限、上限超えないように
    if (w_cx < 0) {//0より小さくしない
        w_cx = 0;
    }
    if (w_cx > 40) {//40より小さくしない
        w_cx = 0;
    }
    if (w_cy < 0) {//0より小さくしない
        w_cy = 0;
    }
    if (w_cy > 30) {//30より小さくしない
        w_cy = 0;
    }
    if (map[w_cy+30][w_cx + scroll_i] >= 1) {
        ene->code = 0;
    }

    chr_hit(ene);
  //画面から出たら消す

    if ((ene->cx < -20) || (ene->cx > 820) || (ene->cy < -20) || (ene->cy > 620)) {
        ene->code = 0;
    }
}

敵弾の場合は消しますが、特殊な敵レーザー等も反射させたりも出来ますね。

地形を這う敵も、地形の当たり判定を見て動かします。


今日はこのくらいかな?

ここまで見てくれてありがとう!

プログラムが大きくなってきたので、分割します。
敵セット、enemy_type001~009まで。

/*************************************
*                                                       *
*           敵キャラプログラム                *
*                                                       *
*               Ver 1.12.01.21.07                  *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
*                                                       *
**************************************/
#include <math.h>
#include "DxLib.h"
#include "enemy.h"
#include "my_chr.h"

                            //    x_hit   y_hit x_graph y_graph   anime  atari next_shot hp  score
ENEMY_DAT enemy_data[1000] = { {      0,      0,      0,      0,      0,     0,    100,   0,     0},//ダミー
                              {      20,     20,     40,     40,      0,     1,    100,   1,   100},//直進する
                              {      20,     20,     40,     40,      0,     1,    100,   1,   100},//直進する
                              {      20,     20,     40,     40,      1,     1,    100,   1,   100},//サインカーブ
                              {      20,     20,     40,     40,     11,     1,    100,   1,   100},//サインカーブ
                              {      20,     20,     40,     40,      9,     1,    100,   1,   300},//追尾してくる敵
                              {      20,     20,     40,     40,     19,     1,    100,   1,   300},//追尾してくる敵
                              {      40,     40,     40,     40,     20,     1,     12,  10,  1000},//ハッチ下から上へ
                              {      40,     40,     40,     40,     20,     1,     12,  10,  1000},//ハッチ上から下へ
                              {      20,     20,     40,     40,     30,     1,     32,   1,   100},//ハッチの敵
                              {      20,     20,     40,     40,     30,     1,     32,   1,   100},//ハッチの敵
                              {      20,     20,     40,     40,     30,     1,     32,   1,   100 },//砲台下
                              {      20,     20,     40,     40,     30,     1,     32,   1,   100 },//砲台上






                              { 0,0,0,0,0,0,0 }};//終わりダミー
const double PI = 3.1415;
int enemy_index;
int enemy_num;
ENEMY_CHR enemy[ENEMY_MAX];
ENEMY_MAP enemy_map[1024];
void set_enemy(void);
void set_map_enemy(int,int,int);
void set1_enemy(ENEMY_CHR *ene,int, double);
void move_enemy(void);
void enemy_type001(ENEMY_CHR *ene);
void enemy_type002(ENEMY_CHR *ene);
void enemy_type003(ENEMY_CHR *ene);
void enemy_type007(ENEMY_CHR *ene);
void enemy_type008(ENEMY_CHR *ene);

void enemy_type009(ENEMY_CHR *ene);
void enemy_type010(ENEMY_CHR *ene);
void enemy_type011(ENEMY_CHR *ene);
void enemy_type012(ENEMY_CHR *ene);

void enemy_type1000(ENEMY_CHR *ene);
void enemy_explosion1(ENEMY_CHR *ene);
void enemy_generate(ENEMY_CHR *ene);
void enemy_map_generate(ENEMY_CHR *ene);
void power_up(ENEMY_CHR *ene);
void chr_hit(ENEMY_CHR *ene);
double enemy_dir(double, double, double, double);
double next_dir(ENEMY_CHR *ene, double);
extern int game_loop;
extern int scroll_wi;
extern int scroll_i;
extern int scroll_speed;
extern MY_CHR chr;
extern unsigned short map[60][1024];
extern int enemy_graph[100];
extern int explosion1_graph[8];
extern void sp_set(double cx, double cy, int gr_x_size, int gr_y_size, double sc_x, double sc_y, double ag, int g_han, int mir, int mo, int pr);

//----------敵セット--------------------------------------------------------
void set_enemy(void) {
    while (game_loop == enemy_map[enemy_index].time) {
        //敵テーブルの空きを探す
        for (int i = 0; i < ENEMY_MAX; i++) {
            ENEMY_CHR *ene = &enemy[i];
            if (ene->code == 0) {
                ene->code = 1100;
                ene->generate_code = enemy_map[enemy_index].code;
                ene->cx = enemy_map[enemy_index].cx;
                ene->cy = enemy_map[enemy_index].cy;
                ene->dir = enemy_map[enemy_index].dir*3.14/180;
                ene->item = enemy_map[enemy_index].item;
                ene->num = enemy_map[enemy_index].num;
                ene->next_generate = enemy_map[enemy_index].next_gene;
                ene->generate= 1;
                ene->next_generate_c = 0;
                ene->x_hit_size = enemy_data[ene->code].x_hit_size;
                ene->y_hit_size = enemy_data[ene->code].y_hit_size;
                ene->x_graph_size = enemy_data[ene->code].x_graph_size;
                ene->y_graph_size = enemy_data[ene->code].y_graph_size;
                ene->w_dir = 0;
                ene->anime = enemy_data[ene->code].anime;
                ene->anime_c = 0;
                ene->atari = enemy_data[ene->code].atari;
                ene->next_shot = enemy_data[ene->code].next_shot;
                ene->next_shot_c = 0;
                ene->hp = enemy_data[ene->code].hp;
                break;
            }
        }
        enemy_index++;
    }
}
//----------敵セット1-------------------------------------------------------
void set1_enemy(ENEMY_CHR *ene,int code,double dir) {
    //敵テーブルの空きを探す
    for (int i = 0; i < ENEMY_MAX; i++) {
        ENEMY_CHR *set_ene = &enemy[i];
        if (set_ene->code == 0) {
                set_ene->code = code;
                set_ene->cx = ene->cx;
                set_ene->cy = ene->cy;
                set_ene->x_graph_size = enemy_data[set_ene->code].x_graph_size;
                set_ene->y_graph_size = enemy_data[set_ene->code].y_graph_size;
                set_ene->x_hit_size = enemy_data[set_ene->code].x_hit_size;
                set_ene->y_hit_size = enemy_data[set_ene->code].y_hit_size;
                set_ene->dir = dir;
                set_ene->w_dir = 0;
                set_ene->anime = enemy_data[set_ene->code].anime;
                set_ene->anime_c = 0;
                set_ene->atari = enemy_data[set_ene->code].atari;
                set_ene->next_shot = enemy_data[set_ene->code].next_shot;
                set_ene->next_shot_c = ene->next_shot;
                ene->hp = enemy_data[ene->code].hp;
                set_ene->item = ene->item;
                ene->generate = 0;
                break;
        }
    }
}
//----------マップ敵セット--------------------------------------------------------
void set_map_enemy(int cx,int cy,int code) {
   
        //敵テーブルの空きを探す
        for (int i = 0; i < ENEMY_MAX; i++) {
            ENEMY_CHR *ene = &enemy[i];
            if (ene->code == 0) {
                ene->code = code;
                ene->cx = cx;
                ene->cy = cy;
                ene->dir = 3.14;
                ene->item = 0;
                ene->num = 0;
                ene->next_generate = 0;
                ene->generate = 0;
                ene->next_generate_c = 0;
                ene->x_hit_size = enemy_data[ene->code].x_hit_size;
                ene->y_hit_size = enemy_data[ene->code].y_hit_size;
                ene->x_graph_size = enemy_data[ene->code].x_graph_size;
                ene->y_graph_size = enemy_data[ene->code].y_graph_size;
                ene->w_dir = 0;
                ene->anime = enemy_data[ene->code].anime;
                ene->anime_c = 0;
                ene->atari = enemy_data[ene->code].atari;
                ene->next_shot = enemy_data[ene->code].next_shot;
                ene->next_shot_c = ene->next_shot;

                break;
            }
        }
  
}
//----------敵動き-----------------------------------------------------------
void move_enemy(void) {
    enemy_num = 0;
    for (int i = 0; i < ENEMY_MAX; i++) {
        ENEMY_CHR *ene = &enemy[i];
        switch (ene->code){
        case 1:
        case 2:enemy_type001(ene); break;
        case 3:
        case 4:enemy_type002(ene); break;
        case 5:
        case 6:enemy_type003(ene); break;
        case 7:enemy_type007(ene); break;
        case 8:enemy_type008(ene); break;
        case 9:enemy_type009(ene); break;
        case 10:enemy_type010(ene); break;
        case 11:enemy_type011(ene); break;
        case 12:enemy_type011(ene); break;
        case 900:enemy_explosion1(ene); break;
        case 910:power_up(ene); break;
        case 1000:enemy_type1000(ene); break;
        case 1100:enemy_generate(ene); break;
        case 1101:enemy_map_generate(ene); break;
        }
        if (ene->code > 0) {
            enemy_num++;
        }
    }
}
//----------直進する---------------------------------------------------------
void enemy_type001(ENEMY_CHR *ene) {
    ene->cx -= 3;
    ene->dir += 8;
    if (ene->dir > 360) {
        ene->dir = 0;
    }
   
    if (ene->next_shot_c < 0) {
        set1_enemy(ene, 1000, enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy));
        ene->next_shot_c = ene->next_shot;
    }
    ene->next_shot_c--;
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size,1,1,ene->dir*3.14/180,enemy_graph[ene->anime],0,0,2);
    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -80) {
        ene->code = 0;
        ene->atari = 0;
    }
}
//----------サインカーブ-----------------------------------------------------
void enemy_type002(ENEMY_CHR *ene) {
    ene->cx -= 3;
    ene->dir += 4;
    if (ene->dir > 360) {
        ene->dir = 0;
    }
    ene->cy += sin(ene->dir*PI/180) * 5;
    if (ene->anime_c >= 31) {
        ene->anime_c = 0;
    }
    
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime_c / 4 + ene->anime], 0, 0, 2);
    ene->anime_c++;
    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -80) {
        ene->code = 0;
    }
}
//----------追尾してくる敵-----------------------------------------------------
void enemy_type003(ENEMY_CHR *ene) {
    if (ene->anime_c < -60) {//初期移動までは直線に動きます
        ene->w_dir = ene->dir;//前回の角度を保存
        ene->dir = enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy);//自機との角度を取得
        ene->dir = next_dir(ene, 2);//新しい角度を更新
    }
    ene->anime_c--;
    //三角関数で移動をさせる
    ene->cx += cos(ene->dir)*3;
    ene->cy += sin(ene->dir)*3;
    chr_hit(ene);
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1,ene->dir, enemy_graph[ene->anime], 0, 0, 2);
}
//---------ハッチ下から上-------------------------------------------------------
void enemy_type007(ENEMY_CHR *ene) {
    ene->cx -= scroll_speed;
    if (ene->anime_c == 80) {
        ene->anime = 21;
    }
    if (ene->anime_c == 90) {
        ene->anime = 22;
    }
    if (ene->anime_c == 100) {
        ene->anime = 23;
    }
    if (ene->anime_c == 110) {
        ene->anime = 24;
    }
    if ((ene->anime_c >= 120) && (ene->anime_c <= 240)) {
        if (ene->next_shot_c < 0) {
            set1_enemy(ene, 9, 270 * PI / 180);
            ene->next_shot_c = ene->next_shot;
        }
        ene->next_shot_c--;
    }
    if (ene->anime_c == 250) {
        ene->anime = 23;
    }
    if (ene->anime_c == 260) {
        ene->anime = 22;
    }
    if (ene->anime_c == 270) {
        ene->anime = 21;
    }
    if (ene->anime_c == 280) {
        ene->anime = 20;
        ene->anime_c = 0;
    }
    ene->anime_c++;

    sp_set(ene->cx - 20, ene->cy - 20, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime], 0, 0, 2);
    sp_set(ene->cx + 20, ene->cy - 20, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime], 1, 0, 2);
    sp_set(ene->cx - 20, ene->cy + 20, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[25], 0, 0, 2);
    sp_set(ene->cx + 20, ene->cy + 20, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[25], 1, 0, 2);
     
    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -160) {
        ene->code = 0;
        ene->atari = 0;
    }
}
//---------ハッチ上から下へ-----------------------------------------------------
void enemy_type008(ENEMY_CHR *ene) {
    ene->cx -= scroll_speed;
   
    if (ene->anime_c == 80) {
        ene->anime = 21;
    }
    if (ene->anime_c == 90) {
        ene->anime = 22;
    }
    if (ene->anime_c == 100) {
        ene->anime = 23;
    }
    if (ene->anime_c == 110) {
        ene->anime = 24;
    }
    if ((ene->anime_c >= 120) && (ene->anime_c <= 240)) {
        if (ene->next_shot_c < 0) {
            set1_enemy(ene, 10, 90 * PI / 180);
            ene->next_shot_c = ene->next_shot;
        }
        ene->next_shot_c--;
    }
    if (ene->anime_c == 250) {
        ene->anime = 23;
    }
    if (ene->anime_c == 260) {
        ene->anime = 22;
    }
    if (ene->anime_c == 270) {
        ene->anime = 21;
    }
    if (ene->anime_c == 280) {
        ene->anime = 20;
        ene->anime_c = 0;
    }
    ene->anime_c++;
  
    sp_set(ene->cx + 20, ene->cy - 20, ene->x_graph_size, ene->y_graph_size, 1, 1, PI, enemy_graph[25], 0, 0, 2);
    sp_set(ene->cx - 20, ene->cy - 20, ene->x_graph_size, ene->y_graph_size, 1, 1, PI, enemy_graph[25], 1, 0, 2);
    sp_set(ene->cx + 20, ene->cy + 20, ene->x_graph_size, ene->y_graph_size, 1, 1, PI, enemy_graph[20], 0, 0, 2);
    sp_set(ene->cx - 20, ene->cy + 20, ene->x_graph_size, ene->y_graph_size, 1, 1, PI, enemy_graph[20], 1, 0, 2);

    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -160) {
        ene->code = 0;
        ene->atari = 0;
    }
}

//----------ハッチの敵下から上へ-----------------------------------------------
void enemy_type009(ENEMY_CHR *ene) {
    ene->cx -= scroll_speed;
    ene->cy -= 3;
   
    if (ene->next_shot_c < 0) {
        set1_enemy(ene, 1000, enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy));
        ene->next_shot_c = ene->next_shot;
    }
    ene->next_shot_c--;
    if (ene->anime_c >= 31) {
        ene->anime_c = 0;
    }
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime_c/4+30], 0, 0, 3);
    ene->anime_c++;
    chr_hit(ene);
    //画面から出たら消す
    if ((ene->cx < -20) || (ene->cx > 820) || (ene->cy < -20) || (ene->cy > 620)) {
        ene->code = 0;
        ene->atari = 0;
    }
}
//----------ハッチの敵上から下へ----------------------------------------------
void enemy_type010(ENEMY_CHR *ene) {
    ene->cx -= scroll_speed;
    ene->cy += 3;

    if (ene->next_shot_c < 0) {
        set1_enemy(ene, 1000, enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy));
        ene->next_shot_c = ene->next_shot;
    }
    ene->next_shot_c--;
    if (ene->anime_c >= 31) {
        ene->anime_c = 0;
    }
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime_c / 4 + 30], 0, 0, 3);
    ene->anime_c++;
    chr_hit(ene);
    //画面から出たら消す
    if ((ene->cx < -20) || (ene->cx > 820) || (ene->cy < -20) || (ene->cy > 620)) {
        ene->code = 0;
        ene->atari = 0;
    }
}
//----------砲台---11の時下 12の時上--------------------------------------------
void enemy_type011(ENEMY_CHR *ene) {
    int kakudo;
    ene->dir = enemy_dir(chr.cx, chr.cy, ene->cx, ene->cy);
    kakudo = abs(int(ene->dir * 180 / PI));
    ene->cx -= scroll_speed;
    if (ene->next_shot_c < 0) {
        set1_enemy(ene, 1000,ene->dir);
        ene->next_shot_c = ene->next_shot;
    }
    ene->next_shot_c--;
    if (ene->code == 11) {//下から上
        switch ((kakudo) / 22) {
        case 0:ene->anime = 48; break;
        case 1:ene->anime = 47; break;
        case 2:ene->anime = 46; break;
        case 3:ene->anime = 45; break;
        case 4:ene->anime = 44; break;
        case 5:ene->anime = 43; break;
        case 6:ene->anime = 42; break;
        case 7:ene->anime = 41; break;
        case 8:ene->anime = 40; break;
        default:ene->anime = 44; break;
        }
        sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime], 0, 0, 3);
    }
    else {//上から下
        switch ((kakudo) / 22) {
        case 0:ene->anime = 40; break;
        case 1:ene->anime = 41; break;
        case 2:ene->anime = 42; break;
        case 3:ene->anime = 43; break;
        case 4:ene->anime = 44; break;
        case 5:ene->anime = 45; break;
        case 6:ene->anime = 46; break;
        case 7:ene->anime = 47; break;
        case 8:ene->anime = 48; break;
        default:ene->anime = 44; break;
        }
        sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1,PI, enemy_graph[ene->anime], 0, 0, 3);
    }
    chr_hit(ene);
    //画面から出たら消す
    if (ene->cx < -20){
        ene->code = 0;
        ene->atari = 0;
    }
}


enemy.cppその1の続きです。
敵弾、爆発、パワーアップアイテム、その他下請け処理。

//----------敵弾-------------------------------------------------------------
void enemy_type1000(ENEMY_CHR *ene) {
    int w_cx, w_cy;
    //三角関数で移動をさせる
    ene->cx += cos(ene->dir) * 3;
    ene->cy += sin(ene->dir) * 3;
   
    sp_set(ene->cx, ene->cy, 40, 40, 1, 1, 0, enemy_graph[90], 0, 0, 3);
   
    chr_hit(ene);
   //壁に当たった時の処理
    w_cx = int(ene->cx / 20);
    w_cy = int(ene->cy / 20);
    //配列の下限、上限超えないように
    if (w_cx < 0) {//0より小さくしない
        w_cx = 0;
    }
    if (w_cx > 40) {//40より小さくしない
        w_cx = 0;
    }
    if (w_cy < 0) {//0より小さくしない
        w_cy = 0;
    }
    if (w_cy > 30) {//30より小さくしない
        w_cy = 0;
    }
    if (map[w_cy+30][w_cx + scroll_i] >= 1) {
        ene->code = 0;
    }

    //画面から出たら消す
   
    chr_hit(ene);
    if ((ene->cx < -20) || (ene->cx > 820) || (ene->cy < -20) || (ene->cy > 620)) {
        ene->code = 0;
    }
}
//----------爆発1-----------------------------------------------------------
void enemy_explosion1(ENEMY_CHR *ene) {
    if (ene->anime_c >= 31) {
        ene->code = 0;
    }
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, explosion1_graph[ene->anime_c / 4 + 1], 0, 0, 1);
    ene->anime_c++;
}
//---------パワーアップアイテム----------------------------------------------
void power_up(ENEMY_CHR *ene) {
    ene->cx -= 1;
    sp_set(ene->cx, ene->cy, ene->x_graph_size, ene->y_graph_size, 1, 1, 0, enemy_graph[ene->anime], 0, 0, 2);
   
    //画面から出たら消す
    if (ene->cx < -80) {
        ene->code = 0;
    }
    chr_hit(ene);
}
//-------敵を発生させる-----------------------------------------------------
void enemy_generate(ENEMY_CHR *ene) {
    if (ene->next_generate_c < 0) {
        if (ene->num >= 0) {
            set1_enemy(ene, ene->generate_code, ene->dir);
            ene->next_generate_c = ene->next_generate;
            ene->num--;
            if (ene->num < 0) {
                ene->code = 0;
            }
        }
    }
    ene->next_generate_c--;
}
//-------マップからの敵を発生させる-----------------------------------------
void enemy_map_generate(ENEMY_CHR *ene) {

    if (scroll_wi != scroll_i) {
        for (int i = 0; i < 30; i++) {
            if (map[i][scroll_i + 44] >= 4) {
                set_map_enemy(880,i*20,map[i][scroll_i]);
               
                map[i][scroll_i + 44] = 0;
            }
        }
        scroll_wi = scroll_i;
    }
    //ステージのの終で消す
    if (game_loop >= 15000) {
        ene->code = 0;
    }

}
//--------自機との当たり判定-------------------------------------------------
void chr_hit(ENEMY_CHR *ene) {
    if ((chr.cx - ene->x_hit_size <= ene->cx + ene->x_hit_size)
        && (chr.cx + ene->x_hit_size >= ene->cx - ene->x_hit_size)
        && (chr.cy - ene->y_hit_size <= ene->cy + ene->y_hit_size)
        && (chr.cy + ene->y_hit_size >= ene->cy - ene->y_hit_size)) {
        if (ene->item >= 1) {
            chr.shot_type = ene->item - 1;
           
        }
        ene->code = 0;
    }
}
//----------自機への角度-----------------------------------------------------
double enemy_dir(double cx, double cy, double ex, double ey) {
    double di;
    if (cx - ex == 0) {
        di = 0;
    }
    else {
        di = atan2(cy - ey, cx - ex);
    }
    return  di;
}
//----------次の自機への角度-------------------------------------------------
double next_dir(ENEMY_CHR *ene, double kakudo) {
    if (ene->w_dir - ene->dir > PI) {
        ene->w_dir -= PI * 2;
    }
    if (ene->w_dir - ene->dir < -PI) {
        ene->w_dir += PI * 2;
    }
    if (ene->w_dir - ene->dir < 0) {
        ene->w_dir += PI / 180 * kakudo;
    }
    if (ene->w_dir - ene->dir > 0) {
        ene->w_dir -= PI / 180 * kakudo;
    }
    return ene->w_dir;
}
簡単でありますが、背景をスクロールさせてみました。
素材は、敵キャラ発生マップを使って簡単なグラフィックを
表示させています。

マップチップの大きさは20x20ピクセルで、マップ情報は
Quoyleのコンバートした、拡張子mapを使用しています。

マップ情報の読み込みは、load_game.cppで行っており、画面の大きさは
800x600ピクセルなので、全体にマップチップを表示させるには、40x30になります。

グラフィックは
LoadDivGraph("enemy_map.bmp", 400, 20, 20, 20, 20, bg_graph_map1);
で読み込んでおり


マップデータはの読み込みでが、変数の宣言時でy方向縦に
2倍の空きをとっているのは、
unsigned short map[60][1024];

地形のデーターを0~29までを、
地形の当たり判定と、敵キャラ発生を30~59までを使っている為です。


FILE *fp;
fp = fopen("st1.map", "rb");
size = fread(map, sizeof(unsigned short), 8, fp);
size = fread(map, sizeof(unsigned short), 1024 * 60, fp);

fclose(fp);

QMPファイルのヘッダーなしとは言え、基本のマップの大きさなどの情報が
8バイトありますが、これは今のところ使わないので8バイト一度読み込んで
後から上書きで消しています。

#include "DxLib.h"
#include "enemy.h"
#include "enemy_map.h"
int chr_graph[100];
int bomb_graph[8];
int enemy_graph[100];
int system_graph[100];
int explosion1_graph[8];
int bg_graph_map1[400];
unsigned short map[60][1024];
void init_load(void);
void stage_load(int);
extern ENEMY_MAP enemy_map[1024];

//---------------キャラクタグラフィックの読み込み-----------------------
void init_load(void) {
    LoadDivGraph("chr_graph.bmp", 100, 10, 10, 40, 40, chr_graph);
    LoadDivGraph("bomb_graph.bmp", 8, 2, 4,128,128, bomb_graph);
    LoadDivGraph("enemy_graph.bmp", 100, 10, 10, 40, 40, enemy_graph);
    LoadDivGraph("system_graph.bmp", 100, 10, 10, 40, 40, system_graph);
    LoadDivGraph("explosion1.bmp", 8, 8, 1, 40, 40, explosion1_graph);
    LoadDivGraph("enemy_map.bmp", 400, 20, 20, 20, 20, bg_graph_map1);
}
//--------------面ごとのキャラクタや敵パターンその他-------------------
void stage_load(int stage) {
    FILE *fp;
    int size;
    switch (stage) {
    case 1:fp = fopen("st1.map", "rb");
        for (int i = 0; i < 1024; i++) {//敵パターンをワークエリアに転送
            enemy_map[i].time = enemy_map1[i].time;
            enemy_map[i].code = enemy_map1[i].code;
            enemy_map[i].cx = enemy_map1[i].cx;
            enemy_map[i].cy = enemy_map1[i].cy;
            enemy_map[i].dir = enemy_map1[i].dir;
            enemy_map[i].item = enemy_map1[i].item;
            enemy_map[i].num = enemy_map1[i].num;
            enemy_map[i].next_gene = enemy_map1[i].next_gene;
        }
        break;
    }
    size = fread(map, sizeof(unsigned short), 8, fp);
    size = fread(map, sizeof(unsigned short), 1024 * 60, fp);

    fclose(fp);
}

スクロールをしている部分は、scroll.cpp内のvoid star_scroll(int);関数で行っています。

スクロールさせる時に、よく例えられることは長い蒔絵を、順番に見ていく感じなのですね。
現在の見ている位置は、scroll_i変数で、細かなスクロールはscroll_xでやっています。

マップチップ1キャラ分スクロールさせると、scroll_iを1足して
次のマップチップから表示させます。

forループは、x方向に1つ先の右端まで描いています。
理由は、20ピクセルスクロールさせると、右側に空白ができるからです。

とりあえずの表示なので、DrawRotaGraphを使っています。
コメントを書いてあるようなことを、おおよそやっています。


//-------------地形スクロール--------------------------------------------
void scroll_bg0(void) {
    for (int y = 0; y < 30; y++) {//画面y座標
        for (int x = 0; x < 41; x++) {//画面x座標
            //マップチップ表示
            DrawRotaGraph(x*20 + scroll_x , y * 20, 1, 0, bg_graph_map1[map[y][x + scroll_i]], TRUE,FALSE);
        }
    }

    if (scroll_x < 0) {//スクロールx座標が0になったか?
        scroll_x = 20;//マップチップの大きさに初期化
        scroll_i++;//次の表示されるマップの位置更新
        if (scroll_i > 1024-41) {//ステージの終が来たらループさせるようにする
            scroll_i = 41;
        }
    }
    scroll_x--;//スクロールを1ピクセルさせる
}

このように簡単なグラフィックが、スクロースされます。


最近更新ができないのは、時間がないことと(誰でもだね)

文章にすることに、時間がかかるのですよね。
考えて書いているつもりですが、誤字脱字ありましたら、すみません。


プログラムの場合、誤字脱字はコンパイル時に、教えてくれるのですが
ブログに書くときは、文字チェック機能がないために


書くときは、自分で思い込んでいるので間違っていても、気づかないのですね。
文書エディタとかに誤字脱字、コンパイルの時みたいな、検索機能あるのかな??


ちょっとググってみるわ!


プログラムは、テーマごとに載せてあります。


こんなんでも、出来るのだw
と思っていただけたらいいですよ。


ここまで見てくれてありがとう!