我正在做蛇游戏,并且被困在使尾巴跟着头部的位置。我听说在头和尾上使用添加和删除操作可能会发生这种情况,但是我不知道从哪里开始。
到目前为止,这是我的代码:
Screen.java
public class Screen extends JPanel implements ActionListener, KeyListener {
public static final JLabel statusbar = new JLabel("Default");
public static final int WIDTH = 800, HEIGHT = 800;
Timer t = new Timer(100, this);
int x = 400;
int y = 400;
int size = 5; //increase size if eat
private boolean right = false, left = false, up = false, down = false;
int head = 0;
private LinkedList<BodyPart> snake = new LinkedList<BodyPart>();
private BodyPart b;
public Screen(){
initSnake();
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void update(){
}
public void direction(){
if(right) x+=10;
if(left) x-=10;
if(up) y-=10;
if(down) y+=10;
}
public void trackOutBound(){
if(x < 0 || x > 800 || y < 0 || y > 800) {
x = 400;
y = 400;
}
}
public void initSnake(){
if(snake.size() == 0){
b = new BodyPart(x, y);
for(int i = 0; i < size; i++) {
snake.add(b);
}
System.out.println(snake);
}
}
public static void main(String[] args) {
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(new Color(10, 50, 0));
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
for(int i = 0; i < WIDTH / 10; i++) {
g.drawLine(i * 10, 0, i * 10, HEIGHT);
}
for(int i = 0; i < HEIGHT / 10; i++) {
g.drawLine(0, i * 10, WIDTH, i * 10);
}
int tempx = 0, tempy = 0;
int temp = 0;
for(int i = 0; i < size; i++){
if(i == head) {
snake.get(i).x = x;
snake.get(i).y = y;
snake.get(i).draw(g);
g.setColor(Color.blue);
g.fillRect(x, y, 10, 10);
g.setColor(Color.white);
g.drawRect(x, y, 10, 10);
} else if(i > 0 && up) {
snake.get(i).x = x;
snake.get(i).y = y + temp;
snake.get(i).draw(g);
} else if(i > 0 && down) {
snake.get(i).x = x;
snake.get(i).y = y - temp;
snake.get(i).draw(g);
} else if(i > 0 && left) {
snake.get(i).x = x + temp;
snake.get(i).y = y;
snake.get(i).draw(g);
} else if(i > 0 && right) {
snake.get(i).x = x - temp;
snake.get(i).y = y;
snake.get(i).draw(g);
}
temp += 10;
}
/*
if(snake.size() == 5){
snake.add(b);
size += 1;
}
*/
}
@Override
public void actionPerformed(ActionEvent e) {
direction();
trackOutBound();
repaint();
// System.out.println(snake);
statusbar.setText("(" + x + " , " + y + ")");
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT && !left) {
up = false;
down = false;
right = true;
}
if(key == KeyEvent.VK_LEFT && !right) {
up = false;
down = false;
left = true;
}
if(key == KeyEvent.VK_UP && !down) {
left = false;
right = false;
up = true;
}
if(key == KeyEvent.VK_DOWN && !up) {
left = false;
right = false;
down = true;
}
}
@Override
public void keyReleased(KeyEvent e) {}
}
BodyPart.java
public class BodyPart {
int x;
int y;
public BodyPart(int x, int y) {
this.x = x;
this.y = y;
}
public void draw(Graphics g) {
this.x = x;
this.y = y;
g.setColor(Color.red);
g.fillRect(x, y, 10, 10);
g.setColor(Color.white);
g.drawRect(x, y, 10, 10);
}
}
框架
public class Frame extends JPanel {
private static JLabel statusbar = new JLabel("Default");
public void statusbar(){
statusbar = Screen.statusbar;
}
public static void main(String[] args) {
JFrame f = new JFrame();
Screen s = new Screen();
f.add(s);
f.add(statusbar, BorderLayout.SOUTH);
f.setSize(800, 800);
f.setVisible(true);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
现在这段代码只会使尾巴翻转到水平或垂直方向,是否可以通过使用此代码使尾巴跟随头部?还是我需要更改代码?
谢谢
基本思想是,您需要某种List
包含蛇的所有点的东西。从概念上讲,List
它将包含虚拟坐标,即1x1
表示虚拟空间中的坐标,该坐标表示虚拟板上的位置(宽度和高度会有所增加)。
然后,您可以将其翻译到屏幕上,这样将允许蛇的每个部分都大于单个像素。因此,如果每个部分都是5x5
像素,则1x1
实际上将5x5
在屏幕中。
每次蛇移动时,都向头部添加一个新值,并从尾部删除最后一个值(假设它没有增长)。当您需要画蛇时,您只需遍历List
,就可以画蛇的每个点。
以下是一个简单的示例,该示例使用一个LinkedList
,将一个新的元素推Point
到上List
,制作一个新的头部,并在每个循环中都删除最后一个元素(尾部)。
基本上可以归结为…
snakeBody.removeLast();
snakeBody.push(new Point(xPos, yPos));
作为可运行的概念
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Snake {
public static void main(String[] args) {
new Snake();
}
public Snake() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
private int xPos, yPos;
private Direction direction = Direction.UP;
private LinkedList<Point> snakeBody = new LinkedList<>();
public TestPane() {
xPos = 100;
yPos = 100;
for (int index = 0; index < 50; index++) {
snakeBody.add(new Point(xPos, yPos));
}
bindKeyStrokeTo("up.pressed", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), new MoveAction(Direction.UP));
bindKeyStrokeTo("down.pressed", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), new MoveAction(Direction.DOWN));
bindKeyStrokeTo("left.pressed", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), new MoveAction(Direction.LEFT));
bindKeyStrokeTo("right.pressed", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), new MoveAction(Direction.RIGHT));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
switch (direction) {
case UP:
yPos--;
break;
case DOWN:
yPos++;
break;
case LEFT:
xPos--;
break;
case RIGHT:
xPos++;
break;
}
if (yPos < 0) {
yPos--;
} else if (yPos > getHeight() - 1) {
yPos = getHeight() - 1;
}
if (xPos < 0) {
xPos--;
} else if (xPos > getWidth() - 1) {
xPos = getWidth() - 1;
}
snakeBody.removeLast();
snakeBody.push(new Point(xPos, yPos));
repaint();
}
});
timer.start();
}
public void bindKeyStrokeTo(String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Point p : snakeBody) {
g2d.drawLine(p.x, p.y, p.x, p.y);
}
g2d.dispose();
}
public class MoveAction extends AbstractAction {
private Direction moveIn;
public MoveAction(Direction direction) {
this.moveIn = direction;
}
@Override
public void actionPerformed(ActionEvent e) {
direction = this.moveIn;
}
}
}
}
现在,它没有碰撞检测或其他功能,但是您可以移动蛇,蛇会自动跟随
我在我的squarespace站点上使用了一些HTML&CSS来创建一个自定义的跟随光标。我只想有一个浮动的圆圈,没有实际的光标显示。我已经得到了它的工作,但当我的网站滚动跟随光标没有移动的页面滚动,只是卡在顶部。 这只会导致follow光标完全停止随鼠标移动而移动,在页面中心变成静态的。 将HTML&CSS注入到squarespace站点以创建自定义跟随光标: null null
本文向大家介绍unity实现摄像头跟随,包括了unity实现摄像头跟随的使用技巧和注意事项,需要的朋友参考一下 代码很简单,这里就不多废话了,直接奉上代码 以上所述就是本文的全部内容了,希望大家能够喜欢,能够对大家学习unity有所帮助。
如果你想创建一个像这样的单链表: 这个列表有方法“追加”、“删除”、“printList”和“findElement”。有必要有尾巴吗?因为使用“最后”你可以地址最后一个节点。 那么,什么时候有必要拥有所有三个节点“头”、“尾”和“最后”?例如,当您想将排序的节点插入列表时?
工具与材料: 光环板,鳄鱼夹或导线,电池盒,剪刀,打孔工具,刻度尺,卡纸,双面胶,杜邦线,9g小舵机(3.3V)等。 制作小猫 在卡纸上画出小猫的身体和尾巴,将它们从卡纸上剪下,眼睛打孔。 注意:小猫眼睛的间距要和光环板最远的两颗LED灯距离相等。 将舵机与光环板连接,四个引脚都可以控制舵机。 舵机的红线是代表电源正极,与鳄鱼夹红线相连接,红线鳄鱼夹与光环板3.3V引脚相连接; 舵机的黑线代表电源
问题内容: 在* NIX中实现tail的有效方法是什么?我提出(编写)了两个简单的解决方案,都使用一种圆形缓冲区将线加载到圆形结构中(数组|双向链接的圆形列表- 很有趣)。我已经看到了busybox中较旧的实现的一部分,并且据我了解,他们使用fseek查找EOF,然后“向后”阅读内容。有没有更干净,更快的东西?我在面试时被问到了,问问者看起来并不满意。先感谢您。 问题答案: 我认为没有其他解决方案
问题内容: 说我有一堂课 然后可以按如下方式解析有效的json: 如果字符串包含的数据多于解析对象所需的数据,是否有办法使解析器失败? 例如,我希望以下操作失败(成功) 我使用带有JsonParser.Feature.AUTO_CLOSE_SOURCE = false的InputStream尝试了此操作,并检查该流是否已被完全消耗,但这不起作用: 那是, 仍然成功,可能是因为解析器从流中消耗了超出