《游戏编程入门 4th》笔记(1 / 14):Windows初步

文章目录

    • Windows编程概述
      • 获取Windows
      • 理解Windows消息机制
      • 多任务
      • 多线程
      • 事件处理
    • DirectX快速概览
      • Direct3D是什么
    • Window程序基础
      • 创建第一个Win32项目
      • 理解WinMain
      • WinMain函数调用
      • 完整的WinMain
      • GetMessage函数调用
      • 寻求帮助

Windows编程概述

DirectX,流行的游戏编程库。它上手易,精通难。

Windows is a multi-tasking, multi-threaded operating system. What this means is that Windows can run many programs at the same time, and each of those programs can have several threads running as well. As you might imagine, this operating system architecture works well with multi-core processors.

获取Windows

旧版本Windows的软件(游戏除外,因PC规格日新月异)无需过多修改便可在新版本Windows运行。

Windows编程可简可繁。

Windows是优秀多任务操作系统,因为它是消息驱动的。

理解Windows消息机制

外部事件,如鼠标单击,会导致小的电信号从鼠标转移到USB口再进入系统总线。Windows操作系统从系统总线拾取这一信号并且生成一个消息传递给正在运行的应用程序(比如我们的游戏),程序对这消息做出反应。

计算机的潜意识(处理所有时间处理逻辑的操作系统)将这一事件“呈现”给程序,让其知晓。

DirectX 9旧版依然很好只在现在流行Windows7。

多任务

Windows使用抢占式任务preemptive multi-tasking。

This means that your PC can run many programs at the same time. Windows accomplishes this by running each program for a very short amount of time, counted in microseconds, or millionths of a second.

This jumping from one program to another very quickly is called time slicing时间分片, and Windows handles time slicing by creating a virtual address space (a small “simulated” computer) for each program in memory.

Each time Windows jumps to the next program, the state of the current program is stored so that it can be brought back again when it is that program’s turn to receive some processor time. This includes processor register values and any data that might be overwritten by the next process.

Then, when the program comes around again in the time-slicing scheme, these values are restored into the processor registers, and program execution continues where it left off. This happens at a very low level, at the processor register level, and is handled by the Windows core.


切换程序在人角度开看,是非常迅速的,不必担心。

If this sounds like a wasteful use of processor cycles, you should be aware that during those few microseconds, the processor is able to run thousands of instructions. Modern processors already run at the gigaflop level, able to easily crunch a billion math calculations in a short “time slice.”


What this means is that the operating system has a very low-level core that manages the computer system. Preemptive抢占式 means that the operating system can preempt the functioning of a program, causing it to pause, and the operating system can then allow the program to start running again later.

When you have many programs and processes (each with one or more threads) begging for processor time, this is called a time-slicing system时间分片系统, which is how Windows works. As you might imagine, having a multi-processor system is a real advantage when you are using an operating system such as this.

多线程

Multi-threading is the process of breaking up a program into multiple threads, each of
which is like a separate program running. This is not the same as multi-tasking on the
system level 多任务不同于多线程. Multi-threading is sort of like multi-multi-tasking, where each program has running parts of its own, and those small program fragments are oblivious of the timeslicing system performed by the operating system.

As far as your main Windows program and all of its threads are concerned, they all have complete control over the system and have no “sense” that the operating system is slicing up the time allotted to each thread or process. Therefore, multi-threading means that each program is capable of delegating processes to its own mini-programs.

For instance, a chess program might create a thread to think ahead while the player is working on his next move. The “thought” thread would continue to update moves and counter-moves while waiting for the player. While this might just as easily be accomplished with a program loop that thinks while waiting for user input, the ability to delegate the process out to a thread might have significant benefits for a program.


Just as an example, you can create two threads in a Windows program and give each thread its own loop.

As far as each thread is concerned, its loop runs endlessly and it runs extremely fast, without interruption.

But at the system level, each thread is given a slice of processor time.

Depending on the speed of the processor and operating system, a thread may be interrupted 1,000 times per second, but the source code running in that thread will not be interrupted in any way.


Multi-threading is very useful for game programming.

多线程在游戏中的应用

