【四圣龙神录的编程教室】第10章、把敌人表示出来看看吧

原文地址:

http://dixq.net/rp/10.html


既然是做STG射击游戏,肯定想快点写弹幕呢,是吧。

要做弹幕的数据的话,首先得把敌人的数据给做出来呢,我们赶紧来制作吧。

————————————————————————————————————————————————————————————————————————————

--struct.h 里加入如下代码--

//敌人相关的构造体
typedef struct{
        //标志、计数、移动模式、方向、敌人种类、HP、HP最大值、掉落道具、图像
        int flag,cnt,pattern,muki,knd,hp,hp_max,item_n[6],img;
        //坐标、速度的x分量、速度的y分量、速度、角度
        double x,y,vx,vy,sp,ang;
        //弹幕开始时间、弹幕的种类、子弹的种类、颜色、状态、待机时间、停滞时间
        int bltime,blknd,blknd2,col,state,wtime,wait;
}enemy_t;

————————————————————————————————————————————————————————————————————————————

这都什么东西啊!!

虽然这么多变量混在一起,但没必要把他们全部都记住。

flag 是标志,cnt 是计数,pattern是敌机的移动模式,就这样用能表示含义的变量名,

在想这个是什么变量的时候,能根据名字直接联想出来就好了。

由于敌人必须带有很多各种各样的信息,所以这里定义了很多的变量,不过这并不是什么很难的东西。

我们把用来表示游戏中的计数的 stage_count 变量,和保存敌机图像的 img_enemy 变量先准备好。

在 define 里,把表示可以同时显示的敌机最大数量设置为30,定义在ENEMY_MAX 里面。

—————————————————————————————————————————————————————————————————————————————

--GV.h 里加入下面代码--

GLOBAL int stage_count;
GLOBAL int img_enemy[3][9];//9张敌机图像 X3份
GLOBAL enemy_t enemy[ENEMY_MAX];

--define.h 里加入下面代码--

//敌机的同时显示的最大数量
#define ENEMY_MAX 30

--load.cpp 里加入下面代码--

LoadDivGraph( "../dat/img/enemy/0.png" , 9 , 3 , 3 , 32 , 32 , img_enemy[0] ) ;

—————————————————————————————————————————————————————————————————————————————

初始化函数分为,启动之后,可以多次执行的初始化,和只在游戏刚开始就得进行的初始化这两种。

下面举个例子吧,键位的初始设置等等,在游戏刚开始的时候就不是必须得执行的,

但自机的数据,敌机的数据的初始化等等,在游戏刚开始时就必须执行。

—————————————————————————————————————————————————————————————————————————————

--ini.cpp改动--

#include "../include/GV.h"

//最开始的初始化
void first_ini(){
        configpad.down=0;
        configpad.left=1;
        configpad.right=2;
        configpad.up=3;
        configpad.bom=4;
        configpad.shot=5;
        configpad.slow=11;
        configpad.start=13;
        configpad.change=6;
}

//游戏的初始化
void ini(){
        stage_count=1;
        memset(&ch,0,sizeof(ch_t));//自机数据的初始化
        ch.x=FIELD_MAX_X/2;
        ch.y=FIELD_MAX_Y*3/4;
        memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);//敌机数据的初始化
}

—————————————————————————————————————————————————————————————————————————————

敌人数据的处理是个大的流程。

当游戏计数到达某个点的时候,敌机就载入(enemy_enter)。

如果有已经载入的敌机,就把敌机的移动模式(enemy_pattern),传入对敌机进行移动的操作函数,进行敌机的移动。

敌机移动画面外面的话,就把敌机载入的标志设置为假。

大概就是这样的流程

—————————————————————————————————————————————————————————————————————————————

--enemy.cpp 改动--

#include "../include/GV.h"

//敌机的移动模式0 的移动操作
void enemy_pattern0(int i){
    if(enemy[i].cnt<60){
        enemy[i].y+=2.0;
    }
    if(enemy[i].cnt>60+240){
        enemy[i].y-=2.0;
    }
}

//敌机数据载入
void enemy_enter(){
    if(stage_count==100){	//从游戏开始后计数到了100时载入
        enemy[0].cnt    =0;
        enemy[0].muki   =1;
        enemy[0].flag   =1;
        enemy[0].bltime =150;
        enemy[0].hp     =1000;
        enemy[0].hp_max =enemy[0].hp;
        enemy[0].pattern=0;
        enemy[0].x      =FIELD_MAX_X/2;
        enemy[0].y      =-20;
    }
}

