首先,我想说我对applets很新(我不打算开发任何,但我有一个学校项目来完成它们)。在发布我的代码之前,我有几个问题:
为什么applet窗口的坐标系如此混乱?我想它应该默认显示坐标系的第一个象限,这应该意味着(0,0)在左下角和(500,500)(如果这是窗口的大小)应该在上面右上角。但是,(0,0)位于左上角,而(500,500)位于右下角。为什么会这样,并且有一个简单的解决方法吗?
在我的代码中(其中一些是由老师提供的),有一个包含以下内容的try-catch块:
Thread.currentThread().sleep(40)
它在我尝试过的任何其他计算机上都能顺利运行。除非我将数字设置为100,否则球会在屏幕上保持闪烁和闪烁,而不是平稳地运行,当我将其设置为100时,它会开始非常缓慢地移动。
现在,我必须制作一个小动画,它可以在倒置的抛物线轨迹上移动一个球,其上升时半径增大,下降时半径减小。它应该在运行期间改变颜色。
这是我的代码:
import java.awt.*;
import java.applet.*;
public class Ball extends Applet implements Runnable
{
private static final long serialVersionUID = 1L;
//double x, y, xInit, wide = 100, high = 400;
//int dx, dy, diam, sizex, sizey;
int wide = 100, high = 400;
int xIncrement = 1;
int xInit = (int)(-parabolaX (0, wide, high));
int x = xInit;
int y = (int)(parabolaY (x, wide, high));
int diam, sizex, sizey;
Thread ballPlay = new Thread(this);
public void init()
{
setBackground(Color.black);
diam = 12;
setSize(500, 500);
sizex = 500;
sizey = 500;
ballPlay.start();
}
public void run()
{
while (true)
{
try { Thread.currentThread().sleep(100); }
catch (InterruptedException e) {};
if ((x <= -xInit) && (y >= 0)) {
x += xIncrement;
} else {
xInit = (int)(-parabolaX (0, wide, high));
x = xInit;
}
repaint();
}
}
//returns y-value of parabola
int parabolaY (int x, int wideness, int highness) {
//equation of parabola
int y = wideness*(x*x) + highness;
return y;
}
//returns x-value of parabola
int parabolaX (int y, int wideness, int highness) {
//equation of parabola
int x = (int)Math.sqrt((y - highness)/wideness);
return x;
}
public void paint(Graphics g)
{
g.setColor(Color.red);
System.out.println("PAINTING... X = " + x + " Y = " + y);
g.fillArc(x, y, diam, diam, 0, 360);
g.drawString(String.valueOf(x), 20, sizey-40);
g.drawString(String.valueOf(y), 20, sizey-20);
}
}
目前,它根本不起作用。通过多种方式调整它,我已经成功地将球放在其初始位置(100,400),但没有任何动作发生。前几天我发现了这个网 - http://www.openprocessing.org/sketch/25434这正是我所需要的(没有半径和颜色变化的部分),但我仍然无法弄明白。显然,有些东西(或很可能很多东西)我做错了但几乎不知道applet是如何工作的,我似乎无法找到问题。代码是我老师提供的一些代码和网页上的代码的混搭。
我想做的是让球的动画在倒置的抛物线轨迹上移动,起始位置(100,400)。完成抛物线后,它应该返回到其初始位置并继续循环动画。但是,使用当前的代码,它甚至不能像我需要的那样接近工作。
答案 0 :(得分:0)
但是,(0,0)位于左上角,而(500,500)位于右下角。为什么会这样,并且有一个简单的解决方法吗?
如果您考虑到它,那么在顶部有0,0是有意义的,当您调整它们时,所有现代GUI窗口都会向上和向左缩小。但是如果你在右下方有0,0点,那么编写数学代码就会非常困难,看看左边和顶部有多少空间,你应该用多少空间填充它们以使它们居中那种事。
除非我将数字设置为100,否则球会在屏幕上保持闪烁和闪烁,而不是平稳地运行,而当我将其设置为100时,它会开始非常缓慢地移动。
这是因为您的计算机可能没有其他计算机那么强大,因为您的计算机在下一个渲染想要进入之前没有足够快地渲染图形,或类似的东西。如果Applet
的绘画方法是双重缓冲的,那么你就不会遇到这个问题。
关于速度,每次执行睡眠都会睡眠40毫秒,所以你可以想到你的应用程序运行在1000毫秒除以每个睡眠的那么多毫秒,所以100,你正在运行大约每秒更新一次。现在与游戏中的大多数动画不同,您的应用程序的移动是基于刻度的,这意味着您的图形在每次更新时移动超过一定数量的像素,因此一秒钟内更新越少,图形移动越少(更好的方法是根据自上次更新以来经过的时间更新图形的位置。
因此,为了摆脱闪烁,你必须缓冲你的绘图。升级您的课程以从JApplet
而不是Applet
延伸将是一个良好的开端。之后,创建另一个扩展JPanel
的类,并将所有逻辑移到那里,并在applet类中覆盖paintComponent(Graphics)而不是paint(Graphics)。你仍然应该使用applet类(现在是一个JApplet),但是你应该在那里添加自定义JPanel类的子组件。您将使用的这种新的绘画方法是双缓冲的,可以消除闪烁。
// This code may not be exactly what you need but here's the general idea
public class Ball extends JApplet
{
public void init()
{
this.add(new MyCustomGraphicsPanel());
}
}
public class MyCustomGraphicsPanel extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
//double x, y, xInit, wide = 100, high = 400;
//int dx, dy, diam, sizex, sizey;
double wide = 100, high = 400;
int xIncrement = 1;
double xInit = -parabolaX (0, wide, high);
double x = xInit;
double y;
int diam, sizex, sizey;
Thread ballPlay = new Thread(this);
// Move init code into the constructor
public MyCustomGraphicsComponent()
{
setBackground(Color.black);
y = parabolaY (x, wide, high);
diam = 12;
setSize(500, 500);
sizex = 500;
sizey = 500;
ballPlay.start();
}
public void run()
{
while (true)
{
try { Thread.currentThread().sleep(100); }
catch (InterruptedException e) {};
if ((x <= -xInit) && (y >= 0)) {
x += xIncrement;
} else {
xInit = -parabolaX (0, wide, high);
x = xInit;
}
repaint();
}
}
}