The many tasks involved in a game loop might be delegated into separate threads that will execute independently, each one communicating with the main program.

A thread might be set up to handle screen updates automatically.

All the program would have to do then is update the double buffer with all of the objects on the screen, and the thread will do the work on a regular basis— perhaps even with timing built in so that the game will run at a uniform speed regardless of the processor.

All of the popular game engines today are multi-threaded (such as Unreal and Unity).

事件处理

At this point, you might be asking yourself, “How does Windows keep track of so many programs running at the same time?” Windows handles the problem,

  • first of all, by requiring that programs be event-driven.
  • Secondly, Windows uses system-wide messages to communicate.

Windows messages are small packets of data sent by the operating system to each running program with three primary features telling that program that some event has occurred:

  • window handle,
  • instance identifier,
  • message type

The events will normally involve user input, such as a mouse click or key press, but might be from a communications port or a TCP/IP socket used by a networking library (which is used in multiplayer games).

Each Windows program must check every message that comes in through the message handler to determine whether the message is important. Messages that are not identified are sent along to the default message handler. (类比)Think of messages as fish—when you catch a fish that is too small or that you don’t like, you throw it back. But you keep the fish that you want.

It is similar in the Windows event-driven architecture; if your program recognizes a message that it wants to keep, that message is taken out of the message stream. Most of the messages will be key presses and mouse movement events (and they are still passed along even if you don’t need to use them).

(MyNote:个人认为它有点像寿司店回转寿司台)

Once you have experimented with Windows programming and have learned to handle some Windows messages, you will see how it was designed for applications, not games. The trick is learning to “tap into” the Windows messaging system and inject your own code, such as a DirectX initialization routine or a function call to refresh the screen.

All of the actions in a game are handled through the Windows messaging system; it is your job to intercept and deal with messages that are relevant to your game.

DirectX快速概览

We’re not going to begin writing any DirectX code just yet, but I do want you to see how it works with Windows.

DirectX provides an interface to the low-level hardware of your PC, providing a consistent一致的 and reliable set of functions for games that tap into the hardware (such as a video card).

This figure shows how DirectX works with the Windows API.

DirectX is closely integrated into Windows and will not work with any other OS, as it relies on the basic libraries in the Windows API to function. Here is a rundown梗概 of the DirectX components:

  • Direct3D is the rendering library that provides access to the video card to render 2D and 3D graphics. This is the most important component.

  • DirectSound is the audio library used to play digital samples loaded from wave files with a multi-channel audio mixer.

  • XACT is a newer audio library that supplements DirectSound.

  • DirectInput is the device input library used to access keyboard, mouse, and joystick游戏杆 devices.

  • XInput is an input library that provides support for an Xbox 360 controller connected via wireless adapter or USB port.

  • DirectPlay is the old networking library that is no longer supported.

Direct3D是什么

Since Direct3D is the most important component of DirectX. Direct3D handles all of the 2D and 3D rendering in a game.

In later chapters, you will learn Direct3D beginning and how to load an image into memory as a texture and then draw the texture (in 2D mode), as well as apply the texture when rendering a 3D model.

You can still program a 2D game using Direct3D or use 2D sprites to enhance a 3D game. You will need to display information on the screen with a 2D font, so learning how to draw 2D graphics is a necessity必要的. For the short term, a brief overview of 2D textures and sprites will help you to understand Direct3D when we explore 3D programming later on.

**Our primary goal is to learn about 2D and 3D rendering necessary to program a game.**My intent is not to try to make you into an expert game programmer, just to give you
enough information (and enthusiasm!) to take yourself to the next level and learn more
about this subject.

We will eventually get into rendering 3D models with texturing and lighting, but that’s pretty advanced, so we’ll spend most of our time learning about 2D sprite-based games. Have fun with the material!

**Try not to get bogged down in the details!**不要过分陷于细节中 Because the details of 3D game programming are complex, the average一般 beginner’s eyes tend to glaze over when hearing about vertex buffers顶点缓冲 and texture coordinates纹理坐标.

I can relate, because it takes time to build up to details like that when you’re just getting started. Honestly, it’s better to program a great 2D sprite精灵 game than a dull 3D game that just isn’t fun.

