Java 平台游戏:玩家跳过平台
Java Platformer: Player Jumps Through Platform
所以,我即将完成一个简单的 Java 平台游戏,但还有一个大问题,当玩家跳跃并从下方与平台相撞时,玩家有时(并且总是如果他们're close to the platform) 跳过平台并落在上面的平台上。这是代码:
package Main;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
public class Platformer extends Applet implements Runnable, KeyListener {
// buffering variables
private Image dbImage;
private Graphics dbg;
// running boolean
private boolean running = true;
// Player coords
private int rectX = 100;
private int rectY = 420;
// initialise dx and dy at zero
private double dx = 0;
private double dy = 0;
private boolean jumping = false;
//debug Strings
private String inter = new String();
private String coords = new String();
private String debugX = "", debugY = "";
//for moving the player
private int worldShift = 0;
//sprites
Rectangle2D player = new Rectangle2D.Double();// = new Rectangle2D.Double(rectX, rectY, 10, 10);
Rectangle2D ground = new Rectangle2D.Double(0, 420, 800, 150);
int[][] platforms = { {300, 300, 100, 20}, { 450, 200, 100, 20 },
{ 500, 250, 100, 20 }, { 100, 200, 100, 20 }, { 600, 300, 100, 20 } };
ArrayList<Rectangle2D> platformList = new ArrayList<Rectangle2D>();
int level = 1;
@Override
public void init() {
setSize(800, 480);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Test");
setVisible(true);
for (int i = 0; i < platforms.length; i++){
// platforms
Rectangle2D platform = new Rectangle2D.Double();
platform.setRect(platforms[i][0] + worldShift, platforms[i][1],
platforms[i][2], platforms[i][3]);
platformList.add(platform);
}
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
public void paint(Graphics g) {
//Double Buffering
Graphics2D g2 = (Graphics2D) g;
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g2.drawImage(dbImage, 0, 0, this);
}
// Paint objects
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//draw platforms
if (level == 1) {
g2.setColor(Color.blue);
g2.draw(ground);
g2.fill(ground);
for (Rectangle2D plat : platformList){
g2.setColor(Color.red);
g2.draw(plat);
g2.fill(plat);
}
g2.setColor(Color.red);
//debug printouts
g.drawString(inter, 400, 30);
g.drawString(coords, 20, 150);
//draw player
g2.setColor(Color.white);
g2.draw(player);
g2.fill(player);
//print debug info to screen
Font bold = new Font("Liberation Sans", Font.BOLD, 36);
setFont(bold);
g.drawString("dx, dy: (" + dx + ", " + dy + ")", 30, 30);
g.drawString("x, y: (" + player.getX() + ", " + player.getY() + ")",
30, 60);
g.drawString("" + debugX + ", " + debugY + "", rectX, rectY);
}
}
@Override
public void run() {
while (running) {
update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update() {
rectX += dx;
rectY += dy + 1;
// stops player running off screen
if (rectX < 1) rectX = 0;
if (rectX > 790) rectX = 790;
// set sprite coords
player.setRect(rectX, rectY, 10, 10);
ground.setRect(0, 420, 800, 480);
// collision detection
if (player.intersects(ground)) {
rectY = (int) (ground.getY() - player.getHeight());
jumping = false;
dy = 0;
}
for (int i = 0; i < platformList.size(); i++){
Rectangle2D plat = platformList.get(i);
//sets platform's coordinates
plat.setRect(plat.getX() + worldShift, plat.getY(), plat.getWidth(), plat.getHeight());
//sets debug Strings
coords = "Not on platform";
inter = " " + platformList.get(0).getX() + worldShift + ", " + worldShift;
debugX = "" + rectX;
debugY = "" + rectY;
//for scrolling the background
if (rectX > 700 && dx == 5){
worldShift = -5;}
else if (rectX < 100 && dx == -5){
worldShift = 5;}
else worldShift = 0;
//collision detection
if (player.intersects(plat)) {
jumping = false;
dy = 0;
coords = " " + plat.getBounds();
//if falling
if (rectY <= (int) (plat.getY() + (plat.getHeight()/2))){
rectY = (int) (plat.getY() - player.getHeight());
//if jumping
else if (rectY >= plat.getY() + (plat.getHeight()/2)){
rectY = (int) (plat.getY() + plat.getHeight());}
break;
}
else if (!player.intersects(plat) && !player.intersects(ground)) {
jumping = true;
}
}
//implements falling
if (jumping)
dy += 1;
}
//button presses
@Override
public void keyPressed(KeyEvent e) {
System.out.println("Key pressed code=" + e.getKeyCode() + ", char=" + e.getKeyChar());
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
// if (e.getKeyCode() == 40) dy -= 5; //40 is down
if (e.getKeyCode() == 38 && jumping == false){
// if on the ground,
// i.e. only jump if on the ground
// 38 is up
dy -= 20;
jumping = true;
}
}
//key release
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 37)
dx = 0; // 37 is left
if (e.getKeyCode() == 39)
dx = 0; // 39 is right
if (e.getKeyCode() == 40)
dy = 0; // 40 is down
// if (e.getKeyCode() == 38)
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
我确信 update()
的“//碰撞检测”部分没有问题,但我不知道问题出在哪里。除其他事项外,我尝试将跳转机制置于更新循环中,但它也没有用。
感谢您的帮助。
看跳跃大小,是20:
public void keyPressed(KeyEvent e) {
System.out.println("Key pressed code=" + e.getKeyCode() + ", char=" + e.getKeyChar());
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
// if (e.getKeyCode() == 40) dy -= 5; //40 is down
if (e.getKeyCode() == 38 && jumping == false){
// if on the ground,
// i.e. only jump if on the ground
// 38 is up
dy -= 20; // <- jump size 20
jumping = true;
}
}
但是你的平台高度也是20
而且你是由平台中心决定的,这意味着它只需要超过中心10个像素,跳跃大小应该小于平台高度的一半
编辑 好的配置:
试试这个配置:
设置下降增量为+0.25
,跳跃增量为-9
删除评论以使其更短
if (jumping)
dy += 0.25;
和
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
if (e.getKeyCode() == 38 && jumping == false){
dy -= 9; // <- jump size set to 9 (half is 10)
jumping = true;
}
}
注意:闪烁很糟糕,我已经解决了将 paint(Graphics)
方法重命名为 update(Graphics)
所以,我即将完成一个简单的 Java 平台游戏,但还有一个大问题,当玩家跳跃并从下方与平台相撞时,玩家有时(并且总是如果他们're close to the platform) 跳过平台并落在上面的平台上。这是代码:
package Main;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
public class Platformer extends Applet implements Runnable, KeyListener {
// buffering variables
private Image dbImage;
private Graphics dbg;
// running boolean
private boolean running = true;
// Player coords
private int rectX = 100;
private int rectY = 420;
// initialise dx and dy at zero
private double dx = 0;
private double dy = 0;
private boolean jumping = false;
//debug Strings
private String inter = new String();
private String coords = new String();
private String debugX = "", debugY = "";
//for moving the player
private int worldShift = 0;
//sprites
Rectangle2D player = new Rectangle2D.Double();// = new Rectangle2D.Double(rectX, rectY, 10, 10);
Rectangle2D ground = new Rectangle2D.Double(0, 420, 800, 150);
int[][] platforms = { {300, 300, 100, 20}, { 450, 200, 100, 20 },
{ 500, 250, 100, 20 }, { 100, 200, 100, 20 }, { 600, 300, 100, 20 } };
ArrayList<Rectangle2D> platformList = new ArrayList<Rectangle2D>();
int level = 1;
@Override
public void init() {
setSize(800, 480);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Test");
setVisible(true);
for (int i = 0; i < platforms.length; i++){
// platforms
Rectangle2D platform = new Rectangle2D.Double();
platform.setRect(platforms[i][0] + worldShift, platforms[i][1],
platforms[i][2], platforms[i][3]);
platformList.add(platform);
}
}
@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
public void paint(Graphics g) {
//Double Buffering
Graphics2D g2 = (Graphics2D) g;
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g2.drawImage(dbImage, 0, 0, this);
}
// Paint objects
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//draw platforms
if (level == 1) {
g2.setColor(Color.blue);
g2.draw(ground);
g2.fill(ground);
for (Rectangle2D plat : platformList){
g2.setColor(Color.red);
g2.draw(plat);
g2.fill(plat);
}
g2.setColor(Color.red);
//debug printouts
g.drawString(inter, 400, 30);
g.drawString(coords, 20, 150);
//draw player
g2.setColor(Color.white);
g2.draw(player);
g2.fill(player);
//print debug info to screen
Font bold = new Font("Liberation Sans", Font.BOLD, 36);
setFont(bold);
g.drawString("dx, dy: (" + dx + ", " + dy + ")", 30, 30);
g.drawString("x, y: (" + player.getX() + ", " + player.getY() + ")",
30, 60);
g.drawString("" + debugX + ", " + debugY + "", rectX, rectY);
}
}
@Override
public void run() {
while (running) {
update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update() {
rectX += dx;
rectY += dy + 1;
// stops player running off screen
if (rectX < 1) rectX = 0;
if (rectX > 790) rectX = 790;
// set sprite coords
player.setRect(rectX, rectY, 10, 10);
ground.setRect(0, 420, 800, 480);
// collision detection
if (player.intersects(ground)) {
rectY = (int) (ground.getY() - player.getHeight());
jumping = false;
dy = 0;
}
for (int i = 0; i < platformList.size(); i++){
Rectangle2D plat = platformList.get(i);
//sets platform's coordinates
plat.setRect(plat.getX() + worldShift, plat.getY(), plat.getWidth(), plat.getHeight());
//sets debug Strings
coords = "Not on platform";
inter = " " + platformList.get(0).getX() + worldShift + ", " + worldShift;
debugX = "" + rectX;
debugY = "" + rectY;
//for scrolling the background
if (rectX > 700 && dx == 5){
worldShift = -5;}
else if (rectX < 100 && dx == -5){
worldShift = 5;}
else worldShift = 0;
//collision detection
if (player.intersects(plat)) {
jumping = false;
dy = 0;
coords = " " + plat.getBounds();
//if falling
if (rectY <= (int) (plat.getY() + (plat.getHeight()/2))){
rectY = (int) (plat.getY() - player.getHeight());
//if jumping
else if (rectY >= plat.getY() + (plat.getHeight()/2)){
rectY = (int) (plat.getY() + plat.getHeight());}
break;
}
else if (!player.intersects(plat) && !player.intersects(ground)) {
jumping = true;
}
}
//implements falling
if (jumping)
dy += 1;
}
//button presses
@Override
public void keyPressed(KeyEvent e) {
System.out.println("Key pressed code=" + e.getKeyCode() + ", char=" + e.getKeyChar());
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
// if (e.getKeyCode() == 40) dy -= 5; //40 is down
if (e.getKeyCode() == 38 && jumping == false){
// if on the ground,
// i.e. only jump if on the ground
// 38 is up
dy -= 20;
jumping = true;
}
}
//key release
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 37)
dx = 0; // 37 is left
if (e.getKeyCode() == 39)
dx = 0; // 39 is right
if (e.getKeyCode() == 40)
dy = 0; // 40 is down
// if (e.getKeyCode() == 38)
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
我确信 update()
的“//碰撞检测”部分没有问题,但我不知道问题出在哪里。除其他事项外,我尝试将跳转机制置于更新循环中,但它也没有用。
感谢您的帮助。
看跳跃大小,是20:
public void keyPressed(KeyEvent e) {
System.out.println("Key pressed code=" + e.getKeyCode() + ", char=" + e.getKeyChar());
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
// if (e.getKeyCode() == 40) dy -= 5; //40 is down
if (e.getKeyCode() == 38 && jumping == false){
// if on the ground,
// i.e. only jump if on the ground
// 38 is up
dy -= 20; // <- jump size 20
jumping = true;
}
}
但是你的平台高度也是20
而且你是由平台中心决定的,这意味着它只需要超过中心10个像素,跳跃大小应该小于平台高度的一半
编辑 好的配置:
试试这个配置:
设置下降增量为+0.25
,跳跃增量为-9
删除评论以使其更短
if (jumping)
dy += 0.25;
和
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37)
dx -= 5; // 37 is left
if (e.getKeyCode() == 39)
dx += 5; // 39 is right
if (e.getKeyCode() == 38 && jumping == false){
dy -= 9; // <- jump size set to 9 (half is 10)
jumping = true;
}
}
注意:闪烁很糟糕,我已经解决了将 paint(Graphics)
方法重命名为 update(Graphics)