Projekt ma być napisany w GUI w Javie: Jest to gra komputerowa przypominająca bardzo grę Mamba (http://www.instalki.pl/gry/download/zrecznosciowe/Mamba.php).
W oknie ma znajdować się biały prostokąt. Gracz (piksel) znajduje się na jednym z jego brzegów (może być również w kącie). Wciśnięcie kursora powodującego ruch gracza w obrębie prostokąta rozpoczyna grę. W prostokącie zamiast węża (tak jak jest to w Mambie) jest piłka (wystarczy kropka z pikseli 2x2, współrzędne piłki i jej początkowy kierunek ruchu losowane Random), gdy piłka zderzy się ze ścianą to odbija się od niej zgodnie z prawem odbicia. Podczas swojego ruchu (tylko poziomego lub pionowego) gracz kreśli linię. Gdy uda mu się dotrzeć do ściany (ew. brzegu zakreślonego wcześniej obszaru) tak, żeby piłka nie trafiła w jego linię, zamalowywuje się obszar zakreślony przez gracza (na polu, na którym nie ma piłki - analogicznie do gry Mamba) i jest on wyłączany z ruchu piłki. Gra kończy się kiedy piłka uderzy w linię gracza bądź w samego gracza. Na bieżąco liczone są punkty (pole zakreślonego obszaru). Pod prostokątem ma być umieszczony suwak regulujący prędkość piłki.

Podstawowe problemy:

  • Jak sprawdzić czy piłka należy do obszaru zakreślonego przez użytkownika czy nie? Potrzebne to jest do zamalowywania obszaru i wyłączania zakreślonego obszaru z ruchu piłki - [b]ten problem jest najbardziej istotny[/b].
  • Jak liczyć pole zakreślonego obszaru?
  • Jak określić rodzaj odbicia piłki.

Proszę Was o pomoc.

To to co udało mi się już nasklecać:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;


public class CloseTheBall extends Robot implements ActionListener, AdjustmentListener, KeyListener {

    static int WIDTH = 610;
    static int HEIGHT = 600;
    static int POOL_WIDTH = WIDTH - 10;
    static int POOL_HEIGHT = HEIGHT/2;

        JPanel panel;
        JScrollBar speed;
        JLabel textSpeed;

    boolean isStarted = false;
    boolean left = false;
    boolean up = false;
    boolean right = false;
    boolean down = false;
    byte [][] area, now;

    PaintMove top;

    public static void main(String[] args) {

        JFrame frame = new JFrame("Pilka");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.toFront();
        try {
            CloseTheBall program = new CloseTheBall();
            JPanel panel = new JPanel(new GridLayout(2, 1, 0, -150) );
            panel.add(program.top);
            panel.add(program.panel);
            frame.add(panel);
            frame.addKeyListener(program);
            frame.setSize(WIDTH,HEIGHT);
            frame.setFocusable(true);
            frame.setVisible(true);
        } catch (AWTException e) {}
    }

    class PaintMove extends Canvas implements Runnable{

        int x, y, direction, oldX, oldY, oldDirection, speed = 2;
        int pX, pY, pDirection = 2, oldPX, oldPY, pSpeed = 1;
        Thread thread;

        public PaintMove() {
            thread = new Thread (this);
            x = randomX();
            y = randomY();
            direction = randomDirection();
            pX = randomX();
            pY = POOL_HEIGHT+2;
        }
        public void paint(Graphics g) {
            background(g);
            g.setColor(Color.red);
            g.fillOval(x, y, 5, 5);
            g.setColor(Color.blue);
            g.fillOval(pX, pY, 1, 1);
        }

        public void background(Graphics g) {
            g.setColor(Color.white);
            g.fillRect(0, 2, CloseTheBall.POOL_WIDTH, CloseTheBall.POOL_HEIGHT);
            g.setColor(Color.black);
            g.drawRect(0, 2, CloseTheBall.POOL_WIDTH, CloseTheBall.POOL_HEIGHT);
        }

        public void update(Graphics g) {
            g.setColor(Color.white);
            g.fillOval(oldX, oldY, 5, 5);
            g.setColor(Color.red);
            g.fillOval(x, y, 5, 5);
            g.setColor(Color.white);
            g.fillOval(oldPX, oldPY, 1, 1);
            g.setColor(Color.red);
            g.fillOval(pX, pY, 1, 1);
            g.setColor(Color.black);
            g.drawLine(oldPX, oldPY, pX, pY);
                g.setColor(Color.black);
                g.drawRect(0, 2, CloseTheBall.POOL_WIDTH, CloseTheBall.POOL_HEIGHT);

        }

        public int randomX() {
            Random r = new Random();
            return r.nextInt(POOL_WIDTH);
        }

        public int randomY() {
            Random r = new Random();
            return r.nextInt(POOL_HEIGHT);
        }

        public int randomDirection() {
            Random r = new Random();
            return r.nextInt(360);
        }


        public void returnOY() {
            x = oldX;
            y = oldY;
            direction = 360 - direction;
            x += (int)((double)speed * Math.cos(Math.PI * direction / 180));
            y += (int)((double)speed * Math.sin(Math.PI * direction / 180));
        }
        public void returnOX () {
            x = oldX;
            y = oldY;
            direction = 180 - direction;
            x += (int)((double)speed * Math.cos(Math.PI * direction / 180));
            y += (int)((double)speed * Math.sin(Math.PI * direction / 180));
        }
        public void calcNewPosition() {
            oldX = x;
            oldY = y;
            x += (int)((double)speed * Math.cos(Math.PI * direction / 180));
            y += (int)((double)speed * Math.sin(Math.PI * direction / 180));
            if(x >= POOL_WIDTH || x <= 0) returnOX();
            else if (y >= POOL_HEIGHT || y <= 0) returnOY();
            else {
                boolean quit = false;
                for(int i=(-Math.abs(oldX-x)); i<Math.abs(oldX-x+1); ++i){
                    for(int j=(-Math.abs(oldX-x)); j<Math.abs(oldX-x+1); ++j){
                        try {
                            if (now[x+i][y+j]==1) {
//te ify to akt rozpaczy,  po prostu prawdopodobienstwo zadzialania jest duze, algorytm jest tragiczny
                                if(now[x+i-2][y+j]==1 && now[x+i-1][y+j]==1 && now[x+i+1][y+j]==1 && now[x+i+2][y+j]==1) returnOY();
                                else if(now[x+i][y+j-2]==1 && now[x+i][y+j-1]==1 && now[x+i][y+j+1]==1 && now[x+i][y+j+2]==1) returnOX();
                                else if ((Math.cos(Math.PI * direction / 180))>Math.sin(Math.PI * direction / 180)) returnOY();
                                else returnOX();
                                quit = true;
                                break;
                            }
                        }
                        catch (Exception e) {
                            System.out.println("blisko!");
                        }
                    }
                    if (quit) {quit = false; break;}
                }

            }
        }
        public void calcNewPlayerPosition() {
            oldPX = pX;
            oldPY = pY;
            switch (pDirection) {
                case 0: { break; }
                case 1: { pX = pX - pSpeed; break; }
                case 2: { pY = pY - pSpeed; break; }
                case 3: { pX = pX + pSpeed; break; }
                case 4: { pY = pY + pSpeed; break; }
            }
            if (pX >= POOL_WIDTH) { --pX; pDirection = 0; }
            else if (pX <= 0) { ++pX; pDirection = 0; }
            else if (pY >= POOL_HEIGHT+2) { --pY; pDirection = 0; }
            else if (pY <= 2) { ++pY; pDirection = 0; }
            now[pX][pY] = 1;
//             System.out.println("area["+pX+"]["+pY+"]="+area[pX][pY]);
        }
        public void run() {
            while(true) {
                try {
                    calcNewPosition();
                    calcNewPlayerPosition();
                    repaint();
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

    }

    public CloseTheBall() throws AWTException {
        now = new byte[POOL_WIDTH][POOL_HEIGHT+2];
        for(int i = 0; i < POOL_HEIGHT + 2 ; ++i){
            for(int j = 0; j < POOL_WIDTH; ++j){
                now[j][i]=0;
            }
        }

        area = new byte[POOL_WIDTH][POOL_HEIGHT+2];
        for(int i = 0; i < POOL_HEIGHT + 2 ; ++i){
            for(int j = 0; j < POOL_WIDTH; ++j){
                if((i == 0) || (j == 0)) { area[j][i] = 1; continue; }
                else if ((i == POOL_HEIGHT+1) || (j == POOL_WIDTH-1)) { area[j][i] = 1; continue; }
                else area[j][i]=0;
            }
        }
//         System.out.println("zrobione "+ area[POOL_WIDTH-1][POOL_HEIGHT+1]);

        top = new PaintMove();

        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();

        panel = new JPanel(gridbag);
        speed = new JScrollBar(JScrollBar.HORIZONTAL, 0, 0, 0, 4);
        speed.addAdjustmentListener(this);
        textSpeed = new JLabel("Szybkosc pilki: 1");
        textSpeed.setHorizontalAlignment(SwingConstants.CENTER);
        c.gridwidth = 0;
        c.gridheight = 2;
        c.ipadx = 150;
        gridbag.setConstraints(textSpeed, c);
        c.gridwidth = GridBagConstraints.REMAINDER;
        gridbag.setConstraints(speed, c);
        panel.add(textSpeed);
        panel.add(speed);
    }

    public void actionPerformed(ActionEvent e) {}

    public void adjustmentValueChanged(AdjustmentEvent e) {
        textSpeed.setText("Szybkosc: " + (1 + speed.getValue()));
        top.speed =  2 * (1 + speed.getValue());
    }
    public void keyReleased(KeyEvent e) {}
    public void keyPressed(KeyEvent e){
        if (isStarted == false) { top.thread.start(); isStarted = true; }
        if (e.getKeyCode() == e.VK_LEFT) {
            if (right) { right = false; top.pDirection = 0; }
            else { top.pDirection = 1; left = true; up = false; right = false; down = false; }
        }
        if (e.getKeyCode() == e.VK_UP) {
            if (down) { down = false; top.pDirection = 0; }
            else { top.pDirection = 2; left = false; up = true; right = false; down = false; }
        }
        if (e.getKeyCode() == e.VK_RIGHT) {
            if (left) { left = false; top.pDirection = 0; }
            else { top.pDirection = 3; left = false; up = false; right = true; down = false; }
        }
        if (e.getKeyCode() == e.VK_DOWN) {
            if (up) { up = false; top.pDirection = 0; }
            else { top.pDirection = 4; left = false; up = false; right = false; down = true; }
        }
    }
    public void keyTyped(KeyEvent e) {}
}

glewap[at]o2.pl