每当它们离开屏幕时,我都试图将它们“传送”到相反的位置。我已经设法用right
&bottom
边做到了这一点,但由于某种原因,我还没有弄清楚,星体不会在TOP
&LEFT
边上离开屏幕,除非 lerping 速度足够高。
主.java
package asteroids;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class Main extends Canvas implements KeyListener {
private boolean gameOver;
private BufferStrategy backBuffer;
private Dimension dimension = new Dimension(Config.WINDOW_WH[0], Config.WINDOW_WH[1]);
private List<Star> stars = new ArrayList<Star>();
private HashMap<Integer,Boolean> keyDownMap = new HashMap<Integer, Boolean>();
private Ship ship;
private Image bg;
private float starGoalX, starGoalY;
public Main() {
// Initialize Window
initWindow();
addKeyListener(this);
this.createBufferStrategy(2);
backBuffer = this.getBufferStrategy();
bg = new ImageIcon(getClass().getResource("/bg.png")).getImage();
// init variables
gameOver = false;
// Generating stars
generateStars();
// Init spaceship
ship = new Ship(25,36,"ship.png");
// Init loop
gameLoop();
}
public void initWindow(){
JFrame window = new JFrame("Asteroids");
setPreferredSize(dimension);
window.add(this);
window.pack();
window.setResizable(false);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.requestFocus();
}
public float lerp(float starGoal, float vel, float speed) {
return starGoal + speed * (vel - starGoal);
}
public void update() {
if(keyDownMap.containsKey(KeyEvent.VK_ESCAPE)){
gameOver = false;
System.exit(0);
}
for(Star s: stars) {
s.posx += lerp(this.starGoalX, s.velX, Config.lerpSpeed);
s.velX += this.starGoalX * Config.lerpSpeed;
s.posy += lerp(this.starGoalY, s.velY, Config.lerpSpeed);
s.velY += this.starGoalY * Config.lerpSpeed;
checkPos(s);
s.update();
}
}
public void checkPos(Star s) {
if(s.posx < -s.width)
s.posx = Config.WINDOW_WH[0]-s.width;
else if(s.posx > Config.WINDOW_WH[0])
s.posx = 0;
if(s.posy < -s.height)
s.posy = Config.WINDOW_WH[1]-s.height;
else if(s.posy > Config.WINDOW_WH[1])
s.posy = 0;
}
public void render(){
Graphics2D g = (Graphics2D) backBuffer.getDrawGraphics();
if (!backBuffer.contentsLost()) {
g.drawImage(this.bg,0,0,Config.WINDOW_WH[0], Config.WINDOW_WH[1], null);
// Draw Stars
g.setColor(Color.WHITE);
for(Star s: stars)
g.fillOval(s.posx - (s.width/2), s.posy - (s.height/2), s.width, s.height);
// Draw ship
g.drawImage(
this.ship.getImage(),
this.ship.posx, this.ship.posy,
this.ship.width, this.ship.height, null);
backBuffer.show();
g.dispose();
}
}
public void generateStars() {
for(int i = 0;i < 50;i++) {
int starX = new Random().nextInt(Config.WINDOW_WH[0]+100)+5;
int starY = new Random().nextInt(Config.WINDOW_WH[1]+100)+5;
stars.add(new Star(starX, starY));
}
}
public void gameLoop(){
while(!gameOver){
update();
render();
try{ Thread.sleep(20);}catch(Exception e){};
}
}
public static void main(String[] args) {
new Main();
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) this.starGoalX = Config.lerpSpeed;
if(e.getKeyCode() == KeyEvent.VK_RIGHT) this.starGoalX = -Config.lerpSpeed;
if(e.getKeyCode() == KeyEvent.VK_UP) this.starGoalY = Config.lerpSpeed;
if(e.getKeyCode() == KeyEvent.VK_DOWN) this.starGoalY = -Config.lerpSpeed;
keyDownMap.put(e.getKeyCode(), true);
}
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT
|| e.getKeyCode() == KeyEvent.VK_RIGHT) this.starGoalX = 0;
if(e.getKeyCode() == KeyEvent.VK_UP
|| e.getKeyCode() == KeyEvent.VK_DOWN) this.starGoalY = 0;
keyDownMap.remove(e.getKeyCode());
}
}
星辰.java
package asteroids;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.HashMap;
import java.util.Random;
public class Star {
int width, height;
int posx, posy;
float velX, velY, velGoalX, velGoalY;
/** CONSTRUCTOR **/
public Star(int x, int y) {
int rand = new Random().nextInt(Config.STAR_SIZES.length);
width = Config.STAR_SIZES[rand];
height = Config.STAR_SIZES[rand];
posx = x;
posy = y;
}
public void update() {
// pass
}
}
Ship.java
package asteroids;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import javax.swing.ImageIcon;
public class Ship {
public int posx, posy;
public int width, height;
private Image image;
public Ship(int w, int h, String img) {
this.posx = Config.WINDOW_WH[0]/2;
this.posy = Config.WINDOW_WH[1]/2;
this.width = w;
this.height = h;
this.image = new ImageIcon(getClass().getResource("/"+img)).getImage();
}
public Image getImage() {
return this.image;
}
public void setPosx(int x) {posx = x;}
public void setPosy(int y) {posy = y;}
public void setImg(Image img) {
this.image = img;
}
public void update(HashMap keyDownMap) {
// pass
}
}
配置文件
package asteroids;
import java.awt.Color;
public class Config {
// MAIN CANVAS SETTINGS
public static int[] WINDOW_WH = {500, 500};
public static String WINDOW_BG_IMG = "";
public static Color WINDOW_BG_CLR = new Color(40, 42, 45);
// OBJECT SETTINGS
public static int[] STAR_SIZES = {10,5,8,3,7};
public static float lerpSpeed = 0.8f;
}