首页 > 其他分享 >SDL下创建移动的图片

SDL下创建移动的图片

时间:2024-10-10 12:49:37浏览次数:11  
标签:longer int 创建 image texture SDL 移动 图片

在上一章,我们已经了解到如何设置窗口背景,现在,我们将继续引进几张新图片,让它能够在窗口移动。下面的链接可以回顾前面的内容:

SDL下设置窗口背景图片

1.我们先要确定我们在窗口移动的是哪些图片和图片的大小。

string a[] = { "furong1.jpg",
               "furong2.jpg",
               "furong3.jpg",
               "furong4.jpg",
               "furong5.jpg" 
              };
const int image_longer = 100;

我们将这些图片放进了一个数组中,方便后面的读取操作,这里放的是图片的位置,因为我是把图片放在当前编译文件夹下的,所以直接用的图片名字,如果放在其他的文件夹下,要写出文件夹的位置。

2.编写一个函数,用来将图片的结构转换成纹理数据,也就是能够显示在窗口上的结构数据。

SDL_Texture* texture_image(const string& oip, SDL_Renderer* render)
{
    // 加载移动图片
    SDL_Surface* move_surface = IMG_Load(oip.c_str());
    if (!move_surface) {
        printf("移动的图片不能被加载! SDL_image Error: %s\n", IMG_GetError());
        return nullptr;
    }
    //将图片数据转换成纹理数据
    SDL_Texture* texture = SDL_CreateTextureFromSurface(render, move_surface);
    if (!texture) {
        printf("不能将Surface转换为Texrure! SDL_Error: %s\n", SDL_GetError());
        return nullptr;
    }
    return texture;
}

在上一章我们已经了解过了,`SDL_Suface()`函数只是将图片初步处理,通常用于存储未经优化的原始图像数据,而`SDL_Texture()`函数是一种专为渲染优化的数据结构,将图片数据转换成纹理数据,也就能直接映射到窗口上显示出来了。

3.初始化图片位置

void RandomPoints(int longer,int higt, int image_longer)
{
    \\定义一个随机数生成器,它可以定义一个伪随机数。
    default_random_engine e;
    \\定义一个整数范围在(1,longer-image_longer)的均匀分布,用于生成指定范围内的随机整数。
    uniform_int_distribution<int> u(1, (longer - image_longer));
    \\保证在多次调用时能保留种子数,这确保了每次程序运行时生成的随机数序列是不同的。
    static bool seeded = false;
    if (!seeded) {
        e.seed(static_cast<unsigned int>(time(0)));
        seeded = true;
    }
    for (int i = 0; i <= 4; i++)
    {

        lo[i].x = u(e);
        cout << i << " " << lo[i].x << endl;
    }
    std::uniform_int_distribution<int> n(1, (higt - image_longer));
    for (int i = 0; i <= 4; i++)
    {

        lo[i].y = n(e);
        cout << i << " " << lo[i].y << endl;
    }
     
}

这里我们是通过一个创建随机数,确定图片距离窗口左上角的位置,我们使用当前时间作为种子,保证随机数生成器能够生成随机序列。(在概率论和统计学中,均匀分布也叫矩形分布,它是对称概率分布,在相同长度间隔的分布概率是等可能的。)

4.使图片能够自主移动

//初始化每张图片在x轴和y轴上的移动方向
int v_x[] = {1,1,1,1,1};
int v_y[] = {1,1,1,1,1};
bool run=true;
while(!run){
 for (int i = 0; i <= 4; i++)
 {
     //获取图片的纹理
     SDL_Texture* texture = texture_image(a[i], renderer);
     //每次移动3像素。
     lo[i].x += v_x[i]*3;
     lo[i].y += v_y[i]*3;
     //如果图片碰到了窗口边缘,向反方向移动。
     if (lo[i].x <= 0|| lo[i].x >= (length - image_longer))
         v_x[i] *= -1;
     else if(lo[i].y<=0||lo[i].y>=(high-image_longer))
         v_y[i] *=-1;
     //更新图片位置
     SDL_Rect rect = { lo[i].x,lo[i].y,image_longer,image_longer};
     SDL_RenderCopy(renderer, texture, NULL, &rect);
     //释放纹理,防止空间泄露
     SDL_DestroyTexture(texture);

 }
}

我们通过不断的更新画面,来达到使图片有动感的效果。但我这里的做法是不准确的,每台电脑的屏幕刷新频率不是统一的,在我的电脑上,可能速度正合适,但是放在其他的电脑上就会出现过快或者过慢的现象。如何避免这种现象,我下次讲吧。最近耍如鸢耍的太入迷了,(这游戏好上头,现在好困)。

