用JAVA编写俄罗斯方块游戏android

时间: 2024-04-28 16:19:53 浏览: 11
好的,编写俄罗斯方块游戏的第一步是了解游戏的规则和逻辑。俄罗斯方块游戏的规则是:玩家控制下落的方块,使其在底部堆积成一行或多行,当堆积的方块触及顶部时,游戏结束。游戏中的方块由四个小方块组成,每个小方块可以是七种不同的颜色之一。 接下来,我们可以使用Java语言编写俄罗斯方块游戏的核心逻辑。我们需要创建一个方块类来表示游戏中的方块,这个类应该包含方块的位置、颜色、形状等属性。然后,我们需要创建一个游戏类来管理游戏的状态、计分等信息,这个类应该包含游戏界面、方块的下落速度、当前下落的方块等属性。 接下来,我们可以使用Android Studio创建一个新的Android应用程序,并在应用程序中添加俄罗斯方块游戏的UI组件,例如游戏界面、得分板等。然后,我们可以将我们编写的Java代码与UI组件集成起来,实现俄罗斯方块游戏的功能。 最后,我们需要对游戏进行测试,并进行必要的调试和优化。我们可以使用Android模拟器或实际设备进行测试,确保游戏在不同的设备上都能正常运行。 以上是一个简单的流程,希望能对您有所帮助。
相关问题

Java编写俄罗斯方块游戏代码

