linux能编写图形c程序吗,Linux系统下用C语言编写2D图形游戏

在Linux系统下,不要以为C语言就只能写那种只有字符的控制台程序,别忘了,Linux系统有FrameBuffer(帧缓冲),只要显示器是彩色的,并且是linux系统的,就可以用C语言代码通过读写FrameBuffer里的数据在屏幕上绘制图形;

图形嘛,有png库,用它的函数解码图片文件,得到图片数组,共有red、green、blue、alpha四种数组,alpha用于图片之间的组合,最终将RGB数组输出到FrameBuffer就能显示了;

想要动态图形效果,自己用算法实现。

目前,我正在为自己的嵌入式设备开发一个游戏,图形素材来源于互联网,游戏截图如下图所示:

a48729cc2462d62094e76646fab57188.gif

6a60416dbd2e1317a5b12314702f02e3.gif

f194f75113abf41789a8f4e62398c307.gif

902d74f9c971725273e97b96039c622f.gif

如上图所示,主菜单中的红色光标有闪烁效果,游戏画面切换有淡入淡出效果。

下面有源码,现在使用的按键控制方法的效果不理想。

linux系统环境,按键判断,使用了getch()和kbhit()函数,函数是模拟实现的。

为了判断按键是否为按住状态,我使用一个变量count来计数,每循环一次自增,也就是按键检测延迟的最大时间,超过了这段时间,如果getch()函数没有再次返回接受到同样的按键的键值,那么就判断为这个按键已经释放,否则,该按键处于按住状态,并继续显示之前的动作。

还有图形显示,目前没掌握局部刷新的技术,游戏显示的每一帧图形都是全屏刷新的,效率低,每秒大概刷新4帧。

源码只提供部分:

[cpp]

voidnext_frames(void)

{//更新到下一帧

frames[0] += speed[0];//玩家1的

frames[1] += speed[1];//AI的

}

voidinit_player_data(void)

//初始化各个玩家的数据

{

direction[0] = IS_RIGHT;//玩家朝向右边

direction[1] = IS_LEFT;//AI角色朝向左边

//各个角色的初始位置

map_site_x[0] = 100;

map_site_x[1] = 300;

map_site_y[1] = map_hight - 20;

map_site_y[0] = map_hight - 20;//在地图上的坐标

speed[0] = 1;//每次循环帧frames自增的的值,之前是想做能设置游戏刷新速度的功能,现在已抛弃,这个变量貌似没用了。

speed[1] = 1;

need_move[0] = 0;//玩家是否需要移动

need_move[1] = 0;//AI是否需要移动

can_use_next[0] = 0;//可以使用下一个动作

can_use_next[1] = 0;//AI可以使用下一个动作

status[0] = STANCE;//玩家为站立状态

status[1] = STANCE;//AI为站立状态

shock_wave_num = 0;//冲击波的总数为0

need_view_shock_wave = 0;//不需要显示冲击波

}

intplay_game(void)