5.总的代码

#include <SDL.h>
#include <SDL_image.h>
#include<stdio.h>
#include<string>
#include<random>
#include<ctime>
#include<iostream>
const int length = 474;
const int high = 998;
const int image_longer = 100;
int v_x[] = {1,1,1,1,1};
int v_y[] = {1,1,1,1,1};
using namespace std;
string a[] = { "furong1.jpg",
               "furong2.jpg",
               "furong3.jpg",
               "furong4.jpg",
               "furong5.jpg" 
              };
typedef struct location
{
    int x;
    int y;
}location;
location lo[5];
SDL_Texture* texture_image(const string& oip, SDL_Renderer* render);
void RandomPoints(int longer, int image_longer,int higt);
int main(int argc, char* argv[]) {
    // 初始化 SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL视频子系统不能被初始化, SDL_Error: %s\n", SDL_GetError());
        return -1;
    }

    // 初始化 SDL_image 以支持 JPG 格式
    if (!(IMG_Init(IMG_INIT_JPG) & IMG_INIT_JPG)) {
        printf("SDL_image 不能被初始化! SDL_image Error: %s\n", IMG_GetError());
        return -1;
    }

    // 创建窗口
    SDL_Window* window = SDL_CreateWindow(
        "SDL Background ",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        length, high,
        SDL_WINDOW_SHOWN
    );
    if (!window) {
        printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
        return -1;
    }

    // 创建渲染器
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        printf("渲染器不能被创造! SDL_Error: %s\n", SDL_GetError());
        return -1;
    }

    // 加载背景图片
    SDL_Surface* background_surface = IMG_Load("OIP-C.jpg");
    if (!background_surface) {
        printf("xiaomu.jpg 不能被加载! SDL_image Error: %s\n", IMG_GetError());
        return -1;
    }
    

    // 将图片数据转换成纹理数据
    SDL_Texture* background_texture = SDL_CreateTextureFromSurface(renderer, background_surface);
    if (!background_texture) {
        printf("不能将Surface转换为Texrure! SDL_Error: %s\n", SDL_GetError());
        return -1;
    }

    // 释放Surface占用的内存
    SDL_FreeSurface(background_surface);
    //创建初始位置
    RandomPoints(length,image_longer,high);

    // 主循环
    bool quit = false;
    SDL_Event event;

    while (!quit) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                quit = true;
            }
        }

        // 清屏
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);

        // 渲染背景
        SDL_RenderCopy(renderer, background_texture, NULL, NULL);
        for (int i = 0; i <= 4; i++)
        {
            SDL_Texture* texture = texture_image(a[i], renderer);
            lo[i].x += v_x[i]*3;
            lo[i].y += v_y[i]*3;
            if (lo[i].x <= 0|| lo[i].x >= (length - image_longer))
                v_x[i] *= -1;
            else if(lo[i].y<=0||lo[i].y>=(high-image_longer))
                v_y[i] *=-1;
            SDL_Rect rect = { lo[i].x,lo[i].y,image_longer,image_longer};
            SDL_RenderCopy(renderer, texture, NULL, &rect);
            SDL_DestroyTexture(texture);

        }

        // 呈现内容
        SDL_RenderPresent(renderer);
    }

    // 清理资源
    SDL_DestroyTexture(background_texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    IMG_Quit();
    SDL_Quit();

    return 0;
}
SDL_Texture* texture_image(const string& oip, SDL_Renderer* render)
{
    // 加载移动图片
    SDL_Surface* move_surface = IMG_Load(oip.c_str());
    if (!move_surface) {
        printf("移动的图片不能被加载! SDL_image Error: %s\n", IMG_GetError());
        return nullptr;
    }
    //将图片数据转换成纹理数据
    SDL_Texture* texture = SDL_CreateTextureFromSurface(render, move_surface);
    if (!texture) {
        printf("不能将Surface转换为Texrure! SDL_Error: %s\n", SDL_GetError());
        return nullptr;
    }
    return texture;
}
void RandomPoints(int longer, int image_longer,int higt)
{
    std::default_random_engine e;
    std::uniform_int_distribution<int> u(1, (longer - image_longer));
    static bool seeded = false;
    if (!seeded) {
        e.seed(static_cast<unsigned int>(time(0)));
        seeded = true;
    }
    for (int i = 0; i <= 4; i++)
    {

        lo[i].x = u(e);
        cout << i << " " << lo[i].x << endl;
    }
    std::uniform_int_distribution<int> n(1, (higt - image_longer));
    for (int i = 0; i <= 4; i++)
    {

        lo[i].y = n(e);
        cout << i << " " << lo[i].y << endl;
    }
     
}