//敌机的行动操作
void enemy_act(){
    int i;
    for(i=0;i<ENEMY_MAX;i++){
        if(enemy[i].flag==1){	//敌机的标志为开启状态
            enemy_pattern0(i);
            enemy[i].cnt++;
            enemy[i].img=enemy[i].muki*3+(enemy[i].cnt%18)/6;
            //敌机从画面中消失
            if(enemy[i].x<-50 || FIELD_MAX_X+50<enemy[i].x || enemy[i].y<-50 || FIELD_MAX_Y+50<enemy[i].y)
                enemy[i].flag=0;
        }
    }
}

//敌机处理的main方法
void enemy_main(){
    enemy_enter();
    enemy_act();
}
—————————————————————————————————————————————————————————————————————————————

绘画处理要增加的,只是对敌机数据的绘制而已。

寻找载入了的敌机数据,对其进行绘制显示。

——————————————————————————————————————————————————————————————————————

--graph.cpp 的改动--

#include "../include/GV.h"

void graph_enemy(){
        int i;
        for(i=0;i<ENEMY_MAX;i++){
                if(enemy[i].flag==1){
                        DrawRotaGraphF(enemy[i].x+FIELD_X,enemy[i].y+FIELD_Y,1.0f,0.0f,img_enemy[0][enemy[i].img],TRUE);
                }
        }
}

void graph_ch(){
        DrawRotaGraphF(ch.x+FIELD_X,ch.y+FIELD_Y,1.0f,0.0f,img_ch[0][ch.img],TRUE);
}

void graph_board(){
        DrawGraph(  0,  0,img_board[10],FALSE);
        DrawGraph(  0, 16,img_board[11],FALSE);
        DrawGraph(  0,464,img_board[12],FALSE);
        DrawGraph(416,  0,img_board[20],FALSE);
}

void graph_main(){
        graph_enemy();
        graph_ch();
        graph_board();
}
————————————————————————————————————————————————————————————————————————————

main函数只改动了红色部分(这里就不标颜色了,主要在case 99 和100 的改动)

—————————————————————————————————————————————————————————————————————————————

--main.cpp 的改动--

#define GLOBAL_INSTANCE
#include "../include/GV.h"

//主循环里必须做的三大处理
int ProcessLoop()
{
    if(ProcessMessage()!=0)
        return -1   ;       //Process处理出错的话,返回-1
    if(ClearDrawScreen()!=0)
        return -1;          //画面清理出错的话,返回-1
    GetHitKeyStateAll_2();  //当前键盘输入处理
    GetHitPadStateAll();    //当前手柄输入处理
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    ChangeWindowMode(TRUE);     //窗口模式
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1; //初始化和设置双缓冲模式

    while(ProcessLoop()==0)     //主循环
    {
        switch(func_state)
        {
        case 0:    			//第一次进入时处理
            load();         //载入数据
            first_ini();    //第一次初始化
            func_state=99;
            break;
        case 99:			//射击游戏开始前的初始化
            ini();
            func_state=100;
            break;
        case 100:    		//一般的处理
            calc_ch();      //计算角色的使用图片
            ch_move();      //角色的移动操作
            enemy_main();	//敌机处理的主函数
            graph_main();   //主绘画函数
            stage_count++;
            break;
        default:
            printfDx("未知的func_state\n");
            break;
        }

        if(CheckStateKey(KEY_INPUT_ESCAPE)==1)
            break;          //按下ESC的话,break
        ScreenFlip();       //交换双缓冲画面
    }

    DxLib_End();    //DxLib中止
    return 0;
}
—————————————————————————————————————————————————————————————————————————————

这次新增的函数还需要声明一下。

——————————————————————————————————————————————————————————————————————————

-- function.h 里面添加如下代码 --

GLOBAL void enemy_main();
GLOBAL void ini();

——————————————————————————————————————————————————————————————————————————

运行结果:

http://dixq.net/rp/swf/10.swf

过一会,敌人会下落,然后过一会,敌人又往上升,就对了。


本人CSDN博客目录:

http://blog.csdn.net/tidus5


展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值