草庐IT

java - 绘制等距墙

coder 2024-03-14 原文

我在使用等距墙时遇到了一些麻烦。

我正在使用从后到前的渲染方法绘制等距的地砖,并且效果很好。我还将地板砖正确排列在一个良好的网格中。代码(对于等轴测平面图,这似乎是非常标准的),如下所示:

for(int x = 0; x < 6; x++){
    for(int y  = 3; y >=0 ; y--){

        int xCo = (y+x)*(tileWidth/2);
        int yCo = (x-y)*(tileHeight/2);
        tile.draw(g, xCo, yCo);
    }            
}

这使地板很漂亮:



网格是从以下图块构建的:

不幸的是,当我对墙壁使用相同的逻辑时,一切都会陷入困境。
for(int x = 0; x < 6; x++){
    for(int y  = 3; y >= 0 ; y--){

        int xCo = (y+x)*(wallWidth()/2);
        int yCo = (x-y)*(wallHeight()/2);
        walls.draw(g, xCo, yCo);    
}
}

我正在使用它作为我的墙砖:

(它是Google图像搜索中的占位符,但是应该都一样)

这是我得到的结果:



我的墙的渲染顺序显然是正确的,较近的墙在更远的墙之上进行渲染,这是我想要的,但是定位也很不正确,而且我不知道该如何正确地使用它来纠正该问题。像素值。

作为引用,我确实使用了硬编码的像素val进行了试验,因为我发现从一堵墙的右角到下一堵墙的右角,其变化恰好是(200,-100)像素。当我为此做渲染循环帐户时
int xCo = (x+y)*200;
int yCo = (y-x)*-100;

它工作正常,但这不是一个可行的解决方案,因为它不允许任何多功能性。

因此,寻找有关如何使我的等距墙对齐的建议。我究竟做错了什么?

谢谢!

最佳答案

您不能简单地使用与地板相同的绘图代码,因为墙壁和地板不在同一平面上:地板是平坦的(水平的),而墙壁是垂直的。因此,您必须稍微不同地绘制它们。

就地板的放置而言,您在地板案例中的x和y坐标表示类似“左/右”和“向前/向后”。对于积木,左和右仍然有意义,但是我们想用上下替换前/后,以反射(reflect)垂直方向。因此我们的“y”有了新的含义。

现在,在数学中,y轴通常指向上方,而在2D计算机图形学中,y轴指向下方。您可以选择-下面的代码假定它指向上方,因此y = 0的意思是“最低层”。

因此,让我们开始考虑顺序。您发布的示例砖是用于墙的,该墙将是地板的(上)左端。由于砖块的黑色部分(墙的深度),我们必须确保首先绘制较右边的砖块,以便左侧的黑色深度将被更近的砖块覆盖。相同的论点适用于墙壁顶部的黑色,我们必须首先绘制较低的砖块。

如果我们像以前讨论的那样坚持x和y方向(x从左到右,y从下到上),这意味着我们必须在负方向上运行两个for循环:

    for (int y = 3; y >= 0; y--) {
        for (int x = 5; x >= 0; x--) {
            ...
        }
    }

现在的主要问题是,相对于其他积木,我们必须偏移多少积木。让我们一次从x方向开始执行一个方向。

让我们想象一下彼此之间只有两块砖:

这两个的左侧具有可见的黑色深度部分,但右侧的不应显示它。因此,我们不能简单地将正确的图像偏移PNG的整个宽度。实际上,假设砖块与地板砖对齐,则墙的实际前部宽度应等于砖块宽度的一半。
int xCo = x * tileWidth / 2;

不应忽略左侧的黑墙深度,因为我们可能希望将每块砖向左偏移一点,以使墙前角的x坐标与地砖对齐,而不是x-后角的坐标。

现在,每个积木的y坐标都比较棘手,因为它不仅取决于积木行,而且还取决于x坐标:越靠右,我们应该画的越高。但是让我们暂时忽略x方向,尝试简单地绘制一列砖块:

同样,两个积木的y坐标之间的差值不是PNG的整个高度。与在左/右情况下我们假设砖块与砖块对齐(允许我们使用tileWidth作为delta-x)不同,砖块可以具有任意高度。但是我们仍然可以根据图像高度计算实际砖块高度,因为我们知道左侧的深度和顶部的深度必须对齐。

如果我们看一下砖PNG右上角的透明小三角形,我们会注意到其宽度和高度的比率必须与地板砖的宽度和高度的比率相同。这使我们可以根据上面计算的xoffset计算yoffset,并使用它来推断砖的实际高度:
int yoffset = xoffset * tileHeight / tileWidth;
int wallHeight = wallHeight() - tileHeight / 2 - yoffset;

请注意,这仅在以下假设下有效:PNG的边界处没有空白,并且由于舍入错误而可能仍会失败。因此,如有必要,您可以在此处添加Math.ceil()(或仅添加+ 1)。

因此,对于简单的列,我们现在就出发了:我们可以简单地将y变量与上面的wallHeight相乘。但是,如前所述,砖的x位置也会影响y像素坐标。如果我们再次看一下第一张图,两块砖彼此相邻,我们需要多少移动右块砖才能与左块砖对齐?嗯,这实际上很容易,因为它与地砖相同:是砖高度的一半!

所以我们都准备好了。如果我们将所有内容放在一起,最终将得到如下代码:
int xoffset = wallWidth() - tileWidth / 2;
int yoffset = xoffset * tileHeight / tileWidth;
int wallHeight = wallHeight() - tileHeight / 2 - yoffset;

for (int y = 3; y >= 0; y--) {
    for (int x = 5; x >= 0; x--) {

        int xCo = x * tileWidth / 2;
        int yCo = y * wallHeight - x * tileHeight / 2;

        walls.draw(g, xCo - xoffset, yCo - yoffset);
    }
}

(我假设wallWidth()和wallHeight()返回砖块PNG的宽度和高度。)

请注意,可以将for循环之前的三个常量移出实际的绘图代码-它们仅取决于图像属性和其他常量,不必在每次绘制墙时都需要重新计算。

关于java - 绘制等距墙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14488989/

有关java - 绘制等距墙的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  3. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  6. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  7. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  8. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  9. java - Ruby 相当于 Java 的 Collections.unmodifiableList 和 Collections.unmodifiableMap - 2

    Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur

  10. java - Java 的 StringReader 的 Ruby 等价物是什么? - 2

    在Java中,可以像这样从一个字符串创建一个IO流:Readerr=newStringReader("mytext");我希望能够在Ruby中做同样的事情,这样我就可以获取一个字符串并将其视为一个IO流。 最佳答案 r=StringIO.new("mytext")和here'sthedocumentation. 关于java-Java的StringReader的Ruby等价物是什么?,我们在StackOverflow上找到一个类似的问题: https://st

随机推荐