我知道如何使用drawTexturePath以任意角度旋转图像:
int displayWidth = Display.getWidth();
int displayHeight = Display.getHeight();
int[] x = new int[] { 0, displayWidth, displayWidth, 0 };
int[] x = new int[] { 0, 0, displayHeight, displayHeight };
int angle = Fixed32.toFP( 45 );
int dux = Fixed32.cosd(angle );
int dvx = -Fixed32.sind( angle );
int duy = Fixed32.sind( angle );
int dvy = Fixed32.cosd( angle );
graphics.drawTexturedPath( x, y, null, null, 0, 0, dvx, dux, dvy, duy, image);
但我需要的是3d projection带有3d变换的简单图像(类似于this)
你能告诉我如何使用drawTexturedPath(我几乎可以肯定这是可能的)吗? 还有其他选择吗?
答案 0 :(得分:6)
此函数使用的方法(2个步行向量)与用于着名的“rotozoomer”效果的oldskool编码技巧相同。 rotozoomer example video
此方法是一种非常快速的旋转,缩放和倾斜图像的方法。只需旋转步行矢量即可完成旋转。简单地通过缩放步行向量来完成缩放。通过相对于彼此旋转助行器来完成偏斜(例如,它们不再成90度角)。
任天堂已经在他们的SNES中制造硬件,以对任何精灵和/或背景使用相同的效果。这为一些非常酷的效果让路。
这种技术的一个很大的缺点是人们不能透视地扭曲纹理。要做到这一点,每个新的水平线,步行矢量应该稍微改变。 (没有图纸很难解释)。
在snes上,他们通过改变walkvectors的每个扫描线来克服这个问题(在那些日子里,当监视器绘制任何扫描线时,可以设置中断)。此模式后来被称为MODE 7(因为它表现得像一种新的虚拟图形模式)。使用这种模式最着名的游戏是Mario kart和F-zero
因此,为了让这个工作在黑莓上,你必须绘制你的图像“displayHeight”次(例如,每次图像的一条扫描线)。这是达到预期效果的唯一方法。 (这无疑会让你受到性能损失,因为你现在用新值调用drawTexturedPath函数很多次,而不只是一次)。
我想通过一些谷歌搜索你可以找到一些公式(甚至实现)如何计算变化的walkvectors。有了一点纸(考虑到你的数学不太糟糕),你也可以自己推断它。当我为Gameboy Advance制作游戏时,我也是自己做的,所以我知道它可以完成。
务必预先确定一切!速度就是一切(尤其是在像手机这样的慢速机器上)
编辑:为你做了一些谷歌搜索。以下是如何创建mode7效果的详细说明。这将帮助您实现与Blackberry功能相同的功能。 Mode 7 implementation答案 1 :(得分:2)
使用以下代码,您可以扭曲图像并获得类似效果的视角:
int displayWidth = Display.getWidth();
int displayHeight = Display.getHeight();
int[] x = new int[] { 0, displayWidth, displayWidth, 0 };
int[] y = new int[] { 0, 0, displayHeight, displayHeight };
int dux = Fixed32.toFP(-1);
int dvx = Fixed32.toFP(1);
int duy = Fixed32.toFP(1);
int dvy = Fixed32.toFP(0);
graphics.drawTexturedPath( x, y, null, null, 0, 0, dvx, dux, dvy, duy, image);
这会使你的图像以45º的角度倾斜,如果你想要某个角度,你只需要使用一些三角法来确定矢量的长度。
答案 2 :(得分:2)
感谢您的回答和指导,给大家+1 MODE 7是我选择实现3D转换的方式,但不幸的是我无法使drawTexturedPath调整我的扫描线的大小......所以我选择了简单的drawImage。
假设您有一个位图inBmp(输入纹理),请创建新的Bitmap outBmp(输出纹理)。
Bitmap mInBmp = Bitmap.getBitmapResource("map.png");
int inHeight = mInBmp.getHeight();
int inWidth = mInBmp.getWidth();
int outHeight = 0;
int outWidth = 0;
int outDrawX = 0;
int outDrawY = 0;
Bitmap mOutBmp = null;
public Scr() {
super();
mOutBmp = getMode7YTransform();
outWidth = mOutBmp.getWidth();
outHeight = mOutBmp.getHeight();
outDrawX = (Display.getWidth() - outWidth) / 2;
outDrawY = Display.getHeight() - outHeight;
}
代码中的某处为outBmp创建一个Graphics outBmpGraphics
然后在从开始y到(纹理高度)* y变换因子的迭代中进行跟随:
1.为一行创建一个Bitmap lineBmp = new Bitmap(width,1)
2.从lineBmp中创建Graphics lineBmpGraphics
3.paint i从纹理到lineBmpGraphics的线
4.将lineBmp编码为EncodedImage img
5.根据MODE 7的尺度img
6.paint img to outBmpGraphics
注意: Richard Puckett's PNGEncoder BB port used in my code
private Bitmap getMode7YTransform() {
Bitmap outBmp = new Bitmap(inWidth, inHeight / 2);
Graphics outBmpGraphics = new Graphics(outBmp);
for (int i = 0; i < inHeight / 2; i++) {
Bitmap lineBmp = new Bitmap(inWidth, 1);
Graphics lineBmpGraphics = new Graphics(lineBmp);
lineBmpGraphics.drawBitmap(0, 0, inWidth, 1, mInBmp, 0, 2 * i);
PNGEncoder encoder = new PNGEncoder(lineBmp, true);
byte[] data = null;
try {
data = encoder.encode(true);
} catch (IOException e) {
e.printStackTrace();
}
EncodedImage img = PNGEncodedImage.createEncodedImage(data,
0, -1);
float xScaleFactor = ((float) (inHeight / 2 + i))
/ (float) inHeight;
img = scaleImage(img, xScaleFactor, 1);
int startX = (inWidth - img.getScaledWidth()) / 2;
int imgHeight = img.getScaledHeight();
int imgWidth = img.getScaledWidth();
outBmpGraphics.drawImage(startX, i, imgWidth, imgHeight, img,
0, 0, 0);
}
return outBmp;
}
然后在paint()
中绘制它protected void paint(Graphics graphics) {
graphics.drawBitmap(outDrawX, outDrawY, outWidth, outHeight, mOutBmp,
0, 0);
}
为了扩展,我做了类似于Resizing a Bitmap using .scaleImage32 instead of .setScale
中描述的方法的事情private EncodedImage scaleImage(EncodedImage image, float ratioX,
float ratioY) {
int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
int currentHeightFixed32 = Fixed32.toFP(image.getHeight());
double w = (double) image.getWidth() * ratioX;
double h = (double) image.getHeight() * ratioY;
int width = (int) w;
int height = (int) h;
int requiredWidthFixed32 = Fixed32.toFP(width);
int requiredHeightFixed32 = Fixed32.toFP(height);
int scaleXFixed32 = Fixed32.div(currentWidthFixed32,
requiredWidthFixed32);
int scaleYFixed32 = Fixed32.div(currentHeightFixed32,
requiredHeightFixed32);
EncodedImage result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
return result;
}
另见
J2ME Mode 7 Floor Renderer - 更详细的内容如果你写一个3D游戏,那就太激动了!
答案 3 :(得分:1)
你想做纹理贴图,那个功能不会削减它。也许你可以克服它,但更好的选择是使用纹理映射算法。
对于每行像素,这涉及确定形状的边缘以及这些屏幕像素映射到的形状上的位置(纹理像素)。实际上并不是那么难,但可能需要一些工作。你只会画一次这张照片。
GameDev在这里有很多带有源代码的文章:
http://www.gamedev.net/reference/list.asp?categoryid=40#212
维基百科也有一篇很好的文章:
http://en.wikipedia.org/wiki/Texture_mapping
另一个包含3d教程的网站:
http://tfpsly.free.fr/Docs/TomHammersley/index.html
在你的位置,我会寻找一个简单的演示程序,它做了一些你想要的东西,并使用他们的资源作为基础来开发我自己的 - 或者甚至找到一个便携式源库,我确定必须有一个少。