{

unsignedchar**game_map;//游戏地图

intmap_id,temp_key = 0,count = 0,key = 0,man_id;//人物代号

//分配内存

man_id = ICHIGO;//人物动画选择黑崎一护

init_player_data();//初始化玩家数据

map_id = 1;

if(map_id == 1) {

game_map = load_map_1();//载入地图数据

}

while(1){

update_graph();//规定镜头,显示玩家所在的区域的图形

view_map_area(game_map[0],game_map[1],game_map[2]);//根据主角的位置,显示地图中的某个区域

if(kbhit()){//调用kbhit()函数检测是否有按键输入

key = getch();//有按键输入就用getch()函数获取键值并赋给key,下面开始判断key的值

if(key == KEY_BACK)break;

if(key =='w'|| key =='W'|| key == KEY_UP) {

temp_key = key;

}

elseif((key =='d'|| key =='D'|| key == KEY_RIGHT) && status[0] != JUMP_ATTACK){//如果按的是a键或者左键

if((temp_key =='d'|| temp_key =='D'|| temp_key == KEY_RIGHT)&& count 

next_action[0] = WALK;//下一个动作还是行走

}

elseif(can_use_next[0] == 0){//如果之前没有按过a键或者左键,并且,可以使用下一个动作

if(temp_status[0] != JUMP) {//如果之前不是跳跃状态

status[0] = WALK;

if(temp_status[0] != WALK) frames[0] = 0;//如果之前不是行走状态

elseif(temp_status[0] == WALK){//如果之前是行走状态

next_action[0] = WALK;//下一个动作还是行走

}

}

elseneed_move[0] = 1;//否则,需要移动

}

direction[0] = IS_RIGHT;

need_move[0] = 1;

temp_key = key;

count = 0;//计数清零

}

elseif((key =='a'|| key =='A'|| key == KEY_LEFT) && status[0] != JUMP_ATTACK){//如果按的是a键或者左键

if((temp_key =='a'|| temp_key =='A'|| temp_key == KEY_LEFT)&& count 

next_action[0] = WALK;//下一个动作还是行走

}

elseif(can_use_next[0] == 0){//如果之前没有按过a键或者左键,并且,可以使用下一个动作

if(temp_status[0] != JUMP) {//如果之前不是跳跃状态

status[0] = WALK;

if(temp_status[0] != WALK) frames[0] = 0;//如果之前不是行走状态

elseif(temp_status[0] == WALK){//如果之前是行走状态

next_action[0] = WALK;//下一个动作还是行走

}

}

elseneed_move[0] = 1;//否则,需要移动

}

direction[0] = IS_LEFT;

need_move[0] = 1;

temp_key = key;

count = 0;//计数清零

}

elseif(key =='s'|| key =='S'|| key == KEY_DOWN){//如果按的是s键或者是下键

if(can_use_next[0] == 0){

status[0] = BLOCK;

if((temp_key =='s'|| temp_key =='S'|| temp_key == KEY_DOWN) && count <10){

//如果之前按过s键或者是下键,并且在最大延迟时间内

if(temp_status[0] == BLOCK && status[0] == BLOCK)//如果之前的动作是防御

{

frames[0] = 2;speed[0] = 0;

}

}

else{

frames[0] = 0;//帧数归零www.linuxidc.com

speed[0] = 1;

}

}

temp_key = key;//保存按键的键值

count = 0;//计数归零

}

elseif(key =='j'|| key =='J'){//如果按的是j键

if(temp_status[0] == JUMP || temp_status[0] == JUMP_ATTACK)//如果之前还处于跳跃状态

{

if(jump_attack_num == 0) {

status[0] = JUMP_ATTACK;//跳跃攻击

jump_attack_num = 1;

}

}

elseif(status[0] == DOWN_ATTACK || status[0] == BLOCK || temp_key == KEY_DOWN || temp_key =='s'|| temp_key =='S'){

status[0] = DOWN_ATTACK;

if(temp_status[0] != DOWN_ATTACK) frames[0] = 0;//帧数归零

}

elseif(temp_key == KEY_UP || temp_key =='w'|| temp_key =='W'){

if(can_use_next[0] == 0){//如果可以使用下一个动作

status[0] = UP_ATTACK;

frames[0] = 0;//帧数归零

}

}

elseif((temp_key =='j'|| temp_key =='J') && count <5){//如果之前按过j键,并且在最大延迟时间内

if(temp_status[0] == FIRST_ATTACK && status[0] == FIRST_ATTACK)//如果之前处于第一段攻击状态下

{

status[0] = FIRST_ATTACK;

if(can_use_next[0] == 0 && first_attack_complete[0] == 0){//如果可以使用下一个动作

status[0] = SECOND_ATTACK;//开始进行第二段攻击

frames[0] = 0;//帧数归零www.linuxidc.com

}

else{

next_action[0] = SECOND_ATTACK;//保存下一个动作,等待之前的动作完成

}

}

elseif(temp_status[0] == SECOND_ATTACK || status[0] == SECOND_ATTACK)//如果之前处于第二段攻击状态下

{

status[0] = SECOND_ATTACK;

if(can_use_next[0] == 0 && second_attack_complete[0] == 0){//如果可以使用下一个动作

status[0] = THIRD_ATTACK;//开始进行第二段攻击

frames[0] = 0;//帧数归零

}

else{

next_action[0] = THIRD_ATTACK;//保存下一个动作,等待之前的动作完成

}

}

elseif(temp_status[0] == THIRD_ATTACK || status[0] == THIRD_ATTACK)//如果之前处于第二段攻击状态下

{

status[0] = THIRD_ATTACK;

if(can_use_next[0] == 0 && third_attack_complete[0] == 0){//如果可以使用下一个动作

status[0] = FIRST_ATTACK;//开始进行第一段攻击

frames[0] = 0;//帧数归零

}

else{

//next_action = FIRST_ATTACK;//保存下一个动作,等待之前的动作完成

}

}

else{

status[0] = FIRST_ATTACK;

frames[0] = 0;

}

}

else{

status[0] = FIRST_ATTACK;

if(temp_status[0] != FIRST_ATTACK) frames[0] = 0;

}

speed[0] = 1;

count = 0;

temp_key = key;//保存按键的键值

}

elseif((key =='k'|| key =='K') && can_use_next[0] == 0){//如果按的是k键,并且能使用下一个动作

status[0] = JUMP;

count = 0;

jump_attack_num = 0;

frames[0] = 0;

}

elseif(key =='U'|| key =='u'){

if(status[0] == DOWN_Y_ATTACK || status[0] == BLOCK || temp_key == KEY_DOWN || temp_key =='s'|| temp_key =='S'){

speed[0] = 1;

status[0] = DOWN_Y_ATTACK;

if(temp_status[0] != DOWN_Y_ATTACK) frames[0] = 0;//帧数归零

}

elseif(can_use_next[0] == 0){//如果可以使用下一个动作

status[0] = Y_ATTACK;//开始进行第二段攻击

frames[0] = 0;//帧数归零

}

else{

next_action[0] = Y_ATTACK;//保存下一个动作,等待之前的动作完成

}

count = 0;

temp_key = key;

}

elseif(key =='L'|| key =='l'){

if(can_use_next[0] == 0){//如果可以使用下一个动作

status[0] = DASH;

frames[0] = 0;//帧数归零

}

else{

next_action[0] = DASH;//保存下一个动作,等待之前的动作完成

}

need_move[0] = 1;//需要移动

}

}

elseif(count > 5 && can_use_next[0] == 0) {//如果在计数大于5时还没有接收到按键输入,并且可以使用下一个动作

status[0] = STANCE;//状态改为站立

speed[0] = 1;

temp_key = 0;

count = 0;//计数清零www.linuxidc.com

}

if_need_move(0,count);//判断是否需要移动

if(man_id == ICHIGO) ichigo(0);//使用黑崎一护的动作图形

ichigo(1);

next_frames();//更新到下一个帧

write_to_fb(screen[0],screen[1],screen[2]);//显示图形

//usleep(10000);//之前用过usleep(30000),牺牲帧的刷新速度,获得按键响应效果的提升,我认为这不值

count++;//计数自增

}

//释放背景图占用的内存

free(game_map[0]);

free(game_map[1]);

free(game_map[2]);

free(game_map);

return0;

}

intmain()

{

init_game();//初始化游戏,获取屏幕尺寸,分配内存

game_boot();//显示游戏启动画面

main_menu();//显示游戏主菜单

system("stty echo");

return0;

}0b1331709591d260c1c78e86d0c51c18.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值