




已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
使用标准使用标准 GDI 实现游戏品质的动画系统实现游戏品质的动画系统 燕良燕良 2002 年年 1 月月 前言前言 2 GDI 基础基础 3 绘制一个位图 BITMAP 对象 3 常用像素格式 4 WINDOWS 下的基本动画系统下的基本动画系统 4 动画驱动方式 4 播放动画 5 消除闪烁 6 透明色 COLOR KEY 处理 7 ALPHA混合 9 读取 JPEG GIF 文件 10 子窗口管理 12 进阶技巧进阶技巧 使用使用 DIB 14 像素操作 14 RLE 压缩 15 参考参考 15 华山论键 15 其它类库 16 前言前言 说到实现游戏品质的动画 很多人会立刻想到 DirectX 没错 DirectDraw 很强大 但 是并不是必须用 DirectDraw 才行 动画后面的理论和技巧都是一样的 这和末端使用什么 API 没有太大关系 如果那 API 不是太 慢的话 就笔者实现的 NewImage Lib 的测试结果 内部所有像素数据的存储和运算都纯软件实现 最后一步输出到屏幕使用 GDI 的性能比 DirectDraw 低不到 10 在 Window9X 系统上要低 20 左右 这对很多软件来说是绝对可 以接受的 现在应用程序界面越做越华丽 除了支持 SKIN 外 很多人都想在程序中加入一些例 如 sprite 动画这种原本用在游戏上的技术 因为这原因引入 DirectX API 显然是不值得的 况且 DX 版本升级频繁 DX8 中已经用 DirectGraphic 取代了 DirectDraw 本文将以笔者 使用标准 GDI 函数实现的商业游戏为例 带你进入高品质 2D 动画编程领域 并且保证其 设备无关性 本文假设读者有 C C 语言知识 Windows 编程基础 GDI 基本概念 下面我将主要 讲述我在过去工作中积累的经验和一些技巧 但是将不讲解以上基本概念 读者最好有 MFC 基础 本文给出的代码将主要使用 MFC 但是其中的道理却不限于 MFC GDI 基础基础 绘制一个位图绘制一个位图 Bitmap 对象对象 GDI 的所有操作都是在 DC device context 上进行的 所以首先你应该有 DC 的概念 如 果你对 DC 还不了解 现在就去翻一翻 Windows 编程的书吧 首先我们要 Load 一个 Bitmap 对象 使用 Win32 API 可以写成这样 从资源从资源 Load 一个位图一个位图 如果从文件如果从文件 load 的话的话 可以使用可以使用 LoadImage HBITMAP hbmp LoadBitmap hInstance MAKEINTRESOURCE IDB MYBMP 如果使用 MFC 可以这样写 CBitmap bmp Bmp LoadBitmap IDB MYBMP 想把这个位图对象绘制到窗口上就要先得到窗口的 DC 然后对这个 DC 操作 请留 意创建 MemoryDC 的代码 后面会用到 Win32 API 的版本 假设位图大小为假设位图大小为 100 100 像素像素 假设假设 hwnd 是要绘制的窗口的是要绘制的窗口的 HANDLE HDC hwnddc GetDC hwnd HDC memdc CreateCompatibleDC hwnddc HBITMAP oldbmp SelectObject memdc hbmp BitBlt hwnddc 0 0 100 100 memdc 0 0 SRCCOPY if oldbmp SelectObject memdc oldbmp DeleteDC memdc ReleaseDC hwnd hwnddc MFC 版本 假设是在一个假设是在一个 CWnd 派生类的成员函数中派生类的成员函数中 CClientDC dc this CDC memdc memdc CreateCompatibleDC CBitmap oldbmp memdc SelectObject dc BitBlt 0 0 100 100 if oldbmp memdc SelectObject oldbmp 也可以这样 CClientDC dc this dc DrawState CPoint 0 0 CSize 100 100 基本的代码就是这样 当然有更多的 API 可以用 这就要看你自己的了 常用像素格式常用像素格式 要进行图像编程的化对像素格式不了解似乎说不过去 我想应该有较多的人并不太了解 所以这里简要的介绍一下 1 8bit 也叫做 256 色模式 每个像素占一个字节 使用调色板 调色板实际上是一个颜色 表 简单的讲就是 我们有 256 个油漆桶 因为像素的取值范围是 0 到 255 每个油漆 桶里面漆的颜色都由红 绿 蓝 RGB 三中基本的油漆按不同比例配置而成 所以我 们指定一个像素的颜色的时候只需要指定它用的第几号桶就好了 这种模式造就了 DOS 时代的神奇模式 13H 320 200 256 色 因为 320 200 1Byte 正好是 16bit 指针寻址能力的范围 这种模式有 2 的 18 次方种颜色 通过改变调色板实 现 可以同时显示 256 中颜色 这模式刚刚推出的时候 有人惊呼这是人类智慧的结 晶呢 也是这种模式造就了 1992 年 WestWood 的 和 1995 年大宇资 讯的 这样的经典游戏 在 Windows 下硬件调色板应该极少用到 但是你可以用软件调色板来压缩你的动画 这也是在 2D 游戏中常用的技巧 2 16bit 这也是笔者最喜欢的模式 它不使用调色板 每个像素占两个字节 存储 RGB 值 我觉得这种像素格式的效果 同时显示颜色数 和存储量 也影响速度 取得了比较好的统 一 但是如果你是写应用程序的话 我劝你不要用它 因为它的 RGB 值都不是整个 BYTE 例如 565 模式 16bit 的一种模式 它的 RGB 所占用的 bit 就是这样的 RRRR RGGG GGGB BBBB 3 24bit 每个像素有三个 BYTE 分别存储 RGB 值 这对你来说是不是很方便 是不是太好 了 可惜对我们可怜的计算机却不是 因为 CPU 访问奇数的地址会很费劲 而且在硬 件工艺上也有很多困难 具体我也不太清楚 请做过硬件的高手指点 所以你会发现 你的显卡不支持这种模式 但是你可以在自己的软件中使用 4 32bit 每个像素 4 个 BYTE 分别存储 RGBA A 值就是 Alpha 也就是透明度 可以用 像素混合算法实现多种效果 后面你就会看到 Windows 下的基本动画系统下的基本动画系统 动画驱动方式动画驱动方式 先略说一下动画的基本原理 程序播放动画一般过程都是 绘制 擦除 绘制 这样的 重复过程 只要你重复的够快 至少每秒 16 次 被称作 16FPS Frame per Second 我们可 怜的眼睛就分辨不出单帧的图像了 看上去就是动画了 在 Windows 环境下要驱动这样重复不停的操作有两种方法 1 设置 Timer 这很简单 只要设置一个足够短的 Timer 然后响应 WM TIME 对应 MFC 中的 OnTimer 函数 就可以满足绝大部分应用程序的需要 缺点是不够精确 而且 Win2000 和 Win9x 系统的精确性又有较大差异 2 在消息循环中执行动画操作 这是在游戏中常用的方法 一般都会把 WinMain 中的消息循环写成这样 while TRUE Look for messages if none are found then update the state and display it if PeekMessage TranslateMessage DispatchMessage else if g bActive 在主窗口不激活时不更新 以节省资源在主窗口不激活时不更新 以节省资源 执行动画更新操作执行动画更新操作 Make sure we go to sleep if we have nothing else to do else WaitMessage 如果你使用 MFC 则需要重载 CWinAPP 的 Run 虚函数 把上述消息循环替换进去 播放动画播放动画 现在我们有了一个适当的时机执行更新操作了 现在就让我们试试动画吧 下面的代 码将不再提供 Win32 的版本 为了叙述方便 我需要一个播放动画的窗口 它必须是一个 CWnd 的派生类 假设这 个类叫做 CMyView 我们将在这个窗口中绘制动画 首先我们为这个类添加一个成员函数 void CMyView RenderView 你可以使用上面提到的方法调用这个函数 现在准备工作都做好了 我们的动画该怎么存储呢 别提动画 GIF89a 格式 如果你觉得 只有 GIF 才有动画的话 那我劝你去做美术好了 别干程序了 如果你只想要个简单的动 画播放当然可以 但是如果你想要做复杂点的 交互式动画 我劝你还是别用那东西 假 设我们有一个 4 帧的动画 怎么存储它呢 我首先想到的就是存 4 个 BMP 文件 然后读入 到一个 CBitmap 对象数组中 但是尊敬的大师 Scott Meyers 警告我们不要使用多态数组 因为编译器在某些情况下不能准确计算数组中对象的大小 所以下标运算符会产生可怕的 效果 然后我就想到了用 CBitmap 指针数组 这到是不错 不过管理起来稍嫌麻烦 现在 看看我最终的解决方法吧 把一个帧序列安顺序拼接成一个文件 象这样 然后用它创建一个 CImageList 对象 让我们仔细看一下创建的方法 使用 BOOL CImageList Create int cx int cy UINT nFlags int nInitial int nGrow 函数 前面两个参数用来指定我们一帧动画的尺寸 这样就创建了一个空的 ImageList 这 样做的好处是可扩展行比较强 下面我们需要把那个帧序列文件 Load 到一个 CBitmap 对 象中 你可以存成 JPG 或者 GIF 文件来节省容量 后面将提到读取这些文件的简单方法 并且附一个实用类 当我们有了一个合适的 CBitmap 对象后 可以把他添加到我们的 ImageList 中 使用 BOOL CImageList int Add CBitmap pbmImage COLORREF crMask 一个实例 const int SPRIRT WIDTH 32 const int SPIRIT HEIGHT 32 m myimglist Create SPIRIT WIDTH SPIRIT HIGHT ILC COLOR24 ILC MASK 1 1 if bmp Load myani bmp m myimglist Add 好了 现在我们已经准备好了这些数据 让我们来实作渲染函数吧 下面这端代码可以 循环播放上面的 4 帧动画 并且支持透明色 如果你不知道这个名字 稍后有讲解 哦 void CMyView RenderView CclientDC dc this Static int curframe 0 m myimglist Draw curframe If curframe m myimglist GetImageCount Curframe 0 上面这个代码没有写擦除的操作 因为这根据具体需要有较大不同 如果你只有一个 精灵动画的话 你可以用一个 Bitmap 对象保存精灵所占矩形区域的图像 你也可能需要有 一个大的背景图每帧都要更新 这里我不讨论象 dirty rect 这样的优化方法 所以你只要每 次都画背景 然后画精灵就好了 怎么样 你已经实现了基本的动画系统 就是这么简单 消除闪烁消除闪烁 如果你真正实现上面的代码的话 你会发现画面一闪一闪的 十分的不爽 很多人都 会怪到 GDI 头上 他们又会骂 MS 说 GDI 太慢了 其实非也 不是指 MS 不该骂 呵呵 任何直接写屏幕的操作都会产生闪烁 在 DOS 下直接写显存或者用 DirectDraw API 直接 写 Primary Surface 都会闪烁 因为你每个更新显示的操作都会被用户马上看到 因为垂直回 扫的原因 或许会有延迟 消除闪烁最简单也是最经典的方法就是双缓冲 Double buffer 所谓的双缓冲其实道理非 常简单 就是说我们在其它地方 简单的说就是不针对屏幕 不显示出来的地方 开辟一个 存储空间 我们把所有的动画都要渲染到这个地方 而不是直接渲染到屏幕上 针对屏幕的 存储区域 在 GDI 中 直接针对屏幕就是窗口 DC 不可见的地方 一般可以用 Memory DC 在把所有动画渲染到后台缓冲之后 再一下次整体拷贝到屏幕缓冲区 在纯软件 2D 图形引擎中 双缓冲一般意味着在内存中开辟一个区域用来存储像素数 据 而在 DirectDraw 中可以创建 Back Surface 在把所有动画渲染到 Back Suface 上之后 然后使用 Flip 操作使其可见 Flip 操作因为只是设置可见 surface 的地址 所以非常快速 让我们重写一下 void CMyView RenderView 函数 来用 GDI 实现双缓冲 void CMyView RenderView CClientDC dc this CRect rc GetClientRect rc CDC memdc memdc CreateCompatibleDC CBitmap bmp Bmp CreateCompatibleBitmap CBitmap oldbmp memdc SelectObject Static int curframe 0 m myimglist Draw curframe If curframe m myimglist GetImageCount Curframe 0 if oldbmp memdc SelectObject oldbmp dc BitBlt 0 0 rc Width rc Height 其中创建一个 Bitmap 对象 然后选入 Memory DC 是必须的 因为 CreateCompatibleDC 所创建的 DC 里面只含有一个 1 1 像素的单色 Bitmap 对象 所以如果 缺了这个步骤 任何在 MemoryDC 上的绘图操作都会没有效果 延伸出一个问题 CreateCompatibleBitmap 函数的第一个参数显然不可写成 if m hObject NULL return FALSE CRect DRect DRect Rect DRect OffsetRect x y if pdc RectVisible COLORREF crOldBack pdc SetBkColor RGB 255 255 255 COLORREF crOldText pdc SetTextColor RGB 0 0 0 CDC dcimg dctrans if dcimg CreateCompatibleDC pdc TRUE return FALSE if dctrans CreateCompatibleDC pdc TRUE return FALSE CBitmap oldbmpimg dcimg SelectObject this CBitmap bmptrans if bmptrans CreateBitmap Width Height 1 1 NULL TRUE return FALSE CBitmap oldbmptrans dctrans SelectObject dcimg SetBkColor mask dctrans BitBlt 0 0 Width Height pdc BitBlt x y Width Height pdc BitBlt x y Width Height pdc BitBlt x y Width Height if oldbmpimg dcimg SelectObject oldbmpimg if oldbmptrans dctrans SelectObject oldbmptrans pdc SetBkColor crOldBack pdc SetTextColor crOldText return TRUE Alpha 混合混合 Alpha 混合是一种像素混合的方法 所谓的像素混合就是使用一定的算法把两个像素的 值混合成一个新的像素值 倒 和没说一样 通常我们都把两个像素的值 分别叫做源 src 和目的 dst 然后把混合后的结果存入 dst 中 dst src blend dst 如果源像素和目的像素都是 RGBA 格式 你可以使用每个像素的 Alpha 信息 或者叫做 Alpha 通道 组合出各种运算公式 例如 dst src src alpha dst dst alpha 或者 dst src src alpha dst 1 src alpha 这里我们假设这里我们假设 alpha 值是值是 0 1 的浮点数 的浮点数 可惜标准 GDI 没有支持类似这种操作的函数 起码我没找到 它只支持另一种 Alpha 混合 我把它叫做 const alpha blend 也就是把两幅都不包含 Alpha 通道的图像的按照一个固定的 Alpha 值混合到一起 也就是每个像素都使用同一 Alpha 值 GDI 的支持这个操作的函数 是 AlphaBlend AlphaBlend HDCHDC hdcDest intint nXOriginDest intint nYOriginDest intint nWidthDest intint hHeightDest HDCHDC hdcSrc intint nXOriginSrc intint nYOriginSrc intint nWidthSrc intint nHeightSrc BLENDFUNCTIONBLENDFUNCTION blendFunction 这个 API 的参数个数略多了一些 但是我想其中的位置参数你可以轻松搞定 还有就 是源 DC 和目的 DC 当然了 我们的 GDI 只能对 DC 操作 而不是对我们的像素数据 而我们只要把我的位图 select 到 DC 中就 OK 了 最后一个参数是一个结构 是用来指定 Alpha 的运算方式的 请看一个实际的例子 BLENDFUNCTION bf bf AlphaFormat 0 bf BlendFlags 0 bf BlendOp AC SRC OVER bf SourceConstantAlpha 100 指明透明度指明透明度 取值范围是取值范围是 0 255 AlphaBlend pdc GetSafeHdc rc left rc top rc Width rc Height memdc GetSafeHdc 0 0 rc Width rc Height bf 也许你看过很多游戏 在弹出文字对话框的时候都是在游戏画面上蒙一层半透明的黑 色 然后在这上面印字 使用上述操作就可以达到此效果 你可以先建立一个 Memory DC 然后把他填充为黑 然后把 Alpha 值设为 128 然后混合到你要绘制的 DC 上 不一定 是窗口 DC 哦 记得我们前面将的双缓冲吗 就 OK 了 读取读取 JPEG GIF 文件文件 JPEG 压缩算法综合的信号学和视觉心理学 而 GIF 格式 特别是支持动画的 GIF89a 格式为了节约容量也做了很多种非常变态的优化 所以要写一个完全支持这些标准格式的 解码器相当困难 也没有必要 如果你需要进行 JPEG 文件的读写我推荐你使用 Intel Jpeg Lib 速度相当令人满意 而 GIF 由于授权问题 没有任何官方组织提供的读写代码 如果你只是需要读入 JPEG 和静态 GIF 或者只一帧的动态 GIF 我推荐你使用 Windows 提供的 OleLoadPicture 函数 下面这段代码可以把一个 JPG GIF BMP 读入到 Bitmap 对象中 BOOL CIJLBitmap Load LPCTSTR lpszPathName BOOL bSuccess FALSE Free up any resource we may currently have DeleteObject open the file CFile f if f Open lpszPathName CFile modeRead TRACE T Failed to open file s Error x n lpszPathName GetLastError return FALSE get the file size DWORD dwFileSize f GetLength Allocate memory based on file size LPVOID pvData NULL HGLOBAL hGlobal GlobalAlloc GMEM MOVEABLE dwFileSize if hGlobal NULL TRACE T Failed to allocate memory for file s Error x n lpszPathName GetLastError return FALSE pvData GlobalLock hGlobal ASSERT pvData if pvData NULL TRACE T Failed to lock memory r n return FALSE read file and store in global memory if f Read pvData dwFileSize dwFileSize TRACE T Failed to read in image date from file s Error x n lpszPathName GetLastError GlobalUnlock hGlobal GlobalFree hGlobal return FALSE Tidy up the memory and close the file handle GlobalUnlock hGlobal create IStream from global memory LPSTREAM pStream NULL if FAILED CreateStreamOnHGlobal hGlobal TRUE GlobalFree hGlobal return FALSE Create IPicture from image file if SUCCEEDED OleLoadPicture pStream dwFileSize FALSE IID IPicture LPVOID if SUCCEEDED m pPicture get Type OLE HANDLE hPalette if SUCCEEDED m pPicture get Handle m Palette Attach HPALETTE hPalette bSuccess TRUE Free up the IStream interface pStream Release return bSuccess 这个 class 的完整代码请看文章最后的参考 子窗口管理子窗口管理 你也许注意过几乎所有游戏界面中的窗口都是使用动画的从屏幕外飞出 而且是半透明的 这你已经可以做到了 游戏中一般都使用自己的 UI 系统 这里我们可以借助 Windows 对 窗口的管理来轻松实现各种动画子窗口 首先让我们从最简单的开始 假设在我们的动画窗口中需要一个漂亮的按钮怎么办 我 劝你最好不要使用 CBitmapButton 因为你已经上了每秒重画窗口 16 次以上这条贼船 我 建议你在每次重画父窗口的时候重画所有子窗口 如此一来子窗口上如果要求有动画操作 也可以轻松实现了 既然做了 就把它做到最好 那我们怎么定义一个 button 呢 你也许想到自己定义一个矩形区域 然后在父窗口的消 息响应函数中检测是否是对此区域操作 这样在重画父窗口的时候特殊的画一次这个矩形 区域就好了 这样是可以实现 但是显然不符合我们的 OOP 精神 界面元素一多 你很可 能就会乱了阵脚 最后的解决方法当然是使用我们可爱的 CWnd 类 显然所有的界面元素 都可以作为一个 CWnd 派生类的对象 不过我建议你不要从 CButton 派生 这带来的麻烦 远多于它的价值 从 CWnd 派生一个类 然后在 Create 时注意使用 WS CHILD 风格 并 且指定父窗口为我们的动画窗口 下面一个问题是如何调用这些子窗口重画操作呢 第一种较好的解决方法是先建立这样 一个虚基类 CmyAniWnd public CWnd virtual void Render CDC pdc 0 假设你有一个 Button 类和一个 TextBox 类 CmyButton public CmyAniWnd CmyTextBox public CmyAniWnd 这两个类都必须实现 Render 函数 这样在父窗口类中你可以保存一个指针数组 例如 这样 CPtrArray m allchild 在创建一个 Button 时这样写 CmyButton pbtn new CmyButton m allchild Add pbtn pbtn Create 然后在我们父窗口的 RenderView 函数 前面提到的 每次更新调用 中这样写即可 CmyAniWnd pchild NULL for int I I m allchild GetSize I pchild static cast m allchild GetAt i ASSERT IsWindow pchild GetSafeHwnd pchild Render 这是一个典型的虚函数的应用 在调用这些子窗口的 Render 函数时 我们不需要知道 它到底是 Button 还是 TextBox 虚函数机制会自动帮我们找到该调用的函数 还有一点就 是 请注意 一定要把子窗口渲染到我们的后台缓冲 也就是 Memory DC 中 否则还是 会闪烁的 上面这种方法适合于子窗口数目固定 更高级的界面会要求触发某个事件的时候产生 一个子窗口 子窗口不断更新自己 并且在适当的时候把自己从 UI 系统中去除 让每个 子窗口管理自己的生命期 是个不错的主意 不是吗 那你最好不要使用上面保存指针数组 的方法 那样的话 子窗口在杀死自己的时候还要通知父窗口 以让父窗口把它的指针从 数组中移除 这显然具有很高的偶合性 不是我们想要的 因为我们的所有子窗口都是标 准的 Windows 对象 所以这使得我们有使用 Windows 消息的机会 我们首先要枚举所有 子窗口 然后发一个自定义的更新消息给它 并把我们的 MemoryDC 的指针作为参数 具 体例子代码如下 void CMyView RenderView 其它更新操作其它更新操作 EnumChildWindows GetSafeHwnd CMyView UpdateChildWnd LPARAM 其它更新操作其它更新操作 其中第二个参数是一个回调函数 你必须把它声明成全局函数 或者类的 static 成员 函数 这里我们使用了后者 BOOL CALLBACK CMyWnd UpdateChildWnd HWND hwnd LPARAM lParam CDC SendMessage hwnd WM COMMAND CHILDCMD RENDER lParam return TRUE 这里我没有使用自定义消息 而是发送标准的 WM COMMAND 这样你可以给那个 CmyAniWnd 虚基类添加一个 CWnd 虚函数 OnCommand 然后在那里面检测如果 wParam 是 CHILDCMD RENDER 的话 就调用纯虚函数 Render 以 lParam 作为参数 子 窗口派生类只要实现自己的 Render 函数就好 其它不用管了 这里还有一个要注意的问题就是绘制的顺序问题 如果你想让子窗口盖住某些动画 就应该先渲染那些动画 然后渲染子窗口 反之亦反 进阶技巧进阶技巧 使用使用 DIB 像素操作像素操作 以上所有操作都局限于标准 GDI 函数 如果我们要实现更进一步的操作 例如当傍晚 你希望把整个画面的颜色渲染能淡红色调 晚上的时候你要把整个画面变暗 早上再把它 恢复到原来的亮度这些 GDI 都无法帮你做到 如果想达到上述效果 就必须自己对像 素的 RGB 值进行操作 首先让我们要得到一个 Bitmap 对象中的像素数据 让我们看一下具体该怎么操作 假 设我们有一个 mybmp 是一个 CBitmap 对象 或者其派生类对象 下面的代码把 CBitmap 中 的像素取出 BITMAP bm mybmp GetBitmap BITMAPIN
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年天津市西青区中考二模物理试题(解析版)
- 《4.3 维权行动》(教学设计)-2023-2024学年五年级下册综合实践活动安徽大学版
- 2025年全国起重机操作证-特种设备作业人员考试题库(含答案)
- 第1课 中华人民共和国成立-2025-2026学年八年级历史下册核心素养驱动说课稿
- 2025年高考生物试题分类汇编酶与ATP及物质运输(原卷版)
- 乡愁题目分析及解析答案
- 2025护肤品采购与销售合同
- 2025合同文件是否应作为合同及组成部分
- 物业安全试题库及答案
- 物权法原来题库及答案
- 主题班会《反对邪教-从我做起》
- 幕墙预埋件专项施工方案
- HDX8000系列安装配置操作指南
- 白虎汤分析课件
- 山东青年政治学院校徽校标
- 2022版义务教育英语课程标准之学业质量标准与考试评价解读PPT
- EDA课程第3~5章QuartusII Verilog HDL 数字电路设计实现
- (高清正版)JJF(浙)1102-2014生物人工气候箱校准规范
- 完整解读新版《义务教育课程方案》2022年《义务教育课程方案(2022版)》PPT课件
- 《文殊真实名经》
- 幼儿各年龄段发展评估指南
评论
0/150
提交评论