欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++基于EasyX框架實現(xiàn)飛機大戰(zhàn)小游戲

 更新時間:2023年01月06日 11:13:27   作者:Leleprogrammer  
EasyX是針對C/C++的圖形庫,可以幫助使用C/C++語言的程序員快速上手圖形和游戲編程。本文將利用EasyX框架實現(xiàn)飛機大戰(zhàn)小游戲,需要的可以參考一下

正式使用Easyx之前,你需要先安裝他??!

EasyX 2022 版 (2022-9-1 更新) - EasyX

選擇合適的版本安裝

安裝結(jié)束后就可以開始敲代碼啦!

這里作者使用的是Visual Studio 2022所以安裝EasyX_20220901版本

啟動Visual Studio 2022,新建一個空項目

這是工程目錄:

首先來看看Bullet(子彈)類

頭文件:

#pragma once
class Bullet
{
public:
    Bullet(int x, int y, int owner);
    int owner; // 0 means player, 1 means enemy
    int x;
    int y;
    int speed;
    int pic_w = 5;
    int pic_h = 11;
    bool dead = false;
    void move();
    void checkBound();
};

源文件:

#include "Bullet.h"
#include "constants.h"
 
Bullet::Bullet(int x, int y, int owner) {
    this->x = x;
    this->y = y;
    this->owner = owner;
    speed = 12;
}
 
void Bullet::move() {
    if (owner == 0) {
        y -= speed;
    }
    else {
        y += speed;
    }
}
 
void Bullet::checkBound() {
    if (owner == 0) {
        if (y + pic_h <= 0) {
            dead = true;
        }
    }
    else {
        if (y >= HEIGHT) {
            dead = true;
        }
    }
}

這里簡單地實現(xiàn)了子彈的移動和檢測超出邊界,不難理解

Enemy類頭文件:

#pragma once
class Enemy
{
public:
    Enemy(int type);
    int x;
    int y;
    int speed;
    int pic_w;
    int pic_h;
    int type;
    int health;
    int static_health;
    bool dead = false;
    void move();
    void checkBound();
};

源文件:

#include "Enemy.h"
#include "constants.h"
 
Enemy::Enemy(int type) {
    this->type = type;
    switch (type) {
    case 1:
        pic_w = 60;
        pic_h = 44;
        health = random(1, 2);
        break;
    case 2:
        pic_w = 70;
        pic_h = 100;
        health = random(3, 4);
        break;
    case 3:
        pic_w = 160;
        pic_h = 250;
        health = random(5, 6);
        break;
    default:
        pic_w = 60;
        pic_h = 44;
        health = 1;
        break;
    }
    x = random(0, WIDTH - pic_w);
    y = 0 - pic_h;
    speed = random(5,8);
    static_health = health;
}
 
void Enemy::move() {
    y += speed;
}
 
void Enemy::checkBound() {
    if (y >= HEIGHT || health <= 0) {
        dead = true;
    }
}

這里的類成員變量type表示敵機大小,3最大,同時血量最多,也實現(xiàn)了移動和檢測超出邊界功能

有的人會發(fā)現(xiàn)random方法以及WIDTH常量等,這里是因為我們將這些常量寫在一個頭文件下:

constants.h:

#pragma once
 
#ifndef WIDTH
#define WIDTH 800
#endif
 
#ifndef HEIGHT
#define HEIGHT 1000
#endif
 
#include <cstdlib>
#include <string>
 
using namespace std;
 
#ifndef random(a,x)
#define random(a,x) a+rand()%x
#endif
 
const string PATH = "./resources/";

接下來是Player.h

#pragma once
#include <string>
#include "constants.h"
using namespace std;
 
class Player
{
public:
    Player();
    int speed;
    int y;
    int x;
    int pic_w;
    int pic_h;
    void move(int a);
    void checkBound();
};

Player.cpp:

#include "Player.h"
#include "constants.h"
 
Player::Player() {
    speed = 12;
    y = HEIGHT - 170;
    x = 300;
    pic_w = 100;
    pic_h = 126;
}
 
void Player::move(int a) {
    if (a == 0) { // left
        x -= speed;
    }
    else { // right
        x += speed;
    }
}
 
void Player::checkBound() {
    if (x < 0) {
        x = 0;
    }
    else if (x + pic_w > WIDTH) {
        x = WIDTH - pic_w;
    }
}

代碼都很短,也實現(xiàn)了移動和限制活動區(qū)域(checkBound)操作,不難理解

接下來是作者自己寫了一個實用的頭文件,用于判斷2者是否碰撞,CheckCollide.h:

#pragma once
 
