有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Swing Java的同步问题

我正试图实现一个简单的足球游戏。我有一门球类课程:

import java.util.ArrayList;
import java.util.Random;

public class Ball {
    Team lastHitBy;
    public int curr_x;
    public int curr_y;
    public int count = 0;


    int neg_y = 0;
    boolean neg_x;

    int prev_x;
    int prev_y;
    int speed;

    public Ball(int curr_x, int curr_y) {
        this.curr_x = curr_x;
        this.curr_y = curr_y;
        this.prev_x = curr_x - 1;
        this.prev_y = curr_y - 1;
    }

    void update_position(int x, int y) {
        System.out.println("Update:" + x + " "+y);
        this.prev_x = this.curr_x;
        this.prev_y = this.curr_y;

        this.curr_x = x;
        this.curr_y = y;
    }

    public Player check_collisions(Player[] players) {      

        for (int i = 0; i < players.length; i++) {

            // first check if any intersection
            if (this.curr_x + Constants.ball_r >= players[i].x                       &&
                this.curr_x + Constants.ball_r <= players[i].x + Constants.player_width &&
                this.curr_y + Constants.ball_r >= players[i].y                       &&
                this.curr_y + Constants.ball_r <= players[i].y + Constants.player_height) {
                return players[i];
            }
        }
        return null;
    }

    public void move_step() {
        count += 1;
        System.out.println(count+" Px,y:" + this.prev_x + "," + this.prev_y + " -- " + this.curr_x + "," + this.curr_y);
        System.out.flush();
        boolean left = false, right = false, top = false, bottom = false;
        if(this.curr_x >= Constants.screen_width - Constants.ball_r / 2){
            right = true;
        }
        if(this.curr_x <= Constants.ball_r / 2){
            left = true;
        }
        if(this.curr_y >= Constants.screen_height - Constants.ball_r / 2){
            bottom = true;
        }
        if(this.curr_y <= Constants.ball_r / 2){
            top = true;
        }

        double slope = (curr_y - prev_y) / (curr_x - prev_x);

        if (right || left || bottom || top) slope = -slope;

        if (right && bottom) this.neg_y = -1;
        else if (right && top) this.neg_y = 1;
        else if (left && top) this.neg_y = 1;
        else if (left && bottom) this.neg_y = -1;
        else if (right || left || bottom || top) this.neg_y = 0;

        if (right) this.neg_x = true;
        if (left) this.neg_x = false;

        double c = (curr_y - slope * curr_x);
        int new_x = curr_x + Constants.step;
        if (this.neg_x) new_x = curr_x - Constants.step;
        int new_y = (int) (slope * new_x + c);
        if (this.neg_y == -1) { new_y = prev_y - Constants.step; }
        if (this.neg_y ==  1) { new_y = prev_y + Constants.step; }
        this.prev_x = this.curr_x;
        this.prev_y = this.curr_y;

        update_position(new_x, new_y);
    }

