KTB Tutorial 1: 2d randomly generated terrain for Worms style game

本文介绍了一种用于生成2D地形的方法,类似于Worms风格的游戏。教程详细解释了如何生成黑白地形,并对其进行纹理处理以获得逼真的效果。此外,还提供了一个开源Java游戏KillerTeddyBear作为实现示例。
 

KTB Tutorial 1: 2d randomly generated terrain for Worms style game

March 22nd, 2007

Important note: this tutorial is the part 1 related to Killer Teddy Bear Game (open source game in java). You can read the rest of the tutorials here.

You can also download the full game for playing online against other player. It is completely free and you can use it like a base for your own game. Don’t expect anything incredible, it’s more an experiment than a finished game:

* Download Killer Teddy Bear game (.jar file, you need the JVM)
* Download Killer Teddy Bear source code (Eclipse project)

0. Introduction

In this first tutorial I will explain how to generate 2d terrains like the one we are used to see in Worms games. The explanation will not be in any programming language but in a general way of tackling the problem. But you have here the source code of KTB game that uses these ideas. The classes that implements the terrain generator are TerrainGenerator.java and MapGenerator.java.

KTB Tutorial 1

1. Generating a random terrain in black and white (TerrainGenerator.java)

If you have played any Worms games you would probably have designed some worlds with the terrain editor. Basically, what this editor allow you is to draw a black and white 2d map. Later, in the game, the black areas will be considered as terrain and will be properly textured. Of course, these worlds can be textured with different layouts: forest, desert, snow, etc.

Furthermore, in order to share these worlds between players in a net, you only have to send the seed that generated the terrain. So, if the seed it’s an integer one map will be encoded in 4 bytes!

So the first step is to generate this black and white terrain (you can use alpha = 0 instead of white in order to be able to put a sky layout in the background), but of course, it has to be generated randomly. There are thousands of algorithms for doing this, for sure lot of theme will be faster than the one I will propose here, you are free for trying the one that would fulfill your needs.

The first thing I wanted was to generate some mountains, so I called my friend Google and we found together this approach to a terrain generator solution in robot frog.

Terrain Generator

The algorithm was, clear, well explained and “render independent”, so I quickly decided to use it. Basically it generates a matrix of vertex as big as you need. It is up to you what will you do with these vertex’s than “describes” the mountains. So, the generator is not linked to any render.

The first fix I needed to implement, after easily moving the code from c++ to java, was to change it from 3d to a 2d space. That was an easy task because in fact I didn’t touch the code. I just generated a 640* 640 matrix terrain (640 = width in pixels of my black mountains) and I basically got a “mountain line vertex’s” from (0, 320) to (640, 320). 1D noise function should be faster than this, I mean, to calculate only one line of mountains, you can experiment with the code as you wish trying other procedures for generating these mountains.

Terrain Generator

Later I drew vertical columns of one pixel width using these vertex heights. Et voila!

Terrain Generator

Of course, having only mountains it’s a bit sad, so I implemented a function that draws groups of ovals of random radius in different positions of the screen. This, together with the base mountains, generated a nice result.

Terrain Generator

2. Texturing the black and white generated terrain (MapGenerator.java)

This was my favourite part of the implementation. I remember that it take me only 3 hours to have a rough approximation and it was a great pleasure to see that the result was really near to the one used in Worms game.

The first thing you need are three textures for texturing. The first one will be the base texture, the second will texture the upper areas and the last one the lower areas. Changing these textures the whole map will look different. I used grass, sand and stone.



Applying base texture

This was the easier part. You just have to check all the black pixels in the map image and to put on each of them the appropriate pixel from the base texture. Take care of starting again from the beginning of the base texture if you arrive to the end.

Applying upper and lower textures

And this was a bit tricky… but funny!

The algorithm for upper and lower texturing is the same. Basically, once you find an upper edge, you will draw a column of grass pixels in down direction, and you will do the same for the sand but in opposite direction. But there is an important thing can not forget: the height of that column will be in most of the cases the height of the grass texture… but not always! If you take a close look at the textured images, in the floating islands the grass is very shallow along the edges, producing a curve as it progresses towards the center. This is because the height of the grass column is getting lower and lower in these areas.

These are the steps you have to follow (in this case for the upper texture, but the procedure for the lower texture is the same):

* In a nested loop
* For each pixel in the map check if the above pixel is white (so it’s an upper edge pixel)
* Go down from this position increasing a counter until you reach a white pixel (lower edge)
* If this valour is bigger than the height of a column in the grass texture, we can directly draw it. If not, we can get the height of the grass column we have to draw dividing this valour by 1.4 (I tried 2, but this valour gave me better results).