bool collide(
    int l,
    int r,
    int t,
    int d,
    int el,
    int er,
    int et,
    int ed) {
    if ((l <= er && t <= ed && l >= el && t >= et) ||
        (r >= el && t <= ed && r <= er && t >= et) ||
        (l <= er && d >= et && l >= el && d <= ed) ||
        (r >= el && d >= et && r <= er && d <= ed)) {
        return true;
    }
    return false;
}

其中,l、r、t、d分別為第一個物體的左邊x坐標、右邊x坐標、上邊y坐標、下邊y坐標,el、er、et、ed是第二個物體的,然后進行判斷,返回bool值,這個待會在main.cpp會用到

接下來也是一個常用的頭文件,因為easyx渲染透明圖片很麻煩,所以這個方法通過計算來繪制,這個是借用了EasyX 繪制透明背景圖這篇文章的代碼,PhotoTransparent.h

#pragma once
 
#include <graphics.h>
#include "constants.h"
 
void drawAlpha(IMAGE* image, int x, int y, int width, int height, int pic_x = 0, int pic_y = 0, double AA = 1)
{
    // 變量初始化
    DWORD* dst = GetImageBuffer();            // GetImageBuffer() 函數(shù),用于獲取繪圖設(shè)備的顯存指針, EasyX 自帶
    DWORD* draw = GetImageBuffer();
    DWORD* src = GetImageBuffer(image);        // 獲取 picture 的顯存指針
    int imageWidth = image->getwidth();        // 獲取圖片寬度
    int imageHeight = image->getheight();    // 獲取圖片寬度
    int dstX = 0;                            // 在 繪圖區(qū)域 顯存里像素的角標
    int srcX = 0;                            // 在 image 顯存里像素的角標
 
    // 實現(xiàn)透明貼圖 公式: Cp=αp*FP+(1-αp)*BP , 貝葉斯定理來進行點顏色的概率計算
    for (int iy = 0; iy < height; iy++)
    {
        for (int ix = 0; ix < width; ix++)
        {
            // 防止越界
            if (ix + pic_x >= 0 && ix + pic_x < imageWidth && iy + pic_y >= 0 && iy + pic_y < imageHeight &&
                ix + x >= 0 && ix + x < WIDTH && iy + y >= 0 && iy + y < HEIGHT)
            {
                // 獲取像素角標
                int srcX = (ix + pic_x) + (iy + pic_y) * imageWidth;
                dstX = (ix + x) + (iy + y) * WIDTH;
 
                int sa = ((src[srcX] & 0xff000000) >> 24) * AA;            // 0xAArrggbb; AA 是透明度
                int sr = ((src[srcX] & 0xff0000) >> 16);                // 獲取 RGB 里的 R
                int sg = ((src[srcX] & 0xff00) >> 8);                    // G
                int sb = src[srcX] & 0xff;                                // B
 
                // 設(shè)置對應(yīng)的繪圖區(qū)域像素信息
                int dr = ((dst[dstX] & 0xff0000) >> 16);
                int dg = ((dst[dstX] & 0xff00) >> 8);
                int db = dst[dstX] & 0xff;
                draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16)  //公式: Cp=αp*FP+(1-αp)*BP  ; αp=sa/255 , FP=sr , BP=dr
                    | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)         //αp=sa/255 , FP=sg , BP=dg
                    | (sb * sa / 255 + db * (255 - sa) / 255);              //αp=sa/255 , FP=sb , BP=db
            }
        }
    }
}

接下來這一個是作者自己寫的一個常用的頭文件StringCharExchange.h:

#pragma once
 
#include <graphics.h>
#define BUFFERSIZE 1024
 
TCHAR* Transform(char c[BUFFERSIZE]) {
    TCHAR result[BUFFERSIZE];
    MultiByteToWideChar(CP_ACP, 0, c, -1, result, BUFFERSIZE);
    return result;
}
 
TCHAR* Transform(string s) {
    TCHAR result[BUFFERSIZE];
    char c[BUFFERSIZE];
    strcpy_s(c, s.c_str());
    MultiByteToWideChar(CP_ACP, 0, c, -1, result, BUFFERSIZE);
    return result;
}

上面實現(xiàn)了char*轉(zhuǎn)TCHAR*以及string轉(zhuǎn)TCHAR*

最后是main.cpp

#include <graphics.h>
#include "constants.h"
#include "Player.h"
#include "PhotoTransparent.h"
#include <time.h>
#include <vector>
#include "Bullet.h"
#include "Enemy.h"
#include "CheckCollide.h"
#include "StringCharExchange.h"
 
Player* player = new Player();
vector<Bullet>* bullets = new vector<Bullet>;
vector<Enemy>* enemies = new vector<Enemy>;
 
