使用基于C4droid的SDL2库写的打飞机游戏(未完成,只是基本能玩)

使用手机C4droid编译器的SDL2库写的打飞机
(水平很有限,仅仅是基本实现能玩)
希望可以和大家一起学习进步

09a48b7945224975a752b28571e8f865.png

e39dd99bdaf24671a5019859719c20e3.png 

681ac219a82d4ba7b1b6424befcc210a.png 

 

这段代码复制下来就能用,图片素材都在上面,字体顺便网上下载


#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);
};

//不足之处请恳请大家积极指导。
 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值