    // @assumption: This method is called after a collision.
    public void reflection(Player player, Player[] players) {
        double slope = - (curr_y - prev_y) / (curr_x - prev_x);
        double c = (curr_y - slope * curr_x);
        int new_x, new_y;
        boolean left = false, right = false;
        if (curr_x > prev_x) new_x = curr_x + Constants.step;
        else new_x = curr_x - Constants.step;

        if (this.curr_y >= player.y &&
            this.curr_y <= player.y + Constants.player_height &&
            this.curr_x <= player.x + Constants.player_width / 2) {
            left = true;
            this.neg_x = true;
        }
        else if (this.curr_y >= player.y && 
                 this.curr_y <= player.y + Constants.player_height &&
                 this.curr_x >= player.x + Constants.player_width / 2) {
            right = true;
            this.neg_x = false;
        }

        if (left) {
            // if left collision pass to the next player/obstacle
            System.out.println("Passed: ");
            ArrayList<Player> passTo= new ArrayList<Player>();

            for (int i=0;i<players.length;i++)
            {
                if (players[i].x>player.x)
                {
                    passTo.add(players[i]);
                }
            }
            if (passTo.size() != 0) {
            Random randomPlayer=new Random();
            int randomIndex=randomPlayer.nextInt(passTo.size());
            int error=(int)(Math.random()*10)-5;
            int error_x=(passTo.get(randomIndex).x+error);
            int error_y=(passTo.get(randomIndex).y+error);

            new_x += Constants.player_width + 5;

            double pass_slope = (double)(curr_y - error_y) / (double)(curr_x - error_x);

            double pass_c = ((double)curr_y - (double)(pass_slope * curr_x));
            new_y = (int) (pass_slope * (new_x) + pass_c);
            System.out.println(pass_c + " " + pass_slope + " " + new_y);
            this.neg_x = false;

            update_position(new_x, new_y);
            return;
            }

            else {
                Constants.speed = (int) (Math.random() * 8) + 2;
                System.out.println("Kicked!\n");
                int goal = Constants.screen_height/2;
                int goal_error = (int)(Math.random()*20)-5;
                int goalx = Constants.screen_width;
                int error_goaly = goal+goal_error;
                new_x += Constants.player_width + 5;
                double kick_slope = (double)(curr_y - error_goaly) / (double)(curr_x - goalx);
                double kick_c = ((double)curr_y - (double)(kick_slope * curr_x));
                new_y = (int) (kick_slope * (new_x) + kick_c);
                this.neg_x = false;
                System.out.println("Kicked at : " + new_x + "," + new_y);
                update_position(new_x, new_y);
                return;
            }

        } 
        if (right) {
            new_x = curr_x + Constants.step;
        }

        new_y = (int) (slope * new_x + c);
        update_position(new_x, new_y);
    }
}

我有一个使用此ball类渲染的面板:

package BigBalls;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Line2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

import sun.font.FileFont;

