Java實現(xiàn)經(jīng)典游戲超級瑪麗的示例代碼
前言
在你的童年記憶里,是否有一個蹦跳、頂蘑菇的小人?
如果你回憶起了它,你定然會覺得現(xiàn)在它幼稚、無聊,畫面不漂亮,游戲不精彩……但請你記?。哼@才是真正的游戲,它給了你無限的歡樂!
馬里奧是靠吃蘑菇成長,聞名世界的超級巨星。特征是大鼻子、頭戴帽子、身穿背帶工作服、還留著胡子。
如此經(jīng)典的游戲,你怎么能錯過,快來玩玩吧。
《超級瑪麗》游戲是用java語言實現(xiàn),采用了swing技術進行了界面化處理,設計思路用了面向?qū)ο笏枷搿?/p>
主要需求
游戲劇情模擬超級瑪麗,用swing來做界面化處理,學會利用面向?qū)ο蟮乃枷雽崿F(xiàn)這個游戲
主要設計
1、游戲背景的設計
2、地圖的顯示
3、臺階的顯示
4、游戲物品的顯示
5、超級瑪麗的設計,左右移動能力、跳動能力
6、小怪的設計,包含出現(xiàn)的地點、殺傷功能、跳動能力
7、游戲的分數(shù)系統(tǒng)設計
8、地圖變動功能
9、射擊功能
10、游戲采用多線程技術
11、背景音樂設計
功能截圖
游戲開始:

超級瑪麗跳動

換地圖

過了這一關

