本文转载自:http://eyehere.net/2011/python-pygame-novice-professional-17/
最近有些忙,没有更新这个系列,不行啊不行,抓紧更新一篇,这几次可是3D啊3D,多么诱人的词啊……
游戏通常希望营造一个真实的世界,越接近真实越好啊,这样的代入感会很强。在早期,由于硬件的限制,游戏只能提供一些2D的图像,因为这对于电脑绘图是最容易的。还好随着技术发展,现在的显卡已经可以画出很逼真的3D画面了,所以“硬件杀手”游戏层出不穷,贫困游戏迷的噩梦啊。
在开开心心的继续之前,是不是有记忆力好的人想起这个系列第一篇里面我说过,pygame不适合做3D,怎么这里又厚颜无耻的开始说3D了?这不是搬石头砸自己的脚么:)这里我要仔细说明一下,所谓3D,说到底就是利用透视原理,在2D的画面上创造出有纵深错觉(说白了也就是近大远小)的画面而已,毕竟,屏幕是平的,怎么可能真的画出距离呢?换句话说,计算机3D的本质还是2D,只不过额外多了很多东西。
在纯pygame中,我们画3D画面就是通过计算在2D图像上画一些大小不一的东西:)
距离的魔法
我们看现实中的东西,和我们看画面上的东西,最大差别在于能感受现实物体的距离。而距离的产生,则是因为我们双眼看到的东西是不同的,两眼交替闭合,你会发现眼前的东西左右移动。一只眼睛则很难正确的判断距离,虽然比上眼睛还是能感觉到远近,但更精细一点,比如很难把线穿过针眼。
我们在3D画面上绘图的时候,就要遵循这个规律,看看下面的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
import
pygame
from
pygame
.
locals
import
*
from
random
import
randint
class
Star
(
object
)
:
def
__init__
(
self
,
x
,
y
,
speed
)
:
self
.
x
=
x
self
.
y
=
y
self
.
speed
=
speed
def
run
(
)
:
pygame
.
init
(
)
screen
=
pygame
.
display
.
set_mode
(
(
640
,
480
)
)
#, FULLSCREEN)
stars
=
[
]
# 在第一帧,画上一些星星
for
n
in
xrange
(
200
)
:
x
=
float
(
randint
(
0
,
639
)
)
y
=
float
(
randint
(
0
,
479
)
)
speed
=
float
(
randint
(
10
,
300
)
)
stars
.
append
(
Star
(
x
,
y
,
speed
)
)
clock
=
pygame
.
time
.
Clock
(
)
white
=
(
255
,
255
,
255
)
while
True
:
for
event
in
pygame
.
event
.
get
(
)
:
if
event
.
type
==
QUIT
:
return
if
event
.
type
==
KEYDOWN
:
return
# 增加一颗新的星星
y
=
float
(
randint
(
0
,
479
)
)
speed
=
float
(
randint
(
10
,
300
)
)
star
=
Star
(
640.
,
y
,
speed
)
stars
.
append
(
star
)
time_passed
=
clock
.
tick
(
)
time_passed_seconds
=
time_passed
/
1000.
screen
.
fill
(
(
0
,
0
,
0
)
)
# 绘制所有的星
for
star
in
stars
:
new_x
=
star
.
x
-
time_passed_seconds
*
star
.
speed
pygame
.
draw
.
aaline
(
screen
,
white
,
(
new_x
,
star
.
y
)
,
(
star
.
x
+
1.
,
star
.
y
)
)
star
.
x
=
new_x
def
on_screen
(
star
)
:
return
star
.
x
>
0
# 星星跑出了画面,就删了它
stars
=
filter
(
on_screen
,
stars
)
pygame
.
display
.
update
(
)
if
__name__
==
"__main__"
:
run
(
)
|
这里你还可以把FULLSCREEN加上,更有感觉。
这个程序给我的画面,发挥一下你的想象,不是一片宇宙么,无数的星云穿梭,近的速度更快,远的则很慢。而实际上看代码,我们只是画了一些长短不同的线而已!虽然很简单,还是用了不少不少python的技术,特别是函数式编程的(小)技巧。不过强大的你一定没问题:)但是pygame的代码,没有任何没讲过的,为什么这样就能有3D的效果了?感谢你的大脑,因为它知道远的看起来更慢,所以这样的错觉就产生了。
理解3D空间
3D空间的事情,基本就是立体几何的问题,高中学一半应该就差不多理解了,这里不多讲了。你能明白下图的小球在(7, 5, 10)的位置,换句话说,如果你站在原点,面朝Z轴方向。那么小球就在你左边7,上面5,前面10的位置。这就够了~
使用3D向量
我们已经学习了二维向量来表达运动,在三维空间内,当然要使用三维的向量。其实和二维的概念都一样,加减缩放啥的,这里就不用三个元素的元组列表先演练一番了,直接祭出我们的gameobjects神器吧!
1
2
3
4
5
6
7
8
9
10
|
from
gameobjects
.
vector3
import
*
A
=
Vector3
(
6
,
8
,
12
)
B
=
Vector3
(
10
,
16
,
12
)
print
"A is"
,
A
print
"B is"
,
B
print
"Magnitude of A is"
,
A
.
get_magnitude
(
)
print
"A+B is"
,
A
+
B
print
"A-B is"
,
A–
B
print
"A normalized is"
,
A
.
get_normalized
(
)
print
"A*2 is"
,
A
*
2
|
运行一下看看结果吧,有些无趣?确实,光数字没法展现3D的美啊,下一次,让我们把物体在立体空间内运动起来。