首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Slitherio单机

Slitherio单机
EN

Code Review用户
提问于 2016-04-28 03:58:18
回答 2查看 3.2K关注 0票数 6

我做了一个单人slither.io游戏。以下是其特点:

  1. 按住鼠标按钮可以加快速度。
  2. 你可以吃东西,长得又宽又长。
  3. 只有100种食物会产生最大数量(吃来产生更多)

在游戏逻辑和代码结构方面,你们有什么建议?

(只有一班)

代码语言:javascript
复制
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的照片

右下角的粉红色点是一条死蛇的遗骸。你把头撞到另一条蛇身上就死了。你死后就变成食物了。

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-04-28 14:35:02

如果可能的话,

变量应该是私有的,

代码语言:javascript
复制
MyFrame frame;
ArrayList<Point> listOfDots;
ArrayList<Point> foods;
Image OSC;
PointerInfo a = MouseInfo.getPointerInfo();
int size = 10;
int speed = 10;
Random r;

只要有可能,就应该使变量privatefinal。这有很多好处。例如,当您不在代码中使用字段时,编译器将警告您。您还希望您的类公开尽可能少的信息。

为游戏循环

考虑一个固定的时间步长。

代码语言:javascript
复制
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实现游戏循环的具体方法。

命名

时不要使用数据结构的类型

代码语言:javascript
复制
ArrayList<Point> listOfDots;

没有理由不直接把这个叫做dots。如果稍后将其更改为Map或其他结构,则不必遍历代码并更改变量名,因为这样会产生误导。

幻数

代码语言:javascript
复制
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);

在阅读代码时,不难理解这些数字的含义,但如果您对这些神奇的数字使用显式变量,代码将更加清晰,更能自我记录。比如screenWidthscreenHeightmaxFoodeatDistance等等。

游戏模型与

的分离

当前,滑动游戏的逻辑及其状态与呈现游戏和处理输入的方式结合在一起。你应该总是尝试把你的游戏模型和它的渲染方式分开。您应该有一个Slither类,它包含有关玩家位置、食物位置和游戏规则的信息。然后,绘制的每一个帧都会查看游戏模型,并根据它们所在的位置绘制物体。

当您这样做时,将游戏移植到另一个图形库非常容易,甚至可以将游戏逻辑移植到另一种语言或游戏引擎。

现在就这些了!问得好。

票数 10
EN

Code Review用户

发布于 2016-04-28 06:24:59

ArrayList<Point> listOfDots; ArrayList<Point> foods;

接口通常比实现生成更好的类型。

代码语言:javascript
复制
    List<Point> listOfDots;
    List<Point> foods;

如果您想在将来更改实现,这将使您变得更容易。

Runner r = new Runner(); r.start();

您已经有了一个名为r的字段。如果添加一个具有相同名称的局部变量来执行不同的操作,则会有些混淆。最好将这两个名称重命名为更长、更具描述性的名称。

a = MouseInfo.getPointerInfo();

这不需要是一个对象字段。您可以在这里将其声明为局部变量并删除该字段。

代码语言:javascript
复制
                PointerInfo a = MouseInfo.getPointerInfo();

作为一般规则,最好在覆盖其所有用途的最小范围内声明变量。

票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/126911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档