C语言学习记录20240626

news2024/12/28 2:52:06

飞船无论朝哪边行驶,都能通过结构体记录获取它的初始坐标、转向角度和在该方向行进的距离,需要根据这些信息计算飞船移动后的坐标。

向量(vector)指具有大小(magnitude)和方向(direction)的量,可以理解为有方向的线段。
标量或纯量(scalar)指只有大小没有方向的量。
向量的分量(component)是指向量在不同方向上的投影或分解。
二维向量 V ⃗ ( 2 , − 5 ) \vec{V}(2, -5) V (2,5),X 轴方向上分量为 2, Y 轴方向上分量为 -5,向量大小 ∣ ∣ V ⃗ ∣ ∣ ||\vec{V}|| ∣∣V ∣∣ 由勾股定理得到 2 2 + ( − 5 ) 2 \sqrt{2^2 + (-5)^2} 22+(5)2 ,书写参考 《Markdown 数学公式详解》https://blog.csdn.net/qq_34745941/article/details/126598575

单位向量(unit vector)为大小或模为1个单位的向量。一个非零向量除以它的模,就可以得到相应的单位向量。所以向量也可以记为标量乘以指定方向的单位向量,然后相加,如 (2,-5) 可以记为 2(1,0)-5(0,1)

向量还有一种记法是以大小和方向表示,这里的方向通常为向量线与 X 正轴的夹角,X 正轴逆时针方向夹角为正,顺时针方向夹角为负。由于屏幕坐标左上角为原点,屏幕范围为正轴,纵轴与通常坐标轴方向相反,Allegro 函数 al_rotate_transform 应用转换矩阵旋转时,弧度为正则是顺时针,为负则是逆时针。

为了便于计算,假设飞船初始朝向与 X 轴平行,绘制初始画面时,飞船朝上与 Y 轴平行,向量夹角为负 90 度,右转 30 度向前行驶一段距离,则飞船终点相对于初始坐标变化 X 坐标为 ∣ ∣ V ⃗ ∣ ∣ c o s ( 30 − 90 ) ||\vec{V}||cos(30-90) ∣∣V ∣∣cos(3090),Y 坐标为 ∣ ∣ V ⃗ ∣ ∣ s i n ( 30 − 90 ) ||\vec{V}||sin(30-90) ∣∣V ∣∣sin(3090)

C 语言 math 模块中的 cos 和 sin 传入参数也是弧度。

Allegro 中按住按键不放,并不会持续产生按键事件,可以在定时器事件中循环检查所有按键状态 al_get_keyboard_state,然后通过 al_key_down 判断指定按键按下状态,未检测到按下状态即为弹起 https://liballeg.org/a5docs/trunk/keyboard.html#al_get_keyboard_state ,类似 pygame.key.get_pressed https://www.pygame.org/docs/ref/key.html#pygame.key.get_pressed

C语言学习记录20240626
spaceship.h

#ifndef _SPACESHIP_H
#define _SPACESHIP_H

#include <allegro5/allegro.h>

extern const int WIDTH;
extern const int HEIGHT;


typedef struct {
	float sx; // 飞船中屏幕中的坐标 
	float sy;
	float heading; //飞船朝向角度,如 30 度为 30.0 
	float speed;
	int gone; // 是否阵亡
	ALLEGRO_COLOR color; 
} Spaceship;

void draw_ship(Spaceship *s);
void rotate_ship(Spaceship *s, int direction);
void accelerate_ship(Spaceship *s, int gas);

#endif

spaceship.c

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <allegro5/allegro_primitives.h>

#define DEGREES(x) ((x) * ALLEGRO_PI / 180.0)
#define DEFAULT_DEGREE 10.0
#define REAL_ROTATE(x) ((x) - 90.0)
#define DEFAULT_SPEED 0.1
#define MAX_SPEED 3.0

#include "./spaceship.h"


// 绘制飞船
void draw_ship(Spaceship *s) {
	ALLEGRO_TRANSFORM transform;
	al_identity_transform(&transform);
	al_rotate_transform(&transform, DEGREES(s->heading));
	al_translate_transform(&transform, s->sx, s->sy);
	al_use_transform(&transform);
	// 画线需要在调用 al_create_display 前设置多重采样以抗锯齿 
	al_draw_line(-8, 9, 0, -11, s->color, 3.0f);
	al_draw_line(0, -11, 8, 9, s->color, 3.0f);
	al_draw_line(-6, 4, -1, 4, s->color, 3.0f);
	al_draw_line(6, 4, 1, 4, s->color, 3.0f);
	// 重置变换矩阵,不然会影响其他绘制内容 
    al_identity_transform(&transform);
    al_use_transform(&transform);
    // 画辅助线 
    al_draw_line(s->sx, 0, s->sx, HEIGHT, al_map_rgb(255, 255, 255), 0.3f);
    al_draw_line(0, s->sy, WIDTH, s->sy, al_map_rgb(255, 255, 255), 0.3f);
}

