如何在不移动其他子类的情况下 move/animate 跨屏幕的单个子类对象?
How to move/animate a single subclass object across the screen without moving the other subclasses?
对于我在 Java 中的最后一个作业,我必须对一些 'monsters' 进行建模并使其中一个在屏幕上移动。为此,我需要使用已经实现的计时器,(timer = new Timer (50, monsterPanel)
使子类 'MovingMonster'
(父类 'Monster'
)的 X 坐标移动到屏幕右侧。同时其他子类,只有“SeeingMonster"
现在,不要在屏幕上移动。
我的猜测是必须更改 MovingMonster 的 void draw(Graphics g)
方法中的 x 坐标,但我不确定如何将其 link 更改为 public void actionPerformed (ActionEvent e)
在 class MonsterPanel
中,如果它甚至应该在同一个侦听器中。
如有任何帮助,我们将不胜感激。以下是该项目的完整代码,可在任何 IDE.
中运行
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
class MonsterMania {
MonsterPanel monsterPanel = new MonsterPanel();
Timer timer;
void createGUI() {
// create the GUI on the event thread.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame frame = new JFrame("Monster Mania");
frame.add(monsterPanel, BorderLayout.CENTER);
frame.setSize( 600, 400 );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
monsterPanel.setBackground( Color.DARK_GRAY );
monsterPanel.addMonsters();
timer = new Timer( 50, monsterPanel);
timer.start();
}
});
}
public static void main( String[] a ) {
new MonsterMania().createGUI();
}
}
class MonsterPanel extends JPanel implements ActionListener {
ArrayList<Monster> monsters = new ArrayList<Monster>(); // the list of monsters on the screen
void addMonsters() {
monsters.add( new Monster( 50, 40 ));
monsters.add( new Monster (150, 200 ));
monsters.add( new Monster (300, 300 ));
monsters.add (new SeeingMonster (150, 50, Color.GREEN));
monsters.add (new MovingMonster (400, 150));
}
public void paintComponent( Graphics g ) {
super.paintComponent( g );
for (Monster monster : monsters) {
monster.draw( g );
}
}
public void actionPerformed( ActionEvent e ) {
for (Monster monster : monsters) {
monster.step( this );
}
repaint();
}
}
class Monster {
int size = 50;
int arcSize = 10; // size of arc that defines roundedness of rounded rectangle
int locx = 0; // x coordinate center (pixel coordinates)
int locy = 0; // y coordinate center (pixel coordinates)
Color fill = Color.YELLOW; // inner color
Color line = Color.BLACK; // color of border
int phase = 0; // phase in the animation, a counter of time steps
Monster( int x, int y ) {
locx = x;
locy = y;
}
// update the monster because a time step has passed
// the parameter monsterPanel can be used for getting information about the panel, e.g., the size
void step( MonsterPanel monsterPanel ) {
phase++;
}
void draw( Graphics g ) {
// draw body
g.setColor( fill );
g.fillRoundRect( locx - size/2, locy - size/2, size, size, arcSize, arcSize );
g.setColor( line );
g.drawRoundRect( locx - size/2, locy -size/2, size, size, arcSize, arcSize );
// draw mouth
// every 5 time steps, mouth is changed
if ( phase % 20 < 10 ) {
int s = size/5; // size of closed mouth
g.drawOval( locx - s/2, locy + size/6, s, s );
} else {
int s = size/3; // size of open mouth
g.fillOval( locx - s/2, locy + size/6, size/3, size/3 );
}
}
}
class SeeingMonster extends Monster{
Color eyecolor;
public SeeingMonster ( int x, int y , Color color){
super( x, y);
locx = x;
locy = y;
eyecolor = color;
}
void draw( Graphics g ) {
super.draw(g);
int s = size/7;
g.setColor(eyecolor);
g.fillOval ( locx + 10, locy - 15 , size/5, size/5 );
g.fillOval ( locx + -15 , locy - 15 , size/5, size/5 );
}
}
class MovingMonster extends Monster{
MovingMonster( int x, int y){
super(x,y);
locx = x;
locy = y;
}
public int getLocationX() {
return locx;
}
void draw (Graphics g ) {
super.draw(g);
}
}
另一种方法是覆盖 SeeingMonster
class 中的 step
方法,让它什么都不做。
class SeeingMonster {
@Override
void step( MonsterPanel monsterPanel ) {}
}
一个更好的方法是使用方法 step
.
创建接口 Movable
public interface Movable {
void step(MonsterPanel monsterPanel);
}
现在您可以将此接口实现到 MovingMonster class 中,您现在可以在其中实现此方法。
class MovingMonster extends Monster implements Movable {
@Override
void step( MonsterPanel monsterPanel ) {
++phase;
}
}
现在您可以单独为 Movable
的实例保留 List
List<Movable> monsters = new ArrayList<Movable>();
您可以创建一个单独的函数来获取一个 Monster 作为参数,如果该 Monster 确实实现了该接口,那么您可以将这个 Monster 添加到您单独的 List
.
private List<Movable> movables = new ArrayList<Movable>();
private List<Monster> monsters = new ArrayList<Monster>();
private void add(Monster monster) {
monsters.add(monster);
if (monster instanceof Movable) {
movables.add((Movable)monster);
}
}
现在你可以让你的 addMonster 方法看起来像这样。
void addMonsters() {
add( new Monster( 50, 40 ));
add( new Monster (150, 200 ));
add( new Monster (300, 300 ));
add (new SeeingMonster (150, 50, Color.GREEN));
add (new MovingMonster (400, 150));
}
最后,您的 actionsPerformed
方法将只能循环遍历 Movable
个实例,这些实例实际上 Monster
可以移动。
public void actionPerformed( ActionEvent e ) {
for (Movable movable : movables) {
movable.step(this);
}
repaint();
}
对于我在 Java 中的最后一个作业,我必须对一些 'monsters' 进行建模并使其中一个在屏幕上移动。为此,我需要使用已经实现的计时器,(timer = new Timer (50, monsterPanel)
使子类 'MovingMonster'
(父类 'Monster'
)的 X 坐标移动到屏幕右侧。同时其他子类,只有“SeeingMonster"
现在,不要在屏幕上移动。
我的猜测是必须更改 MovingMonster 的 void draw(Graphics g)
方法中的 x 坐标,但我不确定如何将其 link 更改为 public void actionPerformed (ActionEvent e)
在 class MonsterPanel
中,如果它甚至应该在同一个侦听器中。
如有任何帮助,我们将不胜感激。以下是该项目的完整代码,可在任何 IDE.
中运行import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.event.*;
class MonsterMania {
MonsterPanel monsterPanel = new MonsterPanel();
Timer timer;
void createGUI() {
// create the GUI on the event thread.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame frame = new JFrame("Monster Mania");
frame.add(monsterPanel, BorderLayout.CENTER);
frame.setSize( 600, 400 );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
monsterPanel.setBackground( Color.DARK_GRAY );
monsterPanel.addMonsters();
timer = new Timer( 50, monsterPanel);
timer.start();
}
});
}
public static void main( String[] a ) {
new MonsterMania().createGUI();
}
}
class MonsterPanel extends JPanel implements ActionListener {
ArrayList<Monster> monsters = new ArrayList<Monster>(); // the list of monsters on the screen
void addMonsters() {
monsters.add( new Monster( 50, 40 ));
monsters.add( new Monster (150, 200 ));
monsters.add( new Monster (300, 300 ));
monsters.add (new SeeingMonster (150, 50, Color.GREEN));
monsters.add (new MovingMonster (400, 150));
}
public void paintComponent( Graphics g ) {
super.paintComponent( g );
for (Monster monster : monsters) {
monster.draw( g );
}
}
public void actionPerformed( ActionEvent e ) {
for (Monster monster : monsters) {
monster.step( this );
}
repaint();
}
}
class Monster {
int size = 50;
int arcSize = 10; // size of arc that defines roundedness of rounded rectangle
int locx = 0; // x coordinate center (pixel coordinates)
int locy = 0; // y coordinate center (pixel coordinates)
Color fill = Color.YELLOW; // inner color
Color line = Color.BLACK; // color of border
int phase = 0; // phase in the animation, a counter of time steps
Monster( int x, int y ) {
locx = x;
locy = y;
}
// update the monster because a time step has passed
// the parameter monsterPanel can be used for getting information about the panel, e.g., the size
void step( MonsterPanel monsterPanel ) {
phase++;
}
void draw( Graphics g ) {
// draw body
g.setColor( fill );
g.fillRoundRect( locx - size/2, locy - size/2, size, size, arcSize, arcSize );
g.setColor( line );
g.drawRoundRect( locx - size/2, locy -size/2, size, size, arcSize, arcSize );
// draw mouth
// every 5 time steps, mouth is changed
if ( phase % 20 < 10 ) {
int s = size/5; // size of closed mouth
g.drawOval( locx - s/2, locy + size/6, s, s );
} else {
int s = size/3; // size of open mouth
g.fillOval( locx - s/2, locy + size/6, size/3, size/3 );
}
}
}
class SeeingMonster extends Monster{
Color eyecolor;
public SeeingMonster ( int x, int y , Color color){
super( x, y);
locx = x;
locy = y;
eyecolor = color;
}
void draw( Graphics g ) {
super.draw(g);
int s = size/7;
g.setColor(eyecolor);
g.fillOval ( locx + 10, locy - 15 , size/5, size/5 );
g.fillOval ( locx + -15 , locy - 15 , size/5, size/5 );
}
}
class MovingMonster extends Monster{
MovingMonster( int x, int y){
super(x,y);
locx = x;
locy = y;
}
public int getLocationX() {
return locx;
}
void draw (Graphics g ) {
super.draw(g);
}
}
另一种方法是覆盖 SeeingMonster
class 中的 step
方法,让它什么都不做。
class SeeingMonster {
@Override
void step( MonsterPanel monsterPanel ) {}
}
一个更好的方法是使用方法 step
.
Movable
public interface Movable {
void step(MonsterPanel monsterPanel);
}
现在您可以将此接口实现到 MovingMonster class 中,您现在可以在其中实现此方法。
class MovingMonster extends Monster implements Movable {
@Override
void step( MonsterPanel monsterPanel ) {
++phase;
}
}
现在您可以单独为 Movable
List
List<Movable> monsters = new ArrayList<Movable>();
您可以创建一个单独的函数来获取一个 Monster 作为参数,如果该 Monster 确实实现了该接口,那么您可以将这个 Monster 添加到您单独的 List
.
private List<Movable> movables = new ArrayList<Movable>();
private List<Monster> monsters = new ArrayList<Monster>();
private void add(Monster monster) {
monsters.add(monster);
if (monster instanceof Movable) {
movables.add((Movable)monster);
}
}
现在你可以让你的 addMonster 方法看起来像这样。
void addMonsters() {
add( new Monster( 50, 40 ));
add( new Monster (150, 200 ));
add( new Monster (300, 300 ));
add (new SeeingMonster (150, 50, Color.GREEN));
add (new MovingMonster (400, 150));
}
最后,您的 actionsPerformed
方法将只能循环遍历 Movable
个实例,这些实例实际上 Monster
可以移动。
public void actionPerformed( ActionEvent e ) {
for (Movable movable : movables) {
movable.step(this);
}
repaint();
}