下面是一个简单的Java编写的俄罗斯方块游戏代码,可以供参考: ```java import java.awt.*; import java.awt.event.*; import java.util.Random; import javax.swing.*; public class Tetris extends JFrame { private static final long serialVersionUID = 1L; private JLabel statusBar; private final int BOARD_WIDTH = 10; private final int BOARD_HEIGHT = 22; private Timer timer; private boolean isFallingFinished = false; private boolean isStarted = false; private boolean isPaused = false; private int numLinesRemoved = 0; private int curX = 0; private int curY = 0; private JLabel[][] board = new JLabel[BOARD_HEIGHT][BOARD_WIDTH]; private Shape curPiece; private Shape.Tetrominoes[] boardArr = new Shape.Tetrominoes[BOARD_HEIGHT * BOARD_WIDTH]; public Tetris() { initUI(); } private void initUI() { statusBar = new JLabel(" 0"); add(statusBar, BorderLayout.SOUTH); Board board = new Board(this); add(board); board.start(); setSize(200, 400); setTitle("Tetris"); setDefaultCloseOperation(EXIT_ON_CLOSE); } public JLabel getStatusBar() { return statusBar; } public boolean isStarted() { return isStarted; } public boolean isPaused() { return isPaused; } public boolean isFallingFinished() { return isFallingFinished; } public int getNumLinesRemoved() { return numLinesRemoved; } public int getBoardWidth() { return BOARD_WIDTH; } public int getBoardHeight() { return BOARD_HEIGHT; } public Shape getCurPiece() { return curPiece; } public int getCurX() { return curX; } public int getCurY() { return curY; } public Shape.Tetrominoes shapeAt(int x, int y) { return boardArr[(y * BOARD_WIDTH) + x]; } private void setShapeAt(int x, int y, Shape.Tetrominoes shape) { boardArr[(y * BOARD_WIDTH) + x] = shape; } public void start() { if (isPaused) return; isStarted = true; isFallingFinished = false; numLinesRemoved = 0; clearBoard(); newPiece(); timer.start(); } public void pause() { if (!isStarted) return; isPaused = !isPaused; if (isPaused) { timer.stop(); statusBar.setText(" paused"); } else { timer.start(); statusBar.setText(String.valueOf(numLinesRemoved)); } repaint(); } private void doDrawing(Graphics g) { Dimension size = getSize(); int boardTop = (int) size.getHeight() - BOARD_HEIGHT * squareHeight(); for (int i = 0; i < BOARD_HEIGHT; ++i) { for (int j = 0; j < BOARD_WIDTH; ++j) { Shape.Tetrominoes shape = shapeAt(j, BOARD_HEIGHT - i - 1); if (shape != Shape.Tetrominoes.NoShape) { drawSquare(g, j * squareWidth(), boardTop + i * squareHeight(), shape); } } } if (curPiece.getShape() != Shape.Tetrominoes.NoShape) { for (int i = 0; i < 4; ++i) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); drawSquare(g, x * squareWidth(), boardTop + (BOARD_HEIGHT - y - 1) * squareHeight(), curPiece.getShape()); } } } @Override public void paint(Graphics g) { super.paint(g); doDrawing(g); } private void dropDown() { int newY = curY; while (newY > 0) { if (!tryMove(curPiece, curX, newY - 1)) break; --newY; } pieceDropped(); } private void oneLineDown() { if (!tryMove(curPiece, curX, curY - 1)) pieceDropped(); } private int squareWidth() { return (int) getSize().getWidth() / BOARD_WIDTH; } private int squareHeight() { return (int) getSize().getHeight() / BOARD_HEIGHT; } private void clearBoard() { for (int i = 0; i < BOARD_HEIGHT * BOARD_WIDTH; ++i) { boardArr[i] = Shape.Tetrominoes.NoShape; } } private void pieceDropped() { for (int i = 0; i < 4; ++i) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); setShapeAt(x, y, curPiece.getShape()); } removeFullLines(); if (!isFallingFinished) newPiece(); } private void newPiece() { curPiece = new Shape(); curX = BOARD_WIDTH / 2 + 1; curY = BOARD_HEIGHT - 1 + curPiece.minY(); if (!tryMove(curPiece, curX, curY)) { curPiece.setShape(Shape.Tetrominoes.NoShape); timer.stop(); isStarted = false; statusBar.setText("game over"); } } private boolean tryMove(Shape newPiece, int newX, int newY) { for (int i = 0; i < 4; ++i) { int x = newX + newPiece.x(i); int y = newY - newPiece.y(i); if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) return false; if (shapeAt(x, y) != Shape.Tetrominoes.NoShape) return false; } curPiece = newPiece; curX = newX; curY = newY; repaint(); return true; } private void removeFullLines() { int numFullLines = 0; for (int i = BOARD_HEIGHT - 1; i >= 0; --i) { boolean lineIsFull = true; for (int j = 0; j < BOARD_WIDTH; ++j) { if (shapeAt(j, i) == Shape.Tetrominoes.NoShape) { lineIsFull = false; break; } } if (lineIsFull) { ++numFullLines; for (int k = i; k < BOARD_HEIGHT - 1; ++k) { for (int j = 0; j < BOARD_WIDTH; ++j) { setShapeAt(j, k, shapeAt(j, k + 1)); } } for (int j = 0; j < BOARD_WIDTH; ++j) { setShapeAt(j, BOARD_HEIGHT - 1, Shape.Tetrominoes.NoShape); } } } if (numFullLines > 0) { numLinesRemoved += numFullLines; statusBar.setText(String.valueOf(numLinesRemoved)); isFallingFinished = true; curPiece.setShape(Shape.Tetrominoes.NoShape); } } private void drawSquare(Graphics g, int x, int y, Shape.Tetrominoes shape) { Color colors[] = { new Color(0, 0, 0), new Color(204, 102, 102), new Color(102, 204, 102), new Color(102, 102, 204), new Color(204, 204, 102), new Color(204, 102, 204), new Color(102, 204, 204), new Color(218, 170, 0) }; Color color = colors[shape.ordinal()]; g.setColor(color); g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2); g.setColor(color.brighter()); g.drawLine(x, y + squareHeight() - 1, x, y); g.drawLine(x, y, x + squareWidth() - 1, y); g.setColor(color.darker()); g.drawLine(x + 1, y + squareHeight() - 1, x + squareWidth() - 1, y + squareHeight() - 1); g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, x + squareWidth() - 1, y + 1); } class Board extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; private Tetris parent; Board(Tetris parent) { this.parent = parent; setPreferredSize(new Dimension(200, 400)); setBackground(Color.BLACK); setFocusable(true); addKeyListener(new TAdapter()); } void start() { timer = new Timer(400, this); timer.start(); } @Override public void actionPerformed(ActionEvent e) { if (parent.isFallingFinished()) { parent.isFallingFinished = false; parent.newPiece(); } else { parent.oneLineDown(); } } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } private void doDrawing(Graphics g) { Dimension size = getSize(); int boardTop = (int) size.getHeight() - BOARD_HEIGHT * squareHeight(); for (int i = 0; i < BOARD_HEIGHT; ++i) { for (int j = 0; j < BOARD_WIDTH; ++j) { Shape.Tetrominoes shape = parent.shapeAt(j, BOARD_HEIGHT - i - 1); if (shape != Shape.Tetrominoes.NoShape) { drawSquare(g, j * squareWidth(), boardTop + i * squareHeight(), shape); } } } if (parent.getCurPiece().getShape() != Shape.Tetrominoes.NoShape) { for (int i = 0; i < 4; ++i) { int x = parent.getCurX() + parent.getCurPiece().x(i); int y = parent.getCurY() - parent.getCurPiece().y(i); drawSquare(g, x * squareWidth(), boardTop + (BOARD_HEIGHT - y - 1) * squareHeight(), parent.getCurPiece().getShape()); } } } private void dropDown() { parent.dropDown(); } private void moveLeft() { parent.tryMove(parent.getCurPiece(), parent.getCurX() - 1, parent.getCurY()); } private void moveRight() { parent.tryMove(parent.getCurPiece(), parent.getCurX() + 1, parent.getCurY()); } private void rotateLeft() { parent.tryMove(parent.getCurPiece().rotateLeft(), parent.getCurX(), parent.getCurY()); } private void rotateRight() { parent.tryMove(parent.getCurPiece().rotateRight(), parent.getCurX(), parent.getCurY()); } private void pause() { parent.pause(); } private class TAdapter extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { if (!parent.isStarted() || parent.getCurPiece().getShape() == Shape.Tetrominoes.NoShape) { return; } int keycode = e.getKeyCode(); if (keycode == 'p' || keycode == 'P') { pause(); return; } if (parent.isPaused()) return; switch (keycode) { case KeyEvent.VK_LEFT: moveLeft(); break; case KeyEvent.VK_RIGHT: moveRight(); break; case KeyEvent.VK_DOWN: dropDown(); break; case KeyEvent.VK_UP: rotateLeft(); break; case KeyEvent.VK_SHIFT: rotateRight(); break; } } } } public static void main(String[] args) { EventQueue.invokeLater(() -> { Tetris tetris = new Tetris(); tetris.setVisible(true); }); } } class Shape { enum Tetrominoes { NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape } private Tetrominoes pieceShape; private int coords[][]; private int[][][] coordsTable; public Shape() { coords = new int[4][2]; setShape(Tetrominoes.NoShape); } void setShape(Tetrominoes shape) { coordsTable = new int[][][] { { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // NoShape { { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } }, // ZShape { { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } }, // SShape { { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } }, // LineShape { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } }, // TShape { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, // SquareShape { { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }, // LShape { { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } } // MirroredLShape }; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 2; ++j) { coords[i][j] = coordsTable[shape.ordinal()][i][j]; } } pieceShape = shape; } private void setX(int index, int x) { coords[index][0] = x; } private void setY(int index, int y) { coords[index][1] = y; } int x(int index) { return coords[index][0]; } int y(int index) { return coords[index][1]; } Tetrominoes getShape() { return pieceShape; } void setRandomShape() { Random r = new Random(); int x = Math.abs(r.nextInt()) % 7 + 1; Tetrominoes[] values = Tetrominoes.values(); setShape(values[x]); } int minX() { int m = coords[0][0]; for (int i = 0; i < 4; i++) { m = Math.min(m, coords[i][0]); } return m; } int minY() { int m = coords[0][1]; for (int i = 0; i < 4; i++) { m = Math.min(m, coords[i][1]); } return m; } Shape rotateLeft() { if (pieceShape == Tetrominoes.SquareShape) return this; Shape result = new Shape(); result.pieceShape = pieceShape; for (int i = 0; i < 4; ++i) { result.setX(i, y(i)); result.setY(i, -x(i)); } return result; } Shape rotateRight() { if (pieceShape == Tetrominoes.SquareShape) return this; Shape result = new Shape(); result.pieceShape = pieceShape; for (int i = 0; i < 4; ++i) { result.setX(i, -y(i)); result.setY(i, x(i)); } return result; } } ```

