我正在尝试为Java Swing GUI中的突破游戏创建一些动画游戏文本。
预期的行为:每当一块砖被击中时,它的点将猛击到屏幕上,暂停0.25秒然后逐渐消失。
我做了什么:在名为AlertText
的类中的方法内使用计时器。当在类GameLogic
中击中砖块时,会创建一个新的AlertText
并且其计时器开始运行。现在在游戏课上我有画画课。
问题:那么如何调用在AlertText
中创建的GameLogic
的特定实例来使用setter和getter方法来设置g.drawString
在Game
类中的paint中。我觉得这应该是一种常见的技巧?它有名字吗?
我使用全局变量处理一种砖的风格,所以我知道动画是有效的,但是我需要100多个全局变量来做各种砖。
游戏类
public class Game extends JPanel
{
public static final int HEIGHT = 720;
public static final int WIDTH = 600;
public Color color;
private GameLogic gl = new GameLogic();
private KeyboardController controller;
public Paddle player = new Paddle(110, HEIGHT-30, 100, 10, 10, color.black, controller);
public Ball gameBall = new Ball(300, 300, 15, color.black);
private boolean PaddleUpdateComplete = false;
private List<AlertText> activeAlerts = new ArrayList<AlertText>();
Game game = new Game();
public void spawnNewAlert(Brick b){
AlertText alert = new AlertText();
alert.setxPos(b.getXPosition());
alert.setyPos(b.getYPosition());
alert.setText(b.getPoints()+"");
alert.setColor(b.getColor());
activeAlerts.add(alert);
alert.fireText();
}
@Override
public void paint(Graphics g)
{
g.clearRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, (int)AlertText.staticAlertSize));
g.setColor(new Color(AlertText.staticRed, AlertText.staticGreen, AlertText.staticBlue));
g.drawString(AlertText.staticAlertOne, AlertText.staticAlertXPos, AlertText.staticAlertYPos);
player.draw((Graphics2D)g);
gameBall.draw((Graphics2D)g);
gl.drawBricks(g);
// Draw GameObjects and anything else here
g.setFont(scoreFont);
g.drawString("Score: " + player.getScore(), 10, 25);
g.drawString("LIVES: " + player.getLives(), 150, 25);
if(gl.gameOver(player) &&
gameBall.getYPosition() >= HEIGHT){
g.setColor(Color.black);
g.setFont(endFont);
g.drawString("Game Over! Score: " + player.getScore(), (WIDTH/2) - 85, (HEIGHT/2));
}
if(gl.empty()){
g.setColor(Color.black);
g.setFont(endFont);
g.drawString("You won! Score: " + player.getScore(), (WIDTH/2) - 85, (HEIGHT/2));
timer.stop();
}
if(PowerUps.isMegaPaddle){
g.setColor(Color.orange);
g.setFont(TimeFont);
g.drawString(PowerUps.megaPaddlecount+"", 300, 500);
}
if(PowerUps.isMegaBall){
g.setColor(Color.red);
g.setFont(TimeFont);
g.drawString(PowerUps.megaBallcount+"", 250, 400);
}
if(!game.activeAlerts.isEmpty()){
for(AlertText alert: game.activeAlerts){
g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, alert.getTextSize()));
g.setColor(alert.getColor());
g.drawString(alert.getText(), alert.getxPos(), alert.getxPos());
if(alert.count<=0){
game.activeAlerts.remove(alert);
}
}
}
}
public void updateGameState()
{
gameBall.move();
player.move(controller);
gl.checkCollisions(gameBall, player, timer, WIDTH, HEIGHT, game);
gl.removeBrick();
// Move GameObjects and check for collisions here
if(Paddle.paddleHits==1 && !PaddleUpdateComplete){
gameBall.setXVelocity(10);
gameBall.setYVelocity(gameBall.getYVelocity()-6);
PaddleUpdateComplete = true;
}
}
public final void setupGame()
{
gameBall.setXVelocity(0);
gameBall.setYVelocity(-10);
player.setLives(5);
gl.makeBricks();
// Instantiate instance variables here
}
// Constructor method should not be modified
public Game()
{
// Set the size of the Panel to the correct size
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
// Set the background color of the Panel to black
this.setBackground(Color.BLACK);
// Instantiate a KeyboardController and listen for input with it
controller = new KeyboardController();
this.addKeyListener(controller);
// Call the setupGame method to initialize instance variables
this.setupGame();
// Get focus in the window
this.setFocusable(true);
this.requestFocusInWindow();
}
// Start method should not be modified
public void start()
{
// Set up a new Timer to repeat every 20 milliseconds (50 FPS)
timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
repaint();
updateGameState();
}
});
timer.setRepeats(true);
timer.start();
}
Timer timer;
}
警报类方法fireText()
public void fireText(){
count = 50;
textSize=0;
Firing=true;
Timer time = new Timer(50, null);
time.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(count>47){
textSize+=10;
xPos-=2;
count--;
}
else if(count>42){
count--;
}
else {
yPos -= 1;
xPos += 1;
textSize -= 1;
count--;
if(count<=0) {
text ="";
count=-1;
Firing =false;
time.stop();
}
}
}
});
time.start();
}
GameLogic方法
public void checkCollisions(Ball ball, Paddle player, Timer time, int WIDTH, int HEIGHT, Game game) {
if(hitPaddle(ball, player)){
ball.setYVelocity(ball.getYVelocity() * -1);
Paddle.paddleHits++;
return;
}
//check if ball hit any walls
if(ball.getXPosition() >= (WIDTH - ball.getDiameter()) || ball.getXPosition() <= 0){
ball.setXVelocity(ball.getXVelocity() * -1);
}
if(ball.getYPosition() > (player.getYPosition() + player.getHeight() + 10)){
resetBall(ball, player, time, WIDTH, HEIGHT);
}
if(ball.getYPosition() <= 0){
ball.setYVelocity(ball.getYVelocity() * -1);
}
//handle collisions between bricks
int brickRowsActive = 0;
for(ArrayList<Brick> alb : bricks){
if(alb.size() == horizontalCount){
++brickRowsActive;
}
}
for(int i = (brickRowsActive==0) ? 0 : (brickRowsActive - 1); i < bricks.size(); ++i){
for(Brick b : bricks.get(i)){
if(brickHitByBall(ball, b)){
checkPowerUps(b, player, ball);
game.spawnNewAlert(b);
player.setScore(player.getScore() + b.getPoints());
b.decrementType();
}
}
}
}
答案 0 :(得分:0)
据我所知,你想要在另一个对象中触发一个方法,而另一个对象都被包裹在第三层,上层一层,对吧?
我会在Game对象中创建AlertText和GameLogic对象,然后将AlertText的引用传递给GameLogic,从而使GameLogic可以触发AletText的fireText()方法。您必须从spawnNewAlert方法中删除AlertText的实例化(实际上您只需要一个AlertText实例),并在每次运行后重写一下fireText方法以重置。
在GameLogic中:
AlertText alert;
public GameLogic(AlertText alert //other parameters) {
this.alert = alert;
//other stuff you do here
}
在游戏中,让我们说:
GameLogic gameLogic;
AlertText alertText;
public Game() {
alertText = new AlertText();
gameLogic = new GameLogic(alertText);
}
public void paint(Graphics g) {
gameLogic.spawnNewAlert(brick);
}
答案 1 :(得分:0)
您可能想要在Game
类中完成渲染的警报列表,并希望能够在您处理所有游戏玩法的GameLogic
类中添加该列表。
有很多方法可以做到这一点。假设您在Game
中引用了GameLogic
课程,请将spawnNewAlert()
的代码移至Game
。然后,GameLogic
中的代码可以调用game.spawnNewAlert(b)
,然后将其留给Game
类进行管理。
您需要在Game
课程中添加一些内容:
private List<AlertText> activeAlerts = new ArrayList<AlertText>();
spawnNewAlert()
中activeAlerts
paint()
中,循环浏览activeAlerts
并绘制每一个,删除任何不再有效的内容(请注意删除方法,使用Iterator
或将删除延迟到在迭代之后阻止ConcurrentModificationException
。)