Java课程设计(双人对战游戏)持续更新......

少废话,当然借助了ai,就这么个实力,后续会逐渐完善......

考虑添加以下功能:

选将,选图,技能,天赋,道具,防反,反重力,物理反弹,击落,计分,粒子效果,打击感加强,陷阱,逃杀......

package game;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;public class GameFrame extends JFrame {public GameFrame() {setTitle("平台射击对战");setSize(800, 600);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);add(new GamePanel());setVisible(true);}public static void main(String[] args) {SwingUtilities.invokeLater(() -> new GameFrame());}
}class GamePanel extends JPanel implements KeyListener, ActionListener {private Player p1, p2;private Timer timer;private boolean[] keys = new boolean[256];private boolean gameOver = false;private boolean gameStarted = false;private JButton startButton, restartButton, exitButton;private List<Platform> platforms = new ArrayList<>();private List<Bullet> bullets = new ArrayList<>();public GamePanel() {setLayout(null);setFocusable(true);addKeyListener(this);// 对称平台布局platforms.add(new Platform(150, 350, 200, 20));  // 左平台platforms.add(new Platform(300, 250, 200, 20));  // 中央平台platforms.add(new Platform(450, 350, 200, 20));  // 右平台startButton = createButton("开始游戏", 300, 250);restartButton = createButton("重新开始", 300, 300);exitButton = createButton("退出游戏", 300, 350);restartButton.setVisible(false);exitButton.setVisible(false);add(startButton);add(restartButton);add(exitButton);startButton.addActionListener(e -> startGame());restartButton.addActionListener(e -> restartGame());exitButton.addActionListener(e -> System.exit(0));}private JButton createButton(String text, int x, int y) {JButton button = new JButton(text);button.setBounds(x, y, 200, 40);button.setFocusable(false);button.setFont(new Font("微软雅黑", Font.BOLD, 18));button.setBackground(new Color(200, 200, 200));return button;}private void startGame() {gameStarted = true;gameOver = false;bullets.clear();startButton.setVisible(false);restartButton.setVisible(false);exitButton.setVisible(false);p1 = new Player(100, 400, Color.BLUE, KeyEvent.VK_A, KeyEvent.VK_D, KeyEvent.VK_W, KeyEvent.VK_F);p2 = new Player(600, 400, Color.RED, KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP, KeyEvent.VK_M);if (timer != null && timer.isRunning()) {timer.stop();}timer = new Timer(16, this);timer.start();requestFocusInWindow();}private void restartGame() {gameOver = false;gameStarted = false;startGame();}@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);if (!gameStarted) {g.setColor(new Color(30, 30, 30));g.fillRect(0, 0, getWidth(), getHeight());g.setColor(Color.WHITE);g.setFont(new Font("微软雅黑", Font.BOLD, 48));g.drawString("平台射击对战", 250, 150);return;}Graphics2D g2d = (Graphics2D) g;g2d.setPaint(new GradientPaint(0, 0, new Color(30, 30, 50), 0, 600, new Color(10, 10, 20)));g2d.fillRect(0, 0, getWidth(), getHeight());g.setColor(new Color(80, 50, 30));g.fillRect(0, 450, getWidth(), 150);g.setColor(new Color(110, 70, 40));for(int i=0; i<getWidth(); i+=30){g.fillRect(i, 450, 15, 10);g.fillRect(i+15, 460, 15, 10);}for (Platform platform : platforms) {platform.draw(g);}p1.draw(g);p2.draw(g);for (Bullet bullet : bullets) {bullet.draw(g);}drawHealthBar(g, p1, 20, 20);drawHealthBar(g, p2, getWidth() - 220, 20);if (gameOver) {g.setColor(new Color(255, 255, 255, 200));g.fillRect(0, 0, getWidth(), getHeight());g.setColor(Color.BLACK);g.setFont(new Font("微软雅黑", Font.BOLD, 48));String winner = p1.getHealth() <= 0 ? "红方胜利!" : "蓝方胜利!";g.drawString(winner, getWidth()/2 - 120, getHeight()/2);restartButton.setVisible(true);exitButton.setVisible(true);}}private void drawHealthBar(Graphics g, Player p, int x, int y) {g.setColor(Color.BLACK);g.fillRect(x, y, 200, 25);g.setColor(p.getColor());g.fillRect(x + 2, y + 2, (int)(196 * (p.getHealth() / 100.0)), 21);}@Overridepublic void actionPerformed(ActionEvent e) {if (!gameOver && gameStarted) {handleInput();updatePlayers();updateBullets();checkCollisions();checkGameOver();}repaint();}private void handleInput() {p1.setMovingLeft(keys[p1.getLeftKey()]);p1.setMovingRight(keys[p1.getRightKey()]);if (keys[p1.getJumpKey()] && p1.isOnGround()) {p1.jump();}if (keys[p1.getAttackKey()] && p1.canAttack()) {bullets.add(p1.shoot());}p2.setMovingLeft(keys[p2.getLeftKey()]);p2.setMovingRight(keys[p2.getRightKey()]);if (keys[p2.getJumpKey()] && p2.isOnGround()) {p2.jump();}if (keys[p2.getAttackKey()] && p2.canAttack()) {bullets.add(p2.shoot());}}private void updatePlayers() {p1.update(getWidth(), platforms);p2.update(getWidth(), platforms);}private void updateBullets() {List<Bullet> toRemove = new ArrayList<>();for (Bullet bullet : bullets) {bullet.update();if (bullet.x < -10 || bullet.x > getWidth() + 10) {toRemove.add(bullet);}}bullets.removeAll(toRemove);}private void checkCollisions() {List<Bullet> toRemove = new ArrayList<>();for (Bullet bullet : bullets) {for (Platform platform : platforms) {if (bullet.hitsPlatform(platform)) {toRemove.add(bullet);break;}}Player target = bullet.shooter == p1 ? p2 : p1;if (bullet.hitsPlayer(target)) {target.takeDamage(10);toRemove.add(bullet);}}bullets.removeAll(toRemove);}private void checkGameOver() {if (p1.getHealth() <= 0 || p2.getHealth() <= 0) {gameOver = true;timer.stop();}}@Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() < keys.length) {keys[e.getKeyCode()] = true;}}@Overridepublic void keyReleased(KeyEvent e) {if (e.getKeyCode() < keys.length) {keys[e.getKeyCode()] = false;}}@Overridepublic void keyTyped(KeyEvent e) {}
}class Player {private static final int GRAVITY = 1;private static final int JUMP_FORCE = -15;private static final int ATTACK_COOLDOWN = 30;private static final int SPEED = 5;private static final int BULLET_SPEED = 10;private int x, y;private int width = 40, height = 80;private int dx, dy;private int health = 100;private Color color;private boolean onGround = false;private int attackTimer = 0;private boolean movingLeft = false;private boolean movingRight = false;private boolean facingRight = true;private int leftKey, rightKey, jumpKey, attackKey;public Player(int x, int y, Color color, int leftKey, int rightKey, int jumpKey, int attackKey) {this.x = x;this.y = y;this.color = color;this.leftKey = leftKey;this.rightKey = rightKey;this.jumpKey = jumpKey;this.attackKey = attackKey;}public void update(int screenWidth, List<Platform> platforms) {// 处理水平移动dx = 0;if (movingLeft) {dx -= SPEED;facingRight = false;}if (movingRight) {dx += SPEED;facingRight = true;}// 保存移动前的坐标int xPrev = x;x += dx;x = Math.max(0, Math.min(screenWidth - width, x));// 水平碰撞检测Rectangle playerRect = getCollisionBounds();for (Platform platform : platforms) {Rectangle platformRect = platform.getBounds();if (playerRect.intersects(platformRect)) {if (dx > 0) { // 向右移动碰撞x = platformRect.x - width;} else if (dx < 0) { // 向左移动碰撞x = platformRect.x + platformRect.width;}break;}}// 处理垂直移动dy += GRAVITY;int yPrev = y;y += dy;// 垂直碰撞检测boolean isFalling = dy > 0;onGround = false;if (isFalling) {// 下落碰撞检测int playerBottomAfter = y + height;int playerBottomBefore = yPrev + height;Platform landingPlatform = null;int highestPlatformY = Integer.MIN_VALUE;for (Platform platform : platforms) {Rectangle platformRect = platform.getBounds();int platformTop = platformRect.y;int platformBottom = platformTop + platformRect.height;boolean xOverlap = (x < platformRect.x + platformRect.width) &&(x + width > platformRect.x);if (xOverlap &&playerBottomBefore <= platformTop &&playerBottomAfter >= platformTop) {if (platformTop > highestPlatformY) {highestPlatformY = platformTop;landingPlatform = platform;}}}if (landingPlatform != null) {y = landingPlatform.getY() - height;dy = 0;onGround = true;} else {// 检查地面碰撞if (playerBottomAfter >= 450) {y = 450 - height;dy = 0;onGround = true;}}} else if (dy < 0) {// 上升碰撞检测(头部碰撞)int playerTopAfter = y;int playerTopBefore = yPrev;Platform headPlatform = null;int lowestPlatformBottom = Integer.MAX_VALUE;for (Platform platform : platforms) {Rectangle platformRect = platform.getBounds();int platformBottom = platformRect.y + platformRect.height;boolean xOverlap = (x < platformRect.x + platformRect.width) &&(x + width > platformRect.x);if (xOverlap &&playerTopBefore >= platformBottom &&playerTopAfter <= platformBottom) {if (platformBottom < lowestPlatformBottom) {lowestPlatformBottom = platformBottom;headPlatform = platform;}}}if (headPlatform != null) {y = headPlatform.getY() + headPlatform.getHeight();dy = 0;}}// 更新攻击计时器if (attackTimer > 0) {attackTimer--;}}public Bullet shoot() {attackTimer = ATTACK_COOLDOWN;int bulletX = facingRight ? x + width : x - 10;int bulletY = y + height/2 - Bullet.SIZE/2;return new Bullet(bulletX, bulletY, facingRight ? BULLET_SPEED : -BULLET_SPEED, this);}public void jump() {if (onGround) {dy = JUMP_FORCE;onGround = false;}}public void takeDamage(int damage) {health = Math.max(0, health - damage);}public void draw(Graphics g) {g.setColor(color);g.fillRect(x, y, width, height);}public Rectangle getCollisionBounds() {return new Rectangle(x + 5, y + 10, width - 10, height - 20);}public int getX() { return x; }public int getY() { return y; }public int getHealth() { return health; }public Color getColor() { return color; }public boolean isOnGround() { return onGround; }public void setMovingLeft(boolean moving) { movingLeft = moving; }public void setMovingRight(boolean moving) { movingRight = moving; }public boolean canAttack() { return attackTimer <= 0; }public int getLeftKey() { return leftKey; }public int getRightKey() { return rightKey; }public int getJumpKey() { return jumpKey; }public int getAttackKey() { return attackKey; }
}class Bullet {int x, y;int speed;Player shooter;static final int SIZE = 10;public Bullet(int x, int y, int speed, Player shooter) {this.x = x;this.y = y;this.speed = speed;this.shooter = shooter;}public void update() {x += speed;}public void draw(Graphics g) {g.setColor(Color.YELLOW);g.fillOval(x, y, SIZE, SIZE);}public boolean hitsPlayer(Player player) {Rectangle bulletRect = new Rectangle(x, y, SIZE, SIZE);return bulletRect.intersects(player.getCollisionBounds());}public boolean hitsPlatform(Platform platform) {Rectangle bulletRect = new Rectangle(x, y, SIZE, SIZE);return bulletRect.intersects(platform.getBounds());}
}class Platform {private int x, y, width, height;public Platform(int x, int y, int width, int height) {this.x = x;this.y = y;this.width = width;this.height = height;}public void draw(Graphics g) {g.setColor(new Color(100, 100, 100));g.fillRect(x, y, width, height);g.setColor(new Color(120, 120, 120));g.fillRect(x, y, width, 3);g.fillRect(x, y + height - 3, width, 3);}public Rectangle getBounds() {return new Rectangle(x, y, width, height);}public int getY() { return y; }public int getHeight() { return height; }
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73778.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ai工作流工具有那些如Dify、coze扣子等以及他们是否开源

Dify &#xff08;https://difycloud.com/&#xff09; 核心定位&#xff1a;专业级 LLM 应用开发平台&#xff0c;支持复杂 AI 工作流构建与企业级管理。典型场景&#xff1a;企业智能客服、数据分析系统、复杂自动化流程构建等。适合需要深度定制、企业级管理和复杂 AI 逻辑…

Debezium系列之:使用Debezium和Apache Iceberg构建数据湖

Debezium系列之:使用Debezium和Apache Iceberg构建数据湖 Debezium Server Iceberg“Debezium Server Iceberg” 消费者设置数据复制Upsert 模式保留已删除的记录使用Upsert模式追加模式优化批处理大小在数据分析的世界中,数据湖是存储和管理大量数据以满足数据分析、报告或机…

docker run -p 5000:5000 my-flask-app

docker run -p 5000:5000 my-flask-app代码的意思是&#xff1a; 运行 my-flask-app 容器&#xff0c;并把 Flask 服务器的 5000 端口映射到本机的 5000 端口。 拆解解释 docker run -p 5000:5000 my-flask-app✅ docker run → 运行一个 Docker 容器 ✅ -p 5000:5000 → 端口…

高光谱工业相机+LED光源系统助力材料分类和异物检测、实现高速在线检测

检测光源包括可见光&#xff0c;如红光、蓝光和绿光以及其他波长的光&#xff0c;如紫外和红外波长&#xff0c;可以选择与检测对象物相应的波长。但由于能够照射的波长较窄&#xff0c;例如受到同色异物混入或多个素材的材质分类等&#xff0c;可能需要使用可照射多种波长的光…

Spring 拦截器(Interceptor)与过滤器(Filter)对比

Spring 拦截器&#xff08;Interceptor&#xff09;与过滤器&#xff08;Filter&#xff09;对比 核心对比表格 对比维度拦截器&#xff08;Interceptor&#xff09;过滤器&#xff08;Filter&#xff09;定义Spring MVC 提供的组件&#xff0c;集成于 Spring 处理器链。Servl…

VulnHub-FALL通关攻略

第一步&#xff1a;确定靶机IP为192.168.40.129 第二步&#xff1a;扫描后台及开放端口 #开放端口 22 --- ssh 25 --- SMTP简单邮件传输协议 80 --- HTTP万维网传输信息协议 110 --- POP3邮件协议3 139 --- NetBIOS服务 443 --- https服务 445 --- SMB协议 3306 --- Mysql 808…

Qt 线程和 QObjects

线程和 QObjects QThread 继承于 QObject。 它发出信号来指示线程开始或结束执行&#xff0c;并提供一些插槽。 更有趣的是&#xff0c;QObjects 可以在多个线程中使用&#xff0c;发出信号以调用其他线程中的插槽&#xff0c;并向 "生活 "在其他线程中的对象发布事件…

华为、浪潮、华三链路聚合概述

1、华为 链路聚合可以提高链路带宽和链路冗余性。有三种类型&#xff0c;分别是手工链路聚合&#xff0c;静态lacp链路聚合&#xff0c;动态lacp链路聚合。 手工链路模式&#xff1a;也称负载分担模式&#xff0c;需手动指定链路&#xff0c;各链路之间平均分担流量。静态LAC…

HarmonyOS NEXT 鸿蒙中关系型数据库@ohos.data.relationalStore API 9+

核心API ohos.data.relationalStore API 9 数据库 数据库是存储和管理数据的系统 数据库&#xff08;Database&#xff09;是一个以特定方式组织、存储和管理数据的集合&#xff0c;通常用于支持各种应用程序和系统的运行。它不仅是存放数据的仓库&#xff0c;还通过一定的…

步进电机 cia402协议 报文自己的理解 (笔记)

1. cai402 协议是什么 CiA 402 协议&#xff08;CAN in Automation 402&#xff09;&#xff0c;它是工业自动化领域中的一种通信协议&#xff0c;主要用于运动控制&#xff08;如伺服驱动器、步进电机等&#xff09;&#xff08; &#xff09;所属标准 CiA 402 是 CANopen 应用…

鸿蒙摄像机,一场智能安防的“平权革命”

2025的春天&#xff0c;全国各行各业都感受到了普惠AI的魅力。大模型带来的技术平权&#xff0c;让每一个人都能轻松用上AI。 这时候&#xff0c;企业想知道&#xff0c;每时每刻离不开的摄像机&#xff0c;究竟什么时候才能迎来智能技术的平权与普惠。 博思数据研究中心的一份…

解决HuggingFaceEmbeddings模型加载报错:缺少sentence-transformers依赖包

遇到报错 报错信息: Error loading model: Could not import sentence_transformers python package. Please install it with pip install sentence-transformers. 装包信息&#xff1a; pip install modelscope langchain sentence_transformers langchain-huggingface on…

从泛读到精读:合合信息文档解析如何让大模型更懂复杂文档

从泛读到精读&#xff1a;合合信息文档解析如何让大模型更懂复杂文档 一、引言&#xff1a;破解文档“理解力”瓶颈二、核心功能&#xff1a;合合信息的“破局”亮点功能亮点1&#xff1a;复杂图表的高精度解析图表解析&#xff1a;为大模型装上精准“标尺”表格数据精准还原 功…

Python+requests实现接口自动化测试框架

为什么要做接口自动化框架 1、业务与配置的分离 2、数据与程序的分离&#xff1b;数据的变更不影响程序 3、有日志功能&#xff0c;实现无人值守 4、自动发送测试报告 5、不懂编程的测试人员也可以进行测试 正常接口测试的流程是什么&#xff1f; 确定接口测试使用的工具…

信息学奥赛一本通 1514:【例 2】最大半连通子图 | 洛谷 P2272 [ZJOI2007] 最大半连通子图

【题目链接】 ybt 1514&#xff1a;【例 2】最大半连通子图 洛谷 P2272 [ZJOI2007] 最大半连通子图 【题目考点】 1. 图论&#xff1a;强连通分量 缩点 2. 图论&#xff1a;拓扑排序 有向无环图动规 【解题思路】 对于图中任意两顶点u、v&#xff0c;满足u到v或v到u有路径…

Android打aar包问题总结

1、moduleA 依赖 moduleB&#xff0c;将moduleA打包成aar时&#xff0c;未包含 moduleB的resources资源&#xff1b; 方法一&#xff1a;将moduleB的资源&#xff0c;手动拷贝一份到moduleA中&#xff1b; 方法二&#xff1a;使用 fat-aar 插件&#xff1b; 2、fat-aar插件使…

【网络协议】【http】http 简单介绍

【网络协议】【http】http 简单介绍 1 HTTP 头部 HTTP 是一种请求-响应协议&#xff0c;客户端向服务器发送请求&#xff0c;服务器返回响应。 1.1 HTTP 状态码 状态码是服务器返回给客户端的 三位数字代码&#xff0c;用于表示请求的执行结果。 状态码按照首位数字分类&am…

谈谈空间复杂度考量,特别是递归调用栈空间消耗?

空间复杂度考量是算法设计的核心要素之一&#xff0c;递归调用栈的消耗问题在前端领域尤为突出。 以下结合真实开发场景进行深度解析&#xff1a; 一、递归调用栈的典型问题 1. 深层次DOM遍历的陷阱 // 危险操作&#xff1a;递归遍历未知层级的DOM树 function countDOMNode…

LeetCode算法题(Go语言实现)_16

题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …

【数据结构】栈 与【LeetCode】20.有效的括号详解

目录 一、栈1、栈的概念及结构2、栈的实现3、初始化栈和销毁栈4、打印栈的数据5、入栈操作---栈顶6、出栈---栈顶6.1栈是否为空6.2出栈---栈顶 7、取栈顶元素8、获取栈中有效的元素个数 二、栈的相关练习1、练习2、AC代码 个人主页&#xff0c;点这里~ 数据结构专栏&#xff0c…