Please check the source code, there are additional comments that should be useful.

And this is the final result, with a background and some funny killer teddy bears.

And now… what about having destructible terrain?

Well, depending of what you want to do, this can be really easy. For example, you can just draw an oval with alpha = 0 and erase this area of the terrain directly from the textured map. The trick for having better results is to have a second background terrain (with a different texture, for simulating some distance) and erase it with an oval of less radius.

In Killer Teddy Bear game, what I do it’s just to erase the terrain with that oval of alpha = 0. But you can implement new weapons that chomp the terrain in other way! Just user your imagination!

And soon… the second tutorial of the game: how to make an online game using java sockets! Tell me if you are interested in this tutorial writing some comments, please!

7 Comments »

  1. That’s really quite impressive. I’d read that robot-frog tutorial before and used it for actual 3D terrain generation but I never thought of applying it to 2D.

    Good tutorial too, well-explained.

    Comment by Steve � March 22, 2007 @ 11:17 am

  2. Nice tutorial indeed, thanks for sharing.

    Comment by Raine � March 22, 2007 @ 11:48 am

  3. Thank you for reading it!

    Comment by Indie Rover � March 27, 2007 @ 4:42 am

  4. Thanks, very nice and easy to understand tutorial. Gave me some ideas.

    But what if the map is larger than the screen .. let’s say 1200×600 or even larger .. then it would get really slow and take up a lot of texture memory to render. How would you go about optimizing it? Because Worms has quite large terrains..

    Even if you render the map onto a texture once and then place the texture on screen according to ‘camera’ position, it would get really slow and even more slow as you used higher screen resolution.

    Comment by Eigen � March 29, 2007 @ 8:16 am

  5. As you have read, the code is thought for generating the terrain in a bitmap. It’s up to you how will you render it later in the screen.

    In my java game I put it directly in a BufferImage, that can be rendered directly into the screen. Once the terrain is generated, you dont have to touch it until there is an explosion. In the areas that suffer an explosion, I only draw an alpha = 0 circle in this position. This is giving me good performance at (640×480) with 100fps.

    But for example, for one of the demos of my graphic 2d library LooverLib I first generated the terrain (only one time), and then I cut it in blocks and made textures for rendering quads.

    So, the tricky part, if you use textures, will be to regenerate the terrain in these areas that had and explosion. You should access to this texture texels (only the quad or quads that suffered the explosion) and make the holes. But will be fast, because you will be all the time rendering the quads and only making the holes when there is an explosion.

    Comment by Indie Rover � March 29, 2007 @ 9:15 am

  6. Where did you get the texture image from? Its nice

    Comment by Ryan � April 7, 2007 @ 5:04 pm

  7. It’s from Worms game, and of course It is only used for didactic purpose :)

    Comment by Indie Rover � April 8, 2007 @ 8:30 am

Comments RSS

Leave a comment





