[Java 游戏编程]STG类游戏的实现2-Bullet

来源:互联网 发布:启动mysql服务 编辑:程序博客网 时间:2024/05/16 23:45

Game.java

import javax.swing.JFrame;public class Game {public static void main(String [] args) {JFrame window = new JFrame("飞碟大战");window.setResizable(false);window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);window.add(new GamePanel());window.pack();window.setLocationRelativeTo(null);window.setVisible(true);}}


GamePanel.java

import java.awt.Color;import java.awt.Dimension;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.image.BufferedImage;import java.util.ArrayList;import javax.swing.JPanel;public class GamePanel extends JPanel implements Runnable, KeyListener {// 640 480public static int WIDTH = 320;public static int HEIGHT = 240;public static int SCALE = 2;// 游戏线程 游戏循环private Thread thread;private boolean running;// 实现双缓冲private BufferedImage image;private Graphics2Dg;private Player player;public static ArrayList<Bullet> bullets;// 设置窗口大小以及事件的捕捉public GamePanel() {setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));setFocusable(true);requestFocus();}// 初始化游戏线程并启动游戏线程 增加键盘监听器public void addNotify() {super.addNotify();if (thread == null) {thread = new Thread(this);thread.start();}addKeyListener(this);}private void init() {running = true;//实现游戏循环image = new BufferedImage(WIDTH*SCALE, HEIGHT*SCALE, BufferedImage.TYPE_INT_RGB);//创建一个后备缓冲g = (Graphics2D) image.getGraphics();player = new Player(WIDTH, HEIGHT);bullets = new ArrayList<Bullet>();}public void run() {init();int fps = 30;long startTime;long elapsedTime;long waitTime;long targetTime = 1000 / fps;while (running) {startTime = System.nanoTime();update();render();draw();elapsedTime = (System.nanoTime() - startTime) / 1000000;waitTime = targetTime - elapsedTime;try {Thread.sleep(waitTime);}catch (Exception e) {e.printStackTrace();}}}private void update() {player.update();for (int i = 0; i < bullets.size(); i++) {boolean remove = bullets.get(i).update();if (remove) {bullets.remove(i);i--;}}}private void render() {g.setColor(new Color(0, 0, 0));g.fillRect(0, 0, GamePanel.WIDTH*GamePanel.SCALE, GamePanel.HEIGHT*GamePanel.SCALE);player.draw(g);for (int i = 0; i < bullets.size(); i++)bullets.get(i).draw(g);}private void draw() {// 主缓冲 Graphics g2 = getGraphics();if (g2 == null) {System.out.println("G2 is NULL");System.exit(0);}// 把后备缓冲绘制到主缓冲 实现平滑的动态效果g2.drawImage(image, 0, 0, null);g2.dispose();}public void keyPressed(KeyEvent event) {int keyCode = event.getKeyCode();player.keyPressed(keyCode);}public void keyReleased(KeyEvent event) {int keyCode = event.getKeyCode();player.keyReleased(keyCode);}public void keyTyped(KeyEvent event) {}}


Player.java

import java.awt.Color;import java.awt.Graphics2D;import java.awt.event.KeyEvent;import java.util.ArrayList;public class Player {// w: 宽度// h: 高度// x, y: 玩家坐标// dx, dy: 要移动的坐标// speed: 速度private int w;private int h;private int x;private int y;private int dx;private int dy;private int speed;private boolean up;private boolean down;private boolean left;private boolean right;private boolean firing;private long firingTimer;private long firingDelay;public Player(int x, int y) {this.x = x;this.y = y;this.dx = 0;this.dy = 0;this.w = 16;this.h = 16;this.speed = 5;this.firing = false;this.firingTimer = System.nanoTime();this.firingDelay = 150;}public void update() {// 角色移动if (left) {dx = -speed;}if (right) {dx = speed;}if (up) {dy = -speed;}if (down) {dy = speed;}x += dx;y += dy;// 碰撞检测if (x < 0) { x = 0; }if (y < 0) { y = 0; }if (x > GamePanel.WIDTH * GamePanel.SCALE - w) {x = GamePanel.WIDTH * GamePanel.SCALE - w;}if (y > GamePanel.HEIGHT * GamePanel.SCALE - h) {y = GamePanel.HEIGHT * GamePanel.SCALE - h;}if (firing) {long elapsed = (System.nanoTime() - firingTimer) / 1000000;if (elapsed > firingDelay) {GamePanel.bullets.add(new Bullet(270, x, y, this));firingTimer = System.nanoTime();}}// 重置目的坐标dx = 0;dy = 0;}public void draw(Graphics2D g) {g.setColor(new Color(0, 120, 255));g.fillRect(x, y, w, h);}public int getw() { return w; }public int geth() { return h; }private void setUp(boolean v) { this.up = v; }private void setDown(boolean v) { this.down = v; }private void setLeft(boolean v) { this.left = v; }private void setRight(boolean v) { this.right = v; }private void setFiring(boolean v) { this.firing = v; }public void keyPressed(int keyCode) {if (keyCode == KeyEvent.VK_UP) {setUp(true);}if (keyCode == KeyEvent.VK_DOWN) {setDown(true);}if (keyCode == KeyEvent.VK_RIGHT) {setRight(true);}if (keyCode == KeyEvent.VK_LEFT) {setLeft(true);}if (keyCode == KeyEvent.VK_SPACE) {setFiring(true);}}public void keyReleased(int keyCode) {if (keyCode == KeyEvent.VK_UP) {setUp(false);}if (keyCode == KeyEvent.VK_DOWN) {setDown(false);}if (keyCode == KeyEvent.VK_RIGHT) {setRight(false);}if (keyCode == KeyEvent.VK_LEFT) {setLeft(false);}if (keyCode == KeyEvent.VK_SPACE) {setFiring(false);}}}


Bullet.java

import java.awt.Color;import java.awt.Graphics2D;public class Bullet {protected Player player;private int x;private int y;private int w;private int h;private int dx;private int dy;private double rad;private double speed;private Color color;public Bullet(double angle, int x, int y, Player player) {this.player = player;this.x = x;this.y = y;this.w = 2;this.h = 2;this.rad = Math.toRadians(angle);this.speed = 15.44;// 确保子弹在角色上方this.dx = (int) (Math.cos(rad) * speed);this.dy = (int) (Math.sin(rad) * speed);color = new Color(255, 220, 0);}public boolean update() {x += dx;y += dy;if (x < -w || x > GamePanel.WIDTH*GamePanel.SCALE + w ||y < -h || y > GamePanel.HEIGHT*GamePanel.SCALE + h) {return true;}return false;}public void draw(Graphics2D g) {g.setColor(color);g.fillRect((int)(x+player.getw()/2), (int)(y+player.geth()/2), w, h);}}


求出角度为270度的弧度,通过Math.cos(弧度) Math.sin(弧度)确定子弹偏移量

保证子弹在角色上方


0 0
原创粉丝点击