Window程序基础

Every Windows program includes a function called WinMain at minimum. Most Windows programs also include a message handler function called WinProc that receives messages (such as key presses and mouse movement).

If you were writing a full-blown Windows application (for instance, a commercial software product like 3ds Max or Microsoft Word), then you would have a very large and complicated
WinProc function in the program to handle the many program states and events.

But in a DirectX program, you don’t really have to mess with events because your main
interest lies with the DirectX interfaces that provide their own functions for dealing with
events.

DirectX is mostly a polled轮询 SDK, in that you must ask for data rather than having it
thrown at you (which is the case with WinProc). For instance, when you start learning
about DirectInput, you’ll find that keyboard and mouse input is mainly gathered by calling functions to see what values have changed.

(MyNote:DirectX 消息接收者主动轮询才能得到信息。)

创建第一个Win32项目

项目实际上是一个管理程序中所有文件的文件。

Visual Studio Express 2013 for Windows Desktop 下载地址

安装过程按照其安装向导步骤安装即可。

1.菜单栏FILE->New Project

2.选择项目模板Installed,Visual C++,Win32->Win32 Project,并命名项目名,选后点击OK

3.接下来是设置向导Overview,点击Next

4.Application Settings中,勾选Empty project,不勾选Security Development Lifecycle(SDL)checks,点击Finish。

5.添加一cpp源文件,菜单栏PROJECT->Add New Item,创建命名为main.cpp源文件。

6.输入以下代码:

#include <windows.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{MessageBox(NULL, "Welcome to Windows Programming!","HELLO WORLD", MB_OK | MB_ICONEXCLAMATION);
}

这个程序仅仅在屏幕上显示一个对话框

一开始BUILD编译时抛出error C2664: 'int MessageBoxW(HWND,LPCWSTR,LPCWSTR,UINT)' : cannot convert argument 2 from 'const char [32]' to 'LPCWSTR'

Now let’s resolve this error.

It has to do with the character set, which can be either ANSI (8-bit) or Unicode (16-bit). Unicode is important for localization—a software engineering term that refers to converting the text in a program to other languages. Not all languages need Unicode characters, but some do—such as Mandarin and Japanese.

We could write all of our code to support Unicode character strings, with funky code鸡肋代码 that is not part of the C++ standard (like the infamous “L” character and TCHAR). But we want to write standards-compliant software without special codes.

解决方法

菜单栏PROJECT-> XXXProperties->Configuration Properties->General->Project Defaults->Character Set 选择 Use Multi-Byte Character Set

编译运行后结果:

When you compile a C++ program with Visual Studio, the executable file(可执行文件exe) is usually written to a folder called Debug (inside your project’s folder).

理解WinMain

Every Windows program has a function called WinMain. WinMain is the Windows equivalent of the main function in console C++ programs, and is the initial entry point for a Windows program.

The most important function in your program will be WinMain, but after you have set up the messaging calls, you probably won’t come back to WinMain while working on other parts of the program.

The WinMain function hasn’t changed much since 16-bit Windows 3.0 back in 1991. WinMain is like the foreman工头 that tells the program what to work on. The job of WinMain is to set up the program, and then to set up the main message loop for the program. This loop processes all of the messages received by the program. Windows sends these messages to every running program.

Most of the messages will not be used by your program, and so the operating system doesn’t even send some messages to your program. Usually, WinMain will send messages over to another function called WinProc, which works closely with WinMain to process user input and other messages.

A comparison of WinMain and WinProc

WinMain函数调用

