手机游戏 2d 编程
The purpose of this tutorial is to teach 2D game programming and C-language through examples. The author used to program games in the mid-1980s and was a game designer at MicroProse for a year in the 90s. Although much of that is not relevant to the programming of today's big 3D games, for small casual games it will serve as a useful introduction.
本教程的目的是通过示例教授2D游戏编程和C语言。 作者曾经在1980年代中期编写游戏程序,并在90年代在MicroProse担任游戏设计师一年。 尽管其中大部分与当今大型3D游戏的编程无关,但对于小型休闲游戏,它将作为有用的介绍。
Games like snake where objects are moving over a 2D field can represent the game objects either in a 2D grid or as a single dimension array of objects. "Object" here meaning any game object, not an object as used in object-oriented programming.
诸如蛇之类的对象在2D字段上移动的游戏可以将游戏对象表示为2D网格或对象的一维数组。 “对象”在这里是指任何游戏对象,而不是面向对象编程中使用的对象。
The keys are move with W=up, A= left, S=down, D=right. Press Esc to quit the game, f to toggle frame rate (this isn't synchronized to the display so can be fast), tab key to toggle debug info and p to pause it. When it's paused the caption changes and the snake flashes,
按键以W =向上,A =向左,S =向下,D =向右移动。 按Esc退出游戏,按f切换帧速率(此速率与显示屏不同步,因此可以很快),按Tab键切换调试信息,按p键暂停。 暂停后,字幕会更改,而蛇会闪烁,
In snake the main game objects are
在蛇中,主要游戏对象是
For purposes of gameplay, an array of ints will hold every game object (or part for the snake). This can also help when rendering the objects into the screen buffer. I've designed the graphics for the game as follows:
为了游戏的目的,一个整数数组将容纳每个游戏对象(或蛇的一部分)。 将对象渲染到屏幕缓冲区时,这也有帮助。 我为游戏设计了如下图形:
So, it makes sense to use these values in a grid type defined as block[WIDTH*HEIGHT]. As there are only 256 locations in the grid I've chosen to store it in a single dimension array. Each coordinate on the 16 x16 grid is an integer 0-255. We've used ints so you could make the grid bigger. Everything is defined by #defines with WIDTH and HEIGHT both 16. As the snake graphics are 48 x 48 pixels (GRWIDTH and GRHEIGHT #defines) the window is initially defined as 17 x GRWIDTH and 17 x GRHEIGHT to be just slightly bigger than the grid.
因此,在定义为block [WIDTH * HEIGHT]的网格类型中使用这些值是有意义的。 由于网格中只有256个位置,因此我选择将其存储在一个维度数组中。 16 x16网格上的每个坐标都是0-255的整数。 我们使用整数,以便您可以扩大网格。 一切都由#defines定义,宽度和高度均为16。由于蛇形图形为48 x 48像素(GRWIDTH和GRHEIGHT #defines),因此窗口最初定义为17 x GRWIDTH和17 x GRHEIGHT,仅略大于网格。
This has benefits in game speed as using two indexes is always slower than one but it means instead of adding or subtracting 1 from the snake's Y coordinates to move vertically, you subtract WIDTH. Add 1 to move right. However being sneaky we've also defined a macro l(x,y) which converts the x and y coordinates at compile time.
这在提高游戏速度方面具有优势,因为使用两个索引总是比一个慢,但是这意味着您要减去WIDTH而不是从蛇的Y坐标中添加或减去1来垂直移动。 加1可向右移动。 但是,我们还是偷偷摸摸地定义了一个宏l(x,y),该宏在编译时会转换x和y坐标。
#define l(X,
The first row is index 0-15, the 2nd 16-31 etc. If the snake is in the first column and moving left then the check to hit the wall, before moving left, must check if coordinate %WIDTH ==0 and for the right wall coordinate %WIDTH == WIDTH-1. The % is the C modulus operator (like clock arithmetic) and returns the remainder after division. 31 div 16 leaves a remainder of 15.
第一行的索引是0-15,第二行的索引是16-31,依此类推。如果蛇在第一列中并向左移动,则在左移之前必须先检查撞到墙的位置,然后检查坐标%WIDTH == 0以及右墙坐标%WIDTH == WIDTH-1。 %是C模运算符(如时钟算术),除后返回余数。 16的31格剩余15。
There are three blocks (int arrays) used in the game.
游戏中使用了三个块(整数数组)。
At the game start, the snake is two segments long with a head and a tail. Both can point in 4 directions. For north the head is index 3, the tail is 7, for the east head is 4, the tail is 8, for the south head is 5 and the tail is 9, and for the west, the head is 6 and tail is 10. While the snake is two segments long the head and tail are always 180 degrees apart, but after the snake grows they can be 90 or 270 degrees.
在游戏开始时,蛇的长度为两段,头部和尾部。 两者都可以指向4个方向。 对于北,头是索引3,尾巴是7,对于东头是4,尾巴是8,对于南头是5,尾巴是9,对于西,头是6,尾巴是10 。尽管蛇是两条长的线,但头和尾总是相隔180度,但是在蛇长大后,它们可以成90度或270度。
The game starts with the head facing north at location 120 and the tail facing south at 136, roughly central. At a slight cost of some 1,600 bytes of storage, we can gain a discernible speed improvement in the game by holding the snake's locations in the snake[] ring buffer mentioned above.
游戏从头朝北在位置120开始,尾巴在南向136在大致中心位置开始。 只需花费大约1600字节的存储空间,我们就可以通过将蛇的位置保持在上述的snake []环形缓冲区中来在游戏中明显提高速度。
A ring buffer is a block of memory used for storing a queue that is a fixed size and must be big enough to hold all data. In this case, it's just for the snake. The data is pushed on the front of the queue and taken off the back. If the front of the queue hits the end of the block, then it wraps around. So long as the block is big enough, the front of the queue will never catch up with the back.
环形缓冲区是用于存储队列的内存块,该队列大小固定,并且必须足够大以容纳所有数据。 在这种情况下,仅用于蛇。 数据被推到队列的最前面,然后从后面取走。 如果队列的最前面碰到了块的末尾,那么它将环绕。 只要街区足够大,队列的前面就永远不会追上后面。
Every location of the snake (i.e., the single int coordinate) from the tail to the head (i.e., backwards) is stored in the ring buffer. This gives speed benefits because no matter how long the snake gets, only the head, tail and the first segment after the head (if it exists) need to be changed as it moves.
从尾部到头部(即向后)的蛇的每个位置(即单个int坐标)都存储在环形缓冲区中。 这给速度带来了好处,因为无论蛇走多长时间,都只需在移动时更改头部,尾巴和头部之后的第一段(如果存在)。
Storing it backwards is also beneficial because when the snake gets food, the snake will grow when it's next moved. This is done by moving the head one location in the ring buffer and changing the old head location to become a segment. The snake is made up of a head, 0-n segments), and then a tail.
向后存储它也是有益的,因为当蛇获得食物时,蛇在下一次移动时就会长大。 这是通过将磁头移动到环形缓冲区中的一个位置并将旧的磁头位置更改为一个段来完成的。 蛇由头,0-n个段和一个尾部组成。
When the snake eats food, the atefood variable is set to 1 and checked in the function DoSnakeMove()
当蛇吃食物时,atefood变量设置为1并在函数DoSnakeMove()中检查
We use two index variables, headindex and tailindex to point to the head and tail locations in the ring buffer. These start at 1 (headindex) and 0. So location 1 in the ring buffer holds the location (0-255) of the snake on the board. Location 0 holds the tail location. When the snake moves one location forward, both the tailindex and headindex are incremented by one, wrapping round to 0 when they reach 256. So now the location that was the head is where the tail is.
我们使用两个索引变量headindex和tailindex指向环形缓冲区中的头尾位置。 它们从1(headindex)和0开始。因此环形缓冲区中的位置1保持着蛇在板上的位置(0-255)。 位置0保留尾部位置。 当蛇向前移动一个位置时,tailindex和headindex都会加一,当它们达到256时将回绕为0。因此,现在的头部位置就是尾巴所在的位置。
Even with a very long snake that is winding and convoluted in say 200 segments. only the headindex, segment next to the head and tailindex change each time it moves.
即使是一条非常长的蛇,也要绕200圈来回曲折。 每次移动时,只有headindex,head和tailindex旁边的段会改变。
Note because of the way SDL works, we have to draw the entire snake every frame. Every element is drawn into the frame buffer then flipped so it's displayed. This has one advantage though in that we could draw the snake smoothly moving a few pixels, not an entire grid position.
注意,由于SDL的工作方式,我们必须在每一帧绘制整个蛇。 每个元素都被绘制到帧缓冲区中,然后翻转以便显示。 尽管这样做有一个优势,因为我们可以使蛇平滑移动几个像素,而不是整个网格位置。
翻译自: https://www.thoughtco.com/game-programming-in-c-four-snake-958418
手机游戏 2d 编程