int startTime[5] = { 0 };
int durations[5] = { 200,1000,0,0,0 };
 
int health = 5;
int score = 0;
bool lose = false;
 
void DrawBackGroundImage() {
    IMAGE img;
    loadimage(&img, Transform(PATH+"background2.png"), WIDTH, HEIGHT);
    putimage(0, 0, &img);
}
 
void DrawPlayer() {
    IMAGE img;
    loadimage(&img, Transform(PATH + "myplane1.png"), player->pic_w, player->pic_h);
    drawAlpha(&img, player->x, player->y, player->pic_w, player->pic_h);
}
 
void DrawBullets() {
    for (int i = 0;i < bullets->size();i++) {
        Bullet* bullet = &(bullets->at(i));
        IMAGE img;
        loadimage(&img, Transform(PATH + "bullet1.png"));
        drawAlpha(&img, bullet->x, bullet->y, bullet->pic_w, bullet->pic_h);
    }
}
 
void DrawEnemies() {
    for (int i = 0;i < enemies->size();i++) {
        Enemy* enemy = &(enemies->at(i));
        IMAGE img;
        switch (enemy->type) {
        case 1:
            loadimage(&img, Transform(PATH + "small_enemy.png"));
            break;
        case 2:
            loadimage(&img, Transform(PATH + "mid_enemy.png"));
            break;
        case 3:
            loadimage(&img, Transform(PATH + "big_enemy.png"));
            break;
        default:
            break;
        }
        drawAlpha(&img, enemy->x, enemy->y, enemy->pic_w, enemy->pic_h);
    }
}
 
void UpdateBullets() {
    for (int i = 0;i < bullets->size();i++) {
        Bullet* bullet = &(bullets->at(i));
        bullet->move();
        bullet->checkBound();
        if (bullet->dead) {
            swap(bullets->at(i), bullets->at(bullets->size() - 1));
            bullets->pop_back();
            i--;
        }
    }
}
 
void UpdateEnemies() {
    for (int i = 0;i < enemies->size();i++) {
        Enemy* enemy = &(enemies->at(i));
        enemy->move();
        enemy->checkBound();
        if (enemy->dead) {
            swap(enemies->at(i), enemies->at(enemies->size() - 1));
            enemies->pop_back();
            i--;
        }
    }
}
 
void CheckPlayerHit() {
    for (int i = 0;i < enemies->size();i++) {
        Enemy* enemy = &(enemies->at(i));
        int l, r, t, d;
        int el, er, et, ed;
        l = player->x;
        r = player->x + player->pic_w;
        t = player->y;
        d = player->y + player->pic_h;
        el = enemy->x;
        er = enemy->x + enemy->pic_w;
        et = enemy->y;
        ed = enemy->y + enemy->pic_h;
        if (collide(l, r, t, d, el, er, et, ed)) {
            health--;
            swap(enemies->at(i), enemies->at(enemies->size() - 1));
            enemies->pop_back();
            i--;
        }
    }
}
 
void CheckBulletHit() {
    for (int i = 0;i < bullets->size();i++) {
        Bullet* bullet = &(bullets->at(i));
        int l, r, t, d;
        l = bullet->x;
        r = bullet->x + bullet->pic_w;
        t = bullet->y;
        d = bullet->y + bullet->pic_h;
        for (int j = 0;j < enemies->size();j++) {
            Enemy* enemy = &(enemies->at(j));
            int el, er, et, ed;
            el = enemy->x;
            er = enemy->x + enemy->pic_w;
            et = enemy->y;
            ed = enemy->y + enemy->pic_h;
            if (collide(l, r, t, d, el, er, et, ed)) {
                enemy->health--;
                if (enemy->health <= 0 || enemy->dead) {
                    score += enemy->static_health;
                    swap(enemies->at(j), enemies->at(enemies->size() - 1));
                    enemies->pop_back();
                }
                j--;
                swap(bullets->at(i), bullets->at(bullets->size() - 1));
                bullets->pop_back();
                i--;
                break;
            }
        }
    }
}
 
void _DrawText() {
    settextcolor(RGB(0, 0, 255));
    settextstyle(26, 0, _T("simhei"));
    char c[BUFFERSIZE];
    snprintf(c, 64, "Health: %d", health);
    TCHAR* c2 = Transform(c);
    outtextxy(10, 10, c2);
    settextcolor(RGB(255, 0, 0));
    settextstyle(26, 0, _T("simhei"));
    char c3[BUFFERSIZE];
    snprintf(c3, 64, "Score: %d", score);
    TCHAR* c4 = Transform(c3);
    outtextxy(10, 44, c4);
}
 
