C语言课设分享:图片加载

前言:

本教程仅针对EasyX函数库中的加载图片功能进行代码优化,均为本人自己的经验总结,如有问题和指正欢迎在评论区留言

目录:

一、问题所在

在使用EasyX库中的putimage函数显示图片时,一般要先进行loadimage操作,先加载图片再显示图片,因此出现了问题:

​ 每一次使用新的图片时,都要为新的IMAGE变量重新定义,在进行putimage操作之前还要loadimage,不仅操作繁琐,一大片的loadimage函数和IMAGE变量写在游戏主函数里看起来也并不美观。

​ 于是产生了这样的思路:将所有的loadimage放在同一个自定义的函数"downloadimage"里,整个程序只需要执行一次downloadimage不就可以了吗?

​ 新问题就出现了,如果使用函数,变量/参数的定义和调用如何安排才能保证流畅、简便、可读性和美观性呢?

二、不同方案的对比

1.直接定义

在游戏主函数里直接定义若干个IMAGE变量,然后downloadimage函数调用直接调用这些IMAGE变量

这是一个很容易想到的方法,但是会出现以下的问题:

问题1:当变量数量多的时候,很容易就会出现一个需要putimage的函数动辄调用十几二十个图片,这样大大降低了可读性和美观性。例如我自己的一个小游戏中的几个函数:

void Spawn(int a, int x, int y, IMAGE h1a, IMAGE h1b, IMAGE h2a, IMAGE h2b, IMAGE h3a, IMAGE h3b, IMAGE h4a, IMAGE h4b, IMAGE h5a, IMAGE h5b, IMAGE h6a, IMAGE h6b, IMAGE sb1, IMAGE sb2, IMAGE tb1, IMAGE tb2, IMAGE cp1, IMAGE cp2);//生成元素
int* Spawnall(int* a, IMAGE background, IMAGE h1a, IMAGE h1b, IMAGE h2a, IMAGE h2b, IMAGE h3a, IMAGE h3b, IMAGE h4a, IMAGE h4b, IMAGE h5a, IMAGE h5b, IMAGE h6a, IMAGE h6b, IMAGE sb1, IMAGE sb2, IMAGE tb1, IMAGE tb2, IMAGE cp1, IMAGE cp2);//生成背景、道具和建筑
void Button(Time* t1, Player& p1, USER& user1, IMAGE background, IMAGE h1a, IMAGE h1b, IMAGE h2a, IMAGE h2b, IMAGE h3a, IMAGE h3b, IMAGE h4a, IMAGE h4b, IMAGE h5a, IMAGE h5b, IMAGE h6a, IMAGE h6b, IMAGE sb1, IMAGE sb2, IMAGE tb1, IMAGE tb2, IMAGE cp1, IMAGE cp2);//右侧按键操作

问题2:当IMAGE变量数量较多的时候,每一次调用putimage函数都要检查一遍参数,导致程序很卡,如图:

方案1

2.全局变量

既然我们需要downloadimage函数调用直接调用很多个IMAGE变量,那我们不妨将这些IMAGE变量改为全局变量,通过实践我们可以得知,在调用的时候十分流畅

方案2

但是全局变量只能作为排查问题的手段,不能作为解决问题的方式

全局存在许多问题,如安全性、不确定性、污染命名空间等等

3.数组定义

如果定义IMAGE img[50]的一个数组,存放不超过50个IMAGE变量,使用downloadimage函数、putimage和其他调用putimage的函数时只需要调用这个数组,理论上调用这些函数的时候只需要一个参数,运行起来会比直接定义的方法流畅(由于难以书写,我没有进行实验测试流畅性问题,如有实践结果与理论不同,还望指正

但如果如下定义这个数组的话

IMAGE background,player1a, player1b, player2a, player2b, player3a, player3b, player4a, player4b......;//先定义若干个IMAGE变量
IMAGE img[50]={background, player1a, player1b, player2a, player2b, player3a, player3b, player4a, player4b......};//将这些IMAGE变量放到IMAGE[50]数组中

仍会出现问题:

(1)寻找具体图片时较麻烦

我们在调用putimage的时候想要知道放的是哪张图片的话,就必须通过后台对照图片是第几号来确定。如果图片数量多,则在写代码时总要手动重新找一次这些类似的图片,是一件头疼的事情

(2)无法利用数组批量操作的优点

在写downloadimage函数的时候,需要对数组中的每个元素都进行形式不同的loadimage操作,如:

void downloadimage(IMAGE pics[50]) {
	loadimage(&img[0], "background.png");
	loadimage(&img[1], "player1a.png");
    ……
}

这是因为虽然数组可以通过遍历操作,但是要加载的图片名字却是无规律的字符串。

如果将这些图片改成有规律的名字,通过sprintf()_s或者swprintf()_s函数来批量读取的话,如:

void downloadimage(IMAGE img[50])
{
	wchar_t filename[100];
	for (int i = 0; i < 50; i++)
	{
		swprintf_s(filename, L"img%d.png", i);
		loadimage(&img[i], filename);
	}
}

这样就要求图片的名称均为img0、img1……,以对应数组的img[0]、img[1]……

那么问题(1)会更加严重,因为在后台对照的时候甚至不能通过图片名称来确定数组下标,只能查看图片来确定

4.结构体

定义一个结构体pic,结构体中放有所有的IMAGE变量。

定义和使用如下:

typedef struct picture {
	IMAGE background, player1a,……
}pic;
void downloadimage(pic q) {
	loadimage(&q.background, "background.png");
	loadimage(&q.player1a, "player1a.png");
    ……
}
int main(){
    pic q;
    downloadimage(q);
    ……
}

由于结构体中的变量可以保留名称,这样就能解决数组的寻找目标问题,即问题(1)被化解了

而且在运行速度上是满足要求的

方案4

但是同样的,结构体不能够批量操作

5.链表

专门为了应对结构体无法批量操作而产生的方案。

定义:

typedef struct picture {
	IMAGE img;
    struct picture* next;
}pic;

这样在创建完成链表的建立之后,调用downloadimage时带入头结点看似就可以批量操作了:

pic* downloadimage(pic* h) {
    for(pic *p=h;p!=NULL;p=p->next){
		loadimage(&q->img, "XXX.png");
    }
    ……
        return h;
}

但实际上同样存在对图片名称“XXX”的限制,比起数组来说没有本质提升

反倒是由于每个调用putimage函数的地方都要遍历一遍链表,导致代码量显著提升

因此用链表去定义图片并不是一个明智之举

三、最终方案(总结)

对比五种方案,前两种明显是最不可取的。

对于图片数量较少的程序,使用数组定义是很方便的方式。由于图片数量不多但需要重复使用,数组的优势可以发挥出来。

而对于图片数量较多的程序,我推荐使用结构体。它的主要优势就是简单快捷,容易区分要用到的图片。

到这里就结束了

这是新人的第二篇CSDN,如有谬误欢迎指正批评

对于这篇文章中的方案,我个人的程序是选择了结构体方案
特别鸣谢:提供帮助的舍友和CSDN的大佬们

参考资料:无(我自己总结的)

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值