java - Java swing 游戏 JPanel 布局辅助
问题描述
我正在制作一个游戏,它有 3 个部分到 JFrame、游戏地图、“玩家视图”:只是一个玩家移动的动画,希望以后包括不同的敌人设计,最后是我拥有的库存部分还没开始呢
就类和方法布局而言,让我的 JPanel 的所有这 3 个部分能够相互通信并根据当前情况动态变化的最佳方式是什么(当他们的瓷砖与另一个瓷砖碰撞时让玩家视图显示敌人或者如果玩家不移动,它不会更新)。
我不介意重写整个游戏,这是我的第一款游戏,希望在结构上得到一些帮助。
而且我不确定 paintComponent 的工作原理或 repaint() 方法。或者如何调用 draw(Graphics g) 来制作图形???
上下文和测试代码:
文本游戏面板.java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Random;
public class TextGamePanel extends JPanel implements ActionListener{
private static final int HEIGHT = 30, WIDTH = 30, MAPVISIBILITY = 8;
private static final int SCREEN_WIDTH = 1080;
private static final int SCREEN_HEIGHT = 1080;
private static final int UNIT_SIZE = 36;
private static final int DELAY = 10;
private String[][] mapBlank = new String[HEIGHT][WIDTH];
private ArrayList<Enemies> enemyList = new ArrayList<Enemies>();
private Random random = new Random();
private Players player;
private int turnCounter = 0;
Timer timer;
boolean active = false , movementMade = false;
TextGamePanel(){
this.setPreferredSize(new Dimension(1920, 1080));
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame(){
newPlayer();
active = true;
timer = new Timer(DELAY, this);
timer.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
draw(g);
}
public void makeMap(){
for(int row = 0; row < mapBlank.length; row++){
for(int col = 0; col < mapBlank[row].length; col++){
mapBlank[row][col] = "";
}
}
for(Enemies enemy : enemyList){
mapBlank[enemy.getXPos()][enemy.getYPos()] = " *";
}
mapBlank[player.getXPos()][player.getYPos()] = " ^";
}
public void draw(Graphics g){
makeMap();
// These loops generate the
g.setColor(new Color(69, 69, 69));
g.fillRect(1080, 0, 840, 360);
g.setFont(new Font("Times Roman", Font.BOLD, 36));
g.setColor(new Color(74, 74, 74));
for(int x = 0; x < 20; x++){
g.drawString(randomString(50), 1020, UNIT_SIZE + x*UNIT_SIZE/2);
}
for(int i = 0; i < 2; i++){
for(int x = 0; x < 13; x++){
g.setColor(new Color(0+x*10, 0+x*10, 0+x*10));
g.setFont(new Font("Times Roman", Font.BOLD, 10+x*2));
g.drawString(randomString(200), 1020, 268 + x * 8);
}
}
//makes the map background grey
g.setColor(new Color(69, 69, 69));
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
//Makes light for context of player view range
g.setColor(new Color(227, 201, 109, 50));
g.fillOval((int)(((player.getXPos()) * UNIT_SIZE) - MAPVISIBILITY/2 * UNIT_SIZE), (int)(((player.getYPos()) * UNIT_SIZE) - MAPVISIBILITY/2 *UNIT_SIZE), (int)((MAPVISIBILITY +1) * UNIT_SIZE), (int)((MAPVISIBILITY +1) * UNIT_SIZE));
g.setColor(new Color(227, 180, 109, 50));
g.fillOval((int)(((player.getXPos()) * UNIT_SIZE) - (MAPVISIBILITY/2 - 1) * UNIT_SIZE), (int)(((player.getYPos()) * UNIT_SIZE) - (MAPVISIBILITY/2 - 1) *UNIT_SIZE), (int)((MAPVISIBILITY -1) * UNIT_SIZE), (int)((MAPVISIBILITY -1) * UNIT_SIZE));
g.setColor(new Color(240, 110, 67, 50));
g.fillOval((int)(((player.getXPos()) * UNIT_SIZE) - (MAPVISIBILITY/2 - 2.5) * UNIT_SIZE), (int)(((player.getYPos()) * UNIT_SIZE) - (MAPVISIBILITY/2 - 2.5) *UNIT_SIZE), (int)((MAPVISIBILITY -4) * UNIT_SIZE), (int)((MAPVISIBILITY -4) * UNIT_SIZE));
g.setColor(new Color(255, 255, 255));
g.setFont(new Font("Times Roman", Font.BOLD, 36));
//draws the grid
for(int i = 0; i < SCREEN_HEIGHT/UNIT_SIZE; i++){
g.drawLine(i*UNIT_SIZE, 0, i*UNIT_SIZE, SCREEN_HEIGHT);
}
for(int i = 0; i < SCREEN_WIDTH/UNIT_SIZE; i++){
g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH, i*UNIT_SIZE);
}
//draws only yourself and enemy around you given MAPVISIBILITY/2 = view range
int xIndex = -1, yIndex = -1;
for(int row = player.getXPos() - MAPVISIBILITY/2; row < player.getXPos() + 1 + MAPVISIBILITY/2; row++){
xIndex ++;
for(int col = player.getYPos() - MAPVISIBILITY/2; col < player.getYPos() + 1 + MAPVISIBILITY/2; col++){
yIndex++;
try{
g.drawString(mapBlank[row][col], row * UNIT_SIZE, (col + 1) * UNIT_SIZE);
}catch(Exception e){
}
}
}
// inventory section (yet to be made)
g.setColor(Color.blue);
g.fillRect(1080, 360, 840, 720);
}
public void movementPhase(){
turnCounter ++;
updateEnemyMovement();
if(turnCounter == 2){
turnCounter = 0;
newEnemy();
}
}
@Override
public void actionPerformed(ActionEvent e){
if(active){
}
}
public class MyKeyAdapter extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e){
switch(e.getKeyCode()){
case KeyEvent.VK_Q: // Move diagonal left up.
if(player.getXPos() > 0 && player.getYPos() > 0){
player.setXPos(player.getXPos() - 1);
player.setYPos(player.getYPos() - 1);
movementMade = true;
}
break;
case KeyEvent.VK_E: // Move diagonal right up.
if(player.getXPos() < HEIGHT - 1 && player.getYPos() > 0){
player.setXPos(player.getXPos() + 1);
player.setYPos(player.getYPos() - 1);
movementMade = true;
}
break;
case KeyEvent.VK_Z: // Move diagonal left down.
if(player.getXPos() > 0 && player.getYPos() < WIDTH - 1){
player.setXPos(player.getXPos() - 1);
player.setYPos(player.getYPos() + 1);
movementMade = true;
}
break;
case KeyEvent.VK_C: // Move diagonal right down.
if(player.getYPos() < WIDTH - 1 && player.getXPos() < HEIGHT - 1){
player.setXPos(player.getXPos() + 1);
player.setYPos(player.getYPos() + 1);
movementMade = true;
}
break;
case KeyEvent.VK_W: // Move up.
if(player.getYPos() > 0){
player.setYPos(player.getYPos() - 1);
movementMade = true;
}
break;
case KeyEvent.VK_X: // Move down.
if(player.getYPos() < WIDTH - 1){
player.setYPos(player.getYPos() + 1);
movementMade = true;
}
break;
case KeyEvent.VK_A: // Move left.
if(player.getXPos() > 0){
player.setXPos(player.getXPos() - 1);
movementMade = true;
}
break;
case KeyEvent.VK_D: // Move right.
if(player.getXPos() < HEIGHT - 1){
player.setXPos(player.getXPos() + 1);
movementMade = true;
}
break;
case KeyEvent.VK_S: // Dont Move.
movementMade = true;
break;
}
if(movementMade){
movementPhase();
movementMade = false;
}
repaint();
}
}
public void updateEnemyMovement(){
Iterator i = (Iterator) enemyList.iterator();
Enemies enemy = new Enemies();
while(i.hasNext()){
enemy = (Enemies) i.next();
enemy.move(player.getXPos(), player.getYPos());
if(enemy.getXPos() == player.getXPos() && enemy.getYPos() == player.getYPos()){
i.remove();
}
}
}
public void newPlayer(){
player = new Players(random.nextInt((int)SCREEN_WIDTH/UNIT_SIZE), random.nextInt((int)SCREEN_HEIGHT/UNIT_SIZE));
}
public void newEnemy(){
enemyList.add(new Enemies(random.nextInt(HEIGHT), random.nextInt(WIDTH)));
}
public String randomString(int n) {
int leftLimit = 49; //'0'
int rightLimit = 122; //'z'
int targetStringLength = n;
Random random = new Random();
StringBuilder buffer = new StringBuilder(targetStringLength);
for (int i = 0; i < targetStringLength; i++) {
int randomLimitedInt = leftLimit + (int)
(random.nextFloat() * (rightLimit - leftLimit + 1));
buffer.append((char) randomLimitedInt);
}
String generatedString = buffer.toString();
return(generatedString);
}
}
`
Players.java :
公共类玩家{
private int x, y;
public Players(){
}
public Players(int x, int y){
this.x = x;
this.y = y;
}
/** Positional Methods */
public int getXPos(){
return x;
}
public int getYPos(){
return y;
}
public void setXPos(int x){
this.x = x;
}
public void setYPos(int y){
this.y = y;
}
}
`
Enemies.java:
public class Enemies {
private int x, y;
public Enemies(){
}
public Enemies(int x, int y){
this.x = x;
this.y = y;
}
/** Positional Methods */
public int getXPos(){
return x;
}
public int getYPos(){
return y;
}
public void setXPos(int x){
this.x = x;
}
public void setYPos(int y){
this.y = y;
}
/** Enemy Movement Method */
public void move(int playerX, int playerY){
if(getXPos() == playerX && getYPos() == playerY){ // x = playerX & y = playery
}/** Diagonal right down */
else if(getXPos() < playerX && getYPos() < playerY){ // x < playerX & y < playerY
setXPos(getXPos() + 1); // x + 1
setYPos(getYPos() + 1); // y + 1
}/** Diagonal right up */
else if(getXPos() > playerX && getYPos() < playerY){ // x > playerX & y < playerY
setXPos(getXPos() - 1); // x - 1
setYPos(getYPos() + 1); // y + 1
}/** Diagonal left down */
else if(getXPos() < playerX && getYPos() > playerY){ // x < playerX & y > playerY
setXPos(getXPos() + 1); // x + 1
setYPos(getYPos() - 1); // y - 1
}/** Diagonal right up */
else if(getXPos() > playerX && getYPos() > playerY){ // x > playerX & y > playerY
setXPos(getXPos() - 1); // x - 1
setYPos(getYPos() - 1); // y - 1
}/** Down */
else if(getXPos() < playerX && getYPos() == playerY){ // x < playerX & y = playerY
setXPos(getXPos() + 1); // x + 1
}/** Up */
else if(getXPos() > playerX && getYPos() == playerY){ // x > playerX & y = playerY
setXPos(getXPos() - 1); // x - 1
}/** Right */
else if(getXPos() == playerX && getYPos() < playerY){ // x = playerX & y < playerY
setYPos(getYPos() + 1); // y + 1
}/** Left */
else if(getXPos() == playerX && getYPos() > playerY){ // x = playerX & y > playerY
setYPos(getYPos() - 1); // y - 1
}
}
}
`
TextGameFrame.java :
导入 javax.swing.*;
公共类 TextGameFrame 扩展 JFrame{
TextGameFrame(){
this.add(new TextGamePanel());
this.setTitle("Text Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
this.setVisible(true);
this.setLocationRelativeTo(null);
}
}
`
TextGameMain.java :
public class TextGameMain{
public static void main(String[] args){
new TextGameFrame();
}
}
`
解决方案
推荐阅读
- javascript - TypeError:“data”参数必须是字符串类型或 Buffer、TypedArray 或 DataView 的实例。收到 IncomingMessage 的一个实例
- windows - 无法获得正确的打印机状态
- java - com.predic8.soamodel.TypeRefAccessException 在为 WSDL 创建 SOAP 请求模板时
- docusignapi - 签名工具不适用于嵌入式签名
- java - Android - Firebase 实时数据库参考指向无效的 url
- python - matplolib 子图的大小调整
- google-cloud-platform - 提交后,Google OAuth 同意屏幕停留在“需要验证”
- pandas - Python - Plotly,Dash 问题 - 基于值的自定义标签和颜色
- xcode - 为什么我不能使用 brew 命令安装 watchman?
- google-api - Google Drive watch API:如何设置请求标头/通知正文