// 飞船左右控制转向, direction -1-左转 1-右转 
void rotate_ship(Spaceship *s, int direction) {
	if (direction == 0) return;
	s->heading += DEFAULT_DEGREE * direction;
	if (abs(s->heading) >= 360.0) {
		s->heading -= 360.0 * direction;
	}
}

// 飞船上下控制加减速 gas -1-减速 1-加速,这里飞船速度为每帧前进距离 
void accelerate_ship(Spaceship *s, int gas) {
	if (gas == 0) return;
	s->speed += DEFAULT_SPEED * gas;
	
	if (s->speed < 0.0) {
		s->speed = 0.0;
		return;
	}
	if (s->speed > MAX_SPEED) {
		s->speed = MAX_SPEED;
	}

	s->sx += s->speed * cos(DEGREES(REAL_ROTATE(s->heading)));
	s->sy += s->speed * sin(DEGREES(REAL_ROTATE(s->heading)));
	printf("Rotate:%.2f X:%.2f Y:%.2f SPEED:%.2f\n", REAL_ROTATE(s->heading), s->sx, s->sy, s->speed);
} 

main.c

#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include "./utility.h"
#include "./spaceship.h"


// 全局变量 
const int WIDTH = 800; // 屏幕尺寸 
const int HEIGHT = 600;
const int FPS = 60; // 帧率 
ALLEGRO_FONT *font_40; // 字体 

int main() {
    // 初始化 Allegro
    if (!al_init()) {
        fprintf(stderr, "Failed to initialize Allegro!\n");
        return -1;
    }

    // 安装键盘驱动,安装成功或已经安装过则返回 true
    if (!al_install_keyboard()) {
        fprintf(stderr, "Failed to initialize keyboard!\n");
        return -1;
    }

    // 初始化图形绘制插件 
    if (!al_init_primitives_addon()) {
        fprintf(stderr, "Failed to initialize primitives addon!\n");
        return -1;
    }
    
    // 初始化字体插件 
    if (!al_init_font_addon()) {
        fprintf(stderr, "Failed to initialize font addon!\n");
        return -1;
    }
    
    // 初始化 TTF 字体插件 
    if (!al_init_ttf_addon()) {
        fprintf(stderr, "Failed to initialize ttf font addon!\n");
        return -1;
    }
    // 加载 TTF 字体,字号 40 
	font_40 = al_load_ttf_font("arial.ttf", 40, 0);
	
    // 启用多重采样
    al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
    al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);
    
    // 创建指定宽高的窗口 
    ALLEGRO_DISPLAY *display = al_create_display(WIDTH, HEIGHT);
    if (!display) {
        fprintf(stderr, "Failed to create display!\n");
        return -1;
    }

    // 创建事件队列 
    ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue();
    if (!event_queue) {
        fprintf(stderr, "Failed to create event queue!\n");
        al_destroy_display(display);
        return -1;
    }
    
    // 创建定时器,每 1.0 / FPS 秒触发一次 
    ALLEGRO_TIMER *timer = al_create_timer(1.0 / FPS);

    // 注册事件源到事件队列 
    al_register_event_source(event_queue, al_get_display_event_source(display));
    al_register_event_source(event_queue, al_get_keyboard_event_source());
    al_register_event_source(event_queue, al_get_timer_event_source(timer));

    // 清除屏幕并填充黑色 
	al_clear_to_color(al_map_rgb(0, 0, 0));
	
	// 绘制背景 logo 
	draw_logo();
		
	// 初始化并绘制飞船 
	Spaceship s = {WIDTH / 2.0, HEIGHT / 2.0, 0.0, 0.0, 0, al_map_rgb(0, 255, 0)};
	draw_ship(&s);
	
	// 交换缓冲区
    al_flip_display();
    
    // 启动定时器 
    al_start_timer(timer);
    
    
    bool done = false; // 游戏是否结束 
    bool redraw = false; // 是否重绘 
    ALLEGRO_KEYBOARD_STATE key_state; // 按键状态
    int rotate = 0; // 转向 
	int accelerate = 0; // 加速 
    
    // 轮询事件 
	while (!done) {
        ALLEGRO_EVENT event;
        // 等待从事件队列取出事件 
        al_wait_for_event(event_queue, &event);
        
        if (event.type == ALLEGRO_EVENT_TIMER) {
        	// 处理定时器事件 
        	redraw = true; // 重绘 
        	
        	// 获取所有按键状态并保存到 key_state
            al_get_keyboard_state(&key_state);
			
			// 如果按下左右键就转向,否则左右键都为弹起状态则方向不变 
			if (al_key_down(&key_state, ALLEGRO_KEY_LEFT)) {
                rotate = -1;
            } else if (al_key_down(&key_state, ALLEGRO_KEY_RIGHT)) {
                rotate = 1;
            } else {
            	rotate = 0;
			}
			// 按上键加速,上键弹起或按下键减速 
            if (al_key_down(&key_state, ALLEGRO_KEY_UP)) {
                accelerate = 1;
            } else {
            	accelerate = -1;
			}
			if (al_key_down(&key_state, ALLEGRO_KEY_DOWN)) {
                accelerate = -1;
            }
            
        } else if (event.type == ALLEGRO_EVENT_KEY_DOWN && event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
        	// 处理单次按键事件,这里响应 ESC 按键 
			done = true;
        } else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
			// 处理窗口事件,这里响应点击窗口右上角关闭 
            done = true;
        }
        
       if (redraw && al_is_event_queue_empty(event_queue)) {
            redraw = false;
            
            // 更新转向和加速状态 
            rotate_ship(&s, rotate);
            accelerate_ship(&s, accelerate);

        	// 清屏并更新绘制
	        al_clear_to_color(al_map_rgb(0, 0, 0));
	        draw_logo();
	        draw_ship(&s);
	        al_flip_display();
        }
    }

    // 销毁资源,释放内存 
    al_destroy_timer(timer);
    al_destroy_font(font_40);
    al_destroy_display(display);
    al_destroy_event_queue(event_queue);

    return 0;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1865517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 7种Join的定义图解示范结果(所有join类型)

