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.pswp.cn/web/73778.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73778.shtml
英文地址,請注明出處:http://en.pswp.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…