这是一个简单但精美的太空冒险游戏,玩家控制一个太空船在星际间航行,躲避障碍物并收集宝石。游戏使用Springboot(JDK 1.8)+JavaFX+HTML+JavaScript技术栈实现,所有游戏元素(包括飞船、障碍物、宝石等)均通过代码绘制,不使用图片资源。游戏既可以作为桌面应用程序运行,也可以在浏览器中以Web应用程序的形式运行。
space-explorer/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── spaceexplorer/
│ │ │ ├── SpaceExplorerApplication.java
│ │ │ ├── controller/
│ │ │ │ └── GameController.java
│ │ │ ├── service/
│ │ │ │ └── GameService.java
│ │ │ ├── model/
│ │ │ │ ├── GameObject.java
│ │ │ │ ├── Player.java
│ │ │ │ ├── Obstacle.java
│ │ │ │ ├── Gem.java
│ │ │ │ ├── Star.java
│ │ │ │ └── Game.java
│ │ │ └── javafx/
│ │ │ ├── JavaFXApplication.java
│ │ │ ├── GameBoard.java
│ │ │ ├── renderer/
│ │ │ │ ├── GameRenderer.java
│ │ │ │ ├── PlayerRenderer.java
│ │ │ │ ├── ObstacleRenderer.java
│ │ │ │ ├── GemRenderer.java
│ │ │ │ └── StarFieldRenderer.java
│ │ │ └── GameController.java
│ │ └── resources/
│ │ ├── static/
│ │ │ ├── css/
│ │ │ │ └── styles.css
│ │ │ ├── js/
│ │ │ │ ├── game.js
│ │ │ │ └── renderers/
│ │ │ │ ├── playerRenderer.js
│ │ │ │ ├── obstacleRenderer.js
│ │ │ │ ├── gemRenderer.js
│ │ │ │ └── starFieldRenderer.js
│ │ ├── templates/
│ │ │ └── index.html
│ │ └── application.properties
└── pom.xml
package com.spaceexplorer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpaceExplorerApplication {
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
// 启动Spring Boot应用
context = SpringApplication.run(SpaceExplorerApplication.class, args);
// 启动JavaFX应用
com.spaceexplorer.javafx.JavaFXApplication.launch(com.spaceexplorer.javafx.JavaFXApplication.class, args);
}
public static ConfigurableApplicationContext getContext() {
return context;
}
}
package com.spaceexplorer.model;
/**
* 游戏对象的基类,定义了游戏中所有对象的基本属性和行为
*/
public abstract class GameObject {
protected double x;
protected double y;
protected double width;
protected double height;
protected double velocityX;
protected double velocityY;
protected boolean active;
public GameObject(double x, double y, double width, double height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.velocityX = 0;
this.velocityY = 0;
this.active = true;
}
/**
* 更新对象状态
*/
public abstract void update();
/**
* 检查与另一对象的碰撞
*/
public boolean collidesWith(GameObject other) {
return (x < other.x + other.width &&
x + width > other.x &&
y < other.y + other.height &&
y + height > other.y);
}
// Getters and Setters
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getVelocityX() {
return velocityX;
}
public void setVelocityX(double velocityX) {
this.velocityX = velocityX;
}
public double getVelocityY() {
return velocityY;
}
public void setVelocityY(double velocityY) {
this.velocityY = velocityY;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
package com.spaceexplorer.model;
/**
* 玩家类,表示玩家控制的太空船
*/
public class Player extends GameObject {
private static final double DEFAULT_WIDTH = 40;
private static final double DEFAULT_HEIGHT = 40;
private static final double MOVE_SPEED = 5.0;
private int lives;
private int score;
private double thrusterPower;
private boolean thrustersActive;
private double rotationAngle; // 飞船旋转角度(弧度)
public Player(double x, double y) {
super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
this.lives = 3;
this.score = 0;
this.thrusterPower = 0;
this.thrustersActive = false;
this.rotationAngle = 0;
}
@Override
public void update() {
// 更新位置
x += velocityX;
y += velocityY;
// 减速(模拟太空中的低摩擦)
velocityX *= 0.98;
velocityY *= 0.98;
// 更新推进器
if (thrustersActive) {
thrusterPower = Math.min(1.0, thrusterPower + 0.05);
// 根据飞船朝向计算加速度
double accelerationX = Math.sin(rotationAngle) * MOVE_SPEED * thrusterPower;
double accelerationY = -Math.cos(rotationAngle) * MOVE_SPEED * thrusterPower;
velocityX += accelerationX * 0.1;
velocityY += accelerationY * 0.1;
} else {
thrusterPower = Math.max(0, thrusterPower - 0.02);
}
}
/**
* 向左旋转飞船
*/
public void rotateLeft() {
rotationAngle -= 0.1;
}
/**
* 向右旋转飞船
*/
public void rotateRight() {
rotationAngle += 0.1;
}
/**
* 激活推进器
*/
public void activateThrusters() {
thrustersActive = true;
}
/**
* 停用推进器
*/
public void deactivateThrusters() {
thrustersActive = false;
}
/**
* 收集宝石
*/
public void collectGem() {
score += 100;
}
/**
* 失去一条命
*/
public void loseLife() {
lives--;
}
/**
* 检查玩家是否死亡
*/
public boolean isDead() {
return lives <= 0;
}
// Getters and Setters
public int getLives() {
return lives;
}
public void setLives(int lives) {
this.lives = lives;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public double getThrusterPower() {
return thrusterPower;
}
public boolean isThrustersActive() {
return thrustersActive;
}
public double getRotationAngle() {
return rotationAngle;
}
public void setRotationAngle(double rotationAngle) {
this.rotationAngle = rotationAngle;
}
}
package com.spaceexplorer.model;
import java.util.Random;
/**
* 障碍物类,表示游戏中的小行星等障碍物
*/
public class Obstacle extends GameObject {
private static final Random random = new Random();
private double rotationSpeed;
private double rotationAngle;
private ObstacleType type;
// 障碍物类型枚举
public enum ObstacleType {
ASTEROID, // 小行星
SPACE_DEBRIS, // 太空碎片
COMET // 彗星
}
public Obstacle(double x, double y, double width, double height, ObstacleType type) {
super(x, y, width, height);
this.type = type;
// 随机速度和旋转
this.velocityX = random.nextDouble() * 2 - 1; // -1到1的随机速度
this.velocityY = random.nextDouble() * 2 - 1;
this.rotationSpeed = (random.nextDouble() * 0.1) - 0.05; // -0.05到0.05的随机旋转速度
this.rotationAngle = random.nextDouble() * Math.PI * 2; // 0到2π的随机初始角度
}
@Override
public void update() {
// 更新位置
x += velocityX;
y += velocityY;
// 更新旋转
rotationAngle += rotationSpeed;
// 保持旋转角度在0-2π之间
if (rotationAngle > Math.PI * 2) {
rotationAngle -= Math.PI * 2;
} else if (rotationAngle < 0) {
rotationAngle += Math.PI * 2;
}
}
// Getters
public double getRotationAngle() {
return rotationAngle;
}
public ObstacleType getType() {
return type;
}
}
package com.spaceexplorer.model;
/**
* 宝石类,表示玩家可以收集的宝石
*/
public class Gem extends GameObject {
private static final double DEFAULT_WIDTH = 20;
private static final double DEFAULT_HEIGHT = 20;
private double rotationAngle;
private double pulseScale; // 用于脉冲效果
private double pulseDirection; // 1为增大,-1为减小
public Gem(double x, double y) {
super(x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
this.rotationAngle = 0;
this.pulseScale = 1.0;
this.pulseDirection = 1;
}
@Override
public void update() {
// 缓慢旋转
rotationAngle += 0.02;
if (rotationAngle > Math.PI * 2) {
rotationAngle -= Math.PI * 2;
}
// 脉冲效果(大小变化)
pulseScale += 0.01 * pulseDirection;
if (pulseScale > 1.2) {
pulseScale = 1.2;
pulseDirection = -1;
} else if (pulseScale < 0.8) {
pulseScale = 0.8;
pulseDirection = 1;
}
}
// Getters
public double getRotationAngle() {
return rotationAngle;
}
public double getPulseScale() {
return pulseScale;
}
}
package com.spaceexplorer.model;
/**
* 星星类,用于背景星空
*/
public class Star {
private double x;
private double y;
private double size;
private double brightness; // 0.0 - 1.0
private double twinkleSpeed;
private double twinklePhase;
public Star(double x, double y, double size, double brightness, double twinkleSpeed) {
this.x = x;
this.y = y;
this.size = size;
this.brightness = brightness;
this.twinkleSpeed = twinkleSpeed;
this.twinklePhase = Math.random() * Math.PI * 2; // 随机初始相位
}
public void update() {
// 更新闪烁效果
twinklePhase += twinkleSpeed;
if (twinklePhase > Math.PI * 2) {
twinklePhase -= Math.PI * 2;
}
}
public double getCurrentBrightness() {
// 根据正弦波计算当前亮度
return brightness * (0.7 + 0.3 * Math.sin(twinklePhase));
}
// Getters
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getSize() {
return size;
}
}
package com.spaceexplorer.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;
/**
* 游戏类,维护整体游戏状态
*/
public class Game {
private String id;
private Player player;
private List obstacles;
private List gems;
private List stars;
private int boardWidth;
private int boardHeight;
private boolean gameOver;
private int level;
private long lastUpdateTime;
private Random random;
// 游戏配置
private static final int MAX_OBSTACLES = 15;
private static final int MAX_GEMS = 5;
private static final int STARS_COUNT = 100;
public Game() {
this.id = UUID.randomUUID().toString();
this.obstacles = new ArrayList<>();
this.gems = new ArrayList<>();
this.stars = new ArrayList<>();
this.gameOver = false;
this.level = 1;
this.lastUpdateTime = System.currentTimeMillis();
this.random = new Random();
}
public void initialize(int boardWidth, int boardHeight) {
this.boardWidth = boardWidth;
this.boardHeight = boardHeight;
// 创建玩家(居中)
player = new Player(boardWidth / 2, boardHeight / 2);
// 创建背景星星
createStars();
// 初始化一些障碍物和宝石
for (int i = 0; i < 5; i++) {
spawnObstacle();
}
for (int i = 0; i < 3; i++) {
spawnGem();
}
}
/**
* 创建背景星空
*/
private void createStars() {
stars.clear();
for (int i = 0; i < STARS_COUNT; i++) {
double x = random.nextDouble() * boardWidth;
double y = random.nextDouble() * boardHeight;
double size = 0.5 + random.nextDouble() * 2.0; // 0.5到2.5的大小
double brightness = 0.2 + random.nextDouble() * 0.8; // 0.2到1.0的亮度
double twinkleSpeed = 0.01 + random.nextDouble() * 0.05; // 闪烁速度
stars.add(new Star(x, y, size, brightness, twinkleSpeed));
}
}
/**
* 生成一个新的障碍物
*/
private void spawnObstacle() {
if (obstacles.size() >= MAX_OBSTACLES) {
return;
}
// 随机位置(屏幕边缘)
double x, y;
if (random.nextBoolean()) {
// 左右边缘
x = random.nextBoolean() ? 0 : boardWidth;
y = random.nextDouble() * boardHeight;
} else {
// 上下边缘
x = random.nextDouble() * boardWidth;
y = random.nextBoolean() ? 0 : boardHeight;
}
// 随机大小
double size = 20 + random.nextDouble() * 40; // 20-60的随机大小
// 随机类型
Obstacle.ObstacleType type = Obstacle.ObstacleType.values()[random.nextInt(Obstacle.ObstacleType.values().length)];
obstacles.add(new Obstacle(x, y, size, size, type));
}
/**
* 生成一个新的宝石
*/
privat