6.运行结果

<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="QBihhHeI-1728226832898" src="https://live.csdn.net/v/embed/428146"></iframe>

SDL下图片移动

代码还有很多可以改进的地方,因为我也是新手,哈哈哈哈哈哈哈,所以很多地方也没有优化思路,自己也不知道咋优化,还在学习中,大家一起加油啊!

标签:longer,int,创建,image,texture,SDL,移动,图片
From: https://blog.csdn.net/weixin_73918008/article/details/142720108

相关文章

  • 使用C#和WCF创建并托管简单服务的指南
    在C#中,实现WindowsCommunicationFoundation(WCF)功能通常涉及几个关键步骤,包括定义服务契约、实现服务、配置服务以及托管服务。下面是一个简单的示例,展示如何使用C#和WCF来创建一个简单的服务。步骤1:创建服务契约首先,我们需要定义一个服务契约,这通常是通过接口来......
  • 基于岗课赛证融合的移动应用开发实训室建设方案
    一、引言在经济与社会的快速发展背景下,5G通信技术正迅速成为主流,这导致了对移动应用开发专业人才的需求急剧上升。作为培养创新技术人才的先锋,高等职业院校不仅需要强化移动应用开发课程的建设,还必须致力于构建一流的移动应用开发实训环境。本文将从四个关键方面,详细探讨......
  • 【D3.js in Action 3 精译_032】第四章 D3 直线、曲线与弧线的绘制 + 4.1 坐标轴的创
    当前内容所在位置(可进入专栏查看其他译好的章节内容)第一部分D3.js基础知识第一章D3.js简介(已完结)1.1何为D3.js?1.2D3生态系统——入门须知1.3数据可视化最佳实践(上)1.3数据可视化最佳实践(下)1.4本章小结第二章DOM的操作方法(已完结)2.1第一......
  • 中国移动宽带 IPv6 连接到公网,家庭宽带设置服务器(2024年10月)
    摘要:1、中国移动的宽带,已经支持IPv6,需要宽带光猫上做好设置。2、需要从中国移动的服务器上获取公网IPv6地址。 操作:1、确保宽带WAN连接的前缀获取方式:PrefixDelegation网关的默认登录用户名(user)、密码,在设备的背面有写着。 如果不是,就联系客服,询问宽带终端的超级......
  • 【NVIDIA NIM 黑客松训练营】使用NVIDIA AI Workbench 创建一个在线代码生成器
    随着人工智能技术的不断进步,越来越多的工具和服务开始集成AI功能来提升用户体验。本教程将指导你如何使用PythonFlask框架结合NVIDIA提供的NIM服务,创建一个简单的在线代码生成器。用户可以通过一个直观的Web界面输入请求,系统将返回对应的Python代码。项目背景对于那些正......
  • 横向移动与痕迹清理
    目录横向移动漏洞利⽤服务利⽤IPC横向+计划任务横向计划任务横向WMI横向SMB横向DCOM横向WinRM横向PSEXEC横向其他⽅式横向软件部署利⽤GPO组策略横向密码喷洒密码策略检查喷洒主机喷洒⽤户名喷洒密码喷洒hash喷洒服务痕迹清除OPSEC清除webshell清除隧道⼯具清除落地......
  • 基于nodejs+vue移动购物管家app[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着移动互联网技术的迅猛发展,智能手机已成为人们日常生活中不可或缺的一部分。在这一背景下,移动购物逐渐取代了传统购物方式,成为现代消费的主流模式。消费......
  • 基于nodejs+vue移动互联时代的设备管理系统[开题+源码+程序+论文]计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,各类智能设备在日常生产和生活中的应用日益广泛。从智能手机到可穿戴设备,从工业控制设备到智能家居系统,这些设备极大地提升了......
  • 创建一个类实现一个打字小游戏(利用time.time()计算参赛者的打字时间,进而利用时间计算
    #打字小游戏面向过程,面向对象#游戏类==》属性、行为##1.外部传入一些数据,数据单词列表[movies,add,open]#2.随机的抽取这个单词列表中的一个单词,作为本局游戏的单词!#3.游戏开始,游戏的展示,游戏的结束,游戏时间,游戏的正确率等importrandom#随机给出列表......
  • MySQL 数据库与表的创建:从入门到实践
    MySQL数据库与表的创建:从入门到实践在当今的信息化时代,数据库作为数据存储和管理的核心组件,扮演着举足轻重的角色。MySQL,作为一款开源的关系型数据库管理系统(RDBMS),凭借其高性能、高可靠性和易用性,成为了众多开发者的首选。本文将详细介绍如何在MySQL中创建数据库和表,并通......