Pomoc w stworzeniu gry snake

0

Cześć wszystkim,
Próbuję stworzyć snake'a w javie, ale mam niezły problem z jego wydłużaniem. Mam jeden segment którym bez problemu poruszam, ale dodanie nowego, który zachowuje sie tak jak bym chciała to już nie taka prosta sprawa:P Może załącze kod tego co napisałam ogólnie jest to poruszanie kulki:P

Main.java

  
package snake;

import javax.swing.*;

public class Main {
   
    public static void main(String[] args) {
      
        JFrame frame=new MainFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

MainFrame.java


package snake;

import javax.swing.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

public class MainFrame extends JFrame implements KeyListener {

    private Ball ball; //głowa węża
    private PaintComponent comp;
    private int x; 
    private int y;
   
    public MainFrame()
    {
        setTitle("Snake");
        setSize(400,400);

        ball=new Ball();
        comp=new PaintComponent();
        comp.add(ball);
        add(comp);

        addKeyListener(this);
        Runnable r=new BallRunnable(ball,comp);
        Thread t=new Thread(r);
        t.start();    
    }

    public void keyPressed(KeyEvent e)
    {
        if(e.getKeyCode()==KeyEvent.VK_LEFT) {
            
            x=-1;
            y=0;
        }

        if(e.getKeyCode()==KeyEvent.VK_RIGHT){
            x=1;
            y=0;
        }

        if(e.getKeyCode()==KeyEvent.VK_UP){
            x=0;
            y=-1;
        }

        if(e.getKeyCode()==KeyEvent.VK_DOWN){
            x=0;
            y=1;
        }
    }

    public void keyReleased(KeyEvent event) {}

    public void keyTyped(KeyEvent event) {}
    
    private class BallRunnable implements Runnable
    {
        private Ball ball;
        private PaintComponent comp;

        public BallRunnable(Ball aBall, PaintComponent acomp)
        {
            ball=aBall;
            comp=acomp;

        }

        public void run()
        {
            try{
                while(true) {
                ball.move(x,y);
                comp.repaint();
                Thread.sleep(5);
                }
            }
            catch(InterruptedException e)
            {

            }
        }
    }
}

Ball.java

package snake;

import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Ball {

    private Image image;
    private int x;
    private int y;

    Ball()
    {
        try {
            image=ImageIO.read(new File("images\\ball.png"));
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
       
    }

    public void move(int ax,int ay)
    {
           x+=ax;
           y+=ay;
    }

    public int getX()
    {
        return x;
    }

    public int getY()
    {
        return y;
    }

    public Image getImage()
    {
        return image;
    }
}

PaintComponent.java

package snake;

import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;

public class PaintComponent extends JPanel {

    static public ArrayList<Ball> balls=new ArrayList<Ball>();

    public void add(Ball b)
    {
        balls.add(b);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        for (Ball b: balls)
            g.drawImage(b.getImage(),b.getX(),b.getY(),null);
    }
}

Jeśli komuś chciałoby się mi pomóc, to byłabym wdzięczna:) Chodzi mi tylko o wydłużanie węża. Dziękuję z góry:)

0

Musisz dodać logikę dodawania i przesuwania kulek:
Wprowadziłem potrzebne zmiany do Twoich klas. Oto zmiany.
Klasa Ball:

import java.awt.Image;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Ball {
    private Image image;
    private int x;
    private int y;
    public Ball(int x, int y) {
    	this.x = x;
        this.y = y;
    	try {
        	image = ImageIO.read(new File("j:\\ball.png"));
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
    public void move(int ax, int ay) {
    	x+=ax;
        y+=ay;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
    public void setX(int x) {
    	this.x = x;
    }
    public void setY(int y) {
    	this.y = y;
    }
    public Image getImage() {
    	return image;
    }
}

Klasa PaintComponent:

import java.awt.Color;
import java.awt.Graphics;
import java.util.List;

import javax.swing.JPanel;

public class PaintComponent extends JPanel {
	private static final long serialVersionUID = 1L;
	private List<Ball> balls;
	private int size = 0;
	public PaintComponent(List<Ball> balls) {
		this.balls = balls;
		this.size = balls.get(0).getImage().getHeight(null);
		this.setBackground(Color.WHITE);
	}
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Ball b : balls)
        	g.drawImage(b.getImage(), b.getX() * this.size, b.getY() * this.size, null);
    }
}

Nowa klasa Snake:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JPanel;

public final class Snake {
	private List<Ball> body;
	private PaintComponent comp;
	private int dX;
	private int dY;
	private Timer timer;
	public Snake() {
		body = Collections.synchronizedList(new ArrayList<Ball>());
		body.add(new Ball(0, 0));
		comp = new PaintComponent(body);
		dX = dY = 0; 
		timer = new Timer();
		timer.schedule(new Move(), 1000, 500);
		timer.schedule(new AddBall(), 5000, 4349);
	}
	public List<Ball> getBody() {
		return body;
	}
	public JPanel getPanel() {
		return comp;
	}
	public void updateDX(int dx) {
		this.dX = dx;
		this.dY = 0;
	}
	public void updateDY(int dy) {
		this.dY = dy;
		this.dX = 0;
	}
	private class Move extends TimerTask {
		public void run() {
			for(int i = body.size() - 2; i >= 0; i--) {
				body.get(i + 1).setX(body.get(i).getX());
				body.get(i + 1).setY(body.get(i).getY());
			}
			body.get(0).move(dX, dY);
			comp.repaint();
		}
	}
	private class AddBall extends TimerTask {
		public void run() { 
			int size = body.size();
			if(size < 10) {	
				body.add(new Ball(body.get(size - 1).getX(), body.get(size - 1).getY()));
			}
		}
	}
}

Oraz klasa MainFrame:

public class MainFrame extends JFrame implements KeyListener {
	private static final long serialVersionUID = 1L;
	private Snake snake;
	private static final int move = 1;
    public MainFrame() {
        setTitle("Snake");
        setSize(400, 400);
        snake = new Snake();
        add(snake.getPanel());
        addKeyListener(this);  
    }

    public void keyPressed(KeyEvent e) {
    	if(e.getKeyCode() == KeyEvent.VK_LEFT) {
        	snake.updateDX(-move);
        } else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
            snake.updateDX(move);
        } else if(e.getKeyCode() == KeyEvent.VK_UP){
        	snake.updateDY(-move);
        } else if(e.getKeyCode() == KeyEvent.VK_DOWN){
            snake.updateDY(move);
        }
    }

    public void keyReleased(KeyEvent event) {}

    public void keyTyped(KeyEvent event) {}
}

Przesuwanie znajduje się w klasie Snake. Umieściłem go w obsłudze zegara. Czas, co ile sekund ma się zmieniać długość i szybkość przesuwania możesz dowolnie zmienić.

0

Do sprawy można podejść zupełnie inaczej.

Można trzymać węża jako listę i przy ruchu dodawać nowy element na początku i kasować ostatni. Jeżeli mamy na planszy pożywienie, które ma wydłużać węża, to przy ruchu na pole z pożywieniem powinniśmy tylko dodawać nowy element na początku i nie usuwać ogona.

Mamy prosty algorytm O(1) zamiast przesuwania wszystkich segmentów.

Waż nie powinien móc przecinać samego siebie. Dlatego dodatkowo warto mieć dwuwymiarową tablicę typu boolean mówiącą, czy na danym polu jest wąż. Dzięki temu można sprawdzić poprawność ruchu w O(1).

btw. jakiś czas temu napisałem węża w Javie 3D. Jak będę mieć czas, to wrzucę.

0

Ogólnie, różnych podejść jest bardzo dużo. Każde ma swoje zalety. Wydaje się być naturalnym aby gra zawierała dodatkową klasę reprezentującą całą planszę: węża, przeszkody, jedzenie, bonusy. Wszystko zależy od pomysłowości programisty.

1 użytkowników online, w tym zalogowanych: 0, gości: 1