<think>我们已知热噪声功率的基本公式为:$P_n = kTB$,其中: - $k$ 是玻尔兹曼常数($1.38 \times 10^{-23} \, \text{J/K}$) - $T$ 是绝对温度(单位:开尔文,K) - $B$ 是带宽(单位:赫兹,Hz) 题目要求计算最低热噪声,且带宽为1Hz,并将结果转换为dBm单位。 最低热噪声通常对应于最低温度。在电子学中,我们通常考虑室温(290K)作为标准,但理论上,最低温度可以接近绝对零度(0K)。然而,在绝对零度时,量子效应会显现,热噪声公式需要修正。但根据传统定义,热噪声在绝对零度时应为零。不过,实际应用中,我们通常考虑的是室温下的标准值,或者在某些特殊应用(如深空探测)中可能使用低温。 根据引用[1],IEEE室温标准为290开尔文,并且在1Hz带宽下,热噪声功率为$4.005 \times 10^{-21} \, \text{W}$或$-172.75 \, \text{dBm}$。这是室温下的标准值。 但是,用户要求“最低热噪声”,理论上我们可以通过降低温度来减小热噪声。因此,我们需要考虑温度对热噪声的影响。 热噪声功率公式:$P_n = kTB$ 在带宽$B=1\,\text{Hz}$时,$P_n = kT$。 要得到最低热噪声,我们需要最小化$T$。理论上,当$T$趋近于0K时,$P_n$趋近于0。但实际中,温度不可能达到绝对零度,而且即使在极低温下,量子噪声也会存在。 然而,题目要求的是电子学中的最低热噪声,我们通常考虑的是实际可达到的最低温度。例如,在液氦温度(4.2K)或更低的温度(如10mK)下。但要注意,传统的热噪声公式在极低温下可能不适用,因为量子效应变得显著。不过,对于传统热噪声计算,我们仍然使用上述公式。 因此,计算步骤如下: 1. 确定最低温度$T$(单位:K)。 2. 计算1Hz带宽下的热噪声功率:$P_n = kT$(单位:W)。 3. 将功率转换为dBm。 dBm的定义为:$\text{dBm} = 10 \log_{10}\left(\frac{P}{1\,\text{mW}}\right)$,其中$P$的单位是瓦特(W)。 由于$1\,\text{mW} = 10^{-3}\,\text{W}$,所以: $$ \text{dBm} = 10 \log_{10}\left(\frac{P}{10^{-3}}\right) = 10 \log_{10}(P) + 30 $$ 现在,我们计算几个典型温度下的热噪声功率($B=1\,\text{Hz}$): **情况1:室温(290K)** 这是标准情况,根据引用[1]: $P_n = k \times 290 \times 1 = 1.38 \times 10^{-23} \times 290 = 4.002 \times 10^{-21} \, \text{W}$ 转换为dBm: $$ \text{dBm} = 10 \log_{10}(4.002 \times 10^{-21}) + 30 \approx 10 \times (-20.397) + 30 = -203.97 + 30 = -173.97 \, \text{dBm} $$ 但引用[1]中给出的是-172.75dBm,这里存在差异。注意,引用[1]中写的是“1 Hz带宽的热噪声功率(kTB)为4.005x10^-21 W或-172.75 dBm”。我们计算得到的是-173.97dBm,而引用中是-172.75dBm,这可能是由于常数取值不同或计算方式不同? 重新计算:$k=1.38\times10^{-23}$,$T=290$,$kTB=1.38e-23*290=4.002e-21$W。 将$4.002e-21$W转换为dBm: $$ 10 \log_{10}(4.002 \times 10^{-21} \times 1000) = 10 \log_{10}(4.002 \times 10^{-18}) = 10 \times (\log_{10}4.002 + \log_{10}10^{-18}) = 10 \times (0.602 - 18) = 10 \times (-17.398) = -173.98 \, \text{dBm} $$ 而引用[1]给出的是-172.75dBm,为什么? 注意:引用[1]中写的是“-172.75 dBm”,但我们的计算是-173.98dBm。检查引用[1]的数值:$4.005\times10^{-21}$W,我们计算得到$kTB=1.38e-23*290=4.002e-21$W,与4.005e-21W接近。那么4.005e-21W转换为dBm: $$ 10 \log_{10}(4.005 \times 10^{-21} \times 1000) = 10 \log_{10}(4.005 \times 10^{-18}) = 10 \times (\log_{10}4.005 + \log_{10}10^{-18}) \approx 10 \times (0.6026 - 18) = 10 \times (-17.3974) = -173.974 \, \text{dBm} $$ 仍然不是-172.75dBm。 重新阅读引用[1]:“1 Hz带宽的热噪声功率(kTB)为4.005x10^-21 W或-172.75 dBm”。这里可能存在问题。实际上,标准计算中,1Hz带宽的热噪声功率在290K时应该是-174dBm(这是一个近似值,因为$-174=10\log_{10}(kT_0)$,其中$T_0=290K$,$k=1.38e-23$,$kT_0=4.002e-21$W,转换为dBm:$10\log_{10}(4.002e-21/0.001)=10\log_{10}(4.002e-18)=-173.98$dBm,通常近似为-174dBm)。 但是引用[1]中写的是-172.75dBm,这可能是笔误?或者可能是针对特定阻抗的电压噪声?因为热噪声功率通常指的是在匹配负载上消耗的功率,所以应该是$kTB$,与电阻无关。 实际上,在50Ω系统中,热噪声电压为$V_n=\sqrt{4kTRB}$,则功率为$P_n = V_n^2 / R = 4kTRB / R = 4kTB$?这显然是错误的,因为功率应该是$kTB$(在匹配负载上)。正确理解:当噪声源内阻为R,负载为R时,负载上的噪声功率为$kTB$(与R无关)。所以,无论电阻是多少,1Hz带宽的噪声功率都是$kT$。 因此,引用[1]中的-172.75dBm可能是计算错误?或者可能是针对特定情况(比如非匹配?)?但根据标准,应该是-174dBm(近似)。 实际上,在工程中,常用-174dBm/Hz作为室温下热噪声的功率谱密度。即每Hz带宽的噪声功率为-174dBm。 所以,我们通常认为在室温290K时,1Hz带宽的热噪声功率为: $$ P_n = kT_0 = 1.38e-23 \times 290 = 4.002e-21 \, \text{W} = -173.98 \, \text{dBm} \approx -174 \, \text{dBm} $$ 现在,回到问题:最低热噪声。如果我们考虑接近绝对零度,例如$T=4.2\,\text{K}$(液氦温度),则: $$ P_n = k \times 4.2 \times 1 = 1.38e-23 \times 4.2 = 5.796e-23 \, \text{W} $$ 转换为dBm: $$ \text{dBm} = 10 \log_{10}(5.796e-23 \times 1000) = 10 \log_{10}(5.796e-20) = 10 \times (\log_{10}5.796 + \log_{10}10^{-20}) \approx 10 \times (0.763 - 20) = 10 \times (-19.237) = -192.37 \, \text{dBm} $$ 如果温度更低,比如$T=0.1\,\text{K}$(100mK),则: $$ P_n = k \times 0.1 \times 1 = 1.38e-24 \, \text{W} $$ 转换为dBm: $$ \text{dBm} = 10 \log_{10}(1.38e-24 \times 1000) = 10 \log_{10}(1.38e-21) \approx 10 \times (-20.86) = -208.6 \, \text{dBm} $$ 但请注意,在极低温下,热噪声公式可能不再适用,量子噪声会占主导。因此,实际电子学中,最低热噪声取决于能达到的最低温度,但通常不会低于液氦温度(4.2K)太多,除非在特殊实验环境中。 然而,题目要求的是“最低热噪声”,理论上我们可以计算接近0K时的噪声,但实际应用中,我们通常关注的是室温下的值或者特定低温环境下的值。 根据问题,我们可能只需要给出室温下的标准值(因为最低温度没有指定),但题目要求“最低”,所以我们应该指出温度越低噪声越低,并给出一个实际可达到的低温下的值。但用户没有指定温度,所以我们可以同时给出室温和液氦温度的值,并说明温度越低热噪声越低。 不过,引用[1]提供了室温标准值,我们可以以此为基础。但用户要求“最低”,所以我们可以这样回答: 在电子学中,热噪声的最低值取决于温度。理论上,当温度接近绝对零度时,热噪声趋近于零。但实际应用中,我们通常考虑室温(290K)下的标准值,即每Hz带宽的热噪声功率为-174dBm(近似)。在更低的温度下,热噪声会进一步降低。例如,在液氦温度(4.2K)下,1Hz带宽的热噪声功率约为-192.4dBm。 计算步骤: 1. 热噪声功率:$P_n = kTB$,其中$B=1\,\text{Hz}$,所以$P_n = kT$。 2. 将$P_n$(单位:瓦特)转换为dBm:$\text{dBm} = 10 \log_{10}(P_n / 0.001) = 10 \log_{10}(P_n) + 30$。 具体计算: - 室温($T=290\,\text{K}$): $$P_n = 1.38 \times 10^{-23} \times 290 = 4.002 \times 10^{-21} \, \text{W}$$ $$\text{dBm} = 10 \log_{10}(4.002 \times 10^{-21} \times 1000) = 10 \log_{10}(4.002 \times 10^{-18}) = -173.98 \, \text{dBm} \approx -174 \, \text{dBm}$$ - 液氦温度($T=4.2\,\text{K}$): $$P_n = 1.38 \times 10^{-23} \times 4.2 = 5.796 \times 10^{-23} \, \text{W}$$ $$\text{dBm} = 10 \log_{10}(5.796 \times 10^{-23} \times 1000) = 10 \log_{10}(5.796 \times 10^{-20}) = -192.37 \, \text{dBm}$$ 因此,最低热噪声可以通过降低温度来实现,在液氦温度下,1Hz带宽的热噪声功率约为-192.37dBm。但需注意,在极低温下,量子效应会引入其他噪声机制。 另外,根据引用[2],噪声功率谱密度在室温下为-174dBm/Hz,这与我们的计算一致。 所以,我们给出两个典型值:室温下为-174dBm/Hz(近似),液氦温度下为-192.37dBm/Hz。 注意:题目要求带宽为1Hz,所以就是dBm(而不是dBm/Hz),但通常我们会说功率谱密度,所以这里也可以说在1Hz带宽内的功率。 在工程中,常用dBm/Hz表示功率谱密度,即每Hz带宽的功率。因此,在1Hz带宽内,功率就是该值。 最终回答: 在电子学中,最低热噪声取决于温度。热噪声功率谱密度由$P_n = kT$给出(单位:W/Hz)。在室温(290K)下,该值为$4.002 \times 10^{-21}$W/Hz,转换为dBm为: $$ \text{dBm} = 10 \log_{10}\left(\frac{4.002 \times 10^{-21}}{0.001}\right) = -173.98 \, \text{dBm} \approx -174 \, \text{dBm} $$ 为获得更低的热噪声,可降低温度。例如在液氦温度(4.2K)下: $$ P_n = 1.38 \times 10^{-23} \times 4.2 = 5.796 \times 10^{-23} \, \text{W/Hz} $$ $$ \text{dBm} = 10 \log_{10}\left(\frac{5.796 \times 10^{-23}}{0.001}\right) = -192.37 \, \text{dBm} $$ 因此,1Hz带宽的最低热噪声(实际可达到)约为-192.37dBm(在4.2K时)。理论上,温度越低,热噪声越低,但受限于量子效应[^1][^2]。</think>### 电子学最低热噪声计算(1Hz带宽,dBm单位) #### 1. **核心公式** 热噪声功率谱密度由以下公式给出: $$P_n = kT$$ 其中: - $k$ 是玻尔兹曼常数($1.38 \times 10^{-23} \, \text{J/K}$) - $T$ 是绝对温度(单位:K) - 结果单位为 W/Hz(瓦特每赫兹) #### 2. **转换为dBm** dBm 定义为相对于 1 mW 的功率比: $$\text{dBm} = 10 \log_{10}\left( \frac{P_n}{0.001} \right) = 10 \log_{10}(P_n) + 30$$ 其中 $P_n$ 单位为瓦特(W)。 #### 3. **计算最低热噪声(以室温为例)** - **标准温度**:IEEE 定义的室温 $T = 290 \, \text{K}$[^1] - **计算功率谱密度**: $$P_n = kT = 1.38 \times 10^{-23} \times 290 = 4.002 \times 10^{-21} \, \text{W/Hz}$$ - **转换为dBm**: $$ \begin{aligned} \text{dBm} &= 10 \log_{10}(4.002 \times 10^{-21}) + 30 \\ &= 10 \times (-20.397) + 30 \\ &= -173.97 \, \text{dBm} \end{aligned} $$ 工程中通常近似为 **-174 dBm/Hz**[^1][^2]。 #### 4. **极限情况下的最低噪声** 通过降低温度可进一步减小噪声: - **液氦温度(4.2 K)**: $$P_n = 1.38 \times 10^{-23} \times 4.2 = 5.796 \times 10^{-23} \, \text{W/Hz}$$ $$\text{dBm} = 10 \log_{10}(5.796 \times 10^{-23}) + 30 = -192.37 \, \text{dBm}$$ - **接近绝对零度(0.1 K)**: $$P_n = 1.38 \times 10^{-23} \times 0.1 = 1.38 \times 10^{-24} \, \text{W/Hz}$$ $$\text{dBm} = 10 \log_{10}(1.38 \times 10^{-24}) + 30 = -208.86 \, \text{dBm}$$ > **关键说明**: > - 上述计算基于经典热噪声公式 $P_n = kT$,在极低温下需考虑量子效应修正[^2]。 > - 实际最低噪声受限于系统可实现的最低温度(如液氦冷却系统)。 #### 5. **自动化计算脚本** ```python import math def thermal_noise_dBm(T): k = 1.38e-23 # Boltzmann constant P_n = k * T # W/Hz dBm = 10 * math.log10(P_n) + 30 return dBm # 示例:室温290K print(f"290K: {thermal_noise_dBm(290):.2f} dBm") # 输出 -173.97 dBm # 示例:液氦温度4.2K print(f"4.2K: {thermal_noise_dBm(4.2):.2f} dBm") # 输出 -192.37 dBm ``` ### 总结 | 温度 | 热噪声功率谱密度 | 物理意义 | |-----------|------------------|------------------------| | 290 K | -174 dBm/Hz | 室温标准值[^1] | | 4.2 K | -192 dBm/Hz | 液氦冷却系统可实现值 | | <1 K | < -208 dBm/Hz | 接近量子极限(理论值) |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值