void CheckLose() {
    if (health <= 0) {
        lose = true;
    }
}
 
void Draw() {
    CheckLose();
    DrawBackGroundImage();
    _DrawText();
    if (!lose) {
        UpdateBullets();
        UpdateEnemies();
        CheckPlayerHit();
        CheckBulletHit();
        DrawPlayer();
        DrawEnemies();
        DrawBullets();
    }
}
 
void Timer() {
    int endTime = clock();
    if (endTime - startTime[0] >= durations[0]) { // Create bullet event
        bullets->push_back(Bullet(player->x + player->pic_w / 2, player->y, 0));
        startTime[0] = endTime;
    }
    if (endTime - startTime[1] >= durations[1]) { // Create enemy event
        enemies->push_back(Enemy(random(1,3)));
        startTime[1] = endTime;
    }
}
 
int Listen() {
    if (GetAsyncKeyState(VK_ESCAPE)) {
        return 1;
    }
    if (GetAsyncKeyState(VK_LEFT)) {
        player->move(0);
        player->checkBound();
    }
    if (GetAsyncKeyState(VK_RIGHT)) {
        player->move(1);
        player->checkBound();
    }
    return 0;
}
 
int main() {
    initgraph(WIDTH, HEIGHT);
    setbkmode(TRANSPARENT);
    BeginBatchDraw();
    while (true) {
        Draw();
        if (Listen()) {
            break;
        }
        Timer();
        FlushBatchDraw();
    }
    EndBatchDraw();
    closegraph();
    return 0;
}

實現(xiàn)了程序的主流程

到此這篇關(guān)于C++基于EasyX框架實現(xiàn)飛機大戰(zhàn)小游戲的文章就介紹到這了,更多相關(guān)C++ EasyX飛機大戰(zhàn)游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++類繼承時的構(gòu)造函數(shù)

    C++類繼承時的構(gòu)造函數(shù)

    這篇文章主要介紹了C++類繼承時的構(gòu)造函數(shù),C++中,子類繼承父類除去構(gòu)造函數(shù)和析構(gòu)函數(shù)以外的所有成員。因此,子類需要編寫自己的構(gòu)造函數(shù)和析構(gòu)函數(shù)。更多相關(guān)詳情需要的小伙伴可以參考下面文章介紹
    2022-03-03
  • C語言中的時間函數(shù)clock()和time()你都了解嗎

    C語言中的時間函數(shù)clock()和time()你都了解嗎

    這篇文章主要為大家詳細介紹了C語言中的時間函數(shù)clock()和time(),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C++多線程實現(xiàn)綁定CPU的方法詳解

    C++多線程實現(xiàn)綁定CPU的方法詳解

    這篇文章主要為大家詳細介紹了C++如何利用多線程實現(xiàn)綁定CPU,文中的示例代碼簡潔易懂,具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-05-05
  • 一篇文章讓你輕松理解C++中vector和list區(qū)別

    一篇文章讓你輕松理解C++中vector和list區(qū)別

    對于學(xué)c語言的同學(xué)來說,vector和list這兩個東西經(jīng)常會搞錯,下面這篇文章主要給大家介紹了關(guān)于C++中vector和list區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • 使用C語言打印月歷

    使用C語言打印月歷

    這篇文章主要為大家詳細介紹了使用C語言打印月歷,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C語言實現(xiàn)數(shù)獨程序的示例代碼

    C語言實現(xiàn)數(shù)獨程序的示例代碼

    數(shù)獨是源自瑞士的一種數(shù)學(xué)游戲。是一種運用紙、筆進行演算的邏輯游戲。本文將利用C語言實現(xiàn)數(shù)獨程序,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03
  • 一篇文章帶你入門C語言數(shù)據(jù)結(jié)構(gòu):緒論

    一篇文章帶你入門C語言數(shù)據(jù)結(jié)構(gòu):緒論

    這篇文章主要介紹了C語言的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對廣大的程序愛好者有所幫助,同時祝大家有一個好成績,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • 探討C++中數(shù)組名與指針的用法比較分析

    探討C++中數(shù)組名與指針的用法比較分析

    本篇文章是對C++中數(shù)組名與指針用法的比較進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++隨機生成迷宮算法

    C++隨機生成迷宮算法

    這篇文章主要為大家詳細介紹了C++隨機生成迷宮算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C++ OpenGL實現(xiàn)三角形的繪制

    C++ OpenGL實現(xiàn)三角形的繪制

    這篇文章主要主要為大家詳細介紹了如何利用C++和OpenGL實現(xiàn)三角形的繪制,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起動手嘗試一下
    2022-06-06

最新評論