我做了一个单人slither.io游戏。以下是其特点:
在游戏逻辑和代码结构方面,你们有什么建议?
(只有一班)
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import javax.swing.JFrame;
public class Controller {
MyFrame frame;
ArrayList<Point> listOfDots;
ArrayList<Point> foods;
Image OSC;
PointerInfo a = MouseInfo.getPointerInfo();
int size = 10;
int speed = 10;
Random r;
public static void main(String[] args) {
Controller c = new Controller();
c.startGame();
}
public void startGame(){
frame = new MyFrame("slitherio");
listOfDots = new ArrayList<Point>();
foods = new ArrayList<Point>();
r = new Random();
listOfDots.add(new Point(100, 100));
Runner r = new Runner();
r.start();
}
class Runner extends Thread {
public void run(){
while(true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(foods.size() < 100)
foods.add(new Point(r.nextInt(900), r.nextInt(900)));
a = MouseInfo.getPointerInfo();
Point p = a.getLocation();
Point last = listOfDots.get(listOfDots.size() - 1);
Point n = new Point();
if(last.distance(p) > 5){
n = calcCoor(last, p);
listOfDots.add(n);
if(listOfDots.size() >= size){
for(int i = 0; i < listOfDots.size() - size; i++){
listOfDots.remove(i);
}
}
System.out.println(n);
}
Iterator<Point> i = foods.iterator();
while(i.hasNext()){
Point food = i.next();
if(food.distance(n) < 20){
i.remove();
size++;
}
}
frame.repaint();
}
}
public Point calcCoor(Point last, Point mouse){
double degree = 0;
if(last.x < mouse.x && last.y < mouse.y){
degree = 360 - Math.toDegrees(Math.atan((double) (mouse.y - last.y) / (mouse.x - last.x)));
}else if(last.x > mouse.x && last.y > mouse.y){
degree = 180 - Math.toDegrees(Math.atan((double) (last.y - mouse.y) / (last.x - mouse.x)));
}else if(last.y > mouse.y && last.x < mouse.x){
degree = Math.toDegrees(Math.atan((double) (last.y - mouse.y) / (mouse.x - last.x)));
}else if(last.y < mouse.y && last.x > mouse.x){
degree = 180 + Math.toDegrees(Math.atan((double) (mouse.y - last.y) / (last.x - mouse.x)));
}
Point p = new Point((int)
(last.x + Math.cos(Math.toRadians(degree)) * speed), (int)
(last.y - Math.sin(Math.toRadians(degree)) * speed));
return p;
}
}
class MyMouseSensor extends MouseAdapter {
boolean mouseDown = false;
public void mousePressed(MouseEvent e){
speed = 20;
mouseDown = true;
size /= 2;
new Thread(){
public void run(){
while(mouseDown){
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
size--;
}
}
}.start();
}
public void mouseReleased(MouseEvent e){
speed = 10;
size *= 2;
mouseDown = false;
}
}
class MyFrame extends JFrame {
public MyFrame(String s){
super(s);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0, 0, 900, 900);
setLayout(new FlowLayout());
setBackground(Color.white);
addMouseListener(new MyMouseSensor());
setVisible(true);
}
public void paint(Graphics g) {
Dimension d = getSize();
checkOffscreenImage();
Graphics offG = OSC.getGraphics();
offG.setColor(Color.white);
offG.fillRect(0, 0, d.width, d.height);
paintOffscreen(OSC.getGraphics());
g.drawImage(OSC, 0, 0, null);
}
private void checkOffscreenImage() {
Dimension d = getSize();
if (OSC == null || OSC.getWidth(null) != d.width
|| OSC.getHeight(null) != d.height) {
OSC = createImage(d.width, d.height);
}
}
public void paintOffscreen(Graphics g) {
g.clearRect(0, 0, 900, 900);
Point first = new Point();
Point last = listOfDots.get(0);
g.setColor(Color.BLACK);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(9 + (float) size / 10));
for(int i = 1; i < listOfDots.size(); i++){
first = listOfDots.get(i);
g2.drawLine(first.x, first.y, last.x, last.y);
last = new Point(first);
}
g2.setColor(Color.red);
for(int i = 0; i < foods.size(); i++){
g2.fillOval(foods.get(i).x, foods.get(i).y, 10, 10);
}
}
}
}这是一张解释Slither.io的照片

右下角的粉红色点是一条死蛇的遗骸。你把头撞到另一条蛇身上就死了。你死后就变成食物了。
发布于 2016-04-28 14:35:02
如果可能的话,
MyFrame frame;
ArrayList<Point> listOfDots;
ArrayList<Point> foods;
Image OSC;
PointerInfo a = MouseInfo.getPointerInfo();
int size = 10;
int speed = 10;
Random r;只要有可能,就应该使变量private和final。这有很多好处。例如,当您不在代码中使用字段时,编译器将警告您。您还希望您的类公开尽可能少的信息。
考虑一个固定的时间步长。
class Runner extends Thread {
public void run(){
while(true){
try {
Thread.sleep(50);我理解你为什么要这么做,但是如果你打算做更多的游戏,那么我会开始学习一个固定的时间步骤,而不是依赖Thread.sleep()和多线程。我发现它讨论了用Swing http://www.java-gaming.org/index.php?topic=24220.0实现游戏循环的具体方法。
时不要使用数据结构的类型
ArrayList<Point> listOfDots;没有理由不直接把这个叫做dots。如果稍后将其更改为Map或其他结构,则不必遍历代码并更改变量名,因为这样会产生误导。
if(foods.size() < 100)
foods.add(new Point(r.nextInt(900), r.nextInt(900)));
if(last.distance(p) > 5){
if(food.distance(n) < 20){
setBounds(0, 0, 900, 900);
g2.fillOval(foods.get(i).x, foods.get(i).y, 10, 10);在阅读代码时,不难理解这些数字的含义,但如果您对这些神奇的数字使用显式变量,代码将更加清晰,更能自我记录。比如screenWidth,screenHeight,maxFood,eatDistance等等。
的分离
当前,滑动游戏的逻辑及其状态与呈现游戏和处理输入的方式结合在一起。你应该总是尝试把你的游戏模型和它的渲染方式分开。您应该有一个Slither类,它包含有关玩家位置、食物位置和游戏规则的信息。然后,绘制的每一个帧都会查看游戏模型,并根据它们所在的位置绘制物体。
当您这样做时,将游戏移植到另一个图形库非常容易,甚至可以将游戏逻辑移植到另一种语言或游戏引擎。
现在就这些了!问得好。
发布于 2016-04-28 06:24:59
ArrayList<Point> listOfDots; ArrayList<Point> foods;
接口通常比实现生成更好的类型。
List<Point> listOfDots;
List<Point> foods;如果您想在将来更改实现,这将使您变得更容易。
Runner r = new Runner(); r.start();
您已经有了一个名为r的字段。如果添加一个具有相同名称的局部变量来执行不同的操作,则会有些混淆。最好将这两个名称重命名为更长、更具描述性的名称。
a = MouseInfo.getPointerInfo();
这不需要是一个对象字段。您可以在这里将其声明为局部变量并删除该字段。
PointerInfo a = MouseInfo.getPointerInfo();作为一般规则,最好在覆盖其所有用途的最小范围内声明变量。
https://codereview.stackexchange.com/questions/126911
复制相似问题