原文地址:
既然是做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();
——————————————————————————————————————————————————————————————————————————
运行结果:
过一会,敌人会下落,然后过一会,敌人又往上升,就对了。
本人CSDN博客目录: