作为一个男孩子,从小就喜欢晚一些游戏。今天就用java写一个类似马里奥的冒险闯关小游戏,但这也不是一两天能完成的事情,我将会持续更新这个游戏(有什么好的介意也非常欢迎大家提出来,也能在我的基础上自己接着写)。目前完成的功能有:人物的流畅运动、跳跃以及自由下落,障碍物(地面)的添加,怪物的添加、移动以及死亡。(代码基本上是完整的,直接粘贴复制就能用)
游戏介绍
和马里奥差不太多,左右键控制移动,空格跳,碰到怪物死亡,可以踩死怪物。目前也就这些功能,也会不断添加新的功能。
代码讲解
view里面是创建页面,handle里写控制方法,pic里存一些需要的图片。
创建Frame
没啥好讲的。
import javax.swing.*;
public class GameFrame {
public static void main(String[] args) {
JFrame jf = new JFrame("冒险闯关小游戏");
jf.add(new GamePanel());
jf.setSize(806,600);
jf.setLocationRelativeTo(null); //居中
jf.setResizable(false);
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
JPanel
这里定义了玩家、怪物、障碍物的一些属性,然后将他们画出来。其实更好的方法是定义三个类,用的时候实例化一下就行,这里后面我也会改。
import game2.handle.MonsterMove;
import game2.handle.MoveHandle;
import javax.swing.*;
import java.awt.*;
import java.util.Vector;
public class GamePanel extends JPanel {
ImageIcon b = new ImageIcon("src\\game2\\pic\\b.jpg");
ImageIcon xyq = new ImageIcon("src\\game2\\pic\\xyq.png");
public boolean up = false;
public boolean down = false;
public boolean left = false;
public boolean right = false;
public int hero_x;
public int hero_y;
// public int hero_width = xyq.getIconWidth();
// public int hero_height = xyq.getIconHeight();
public int hero_width = 30;
public int hero_height = 60;
public Vector<int[]> v = new Vector<>();
int[] f0 = {0,500,800,10};
int[] f1 = {300,500-80,200,10};
int[] f2 = {500,500-40,50,40};
int[] f3 = {100,500-150,80,30};
int[] f4 = {200,500-250,340,10};
{
v.add(f0);
v.add(f1);
v.add(f2);
v.add(f3);
v.add(f4);
}
public Vector<int[]> ms = new Vector<>(); //怪物列表
public int[] m0 = {600,500-40,40,40,600,750,1}; //x,y,w,h,起点,终点,速度
public int[] m1 = {0,500-40,40,40,0,100,1};
{
ms.add(m0);
ms.add(m1);
}
public boolean mIsDie = false;
public GamePanel() {
setFocusable(true);
MoveHandle moveHandle = new MoveHandle(this);
addKeyListener(moveHandle);
Thread thread = new Thread(moveHandle);
thread.start();
MonsterMove monsterMove = new MonsterMove(this);
Thread thread2 = new Thread(monsterMove);
thread2.start();
init();
}
public void init() {
hero_x = 200;
hero_y = 500-hero_height;
}
@Override
public void paint(Graphics g) {
super.paintComponent(g);
b.paintIcon(this,g,0,0);
g.setColor(Color.blue);
g.fillRect(hero_x, hero_y, hero_width, hero_height);
// xyq.paintIcon(this,g,hero_x,hero_y);
g.setColor(Color.red);
for(int i=0;i<ms.size();i++){
g.fillRect(ms.get(i)[0],ms.get(i)[1],ms.get(i)[2],ms.get(i)[3]);
}
paintRect(g,v);
}
private void paintRect(Graphics g,Vector<int[]> v){
g.setColor(Color.black);
for(int i = 0; i<v.size(); i++){
int[] f = v.get(i);
g.fillRect(f[0],f[1],f[2],f[3]);
}
}
}
MoveHandle
我觉得我这里最好的一点代码就在这里面,其实从学写swing时候,就发现如果用键盘控制人物移动的时候它的移动并不顺畅。我这里是用线程的方法做成了顺畅移动。
简单讲,就是创建一个进程,一直让他循环执行,每当按下右(左)键,就会一直循环执行向右(左)走的方法,每次运行方法中间间隔几毫秒(不然移动的太快根本看不到)。
然后中间再添加一些其他判断,如是否碰到障碍物,是否碰到怪物等。
import game2.view.GamePanel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class MoveHandle implements KeyListener, Runnable {
GamePanel gamePanel;
JumpHandle jump;
public MoveHandle(GamePanel gamePanel) {
this.gamePanel = gamePanel;
jump = new JumpHandle(gamePanel);
Thread thread1 = new Thread(jump);
thread1.start();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_LEFT:
gamePanel.left = true;
break;
case KeyEvent.VK_RIGHT:
gamePanel.right = true;
break;
case KeyEvent.VK_SPACE:
jump.isSky = true;
if (jump.c < 2) {
jump.isJump = true;
}
break;
default:
break;
}
gamePanel.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_LEFT:
gamePanel.left = false;
break;
case KeyEvent.VK_RIGHT:
gamePanel.right = false;
break;
default:
break;
}
}
@Override
public void run() {
while (true) {
move();
if (!jump.isSky) {
loop:
while (true) {
for (int i = 0; i < gamePanel.v.size(); i++) {
if (gamePanel.hero_x + gamePanel.hero_width > gamePanel.v.get(i)[0]
&& gamePanel.hero_x < gamePanel.v.get(i)[0] + gamePanel.v.get(i)[2]) {
if (gamePanel.hero_y == gamePanel.v.get(i)[1] - gamePanel.hero_height) {
break loop;
}
}
}
gamePanel.hero_y += 1;
for(int i=0;i<gamePanel.ms.size();i++) {
if (gamePanel.hero_y + gamePanel.hero_height == gamePanel.ms.get(i)[1]
&& gamePanel.hero_x + gamePanel.hero_width > gamePanel.ms.get(i)[0]
&& gamePanel.hero_x < gamePanel.ms.get(i)[0] + gamePanel.ms.get(i)[2]) {
gamePanel.ms.remove(i);
break ;
}
}
gamePanel.repaint();
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
move();
}
}
gamePanel.repaint();
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void move() {
if (gamePanel.right) {
if (gamePanel.hero_x + gamePanel.hero_width < 800 && isMoveRight()) {
gamePanel.hero_x += 1;
}
} else if (gamePanel.left) {
if (gamePanel.hero_x > 0 && isMoveLeft()) {
gamePanel.hero_x -= 1;
}
}
isDie();
}
private boolean isMoveRight() {
for (int i = 0; i < gamePanel.v.size(); i++) {
if (gamePanel.hero_x + gamePanel.hero_width == gamePanel.v.get(i)[0]
&& gamePanel.hero_y + gamePanel.hero_height > gamePanel.v.get(i)[1]
&& gamePanel.hero_y < gamePanel.v.get(i)[1] + gamePanel.v.get(i)[3]) {
return false;
}
}
return true;
}
private boolean isMoveLeft() {
for (int i = 0; i < gamePanel.v.size(); i++) {
if (gamePanel.hero_x == gamePanel.v.get(i)[0] + gamePanel.v.get(i)[2]
&& gamePanel.hero_y + gamePanel.hero_height > gamePanel.v.get(i)[1]
&& gamePanel.hero_y < gamePanel.v.get(i)[1] + gamePanel.v.get(i)[3]) {
return false;
}
}
return true;
}
private void isDie() {
for(int i=0;i<gamePanel.ms.size();i++) {
int[] m = gamePanel.ms.get(i);
if ((gamePanel.hero_x + gamePanel.hero_width == m[0] || gamePanel.hero_x == m[0] + m[2])
&& gamePanel.hero_y + gamePanel.hero_height > m[1]
&& gamePanel.hero_y < m[1] + m[3]) {
gamePanel.init();;
}
}
}
}
JumpHandle
这段是用来实现跳跃的功能,我这里设置的上下跳跃是匀速的,可以自己改一下,让它符合真实物理情况。
这里我设置了最多跳两次。
并且在下降的时候增加了两个判断:1是是否落到实体障碍物上,2是是否踩到怪物,踩到怪物就被判断死亡。文章来源:https://www.toymoban.com/news/detail-451347.html
import game2.view.GamePanel;
import java.util.Arrays;
public class JumpHandle implements Runnable {
GamePanel gamePanel;
boolean isJump = false;
boolean isSky = false;
int c;
public JumpHandle(GamePanel gamePanel) {
this.gamePanel = gamePanel;
}
@Override
public void run() {
while (true) {
c = 0;
if (isJump) {
isJump = false;
jumpUp();
jumpDown();
}
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void jumpDown() {
loop:
while (true) {
for (int i = 0; i < gamePanel.v.size(); i++) {
if (gamePanel.hero_x + gamePanel.hero_width> gamePanel.v.get(i)[0]
&& gamePanel.hero_x < gamePanel.v.get(i)[0] + gamePanel.v.get(i)[2]) {
if (gamePanel.hero_y == gamePanel.v.get(i)[1] - gamePanel.hero_height) {
isSky = false;
break loop;
}
}
}
if (isJump && c < 2) {
isJump = false;
jumpUp();
}
gamePanel.hero_y += 1;
for(int i=0;i<gamePanel.ms.size();i++) {
if (gamePanel.hero_y + gamePanel.hero_height == gamePanel.ms.get(i)[1]
&& gamePanel.hero_x + gamePanel.hero_width > gamePanel.ms.get(i)[0]
&& gamePanel.hero_x < gamePanel.ms.get(i)[0] + gamePanel.ms.get(i)[2]) {
gamePanel.ms.remove(i);
break ;
}
}
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private void jumpUp() {
c++;
for (int i = 0; i < 80; i++) {
if (isJump && c < 2) {
isJump = false;
jumpUp();
break;
}
if(!isJumpD()){
break;
}
gamePanel.hero_y -= 1;
try {
Thread.sleep(3);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private boolean isJumpD() {
for (int i = 0; i < gamePanel.v.size(); i++) {
if (gamePanel.hero_y == gamePanel.v.get(i)[1] + gamePanel.v.get(i)[3]
&& gamePanel.hero_x + gamePanel.hero_width> gamePanel.v.get(i)[0]
&& gamePanel.hero_x < gamePanel.v.get(i)[0] + gamePanel.v.get(i)[2]) {
return false;
}
}
return true;
}
}
MonsterMove
这里是实现怪物的移动。文章来源地址https://www.toymoban.com/news/detail-451347.html
import game2.view.GamePanel;
public class MonsterMove implements Runnable {
GamePanel gamePanel;
public MonsterMove(GamePanel gamePanel) {
this.gamePanel = gamePanel;
}
@Override
public void run() {
while(true) {
for (int i = 0; i < gamePanel.ms.size(); i++) {
gamePanel.ms.get(i)[0]+=gamePanel.ms.get(i)[6];
if(gamePanel.ms.get(i)[0]==gamePanel.ms.get(i)[4]||gamePanel.ms.get(i)[0]+gamePanel.ms.get(i)[2]==gamePanel.ms.get(i)[5]){
gamePanel.ms.get(i)[6] = -gamePanel.ms.get(i)[6];
}
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
到了这里,关于java 300行代码 冒险闯关小游戏(代码+讲解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!