文章目录 MySQL 7种Join的定义&图解&示范&结果&#xff08;所有join类型&#xff09;基本知识笛卡尔积 建表&填充数据1-Join不带条件account筛选 1-Inner Join 内连接不带条件account相同where筛选玩点特殊的 2-Left Join 左连接不带条件account筛选 3-Right J…

django 和 pyecharts实现可视化大屏(完整代码)

1.配置settings文件 &#xff08;1&#xff09;注意&#xff1a;需要先创建app(djnago-admin startapp app名称) &#xff08;2&#xff09;配置模板文件 DIRS: [os.path.join(BASE_DIR, templates)], &#xff08;3&#xff09;配置静态文件(这里我由于存放清洗好的需要进行可…

基于Java+MySQL停车场车位管理系统详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

基于51单片机密码锁—六位密码LCD1602显示

基于51单片机密码锁设计 &#xff08;仿真&#xff0b;程序&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.密码为六位数字&#xff0c;有键按下&#xff0c;LCD1602就会显示出字符 “*”&#xff1b; 2.当用户键入正确密码后&#xff0c;再按确认键&a…

HistoQC|病理切片的质量控制工具

小罗碎碎念 这期推文介绍的内容&#xff0c;我相信研究病理组学的人&#xff0c;一定都非常熟悉——HistoQC——病理切片的质量控制。 之前写过Hover Net系列的推文&#xff0c;反响还可以&#xff0c;但是Hover Net是用于细胞核检测和分类的&#xff0c;直接从这里开始还不够系…

应用程序任务驱动:详细解析LLM的评估指标

在自然语言处理(NLP)的动态环境中&#xff0c;大型语言模型(LM)性能的评估是衡量其在各种下游应用程序中的有效性的关键因素。不同的应用程序需要与其目标一致的不同性能指标。本文将详细介绍各种LLM评估指标&#xff0c;探索它们如何应用于实际场景。 从传统的摘要任务到更细…

华三中小企业组网

一、组网需求 在中小园区中&#xff0c;S5130系列或S5130S系列以太网交换机通常部署在网络的接入层&#xff0c;S5560X系列或 S6520X系列以太网交换机通常部署在网络的核心&#xff0c;出口路由器一般选用MSR系列路由器。 核心交换机配置VRRP保证网络可靠性。园区网中不同的…

python flask 入门-helloworld

学习视频链接&#xff1a; 01-【前奏】课程介绍_哔哩哔哩_bilibili 1.安装flask pip install flask 踩坑记&#xff1a;本机不要连代理&#xff0c;否则无法install 提示报错valueError: check_hostname requires server_hostname 2.程序编写 在根目录下创建 app.py fr…