import foosball.commonClasses.*;
public class BouncyBall extends JPanel implements ActionListener, KeyListener {
    int speed = 10;
    int frameCount = 0;
    boolean player_has_moved = true;
    int oneX = 100, oneY = 100;
    Ball b;
    Rod[] rods = new Rod[8];
    public Team[] teams = new Team[2];
    boolean firstPaint = true;
    Player[] players_left = new Player[11];
    Player[] players_right = new Player[11];
    Timer t;
    JFrame f;
    Image background;
    private static final long serialVersionUID = 1L;
    public BouncyBall() {
        b = new Ball(10, 10);
        this.repaint();
        this.t = new Timer(2, this);
        t.start();
        addKeyListener((KeyListener) this);
        setFocusable(true);
        for (int i = 0; i < players_left.length; i++) {
            players_left[i] = new Player(teams[0], 1000, 1000, i);
        }

        for (int i = 0; i < players_right.length; i++) {
            players_right[i] = new Player(teams[1], 1000, 1000, i);
        }


        teams[0] = new Team(2, 5, 3, players_left, true);
        teams[1] = new Team(2, 5, 3, players_right, false);

        rods[0] = new Rod(100, teams[0], 0, 1);
        rods[1] = new Rod(200, teams[0], 1, 2);
        rods[2] = new Rod(300, teams[1], 8, 3);
        rods[3] = new Rod(400, teams[0], 3, 5);
        rods[4] = new Rod(500, teams[1], 3, 5);
        rods[5] = new Rod(600, teams[0], 8, 3);
        rods[6] = new Rod(700, teams[1], 1, 2);
        rods[7] = new Rod(800, teams[1], 0, 1);

        initUI();
        try {
            background = ImageIO.read(new File("img/background.jpg"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void animate() {
        Player left_p = this.b.check_collisions(this.teams[0].players);
        if (left_p != null)
            this.b.reflection(left_p, this.teams[0].players);
        this.b.move_step();     
        this.repaint();

    }
    public void paintComponent(Graphics g){
        frameCount+=1;
        super.paintComponent(g);
        //if (frameCount == 30) { this.t.setDelay((int)(Constants.speed)); frameCount = 0; }
         g.drawImage(this.background, 0, 0, 1000, 600, this);
        // g.fillRect(5, 84, 770, 450);
        // g.setColor(Color.green);
        // g.fillRect(5, 5, 900, 500);

       int i,j,dist;
       for (i = 0; i < 8; i++)
       {
           dist = (500/(rods[i].number_of_players+1));
           int Ycoordinate=dist;
           for (j=0;j<rods[i].number_of_players;j++)
           {
               if (i == 0 || i == 1 || i == 3 || i == 5)
                   g.setColor(Color.red);
               else
                   g.setColor(Color.black);

               if (rods[i].team.players[rods[i].start + j].y == 1000) {
                   rods[i].team.players[rods[i].start + j].x = rods[i].x - 5;
                   rods[i].team.players[rods[i].start + j].y = Ycoordinate - 10;
                   g.drawRect((rods[i].x - 5), (Ycoordinate-10), Constants.player_height, Constants.player_width);
                   g.fillRect((rods[i].x - 5), (Ycoordinate-10), Constants.player_height, Constants.player_width);
                   Ycoordinate=Ycoordinate+dist;
               } else {
                   g.drawRect((rods[i].x - 5), (rods[i].team.players[rods[i].start + j].y), Constants.player_height, Constants.player_width);
                   g.fillRect((rods[i].x - 5), (rods[i].team.players[rods[i].start + j].y), Constants.player_height, Constants.player_width);
               }
           }

       }
        // Draw ball
        g.setColor(Color.yellow);
        //player_has_moved = false;
        g.fillOval(this.b.curr_x, this.b.curr_y, 10, 10);
    }
    private void initUI() {
        //setTitle("Foosball");
        setSize(1000,650);
        //setLocationRelativeTo(null);
        //setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    public static void main(String[] args) {
        JPanel f = new BouncyBall();
        f.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent arg0) {
        this.animate();
    }
    @Override
    public void keyPressed(KeyEvent arg0) {
        if (arg0.getKeyCode() == KeyEvent.VK_UP) {
            ArrayList<Integer> al = new ArrayList<Integer>();
            for (int i = 0; i < teams[0].players.length; i++) {
                if (teams[0].players[i].y <= Constants.step+10) {
                    al.add(teams[0].players[i].x);
                }
            } for (int i = 0; i < teams[0].players.length; i++) {
                if (!al.contains(teams[0].players[i].x)) {
                    teams[0].players[i].y -= Constants.step_player;
                }
            }
        }
        if (arg0.getKeyCode() == KeyEvent.VK_DOWN) {
            ArrayList<Integer> al = new ArrayList<Integer>();
            for (int i = 0; i < teams[0].players.length; i++) {
                if (teams[0].players[i].y >= Constants.screen_height + Constants.step) {
                    al.add(teams[0].players[i].x);
                }
            } for (int i = 0; i < teams[0].players.length; i++) {
                if (!al.contains(teams[0].players[i].x)) {
                    teams[0].players[i].y += Constants.step_player;
                }
            }
        }
    }
    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }
}

我面临的bug非常奇怪:

首先,打印球中的语句。move_next()打印两次(计数值相同)。我猜这是因为Swing使用了一些我不知道的内部线程

当球从左侧撞击玩家对象时,球将获得预期的新方向和该方向上的一组新坐标(预期),但随后球将改变其坡度并开始沿平行于x轴的方向移动

错误日志:

180 Px,y:188,188 -- 189,189
Update:190 190
181 Px,y:189,189 -- 190,190
Update:191 191
181 Px,y:189,189 -- 190,190
Update:191 191
Passed: 
211.59803921568627 -0.10784313725490197 188
Update:217 188
182 Px,y:191,191 -- 217,188
Update:218 188
182 Px,y:190,190 -- 191,191
Update:192 192

注意最后2个“Px”打印语句


共 (0) 个答案