Java编写俄罗斯方块游戏源代码

以下是一个简单的 Java 代码示例,用于实现俄罗斯方块游戏: ```java import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; public class Tetris extends JPanel implements ActionListener, KeyListener { private static final long serialVersionUID = -8715353373678321308L; private final Point[][][] Tetraminos = { // I-Piece { { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(3, 1) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(1, 3) }, { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(3, 1) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(1, 3) } }, // J-Piece { { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(2, 0) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(2, 2) }, { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(0, 2) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(0, 0) } }, // L-Piece { { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(2, 2) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(0, 2) }, { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(0, 0) }, { new Point(1, 0), new Point(1, 1), new Point(1, 2), new Point(2, 0) } }, // O-Piece { { new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, 1) }, { new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, 1) }, { new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, 1) }, { new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, 1) } }, // S-Piece { { new Point(1, 0), new Point(2, 0), new Point(0, 1), new Point(1, 1) }, { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 2) }, { new Point(1, 0), new Point(2, 0), new Point(0, 1), new Point(1, 1) }, { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 2) } }, // T-Piece { { new Point(1, 0), new Point(0, 1), new Point(1, 1), new Point(2, 1) }, { new Point(1, 0), new Point(0, 1), new Point(1, 1), new Point(1, 2) }, { new Point(0, 1), new Point(1, 1), new Point(2, 1), new Point(1, 2) }, { new Point(1, 0), new Point(1, 1), new Point(2, 1), new Point(1, 2) } }, // Z-Piece { { new Point(0, 0), new Point(1, 0), new Point(1, 1), new Point(2, 1) }, { new Point(1, 1), new Point(0, 2), new Point(1, 2), new Point(0, 3) }, { new Point(0, 0), new Point(1, 0), new Point(1, 1), new Point(2, 1) }, { new Point(1, 1), new Point(0, 2), new Point(1, 2), new Point(0, 3) } } }; private final Color[] tetraminoColors = { Color.cyan, Color.blue, Color.orange, Color.yellow, Color.green, Color.pink, Color.red }; private Point pieceOrigin; private int currentPiece; private int rotation; private ArrayList<Integer> nextPieces = new ArrayList<Integer>(); private long score; private Color[][] well; // Creates a border around the well and initializes the dropping piece private void init() { well = new Color[12][24]; for (int i = 0; i < 12; i++) { for (int j = 0; j < 23; j++) { if (i == 0 || i == 11 || j == 22) { well[i][j] = Color.GRAY; } else { well[i][j] = Color.BLACK; } } } newPiece(); } // Put a new, random piece into the dropping position public void newPiece() { pieceOrigin = new Point(5, 2); rotation = 0; if (nextPieces.isEmpty()) { Collections.addAll(nextPieces, 0, 1, 2, 3, 4, 5, 6); Collections.shuffle(nextPieces, new Random()); } currentPiece = nextPieces.get(0); nextPieces.remove(0); } // Collision test for the dropping piece private boolean collidesAt(int x, int y, int rotation) { for (Point p : Tetraminos[currentPiece][rotation]) { if (well[p.x + x][p.y + y] != Color.BLACK) { return true; } } return false; } // Rotate the piece clockwise or counterclockwise public void rotate(int i) { int newRotation = (rotation + i) % 4; if (newRotation < 0) { newRotation = 3; } if (!collidesAt(pieceOrigin.x, pieceOrigin.y, newRotation)) { rotation = newRotation; } repaint(); } // Move the piece left or right public void move(int i) { if (!collidesAt(pieceOrigin.x + i, pieceOrigin.y, rotation)) { pieceOrigin.x += i; } repaint(); } // Drops the piece one line or fixes it to the well if it can't drop public void dropDown() { if (!collidesAt(pieceOrigin.x, pieceOrigin.y + 1, rotation)) { pieceOrigin.y += 1; } else { fixToWell(); } repaint(); } // Make the dropping piece part of the well, so it is available for // linescanning. public void fixToWell() { for (Point p : Tetraminos[currentPiece][rotation]) { well[pieceOrigin.x + p.x][pieceOrigin.y + p.y] = tetraminoColors[currentPiece]; } clearRows(); newPiece(); } public void deleteRow(int row) { for (int j = row-1; j > 0; j--) { for (int i = 1; i < 11; i++) { well[i][j+1] = well[i][j]; } } } // Clear completed rows from the field and award score according to // the number of simultaneously cleared rows. public void clearRows() { boolean gap; int numClears = 0; for (int j = 21; j > 0; j--) { gap = false; for (int i = 1; i < 11; i++) { if (well[i][j] == Color.BLACK) { gap = true; break; } } if (!gap) { deleteRow(j); j += 1; numClears += 1; } } switch (numClears) { case 1: score += 100; break; case 2: score += 300; break; case 3: score += 500; break; case 4: score += 800; break; } } // Draw the falling piece private void drawPiece(Graphics g) { g.setColor(tetraminoColors[currentPiece]); for (Point p : Tetraminos[currentPiece][rotation]) { g.fillRect((p.x + pieceOrigin.x) * 26, (p.y + pieceOrigin.y) * 26, 25, 25); } } @Override public void paintComponent(Graphics g) { // Paint the well g.fillRect(0, 0, 26*12, 26*23); for (int i = 0; i < 12; i++) { for (int j = 0; j < 23; j++) { g.setColor(well[i][j]); g.fillRect(26*i, 26*j, 25, 25); } } // Display the score g.setColor(Color.WHITE); g.drawString("" + score, 19*12, 25); // Draw the currently falling piece drawPiece(g); } public static void main(String[] args) { JFrame f = new JFrame("Tetris"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(12*26+10, 26*23+25); f.setVisible(true); final Tetris game = new Tetris(); game.init(); f.add(game); // Keyboard controls f.addKeyListener(new KeyListener() { public void keyTyped(KeyEvent e) { switch (e.getKeyChar()) { case 'a': game.move(-1); break; case 'd': game.move(+1); break; case 's': game.dropDown(); game.score += 1; break; case 'w': game.rotate(+1); break; case 'q': game.rotate(-1); break; } } public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: game.move(-1); break; case KeyEvent.VK_RIGHT: game.move(+1); break; case KeyEvent.VK_DOWN: game.dropDown(); game.score += 1; break; case KeyEvent.VK_UP: game.rotate(+1); break; case KeyEvent.VK_CONTROL: game.rotate(-1); break; } } public void keyReleased(KeyEvent e) { } }); // Make the falling piece drop every second new Timer(1000, game).start(); } @Override public void actionPerformed(ActionEvent e) { dropDown(); } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } } ``` 这只是一个基本的示例,如果你想要实现更多的功能或添加更多的特性,你可以根据自己的需求进行修改和扩展。

