本文转自:http://eyehere.net/2011/python-pygame-novice-professional-18/

3D是非常酷的技术,同时也就意味着更多的工作,上次的简单介绍之后,这次还要讲更多2D到3D的新概念。

基于时间的三维移动

我们使用Vector3类来进行3D上的移动,与2D非常类似,看下面一个例子:

直升机A在(-6, 2, 2)的位置上,目标是直升机B(7, 5, 10),A想摧毁B,所以发射了一枚火箭AB,现在我们得把火箭的运动轨迹过程给画出来,否则一点发射敌机就炸了,多没意思啊~~ 通过计算出两者之间的向量为(13, 3, 8),然后单位化这个向量,这样就可以在运动中用到了,下面的代码做了这些事情。

  1. from gameobjects.vector3 import *
  2. A = (–6, 2, 2)
  3. B = (7, 5, 10)
  4. plasma_speed = 100. # meters per second
  5. AB = Vector3.from_points(A, B)
  6. print “Vector to droid is”, AB
  7. distance_to_target = AB.get_magnitude()
  8. print “Distance to droid is”, distance_to_target, “meters”
  9. plasma_heading = AB.get_normalized()
  10. print “Heading is”, plasma_heading
  11. #######输出结果#########
  12. Vector to droid is (13, 3, 8)
  13. Distance to droid is 15.5563491861 meters
  14. Heading is (0.835672, 0.192847, 0.514259)

然后不停的重绘火箭的位置,用这个语句:
rocket_location += heading * time_passed_seconds * speed

不过我们还不能直接在pygame中绘制3D物体,得先学习一下下面讲的,“如何把3D转换为2D”。

3D透视

如果您初中美术认真学了的话,应该会知道这里要讲什么,还记得当初我们是如何在纸上画立方体的?

忘了?OK,从头开始说起吧,存储、计算3D坐标是非常容易的,但是要把它展现到屏幕上就不那么简单了,因为pygame中所有的绘图函数都只接受2D坐标,因此,我们必须把这些3D的坐标投影到2D的图面上。

平行投影

最简单的投影方法是——把第三个坐标z坐标给丢弃,用这样的一个简单的函数就可以做到:

  1. def parallel_project(vector3):
  2. return (vector3.x, vector3.y)

尽管这样的转换简单又快速,我们却不能用它。为什么?效果太糟糕了,我们甚至无法在最终的画面上感受到一点立体的影子,这个世界看起来还是平的,没有那个物体看起来比其他物体更远或更近。就好像我右边这幅图一样。

立体投影

在3D游戏中使用的更为广泛且合理的技术是立体投影,因为它的结果更为真实。立体投影把远处的物体缩小了,也就是使用透视法(foreshortening),如左图所示,然后下面是我们的转换函数,看起来也很简单:

  1. def perspective_project(vector3, d):
  2. x, y, z = vector3
  3. return (x * d/z, –y * d/z)

与上一个转换函数不同的是,这个转换函数还接受一个d参数(后面讨论),然后所有的x、y坐标都会接受这个d的洗礼,同时z也会插一脚,把原本的坐标进行缩放。

d的意思是视距(viewing distance),也就是摄像头到3D世界物体在屏幕上的像素体现之间的距离。比如说,一个在(10, 5, 100)的物体移动到了(11, 5, 100),视距是100的时候,它在屏幕上就刚好移动了1个像素,但如果它的z不是100,或者视距不是100,那么可能移动距离就不再是1个像素的距离。有些抽象,不过玩过3D游戏的话(这里指国外的3D大作),都有一种滚轮调节远近的功能,这就是视距(当然调的时候视野也会变化,这个下面说)。

在我们玩游戏的时候,视距就为我们的眼睛到屏幕的直线距离(以像素为单位)。

视野

那么我们怎么选取一个好的d呢?我们当然可以不断调整实验来得到一个,不过我们还可以通过视野(field of view)来计算一个出来。视野也就是在一个时刻能看到的角度。看一下左图的视野和视距的关系,可以看到两者是有制约关系,当视野角度(fov)增大的时候,d就会减小;而d增加的话,视野角度就会减小,能看到的东西也就变少了。

视野是决定在3D画面上展现多少东西的绝好武器,然后我们还需要一个d来决定透视深度,使用一点点三角只是,我们就可以从fov计算出d,写一下下面的代码学习学习:
在Internet上,你总是能找到99%以上的需要的别人写好的代码。不过偶尔还是要自己写一下的,不用担心自己的数学是不及格的,这个很简单~ 很多时候实际动手试一下,你就能明白更多。

  1. from math import tan
  2. def calculate_viewing_distance(fov, screen_width):
  3. d = (screen_width/2.0) / tan(fov/2.0)
  4. return d