int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow )
  • HINSTANCE hInstance. The first parameter identifies the instance of the program
    being called, as a program may be run several times. hInstance tells the program
    which instance is trying to run. If the program is run more than once, the
    general practice is to just close the new instance rather than running the
    program again.(MyNote:这句看得不太懂。)
  • HINSTANCE hPrevInstance. The second parameter identifies the previous instance of
    the program and is related to the first parameter. If hPrevInstance is NULL, then this
    is the first instance of the program.
  • LPTSTR lpCmdLine. The third parameter is a string that contains the command-line
    parameters passed to the program. This could be used to tell the program to use
    certain options.
  • int nCmdShow. The last parameter specifies the options used when creating the
    program window. 该参数可以是下列值之一:
    • SW_HIDE:隐藏窗口并且激活另外一个窗口。
    • SW_MINIMIZE:最小化指定的窗口,并且激活在系统表中的顶层窗口。
    • SW_RESTORE:激活并显示窗口。如果窗口已经最小化或最大化,系统将以恢复到原来的尺寸和位置显示窗口(与SW_SHOWNORMAL相同)。
    • SW_SHOW:激活一个窗口并以原来的尺寸和位置显示窗口。
    • SW_SHOWMAXIMIZED:激活窗口并且将其最大化。
    • SW_SHOWMINIMIZED:激活窗口并将其目标化。
    • SW_SHOWMINNOACTIVE:将一个窗口显示为图标。激活窗口维持活动状态。
    • SW_SHOWNA:以窗口的当前状态显示窗口。激活窗口保持活动状态。
    • SW_SHOWNOACTIVATE:以窗口的最近一次的尺寸和位置显示窗口。激活窗口维持激活状态。
    • SW_SHOWNORMAL:激活并显示窗口。如果窗口最大化或最小化,系统将其恢复到原来的尺寸和位置(与SW_RESTORE相同)

You might have noticed that WinMain returns a value with the words int WINAPI in front of the function call. This is also standard practice and goes back to Windows 3.0.

A return value of zero indicates that the program never made it to the main loop and was terminated prematurely. Any non-zero value indicates success.

hInstance是程序的当前实例的句柄。在Windows这样的多任务操作系统中,一个程序可以同时运行多个实例。不同的实例间需要彼此区别,句柄就是干这个的。

Link

HINSTANCE 实际是本模块在内存中的首地址。
程序的资源如菜单 对话框 字符 串 光标等等 还有函数 导入导出表等,都存储在本模块里。
所以要使用这些资源必须知道首地址,然后根据预定义的 找到各个资源 。

Link

完整的WinMain

Listed below is more of a standard version of WinMain that you will often see in app code.