相关推荐

最新推荐

recommend-type

Python小游戏之300行代码实现俄罗斯方块

主要给大家介绍了关于Python小游戏之300行代码实现俄罗斯方块的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧
recommend-type

python实现俄罗斯方块小游戏

主要为大家详细介绍了python实现俄罗斯方块小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

毕业论文俄罗斯方块游戏java

毕业论文俄罗斯方块游戏java毕业论文俄罗斯方块游戏java毕业论文俄罗斯方块游戏java
recommend-type

华中科技大学电信专业 课程资料 作业 代码 实验报告-数据结构-内含源码和说明书.zip

华中科技大学电信专业 课程资料 作业 代码 实验报告-数据结构-内含源码和说明书.zip
recommend-type

java 游戏飞翔的小鸟

java 制作游戏 飞翔的小鸟
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

用 Python 画一个可以动的爱心

好的,我可以帮助您使用Python来绘制一个动态的爱心。您可以使用turtle库来实现。以下是实现代码: ```python import turtle import math # 设置画布和画笔 canvas = turtle.Screen() canvas.bgcolor("black") pencil = turtle.Turtle() pencil.speed(0) pencil.color("red", "pink") pencil.pensize(3) # 定义爱心函数 def draw_love(heart_size, x_offset=0, y_offset=0):
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。