使用手机C4droid编译器的SDL2库写的打飞机
(水平很有限,仅仅是基本实现能玩)
希望可以和大家一起学习进步
这段代码复制下来就能用,图片素材都在上面,字体顺便网上下载
#include <iostream>
#include <string>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <time.h>
#include <SDL2/SDL_ttf.h>
#define WIDTH 1000
#define HEIGHT 2000
#define ERROR_FONT_SIZOF 80
//字体大小
#define FRAMERATE 60
//帧率
#define BULLET_SPEED 5
//子弹速度
#define ENEMY_SPEED 3
//敌机速度
#define FONT_NANE "/storage/emulated/0/1/resource//ttf/15.ttf"
#define PLANE_FILE "/storage/emulated/0/1/resource/aircraft.png"
#define BULLET_FILE "/storage/emulated/0/1/resource/bullet.png"
#define ENEMY_FILE "/storage/emulated/0/1/resource/enemy.png"
//上面的路径自己修改自己手机图片的路径就好
using namespace std;
SDL_Window *window;
SDL_Renderer *renderer;
TTF_Font *font = NULL;
SDL_bool move_no = SDL_FALSE;
bool init();
void showvalue(string a, int g, int x, int y);
void close();
class plane //飞机类
{
public:
plane();
SDL_Texture *img;
SDL_Surface *simg;
int planew;
int planeh;
SDL_Rect imgr;
SDL_Rect srcr;
int mouseplane(SDL_Event *event);
SDL_Rect &draw();
~plane();
};
class bullet //子弹类
{
public:
bullet();
SDL_Texture *img;
SDL_Surface *simg;
SDL_Rect imgr;
SDL_Rect srcr;
bullet *last;
bullet *next;
bool show;
void move(SDL_Rect rect);
int bulletw;
int bulleth;
SDL_Rect *returect();
void draw(int y);
~bullet();
};
class enemy //敌机类
{
public:
enemy();
SDL_Texture *img;
SDL_Surface *simg;
SDL_Rect imgr;
SDL_Rect srcr;
enemy *last;
enemy *next;
bool show;
SDL_Rect *returect();
int enemyw;
int enemyh;
SDL_Rect &draw(int y);
~enemy();
};
int main(int argc, char *argv[])
{
init(); //初始化函数
plane plane1; //飞机对象
//这里用指针圆形链表创建子弹和敌机
bullet *butemp = new bullet;
bullet *butip2, *butip;
butip = butemp;
butemp->srcr.y = HEIGHT - 50;
butemp->next = butemp;
butemp->last = butemp;
//
enemy *entemp = new enemy;
enemy *entip2 = new enemy;
entip2->srcr.y = 50;
enemy *entip = entemp;
entip2->next = entemp;
entip2->last = entemp;
entemp->next = entip2;
entemp->last = entip2;
//
int i = 0; //帧数
int grade = 0; //分数
int tt = 0;
while (1)
{
long begin = SDL_GetTicks(); //测时间开点
SDL_SetRenderDrawColor(renderer, 55, 55, 55, 255);
SDL_RenderClear(renderer); //以上面的颜色清屏,分别是R.G.B.α透明
SDL_Rect bullet_rect;
bullet_rect = plane1.draw();
//创建子弹链
if (i % 40 == 1) //每到这里往链表里面塞一个对象
{
butemp = butip;
butip = new bullet;
butip->next = butemp->next;
butip->last = butemp;
butemp->next->last = butip;
butemp->next = butip;
butip->move(bullet_rect); //子弹的初始位置等于当前本机的位置
}
butip2 = butip;
do
{
butip->draw(5);
if (butip->srcr.y < -400) //判断是否到达边界,这里设置的比较远是因为不能让同时只能存在一个子弹
{
butemp = butip;
butip->last->next = butip->next;
butip->next->last = butip->last;
butip = butip->last;
butemp->~bullet();
free(butemp);
butemp = NULL;
}
butip = butip->next;
} while (butip != butip2);
//
//创建敌机链
if (i % (60 - (i / 100)) == 1)//敌机的创建速度跟随帧率
{
entip = entip2->next;
entemp = new enemy;
entip2->next = entemp;
entip->last = entemp;
entemp->next = entip;
entemp->last = entip2;
entip = entemp;
}
entip2 = entip;
do
{
entip->draw(ENEMY_SPEED + i / 800);//帧数每增加800个,速度加1
if (entip->srcr.y > HEIGHT) //判断是否到达边界
{
entemp = entip;
entip->last->next = entip->next;
entip->next->last = entip->last;
entip = entip->last;
entemp->~enemy();
free(entemp);
entemp = NULL;
}
entip = entip->next;
} while (entip != entip2);
///*
butip2 = butip;
entip2 = entip;
do
{
do
{
//判断是否接触
if (SDL_HasIntersection(entip->returect(), butip->returect()))
{
//showvalue("jz", entip->srcr.y, 0, 300);
butip->show = false; //这里不删除,发现总会删除标记指针,索性直接这个链元素直接隐藏,
entip->show = false; //并且上面的判断函数里面的返回该链对象Rect的函数都返回一个固定框,确保不会相交
grade++;
}
entip = entip->next;
} while (entip != entip2);
butip = butip->next;
} while (butip != butip2);
showvalue("grade:", grade, 0, 100);
i++;
showvalue("zhen", i, 0, 500);
int bb = 0;
do //循环判断敌机与本机是否接触,但这里使用图片的大小方块,判定距离有点大
{
if (SDL_HasIntersection(&(plane1.srcr), entip->returect()))
{
showvalue("jz", entip->srcr.y, 0, 300);
bb = 1;
break;
}
entip = entip->next;
} while (entip != entip2);
if (bb)
{
break;
}
SDL_RenderPresent(renderer);
//
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_MOUSEMOTION:;
case SDL_MOUSEBUTTONDOWN:;
case SDL_MOUSEBUTTONUP:
plane1.mouseplane(&event);
break;
case SDL_QUIT:
return 0;
}
}
//*/
long current = SDL_GetTicks(); //测时间结束点
long cost = current - begin;
long frame = 1000 / FRAMERATE;
long delay = frame - cost;
if (delay > 0) //通过上面的来计算一帧的时间。
{
SDL_Delay(delay);
}
}
showvalue("beybey", 0, WIDTH / 3, HEIGHT / 2);
SDL_RenderPresent(renderer);
SDL_Delay(2000);
close();
return 0;
}
bool init()
{
// 初始化SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "SDL初始化失败。SDL错误:" << SDL_GetError() << std::endl;
return false;
}
// 创建窗口
window = SDL_CreateWindow("SDL Font Rendering", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL)
{
std::cout << "窗口创建失败。SDL错误:" << SDL_GetError() << std::endl;
return false;
}
// 创建渲染器
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL)
{
std::cout << "渲染器创建失败。SDL错误:" << SDL_GetError() << std::endl;
return false;
}
// 设置渲染器绘制颜色为白色
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
// 初始化SDL_ttf
if (TTF_Init() == -1)
{
std::cout << "SDL_ttf初始化失败。SDL_ttf错误:" << TTF_GetError() << std::endl;
return false;
}
font = TTF_OpenFont(FONT_NANE, ERROR_FONT_SIZOF);
if (font == NULL)
{
std::cout << "字体加载失败。TTF错误:" << TTF_GetError() << std::endl;
return false;
}
return true;
}
void showvalue(string a, int g, int x = 100, int y = 100) //这是一个显示字符的函数
{
char yy[16];
sprintf(yy, "%s:%d", a.c_str(), g);
SDL_Color color = {255, 0, 0, 0};
SDL_Surface *fontsurface = TTF_RenderText_Solid(font, yy, color);
SDL_Texture *fontTexture = SDL_CreateTextureFromSurface(renderer, fontsurface);
SDL_Rect textRect;
textRect.x = x;
textRect.y = y;
textRect.w = fontsurface->w;
textRect.h = fontsurface->h;
SDL_FreeSurface(fontsurface);
SDL_RenderCopy(renderer, fontTexture, NULL, &textRect);
SDL_DestroyTexture(fontTexture);
}
void close()
{
// 释放字体资源
TTF_CloseFont(font);
font = NULL;
// 销毁渲染器和窗口
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
renderer = NULL;
window = NULL;
// 退出SDL_ttf
TTF_Quit();
// 退出SDL
SDL_Quit();
}
plane::plane() //飞机类的构造函数
{
this->img = IMG_LoadTexture(renderer, PLANE_FILE);
if (this->img == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
}
this->simg = IMG_Load(PLANE_FILE);
if (this->simg == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
};
this->planew = WIDTH / 5; //是图像大小为屏幕宽度的1/5
this->planeh = WIDTH / 5;
//(int)( (float)(planew) /(float)(this->simg->w) * (float)(this->simg->h));
this->imgr = {0, 0, (this->simg->w), (this->simg->h)};
this->srcr = {WIDTH / 2 - planew / 2, HEIGHT - planeh * 2, planew, planeh};
}
int plane::mouseplane(SDL_Event *event) 把鼠标的位置传给图像方块
{
SDL_Point mousep = {event->button.x,
event->button.y};
switch (event->type)
{
case SDL_MOUSEMOTION:
{
if (move_no == SDL_TRUE) //按下且移动鼠标时才能移动
{
showvalue("1", mousep.x, 0, 0);
this->srcr.x = event->button.x - this->planew / 2;
this->srcr.y = event->button.y - this->planeh / 2;
move_no = SDL_TRUE;
return 0;
}
break;
}
case SDL_MOUSEBUTTONDOWN:
{
if (SDL_PointInRect(&mousep, &(this->srcr))) //判断鼠标按下的位置是不是在图像的上
{
showvalue("down", 1, 0, 100);
move_no = SDL_TRUE; //在图像上按下了鼠标
return 0;
}
break;
}
case SDL_MOUSEBUTTONUP:
{
move_no = SDL_FALSE; //松开鼠标停止移动。
return 0;
break;
}
default:
break;
}
return 0;
}
SDL_Rect &plane::draw()
{
SDL_RenderCopy(renderer, this->img, &(this->imgr), &(this->srcr));
return this->srcr;
}
plane::~plane()
{
SDL_DestroyTexture(this->img);
SDL_FreeSurface(this->simg);
};
bullet::bullet()
{
this->img = IMG_LoadTexture(renderer, BULLET_FILE);
if (this->img == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
}
this->simg = IMG_Load(BULLET_FILE);
if (this->simg == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
};
this->bulletw = WIDTH / 30; //根据屏幕宽度设置子弹的大小
this->bulleth = WIDTH / 18;
this->show = true; //默认显示子弹
this->imgr = {0, 0, (this->simg->w), (this->simg->h)};
this->srcr = {WIDTH / 2, HEIGHT - 100, bulletw, bulleth};
}
void bullet::move(SDL_Rect rect) //鼠标位置转换成子弹的位置。
{
this->srcr.x = rect.x + rect.w / 2 - this->srcr.w / 2;
this->srcr.y = rect.y;
}
void bullet::draw(int y) //显示子弹,并按照传入的数值每帧移动。
{
this->srcr.y = this->srcr.y - y;
if (this->show)
{
SDL_RenderCopy(renderer, this->img, &(this->imgr), &(this->srcr));
}
return;
}
SDL_Rect *bullet::returect()
{
if (this->show)
{
return &(this->srcr); //如果依旧没有结束,始终是判断为显示,则输出该方块的位置
}
else
{
SDL_Rect temp = {0, 3, 0, 0}; //如果接触了,位置始终是在这个点。
return &temp;
}
}
bullet::~bullet() //子弹类的析构函数
{
SDL_DestroyTexture(this->img);
SDL_FreeSurface(this->simg);
};
enemy::enemy() //敌机类的构造函数。
{
this->img = IMG_LoadTexture(renderer, ENEMY_FILE);
if (this->img == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
}
this->simg = IMG_Load(ENEMY_FILE);
if (this->simg == NULL)
{
SDL_Log("图片加载失败:%s", SDL_GetError());
return;
};
this->enemyw = WIDTH / 6; //按屏幕宽度的比值显示敌机
this->enemyh = WIDTH / 6;
this->show = true;
//srand(time(0));
//(int)( (float)(planew) /(float)(this->simg->w) * (float)(this->simg->h));
this->imgr = {0, 0, (this->simg->w), (this->simg->h)};
this->srcr = {(rand() % (WIDTH / this->enemyw)) * this->enemyw, -(this->enemyh), this->enemyw, this->enemyh};
}
SDL_Rect &enemy::draw(int y)
{
this->srcr.y = this->srcr.y + y;
if (this->show)
{
SDL_RenderCopy(renderer, this->img, &(this->imgr), &(this->srcr));
}
return this->srcr;
}
SDL_Rect *enemy::returect()
{
if (this->show) //如果你是没有接触显示,则输出敌机的位置。
{
return &(this->srcr);
}
else
{
SDL_Rect temp = {0, 0, 0, 0}; //如果接触了判断不显示,则始终输出该位置。
return &temp;
}
}
enemy::~enemy()
{
SDL_DestroyTexture(this->img);
SDL_FreeSurface(this->simg);
};
//不足之处请恳请大家积极指导。