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

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 480
	public static int WIDTH = 320;
	public static int HEIGHT = 240;
	public static int SCALE = 2;
	
	// 游戏线程 游戏循环
	private Thread thread;
	private boolean running;
	
	// 实现双缓冲
	private BufferedImage image;
	private Graphics2D	g;
	
	private Player player;
	public static ArrayList 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();
	}
	
	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);
	}
}


[Java 游戏编程]STG类游戏的实现2-Bullet_第1张图片

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

保证子弹在角色上方

[Java 游戏编程]STG类游戏的实现2-Bullet_第2张图片[Java 游戏编程]STG类游戏的实现2-Bullet_第3张图片

你可能感兴趣的:(Java,Game)