Java 俄罗斯方块游戏-快速左右移动独立的计时器
我想用java做一个俄罗斯方块游戏 我用摆动计时器来扔瓷砖。 但问题是,当我试图左右移动我的瓷砖时, 运动速度受计时器延迟值的限制。瓷砖每秒钟都会掉落,因此,我只能在计时器重置和重新绘制时更改它们的位置。我怎样才能独立完成第二个动作,或者其他任何可以帮助我的方法。在这种情况下,非常感谢您的帮助Java 俄罗斯方块游戏-快速左右移动独立的计时器,java,swing,Java,Swing,我想用java做一个俄罗斯方块游戏 我用摆动计时器来扔瓷砖。 但问题是,当我试图左右移动我的瓷砖时, 运动速度受计时器延迟值的限制。瓷砖每秒钟都会掉落,因此,我只能在计时器重置和重新绘制时更改它们的位置。我怎样才能独立完成第二个动作,或者其他任何可以帮助我的方法。在这种情况下,非常感谢您的帮助 package gui; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; impo
package gui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
enum Shapes {
// T, S1, S2, K,L1, L2,
//above members will be left commented until other tiles are prepared
I;
public static Shapes getRandomShapes() {
Random random = new Random();
return values()[random.nextInt(values().length)];
}
}
public class Engine extends JPanel implements KeyListener, ActionListener {
private static final long serialVersionUID = 1L;
private int[] xPos = new int[800];
private int[] yPos = new int[800];
int moves = 0;
Timer timer;
int delay;
Engine() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
delay = 1000;
timer = new Timer(delay, this);
timer.start();
}
private boolean left;
private boolean right;
private void fall() {
yPos[0] += 30;
yPos[1] += 30;
yPos[2] += 30;
yPos[3] += 30;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.drawRect(5, 5, 482, 842);
g.setColor(Color.BLACK);
g.fillRect(7, 7, 478, 838);
if (Shapes.getRandomShapes() == Shapes.I) {
if (moves == 0) {
xPos[0] = 60;
xPos[1] = 90;
xPos[2] = 120;
xPos[3] = 150;
yPos[0] = 6;
yPos[1] = 6;
yPos[2] = 6;
yPos[3] = 6;
moves++;
}
for (int x = 0; x < 4; x++) {
ImageIcon Iimage = new ImageIcon(Engine.class.getClassLoader().getResource("images/I.png"));
Iimage.paintIcon(this, g, xPos[x], yPos[x]);
}
}
g.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
timer.start();
fall();
if (left) {
xPos[0] -= 30;
xPos[1] -= 30;
xPos[2] -= 30;
xPos[3] -= 30;
left = false;
}
if (right) {
xPos[0] += 30;
xPos[1] += 30;
xPos[2] += 30;
xPos[3] += 30;
right = false;
}
repaint();
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = true;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = true;
}
}
}
packagegui;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.util.Random;
导入javax.swing.ImageIcon;
导入javax.swing.JPanel;
导入javax.swing.Timer;
枚举形状{
//T,S1,S2,K,L1,L2,
//上述成员将留下评论,直到其他瓷砖准备好
我
公共静态形状getRandomShapes(){
随机=新随机();
返回值()[random.nextInt(values().length)];
}
}
公共类引擎扩展JPanel实现KeyListener、ActionListener{
私有静态最终长serialVersionUID=1L;
私有int[]xPos=新int[800];
私有整数[]yPos=新整数[800];
int=0;
定时器;
整数延迟;
引擎(){
addKeyListener(此);
设置聚焦(真);
setFocusTraversalKeysEnabled(false);
延迟=1000;
定时器=新定时器(延迟,此);
timer.start();
}
私有布尔左;
私权;
私人空降{
yPos[0]+=30;
yPos[1]+=30;
yPos[2]+=30;
yPos[3]+=30;
}
公共组件(图形g){
超级组件(g);
g、 setColor(Color.WHITE);
g、 drawRect(5,5482842);
g、 设置颜色(颜色为黑色);
g、 fillRect(7,747838);
if(Shapes.getRandomShapes()==Shapes.I){
如果(移动==0){
xPos[0]=60;
xPos[1]=90;
xPos[2]=120;
xPos[3]=150;
yPos[0]=6;
yPos[1]=6;
yPos[2]=6;
yPos[3]=6;
移动++;
}
对于(int x=0;x<4;x++){
ImageIcon Iimage=新的ImageIcon(Engine.class.getClassLoader().getResource(“images/I.png”);
Iimage.paintIcon(这个,g,xPos[x],yPos[x]);
}
}
g、 处置();
}
@凌驾
已执行的公共无效操作(操作事件e){
//TODO自动生成的方法存根
timer.start();
fall();
如果(左){
xPos[0]-=30;
xPos[1]=30;
xPos[2]=30;
xPos[3]=30;
左=假;
}
如果(右){
xPos[0]+=30;
xPos[1]+=30;
xPos[2]+=30;
xPos[3]+=30;
右=假;
}
重新油漆();
}
@凌驾
按下公共无效键(按键事件e){
//TODO自动生成的方法存根
if(e.getKeyCode()==KeyEvent.VK_RIGHT){
右=真;
}
如果(例如getKeyCode()==KeyEvent.VK_左){
左=真;
}
}
}
将移动逻辑(向下)与计时器分离,以便计时器能够以更高的速率运行
我会捕捉“最后一滴”的瞬间
,并计算每个滴答声经过的时间量,当滴答声等于或大于1秒时,将碎片放下
下面的示例演示了使用瞬间
计算所经过时间的持续时间
,然后根据需要执行某些操作的基本思想
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Drop {
public static void main(String[] args) {
new Drop();
}
public Drop() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Instant lastDropTime;
private JLabel label;
public TestPane() {
setLayout(new BorderLayout());
label = new JLabel("Drop in ...");
add(label);
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (lastDropTime == null) {
lastDropTime = Instant.now();
}
// I'm using toMillis so I can display the time
// but you could just use toSeconds
Duration duration = Duration.between(lastDropTime, Instant.now());
long millis = duration.toMillis();
long seconds = duration.toSeconds();
if (seconds >= 1) {
// Drop down here...
lastDropTime = Instant.now();
millis = 1000;
}
label.setText("Drop in " + (1000 - millis));
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
将移动逻辑(向下)与计时器分离,以便计时器能够以更高的速率运行。我会捕捉“最后一滴”的
瞬间
,并计算每个滴答所经过的时间量,当它等于或大于1秒时,放下这一块谢谢你的回答!我对java和编程相当陌生。因此,我不知道如何将您的解决方案应用到我的代码中。我正在互联网上寻找“即时”的方法来理解现在。我愿意在这一点上提供进一步的帮助:D再次感谢你!首先,您不应该使用KeyListener。您应该使用键绑定
来处理左/右键。在任何情况下,基本的解决方案都是重置侦听器代码中“片段”的位置,然后立即调用repaint()在其新位置绘制“片段”。因此,它将独立于计时器重新绘制。您可以查看:例如,这种方法。哇,它非常有效。你们俩太棒了!!谢谢你的帮助。