深入探讨C++的高级反射机制(2):写个能用的反射库

在现代软件开发中&#xff0c;反射是一种强大的特性&#xff0c;它可以支持程序在运行时查询和调用对象的属性和方法。 但是在C中&#xff0c;没有内置的反射机制。我们可以通过一些巧妙的技术模拟反射的部分功能。 上一篇文章写了个简单的反射功能&#xff0c;这回完善一下&a…

Linux-笔记 OverlayFS文件系统入门

目录 前言 主要概念 工作原理 特点特性 1、上下合并 2、同名文件覆盖 3、同名目录合并 4、写时拷贝 实操入门 内核配置 挂载文件系统 验证 1、同名文件覆盖 2、同名目录合并 3、写时拷贝 1&#xff09;验证新增文件或目录 2&#xff09;验证修改文件 3&…

[leetcode]assign-cookies. 分发饼干

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int m g.size(), n s.size();int count 0;for (int i 0, j 0; i…

【嵌入式Linux】i.MX6ULL GPIO 中断服务函数注册与编写

文章目录 1 外部中断初始化与中断服务函数1.2 外部中断初始化函数 exti_init1.2.1 GPIO引脚配置1.2.2 中断使能与注册1.2.3 GIC_EnableIRQ()函数的分析 1.3 中断服务函数 gpio1_io20_irqhandler1.3.1 消抖处理1.3.2 中断事件处理1.3.3 清除中断标志 2 BUG处理2.1 问题描述2.2 解…

【开源项目】自然语言处理领域的明星项目推荐:Hugging Face Transformers

在当今人工智能与大数据飞速发展的时代&#xff0c;自然语言处理&#xff08;NLP&#xff09;已成为推动科技进步的重要力量。而在NLP领域&#xff0c;Hugging Face Transformers无疑是一个备受瞩目的开源项目。本文将从项目介绍、代码解释以及技术特点等角度&#xff0c;为您深…

泰迪智能科技大数据挖掘企业服务平台典型合作案例介绍

泰迪大数据挖掘企业服务平台 是一款通用的、企业级、智能化的数据分析模型构建与数据应用场景设计工具&#xff0c;能够一体化地完成数据集成、模型构建、模型发布&#xff0c;为数据分析、探索、服务流程提供支撑&#xff0c;提供完整的数据探索、多数据源接入、特征处理、模型…

编程设计思想

健康检查脚本 nmap:扫描端口 while true do healthycurl B:httpPORT/healthy -i | grep HTTP/1.1 | tail -n 1 | awk {print $2} done 批量操作类型脚本&#xff08;记录每一步日志&#xff09; 将100个nginx&#xff1a;vn推送到harbor仓库192.168.0.100 根据镜像对比sha值…

高效修复机床导轨磨损,保障加工精度!

机床导轨是支承和引导运动构件沿着一定轨迹运动的传动装置&#xff0c;在机器设备中是个十分重要的部件&#xff0c;在机床中是常见的部件。机床的加工精度与导轨精度有直接的联系&#xff0c;且导轨一旦损坏&#xff0c;维修较复杂且困难。我们简单总结了以下几点对于机床导轨…

rocketMQ消息中间件,onMessage报错,MessageExt of onessage method is not supported

本地启动不会报错&#xff0c;生产者和消费者都运行的好好的&#xff0c;但是打包之后就不断的报错误&#xff0c; 起初以为是maven出现了问题&#xff0c;但是刷新和重写都不管用&#xff0c;并且打的jar包解压后发现类里 有这个类和方法。最后认为是打包出现问题 解决方式&am…

SEO之竞争对手研究

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议 2、新手上云 竞争对手研究是市场竞争研究的重要部分&#xff0c;对判断特定关键词竞争程度及了解行业整体情况非常有价值。…

AutoStudio: 开源 AI 漫画创作神器

AutoStudio是一个用于生成系列连续且一致的图片系统&#xff0c;可用于漫画创作&#xff0c;其核心由四个 Agent 组成&#xff1a; 主题管理器&#xff1a;理解用户对话&#xff0c;跟踪角色信息。 布局生成器&#xff1a;确定图像中角色的位置。 监督者&#xff1a;给出改进…

昇思25天学习打卡营第3天|张量Tensor

张量Tensor 概念创建张量&#xff08;4种方式&#xff09;张量的属性张量索引张量运算Tensor与NumPy转换 概念 张量&#xff08;Tensor&#xff09;是一种特殊的数据结构&#xff0c;与数组和矩阵非常相似。张量是MindSpore网络运算中的基本数据结构。 创建张量&#xff08;4…