fov角度可能取45~60°比较合适,这样看起来很自然。当然每个人每个游戏都有特别的地方,比如FPS的话,fov可能比较大;而策略性游戏的fov角度会比较小,这样可以看到更多的东西。很多时候还需要不停的变化fov,最明显的CS中的狙击枪(从没玩过,不过听过),开出来和关掉是完全不同的效果,改的就是视野角度。

今天又是补充了一大堆知识,等不及了吧~我们下一章就能看到一个用pygame画就的3D世界了!

如何用Pygame写游戏(十八)相关推荐

  1. 如何用Pygame写游戏(八)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-8/ 是时候让我们的游戏活泼起来了.电脑游戏和桌面游戏的一个巨大差别,想来 ...

  2. 如何用Pygame写游戏(十)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-10/ 有时候无聊在网上翻翻小说看看,绝大多数那叫一个无聊.比如说修炼的境 ...

  3. 如何用Pygame写游戏(一)

    转载地址:http://eyehere.net/2011/python-pygame-novice-professional-1/ Pygame的历史  Pygame是一个利用SDL库的写就的游戏 ...

  4. 如何用Pygame写游戏(二十二)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-22/ 辛苦啦~ 这次是我们系统的pygame理论学习的最后一章了,把这次 ...

  5. 如何用Pygame写游戏(十九)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-19/ 3D世界 让我们现在开始写一个3D的程序,巩固一下这几次学习的东西 ...

  6. 如何用Pygame写游戏(十六)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-16/ 经历了长年的艰苦卓绝的披星戴月的惨绝人寰的跋山涉水,我们终于接近了 ...

  7. 如何用Pygame写游戏(十四)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-14/ 上一次稍微说了一下AI,为了更好的理解它,我们必须明白什么是状态机 ...

  8. 如何用Pygame写游戏(二十)

    本文转自:http://eyehere.net/2011/python-pygame-novice-professional-20/ 声音是游戏中必要的元素之一,音效可以给予用户良好的反馈体验.赛车的 ...

  9. 如何用Pygame写游戏(十五)

    本文转自: http://eyehere.net/2011/python-pygame-novice-professional-15/ 在继续我们的AI之旅前,分享一个在煎蛋上看到的有趣新闻,能通过读 ...

最新文章

  1. linux压缩一个文件的命令行,linux下用命令行解压缩文件
  2. Python 基础入门--简介和环境配置
  3. websocket 获取ip_Spark+Kafka+WebSocket+eCharts实时分析-完全记录(1)
  4. 【超详细】在Linux上远程登录遇到的若干问题及解决方法(一)
  5. 多校第二场 1004 hdu 5303 Delicious Apples(背包+贪心)
  6. linux系统升级后,手动编译的kernel无法启动问题
  7. MQTT 控制报文 - PINGREQ心跳报文,PINGRESP - 第4章
  8. android DisplayMetrics
  9. 一道头条面试题,小夕差点没读懂题目,找出数组中缺失的数字,最近击败100%的用户!...
  10. Linux好用命令之dig命令
  11. 淘宝京东查看价格历史的chrome插件
  12. 我的权限控制(JBX + struts + hibernate + ORACLE)
  13. 计算机视觉关于进化计算表达方式0.0.6
  14. python版本降级
  15. 一个高逼格开发者必须理解的大型分布式网站的几点概念
  16. 《Linuxnbsp;Kernelnbsp;Development》读书…
  17. 我的世界java防火墙_我的世界Java版更新:烟花和自由堡垒!
  18. ubuntu下安装qq2012
  19. LMV321进行运算符电压放大电路设计
  20. MacOS上安装有多个Java版本,如何卸载?

热门文章

  1. 分布式块设备复制:客户端
  2. python输入end退出循环_4.学习python获取用户输入和while循环及if判断语句
  3. PyCharm:调试遇到问题
  4. C++: new是否进行初始化的问题
  5. Python with open() as 读写文件
  6. Hbuilder 左侧项目栏文件打开方式(单击?双击?) - 设置篇
  7. js 免费语音合成 (百度AI)- 代码篇
  8. 关于MongoDB数据库的可连接性稳定性 - 抛转篇
  9. 酷黑风个人主页+引导页源码
  10. 好看的扁平化大气IT个人简历网页模板