代碼實現(xiàn)
游戲主界面
public class MyFrame extends JFrame implements KeyListener,Runnable {
//用于存儲所有的背景
private List<BackGround> allBg = new ArrayList<>();
//用于存儲當前的背景
private BackGround nowBg = new BackGround();
//用于雙緩存
private Image offScreenImage = null;
//馬里奧對象
private Mario mario = new Mario();
//定義一個線程對象,用于實現(xiàn)馬里奧的運動
private Thread thread = new Thread(this);
public MyFrame() {
//設置窗口的大小為800 * 600
this.setSize(800,600);
//設置窗口居中顯示
this.setLocationRelativeTo(null);
//設置窗口的可見性
this.setVisible(true);
//設置點擊窗口上的關閉鍵,結(jié)束程序
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設置窗口大小不可變
this.setResizable(false);
//向窗口對象添加鍵盤監(jiān)聽器
this.addKeyListener(this);
//設置窗口名稱
this.setTitle("超級瑪麗");
//初始化圖片
StaticValue.init();
//初始化馬里奧
mario = new Mario(10,355);
//創(chuàng)建全部的場景
for (int i = 1;i <= 3;i++) {
allBg.add(new BackGround(i, i == 3 ? true : false));
}
//將第一個場景設置為當前場景
nowBg = allBg.get(0);
mario.setBackGround(nowBg);
//繪制圖像
repaint();
thread.start();
try {
new Music();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
}
}
@Override
public void paint(Graphics g) {
if (offScreenImage == null) {
offScreenImage = createImage(800,600);
}
Graphics graphics = offScreenImage.getGraphics();
graphics.fillRect(0,0,800,600);
//繪制背景
graphics.drawImage(nowBg.getBgImage(),0,0,this);
//繪制敵人
for (Enemy e : nowBg.getEnemyList()) {
graphics.drawImage(e.getShow(),e.getX(),e.getY(),this);
}
//繪制障礙物
for (Obstacle ob : nowBg.getObstacleList()) {
graphics.drawImage(ob.getShow(),ob.getX(),ob.getY(),this);
}
//繪制城堡
graphics.drawImage(nowBg.getTower(),620,270,this);
//繪制旗桿
graphics.drawImage(nowBg.getGan(),500,220,this);
//繪制馬里奧
graphics.drawImage(mario.getShow(),mario.getX(),mario.getY(),this);
//添加分數(shù)
Color c = graphics.getColor();
graphics.setColor(Color.BLACK);
graphics.setFont(new Font("黑體",Font.BOLD,25));
graphics.drawString("當前的分數(shù)為: " + mario.getScore(),300,100);
graphics.setColor(c);
//將圖像繪制到窗口中
g.drawImage(offScreenImage,0,0,this);
}
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
}
@Override
public void keyTyped(KeyEvent e) {
}
//當鍵盤按下按鍵時調(diào)用
@Override
public void keyPressed(KeyEvent e) {
//向右移動
if (e.getKeyCode() == 39) {
mario.rightMove();
}
//向左移動
if (e.getKeyCode() == 37) {
mario.leftMove();
}
//跳躍
if (e.getKeyCode() == 38) {
mario.jump();
}
}
//當鍵盤松開按鍵時調(diào)用
@Override
public void keyReleased(KeyEvent e) {
//想左停止
if (e.getKeyCode() == 37) {
mario.leftStop();
}
//向右停止
if (e.getKeyCode() == 39) {
mario.rightStop();
}
}
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(50);
if (mario.getX() >= 775) {
nowBg = allBg.get(nowBg.getSort());
mario.setBackGround(nowBg);
mario.setX(10);
mario.setY(355);
}
//判斷馬里奧是否死亡
if (mario.isDeath()) {
JOptionPane.showMessageDialog(this,"馬里奧死亡!!!");
System.exit(0);
}
//判斷游戲是否結(jié)束
if (mario.isOK()) {
JOptionPane.showMessageDialog(this,"恭喜你!成功通關了");
System.exit(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}馬里奧
public class Mario implements Runnable{
//用于表示橫縱坐標
private int x;
private int y;
//用于表示當前的狀態(tài)
private String status;
//用于顯示當前狀態(tài)對應的圖像
private BufferedImage show = null;
//定義一個BackGround對象,用來獲取障礙物的信息
private BackGround backGround = new BackGround();
//用來實現(xiàn)馬里奧的動作
private Thread thread = null;
//馬里奧的移動速度
private int xSpeed;
//馬里奧的跳躍速度
private int ySpeed;
//定義一個索引
private int index;
//表示馬里奧上升的時間
private int upTime = 0;
//用于判斷馬里奧是否走到了城堡的門口
private boolean isOK;
//用于判斷馬里奧是否死亡
private boolean isDeath = false;
//表示分數(shù)
private int score = 0;
public Mario() {
}
public Mario (int x,int y) {
this.x = x;
this.y = y;
show = StaticValue.stand_R;
this.status = "stand--right";
thread = new Thread(this);
thread.start();
}
//馬里奧的死亡方法
public void death() {
isDeath = true;
}
//馬里奧向左移動
public void leftMove() {
//改變速度
xSpeed = -5;
//判斷馬里奧是否碰到旗子
if (backGround.isReach()) {
xSpeed = 0;
}
//判斷馬里奧是否處于空中
if (status.indexOf("jump") != -1) {
status = "jump--left";
}else {
status = "move--left";
}
}
//馬里奧向右移動
public void rightMove() {
xSpeed = 5;
//判斷馬里奧是否碰到旗子
if (backGround.isReach()) {
xSpeed = 0;
}
if (status.indexOf("jump") != -1) {
status = "jump--right";
}else {
status = "move--right";
}
}
//馬里奧向左停止
public void leftStop() {
xSpeed = 0;
if (status.indexOf("jump") != -1) {
status = "jump--left";
}else {
status = "stop--left";
}
}
//馬里奧向右停止
public void rightStop() {
xSpeed = 0;
if (status.indexOf("jump") != -1) {
status = "jump--right";
}else {
status = "stop--right";
}
}
//馬里奧跳躍
public void jump() {
if (status.indexOf("jump") == -1) {
if (status.indexOf("left") != -1) {
status = "jump--left";
}else {
status = "jump--right";
}
ySpeed = -10;
upTime = 7;
}
//判斷馬里奧是否碰到旗子
if (backGround.isReach()) {
ySpeed = 0;
}
}
//馬里奧下落
public void fall() {
if (status.indexOf("left") != -1) {
status = "jump--left";
}else {
status = "jump--right";
}
ySpeed = 10;
}
@Override
public void run() {
while (true) {
//判斷是否處于障礙物上
boolean onObstacle = false;
//判斷是否可以往右走
boolean canRight = true;
//判斷是否可以往左走
boolean canLeft = true;
//判斷馬里奧是否到達旗桿位置
if (backGround.isFlag() && this.x >= 500) {
this.backGround.setReach(true);
//判斷旗子是否下落完成
if (this.backGround.isBase()) {
status = "move--right";
if (x < 690) {
x += 5;
}else {
isOK = true;
}
}else {
if (y < 395) {
xSpeed = 0;
this.y += 5;
status = "jump--right";
}
if (y > 395) {
this.y = 395;
status = "stop--right";
}
}
}else {
//遍歷當前場景里所有的障礙物
for (int i = 0; i < backGround.getObstacleList().size(); i++) {
Obstacle ob = backGround.getObstacleList().get(i);
//判斷馬里奧是否位于障礙物上
if (ob.getY() == this.y + 25 && (ob.getX() > this.x - 30 && ob.getX() < this.x + 25)) {
onObstacle = true;
}
//判斷是否跳起來頂?shù)酱u塊
if ((ob.getY() >= this.y - 30 && ob.getY() <= this.y - 20) && (ob.getX() > this.x - 30 && ob.getX() < this.x + 25)) {
if (ob.getType() == 0) {
backGround.getObstacleList().remove(ob);
score += 1;
}
upTime = 0;
}
//判斷是否可以往右走
if (ob.getX() == this.x + 25 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {
canRight = false;
}
//判斷是否可以往左走
if (ob.getX() == this.x - 30 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {
canLeft = false;
}
}
//判斷馬里奧是否碰到敵人死亡或者踩死蘑菇敵人
for (int i = 0;i < backGround.getEnemyList().size();i++) {
Enemy e = backGround.getEnemyList().get(i);
if (e.getY() == this.y + 20 && (e.getX() - 25 <= this.x && e.getX() + 35 >= this.x)) {
if (e.getType() == 1) {
e.death();
score += 2;
upTime = 3;
ySpeed = -10;
}else if (e.getType() == 2) {
//馬里奧死亡
death();
}
}
if ((e.getX() + 35 > this.x && e.getX() - 25 < this.x) && (e.getY() + 35 > this.y && e.getY() - 20 < this.y)) {
//馬里奧死亡
death();
}
}
//進行馬里奧跳躍的操作
if (onObstacle && upTime == 0) {
if (status.indexOf("left") != -1) {
if (xSpeed != 0) {
status = "move--left";
} else {
status = "stop--left";
}
} else {
if (xSpeed != 0) {
status = "move--right";
} else {
status = "stop--right";
}
}
} else {
if (upTime != 0) {
upTime--;
} else {
fall();
}
y += ySpeed;
}
}
if ((canLeft && xSpeed < 0) || (canRight && xSpeed > 0)) {
x += xSpeed;
//判斷馬里奧是否到了最左邊
if (x < 0) {
x = 0;
}
}
//判斷當前是否是移動狀態(tài)
if (status.contains("move")) {
index = index == 0 ? 1 : 0;
}
//判斷是否向左移動
if ("move--left".equals(status)) {
show = StaticValue.run_L.get(index);
}
//判斷是否向右移動
if ("move--right".equals(status)) {
show = StaticValue.run_R.get(index);
}
//判斷是否向左停止
if ("stop--left".equals(status)) {
show = StaticValue.stand_L;
}
//判斷是否向右停止
if ("stop--right".equals(status)) {
show = StaticValue.stand_R;
}
//判斷是否向左跳躍
if ("jump--left".equals(status)) {
show = StaticValue.jump_L;
}
//判斷是否向右跳躍
if ("jump--right".equals(status)) {
show = StaticValue.jump_R;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public BufferedImage getShow() {
return show;
}
public void setShow(BufferedImage show) {
this.show = show;
}
public void setBackGround(BackGround backGround) {
this.backGround = backGround;
}
public boolean isOK() {
return isOK;
}
public boolean isDeath() {
return isDeath;
}
public int getScore() {
return score;
}
}小怪
public class Enemy implements Runnable{
//存儲當前坐標
private int x;
private int y;
//存儲敵人類型
private int type;
//判斷敵人運動的方向
private boolean face_to = true;
//用于顯示敵人的當前圖像
private BufferedImage show;
//定義一個背景對象
private BackGround bg;
//食人花運動的極限范圍
private int max_up = 0;
private int max_down = 0;
//定義線程對象
private Thread thread = new Thread(this);
//定義當前的圖片的狀態(tài)
private int image_type = 0;
//蘑菇敵人的構(gòu)造函數(shù)
public Enemy(int x,int y,boolean face_to,int type,BackGround bg) {
this.x = x;
this.y = y;
this.face_to = face_to;
this.type = type;
this.bg = bg;
show = StaticValue.mogu.get(0);
thread.start();
}
//食人花敵人的構(gòu)造函數(shù)
public Enemy(int x,int y,boolean face_to,int type,int max_up,int max_down,BackGround bg) {
this.x = x;
this.y = y;
this.face_to = face_to;
this.type = type;
this.max_up = max_up;
this.max_down = max_down;
this.bg = bg;
show = StaticValue.flower.get(0);
thread.start();
}
//死亡方法
public void death() {
show = StaticValue.mogu.get(2);
this.bg.getEnemyList().remove(this);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public BufferedImage getShow() {
return show;
}
public int getType() {
return type;
}
@Override
public void run() {
while (true) {
//判斷是否是蘑菇敵人
if (type == 1) {
if (face_to) {
this.x -= 2;
}else {
this.x += 2;
}
image_type = image_type == 1 ? 0 : 1;
show = StaticValue.mogu.get(image_type);
}
//定義兩個布爾變量
boolean canLeft = true;
boolean canRight = true;
for (int i = 0;i < bg.getObstacleList().size();i++) {
Obstacle ob1 = bg.getObstacleList().get(i);
//判斷是否可以右走
if (ob1.getX() == this.x + 36 && (ob1.getY() + 65 > this.y && ob1.getY() - 35 < this.y)) {
canRight = false;
}
//判斷是否可以左走
if (ob1.getX() == this.x - 36 && (ob1.getY() + 65 > this.y && ob1.getY() - 35 < this.y)) {
canLeft = false;
}
}
if (face_to && !canLeft || this.x == 0) {
face_to = false;
}
else if ((!face_to) && (!canRight) || this.x == 764) {
face_to = true;
}
//判斷是否是食人花敵人
if (type == 2) {
if (face_to) {
this.y -= 2;
}else {
this.y += 2;
}
image_type = image_type == 1 ? 0 : 1;
//食人花是否到達極限位置
if (face_to && (this.y == max_up)) {
face_to = false;
}
if ((!face_to) && (this.y == max_down)) {
face_to = true;
}
show = StaticValue.flower.get(image_type);
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}總結(jié)
通過此次的《超級瑪麗》游戲?qū)崿F(xiàn),讓我對JAVA的相關知識有了進一步的了解,對java這門語言也有了比以前更深刻的認識。
java的一些基本語法,比如數(shù)據(jù)類型、運算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷?,對于這一個概念,終于悟到了一些。
以上就是Java實現(xiàn)經(jīng)典游戲超級瑪麗的示例代碼的詳細內(nèi)容,更多關于Java超級瑪麗游戲的資料請關注腳本之家其它相關文章!
相關文章
使用RabbitMQ實現(xiàn)延時消息自動取消的案例詳解
這篇文章主要介紹了使用RabbitMQ實現(xiàn)延時消息自動取消的簡單案例,案例代碼包括導包的過程和相關配置文件,本文結(jié)合代碼給大家講解的非常詳細,需要的朋友可以參考下2024-03-03
java.net.UnknownHostException異常的一般原因及解決步驟
關于java.net.UnknownHostException大家也許都比較熟悉,這篇文章主要給大家介紹了關于java.net.UnknownHostException異常的一般原因及解決步驟,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-02-02
SpringBoot如何監(jiān)控Redis中某個Key的變化(自定義監(jiān)聽器)
這篇文章主要介紹了SpringBoot如何監(jiān)控Redis中某個Key的變化(自定義監(jiān)聽器),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09

