gpt4 book ai didi

java - MVC结构中图形的问题

转载 作者:行者123 更新时间:2023-12-01 09:18:36 27 4
gpt4 key购买 nike

我正在测试将图形实现到 MVC 结构中,但我有点卡住了。这是我到目前为止所得到的。现在我只想让红球来回弹跳。并使用“start”按钮启动线程,使用“stop”按钮停止 Controller 中运行 GameLoop 的线程。

但我认为我有点混淆了。非常感谢一些反馈!

这是我到目前为止得到的:

游戏模型假设控制弹跳。如果球的位置低于 40 px 或高于 80 px - 将 locationX 乘以 -1 以使球改变方向

游戏 View 我在这里将标签放在 JFrame 上。我还想显示按钮开始和停止来控制线程,但我猜它们被 TheGraphics 类中的 JPanel 隐藏了

游戏 Controller 使用 ActionListener 启动和停止线程。包含 GameLoop

图形绘制球并控制方向

我想我有很多事情都是错误的,但这是我目前能做的最好的事情。非常感谢您的帮助!

谢谢!

主要:

public class MVCgame {

public static void main(String[] args) {
GameModel gm = new GameModel();
GameView gv = new GameView();
GameController gc = new GameController(gm, gv);
}
}

型号:

public class GameModel {
private int multi = 1;


public void setMulti(int locX) {
if(locX < 40 || locX > 80) {
multi = multi * -1;
}
}

public int multi() {
return multi;
}
}

查看:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GameView extends JFrame {

private JPanel jp = new JPanel();
private JButton start = new JButton("Start");
private JButton stop = new JButton("Stop");
TheGraphics gr = new TheGraphics();

public GameView() {
add(jp);
add(gr);

jp.add(start);
jp.add(stop);
setSize(250, 250);
setVisible(true);
}

public void addListener(ActionListener theListener) {
start.addActionListener(theListener);
stop.addActionListener(theListener);
}

public JButton getStart() {

return start;
}

public JButton getStop() {
return stop;
}

// GUESS I SHOULD PUT THIS IN THE VIEW???
public void paintEllipse(Graphics theG) {
Graphics2D g2d = (Graphics2D) theG;
g2d.setColor(new Color(255, 0, 0));
g2d.fillOval(0, 0, 10, 10);
}
}

Controller :

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class GameController implements Runnable {

GameView gv;
GameModel gm;
private Thread thread;
private boolean running = false;

public GameController(GameModel gm, GameView gv) {
this.gv = gv;
this.gm = gm;
gv.addListener(theListener);
start();
}

ActionListener theListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == gv.getStart()) {
start();
System.out.println("PLAY = ");
} else if (e.getSource() == gv.getStop()) {
stop();
System.out.println("STOP = ");
}
}
};

public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}

public synchronized void stop() {
thread.interrupt();
running = false;
}

// GameLoop
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;

while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 10) {
// tick();
delta--;

// repainting the graphics
gv.gr.drawer();
gm.setMulti(gv.gr.drawer());
System.out.println("gv.gr.drawer() = " + gv.gr.drawer() + " gm.multi() " + gm.multi());
// I want to use this value in the model to change the direction
}
if (running) {
}
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
}
}

图形:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class TheGraphics extends JPanel {

private int locX = 40;

public TheGraphics() {

}

public int drawer() {
locX++;

repaint();
return locX;
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(255, 0, 0));
g2d.fillOval(locX, 30, 10, 10);
}
}

最佳答案

GameModell suppose to controll the bouncing. If the location of the ball is under 40 px or above 80 px - multiply the locationX with -1 to make the ball change direction

public void setMulti(int locX) {
if(locX < 40 || locX > 80) {
multi = multi * -1;
}
}

真是个糟糕的主意。您应该始终检查位置方向(符号(速度))。否则,您的对象可能会卡在边界之外,总是改变方向,而不会永远离开原来的位置。

除此之外,在我看来,使用 MVC 概念有点过分了,不应该在这么小的项目或游戏中使用。在游戏中,你或多或少应该将这三者放在一起。当然可以,但是 MVC 概念的优点和缺点在很多方面都不适合游戏的需求(也许 GUI 除外)。

你的主循环可能看起来像这样(你已经这样做了,但为什么在你的代码中注释掉了tick()?):

while (running) {
update(); // Update all game objects
paint(); // Paint them all
}

每个游戏对象都有自己的 update() 和 Paint() 实现。您绝对需要将更新和绘制的逻辑分开,即使它们位于同一个类中。所以这个:

public int drawer() {
locX++;

repaint();
return locX;
}

这是绝对不行的。

编辑:(引用您的更新答案)

您将 location() 方法用于不同的目的。根据 Java 命名约定,您应该根据用途将其重命名为 getLocation()setLocation() 以澄清代码。

(即使这不再是真正的 MVC,我也会让 GameFrame 实现 ActionListener,而不是将其指定为 GameController 的变量。 )

您真正应该改变的一件事是:

private int locX = 0;

public void location(int loc) {
this.locX = (int) loc;
}

基本上,您会在每一帧复制位置值并创建未使用的冗余数据。另一个问题是,这可能只适用于一个变量,但如果稍后向模型中添加的变量超过该位置会怎样?相反,TheGraphics 必须在数据模型的实例上呈现,而不是其值。只要您使用一个 GameModel

private GameModel model; // set value once at initialisation

并在paintComponent中渲染其值可以正常工作,但如果您想添加多个GameModel(更像是GameObjectModel一样处理GameModel),您将需要将其作为 Paint 方法中的参数传递。

public void update() {
repaint();
}

删除它并尝试在没有它的情况下四处走动。大多数时候,从一个地方调用的方法转发到另一个方法是一个坏主意,特别是当它用不同的名称混淆功能时。

            gv.gr.update();
gv.gr.location(gm.location());

您是先重新绘制图像,然后设置位置吗?基本上,您的游戏始终落后一帧。交换该顺序。

            gv.gr.location(gm.location());
gv.gr.repaint();

会好的(我已经说过location())。

关于java - MVC结构中图形的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40331460/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com