This is just an example, not a complete project.

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{//1. declare variables//The MSG variable is used by the GetMessage function to retrieve the details of each Windows message. MSG msg;// register the class// 还未介绍MyRegisterClass(hInstance);// initialize application// **This code uses the hInstance variable passed to WinMain by Windows**. The variable is then passed on to the InitInstance function. //InitInstance is located farther down in the program, and basically checks to see whether the program is already running and then creates the main program window.if (!InitInstance (hInstance, nCmdShow)) return FALSE;// main message loop// The while loop in this part of WinMain will continue to run forever unless a message to kill the program comes along.while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}

Even the simplest of graphics programs will need to process messages. Believe it or not, doing something as simple as printing “Hello World” on the screen requires that you wait for a message to come along for painting the screen.

Message handling does take some getting used to if you’re used to just calling a function when you need something (such as displaying text on the screen) done. (MyNote:不是”呼之即来挥之即去“易用性???)

GetMessage函数调用

  • LPMSG lpMsg. This parameter is a pointer to a MSG structure that handles the message
    information.

  • HWND hWnd. The second parameter is a handle to a specific window’s messages. If
    NULL is passed, then GetMessage will return all of the messages for the current
    instance of the program.

  • UINT wMsgFilterMin and UINT wMsgFilterMax. These parameters tell GetMessage to
    return messages in a certain range. The GetMessage call is the most crucial决定性的 line of code
    in the entire Windows program! Without this single line in WinMain, your program
    will be sensory-deprived感觉剥夺, unable to respond to the world.

The two core lines of code within the GetMessage loop work to process the message returned by GetMessage.

The Windows API Reference states that the TranslateMessage function is used to translate virtual-key messages into character messages, and then sent back through the Windows messaging system with DispatchMessage. These two functions will jointly set up the messages that you will expect to receive in WinProc (the window callback function) for your game window, such as WM_CREATE to create a window and WM_PAINT to draw the window.

I will cover WinProc in the next chapter. If you feel confused about Windows messaging, don’t worry about it, because this is just a precursor前导 to working with DirectX; once you have written a Windows message loop, you will not need to deal with it again, and you can focus on your DirectX code.

寻求帮助

If you need help with a Windows or DirectX function (such as Direct3DCreate9), highlight it in Visual Studio and press F1. This will bring up context-sensitive help in the default web browser by opening a Microsoft Developer Network web page with details about that function.

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

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

相关文章

《游戏编程入门 4th》笔记(2 / 14):监听Windows消息

文章目录编写一个Windows程序理解InitInstanceInitInstance函数调用InitInstance的结构理解MyRegisterClassMyRegisterClass函数调用MyRegisterClass的作用揭露WinProc的秘密WinProc函数调用WinProc的大秘密什么是游戏循环The Old WinMain对持续性的需要实时终止器WinMain和循环…

数据结构课上笔记6

本节课介绍了单链表的操作实现细节&#xff0c;介绍了静态链表。 链表带头的作用&#xff1a;对链表进行操作时&#xff0c;可以对空表、非空表的情况以及 对首元结点进行统一处理&#xff0c;编程更方便。 下面给出带头的单链表实现思路&#xff1a; 按下标查找&#xff1a; …

17校招真题题集(3)11-15

注&#xff1a;本系列题目全是按照通过率降序来排列的&#xff0c;基本保证题目难度递增。 11、 题目名称&#xff1a;买苹果 来源&#xff1a;网易 题目描述 小易去附近的商店买苹果&#xff0c;奸诈的商贩使用了捆绑交易&#xff0c;只提供6个每袋和8个每袋的包装(包装不…

QT5生成.exe文件时,出现缺少QT5core.dll文件解决方法

在 http://qt-project.org/downloads 下载Qt SDK安装需要Qt版本。在QtCreator下&#xff0c;程序可以正常运行&#xff0c;但是当关闭QtCreator后&#xff0c;在DeBug目录下再运行相应的*.exe程序时&#xff0c;会提示缺少Qt5Core.dll错误。解决方法&#xff1a;添加电脑环境变…

《基于Java实现的遗传算法》笔记(7 / 7):个人总结

文章目录为何采用遗传算法哪些问题适合用遗传算法解决遗传算法基本术语一般遗传算法的过程基本遗传算法的伪代码为何采用遗传算法 遗传算法是机器学习的子集。在实践中&#xff0c;遗传算法通常不是用来解决单一的、特定问题的最好算法。对任何一个问题&#xff0c;几乎总有更…

Java设计模式(4 / 23):单例模式

文章目录单例模式的应用场景饿汉式单例模式懒汉式单例模式改进&#xff1a;synchronized改进&#xff1a;双重检查锁改进&#xff1a;静态内部类破坏单例用反射破坏单例用序列化破坏单例解密注册式单例模式枚举式单例模式解密容器式单例线程单例实现ThreadLocal单例模式小结参考…

约瑟夫环-(数组、循环链表、数学)

约瑟夫环&#xff08;约瑟夫问题&#xff09;是一个数学的应用问题&#xff1a;已知n个人&#xff08;以编号1&#xff0c;2&#xff0c;3...n分别表示&#xff09;围坐在一张圆桌周围。从编号为k的人开始报数&#xff0c;数到m的那个人出列&#xff1b;他的下一个人又从1开始报…

链表相交问题

本来想自己写&#xff0c;写了一半发现一篇文章&#xff0c;解释写得简单易懂&#xff0c;我就直接拿过来了。 这个问题值得反复地写&#xff0c;锻炼链表coding能力的好题。 //如果两个链表都不带环 int NotCycleCheckCross(pLinkNode head1,pLinkNode head2) {pLinkNode lis…

双栈

利用栈底位置相对不变的特性&#xff0c;可以让两个顺序栈共享一个空间。 具体实现方法大概有两种&#xff1a; 一种是奇偶栈&#xff0c;就是所有下标为奇数的是一个栈&#xff0c;偶数是另一个栈。但是这样一个栈的最大存储就确定了&#xff0c;并没有起到互补空缺的作用&a…

单调队列优化的背包问题

对于背包问题&#xff0c;经典的背包九讲已经讲的很明白了&#xff0c;本来就不打算写这方面问题了。 但是吧。 我发现&#xff0c;那个最出名的九讲竟然没写队列优化的背包。。。。 那我必须写一下咯嘿嘿&#xff0c;这么好的思想。 我们回顾一下背包问题吧。 01背包问题 …

用Python去除扫描型PDF中的水印

内容概述 含水印扫描型PDF文件&#xff0c;其中某页如下图所示&#xff0c;用Python去除其页顶及页底的水印。 处理思路&#xff1a;PDF中的每一页的水印的相对位置基本相同&#xff0c;将PDF每一页输出成图片&#xff0c;然后进行图片编辑&#xff0c;用白色填充方形覆盖水印…

二阶有源滤波器

滤波器是一种使用信号通过而同时抑制无用频率信号的电子装置, 在信息处理、数据传送和抑制干扰等自动控制、通信及其它电子系统中应用广泛。滤波一般可分为有源滤波和无源滤波, 有源滤波可以使幅频特性比较陡峭, 而无源滤波设计简单易行, 但幅频特性不如滤波器, 而且体积较大。…

用JS写了一个30分钟倒计时器

效果图 额外功能 左键单击计时器数字区&#xff0c;不显示或显示秒钟区。左键双击计时器数字区&#xff0c;暂停或启动计时器。计时完毕&#xff0c;只能刷新页面启动计时器。输入框可输入备注信息&#xff0c;输入框失去焦点或计时完毕后&#xff0c;时间戳附带备注信息会存入…

为什么高手离不了Linux系统?我想这就是理由!

通过本文来记录下我在Linux系统的学习经历&#xff0c;聊聊我为什么离不了Linux系统&#xff0c;同时也为那些想要尝试Linux而又有所顾忌的用户答疑解惑&#xff0c;下面将为你介绍我所喜欢的Linux系统&#xff0c;这里有一些你应该知道并为之自豪的事实。 这里你应该首先抛开W…

用JS写一个电影《黑客帝国》显示屏黑底绿字雨风格的唐诗欣赏器

效果图 放码过来 <!DOCTYPE HTML> <html><head><meta http-equiv"Content-Type" content"text/html;charsetutf-8"/><title>Black Screen And Green Characters</title><style type"text/css">table…

元器件封装大全:图解+文字详述

先图解如下&#xff1a; 元器件封装类型&#xff1a; A.Axial  轴状的封装&#xff08;电阻的封装&#xff09;AGP &#xff08;Accelerate raphical Port&#xff09; 加速图形接口 AMR(Audio/MODEM Riser) 声音/调制解调器插卡BBGA&#xff08;Ball Grid Array&#xff09;…

用JS写一个丐版《2048》小游戏

效果图 放马过来 <!DOCTYPE HTML> <html><head><meta http-equiv"Content-Type" content"text/html;charsetutf-8"/><title>2048</title><style type"text/css">.basic{height:80px;width:80px;back…

如何有效申请TI的免费样片

转自如何有效申请TI的免费样片 TI公司愿意为支持中国大学的师生们的教学、实验、创新实践、竞赛和科研项目&#xff0c;提供有限数量的免费样片。首先需要指出的是&#xff1a;所有的样片申请应该是诚实正当的&#xff0c;所有不恰当的申请&#xff08;包括不必要或多余的&…

用Python批量生成字幕图片用于视频剪辑

说明 视频剪辑时需要为视频添加字幕&#xff0c;添加字幕方法之一&#xff1a;根据字幕文本文件批量生成透明底只有字幕内容的图片文件&#xff0c;如下图&#xff0c;然后将这些图片文件添加到视频剪辑软件轨道中。 于是用pillow这Python图片工具库执行本次批量生成工作。 …

关于接地:数字地、模拟地、信号地、交流地、直流地、屏蔽地、浮

除了正确进行接地设计、安装,还要正确进行各种不同信号的接地处理。控制系统中&#xff0c;大致有以下几种地线&#xff1a; &#xff08;1&#xff09;数字地&#xff1a;也叫逻辑地&#xff0c;是各种开关量&#xff08;数字量&#xff09;信号的零电位。 &#xff08;2&…