当前位置: 首页 > news >正文

项目——超级马里奥——Day(3)

一、游戏开发思路:

1.Frame--->BackGround--->Obstacle---->BufferedImage,人物等

2.BackGround的构造函数:

只要记住窗口里边的每一个场景,只要游戏一开始就已经出现在屏幕里边的,都是在构造函数里边

3.绘制上地面:

上地面要铺满整个第一关背景图片,由于BackGround的宽度为800,一个上地面的图片的宽度为30,所以要进行27次循环才能把BackGround的宽度铺满 

4.Obstacle类:

要有坐标,以及当前是什么障碍物类型,图片的显示以及当前的场景对象(用于关联每一关的不同的障碍物对象)

    //用于表示当前的坐标private int x;private int y;//用于记录障碍物类型private int type;    //type1 是上地面  type2是下地面//用于显示图像  !!!!private BufferedImage show =null;//定义当前的场景对象  !!!private BackGround bg =null;

5.把Obstacle类加载到BackGround里边,由于每一关都有不一样的障碍物,所以BackGround是和Obstacle相关联的,在BackGround类里边设置一个存放障碍物的集合,把我们原先已经定义好的Obstacle对象放到这个集合中去

6.马里奥类

用来获取障碍物的信息那个很重要!!!!

    //用于表示横纵坐标private int x;private int y;//用于表示当前的状态private String status;//用于显示当前状态对应的图像private BufferedImage show=null;//定义一个BackGround对象,用来获取障碍物的信息!!!private BackGround background=new BackGround();//用于实现马里奥的动作private Thread thread=null;

二、游戏场景设计示例图:

第一个场景:

分析图片:

我们以结果为导向,以项目要求为导向,分析出整个项目的要求来进行游戏制作 

以左上角为(0,0)起点

1.上地面
1)位置     

距离天空最上面的是420cm,只有一排上地面

2.下地面
1)位置  

使用双重for循环来控制位置,外层循环控制第几列,内层循环控制生成一排的地面

一共有五层下地面---泥土,每一排循环完之后,还要再循环生成四排

3.水管
1)位置

最上边的3和4是特殊的两个水管图片,所以在for循环里边应该用if条件判断来单独画这两个的水管图片的位置----->怎么单独控制?找他俩的共同点:纵坐标都是360 

4.砖块
1)位置

说明:这里的砖块的纵坐标有一点问题,应该是

G的纵坐标是 240

A这一排的纵坐标是300

2)是否可被破坏

其中:

B、D、F是可被破坏的  ------> 对应type是0

不可被破坏的砖块  ------> 对应type是7

第二个场景:

第三个场景:

 其他两关的设置是类似的,这里先不再赘述了,以后有时间再讲后两关的设计

三、马里奥人物设计:

1.创建马里奥的类对象:

1.关于马里奥自身的一些属性:
1)  位置坐标

马里奥的X,Y坐标

2)状态

表示马里奥当前是站立还是跳跃还是死亡

3)状态图片

用于以后在MyFrame里边画出来,画的图像就是马里奥类里边定义的这个图象

2.涉及到马里奥日后行为可能会涉及到的:
4)一个BackGround对象,用于获取障碍物的信息

由于马里奥以后会撞碎可以撞碎的砖块,也可以踩死怪物,或者被怪物杀死,或者被食人花杀死,所以要定义一个障碍物的对象

5)一个线程用于实现马里奥的动作

以后在这个游戏中会有同时怪物在动,马里奥在移动,食人花在不停的进出,这些都属于是线程,也就是说一个游戏里边同时有这几个移动的东西,这些都需要用程序来控制他们

2.把马里奥画在窗口里边

只需要在窗口里边用graphics调用drawImage方法即可

但是由于我们把mario里边的坐标等变量属性设置成了private,所以由于访问修饰符的限制,private修饰的变量,只允许在这个类里边访问,那么我们怎么获取它的属性值呢?

可以在类里边实现x,y, show的getter和setter方法

而为什么要把变量设置为private,这就涉及到我们上次讲的javabean封装,确保数据的安全性,不会随便被别人修改

四、支撑知识点:

1.自加运算符

比如a+=1

就相当于a=a+1

2.增强for循环

1)用途:用来遍历集合、数组

2)分类:

        遍历集合

    for(集合元素的类型  局部变量  :  集合对象)
            内部代码仍然调用迭代器


    for(Object obj : coll){
        System.out.println(obj);
    }
 

          遍历数组 

    for(数组元素的类型  局部变量  :  数组对象)
    for (int i : arr){
        System.out.println(i);
    } 

3.多线程(重点和难点)

但这里只简单学一下,毕竟将给新生听的,等到时候我出一个面经背诵和学习专栏就可能要研究深入一点了!!

深入学习多线程可参考:多线程(看这一篇就够了,超详细,满满的干货)_线程csdn-CSDN博客

简单来讲就是一个程序同时做多件事情

五、代码展示:

1.目前的MyFrame类代码:

package com.View;import com.Constants.StaticValue;
import com.game.Mario;
import com.game.Obstacle;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;public class MyFrame extends JFrame implements KeyListener {//为什么要存储场景   TODO惹??//BackGround类的list,里边全部是background类,不是buffered图片,要区别开来//用于存储  所有的背景private List<BackGround> allBg =new ArrayList<>();//用于存储  当前的背景private BackGround nowBg =new BackGround();//用于双缓存//定义一个变量用于双缓存       TODO????????private Image offScreenImage =null;//马里奥对象private Mario mario = new Mario();//无参构造public MyFrame() {//设置窗口的大小为800*600this.setSize(800,600);//设置窗口的居中显示this.setLocationRelativeTo(null);//设置窗口的可见性this.setVisible(true);//设置点击窗口上的关闭键,结束程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口大小不可变this.setResizable(false);//向窗口对象添加键盘监听器this.addKeyListener(this);//设置窗口名称this.setTitle("超级玛丽");//初始化图片StaticValue.init();//初始化马里奥mario =new Mario(10,395);//创建全部的场景for(int i=1;i<=3;i++){allBg.add(new BackGround(i, i==3? true:false));}//将第一个场景设置为当前的场景nowBg =allBg.get(0);//绘制图像   进行图像的绘制repaint();}@Overridepublic void paint(Graphics g) {if(offScreenImage ==null){offScreenImage =createImage(800,600);}Graphics graphics = offScreenImage.getGraphics();graphics.fillRect(0,0,800,600);//fillRect 用于在指定的矩形内绘制一个填充的矩形//绘制背景   将图像绘制到了缓冲区上graphics.drawImage(nowBg.getBgImage(), 0,0,this);//绘制障碍物for(Obstacle ob : nowBg.getObstacleList()){graphics.drawImage(ob.getShow(),ob.getX(),ob.getY(),this);}//绘制马里奥graphics.drawImage(mario.getShow(),mario.getX(),mario.getY(),this);       //注意马里奥绘制要在g.drawImage之前//将缓冲区的图片绘制到窗口中g.drawImage(offScreenImage,0,0,this);}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {}public static void main(String[] args) {new MyFrame();}
}

2.BackGround类

package com.View;import com.Constants.StaticValue;
import com.game.Obstacle;import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;//加载图片常量之后方便日后的使用
public class BackGround {//当前场景要显示的图片private BufferedImage bgImage =null;//记录当前是第几个场景   玩到了第几关private int sort;//判断是否是最后一个场景private boolean flag;//空参构造//用于存放我们所有的障碍物private List<Obstacle> obstacleList =new ArrayList<>();public BackGround() {}public BufferedImage getBgImage() {return bgImage;}public int getSort() {return sort;}public boolean isFlag() {return flag;}public BackGround(int sort, boolean flag) {this.sort = sort;this.flag = flag;if(flag) {   //表示此时为最后一个场景bgImage = StaticValue.bg2;}else{bgImage = StaticValue.bg;}//只要记住窗口里边的每一个场景,只要游戏一开始就已经出现在屏幕里边的,都是在构造函数里边//判断是否是第一关if(sort==1){//绘制第一关的地面,上地面type=1,下地面type=2for (int i = 0; i <= 26; i++) {obstacleList.add(new Obstacle(420,i*30,1,this));}for (int i = 1; i <=5; i++) {for(int j = 0; j <= 26; j++){obstacleList.add(new Obstacle(420+i*30,j*30,2,this));}}//绘制砖块Afor (int i = 120; i <=150; i+=30) {obstacleList.add(new Obstacle(300,i,7,this));}//绘制砖块B-Ffor (int i = 300; i <=570; i+=30) {   //0是普通砖块   7是不能被破坏的砖块if(i==360||i==390||i==480||i==510||i==540){obstacleList.add(new Obstacle(300,i,7,this));}else{obstacleList.add(new Obstacle(300,i,0,this));}}//绘制砖块Gfor (int i = 420; i <=450 ; i+=30) {obstacleList.add(new Obstacle(240,i,7,this));}//绘制水管for (int i = 360; i <=600 ; i+=25) {if(i==360){  //纵坐标为360.最高的两个水管图片obstacleList.add(new Obstacle(i,620,3,this));obstacleList.add(new Obstacle(i,645,4,this));}else{obstacleList.add(new Obstacle(i,620,5,this));obstacleList.add(new Obstacle(i,645,6,this));}}}}public List<Obstacle> getObstacleList() {return obstacleList;}
}

3.马里奥类

package com.game;import com.Constants.StaticValue;
import com.View.BackGround;import java.awt.image.BufferedImage;public class Mario implements Runnable{//用于表示横纵坐标private int x;private int y;//用于表示当前的状态private String status;//用于显示当前状态对应的图像private BufferedImage show=null;//定义一个BackGround对象,用来获取障碍物的信息!!!private BackGround background=new BackGround();//用于实现马里奥的动作private Thread thread=null;//马里奥的移动速度//马里奥的跳跃速度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();//启动线程}//马里奥向左移动//马里奥向右移动//马里奥向左停止//马里奥向右停止@Overridepublic void run() {}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;}
}

4.障碍物类

package com.game;import com.Constants.StaticValue;
import com.View.BackGround;import java.awt.image.BufferedImage;public class Obstacle {//用于表示当前的坐标private int x;private int y;//用于记录障碍物类型private int type;    //type1 是上地面  type2是下地面//用于显示图像  !!!!private BufferedImage show =null;//定义当前的场景对象  !!!private BackGround bg =null;public Obstacle(int y, int x, int type, BackGround bg) {this.y = y;this.x = x;this.type = type;this.bg = bg;show = StaticValue.obstacle.get(type);   //得到当前的障碍物类型,在StaticValue第三十行左右}public int getX() {return x;}public int getY() {return y;}public int getType() {return type;}public BufferedImage getShow() {return show;}
}

相关文章:

项目——超级马里奥——Day(3)

一、游戏开发思路&#xff1a; 1.Frame--->BackGround--->Obstacle---->BufferedImage&#xff0c;人物等 2.BackGround的构造函数&#xff1a; 只要记住窗口里边的每一个场景&#xff0c;只要游戏一开始就已经出现在屏幕里边的&#xff0c;都是在构造函数里边 3.绘…...

测试-BUG篇

文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办&#xff08;高频考题&#xff09; 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 BUG bug的概念 是指计算机程序中存在的一个错误(error)、缺陷(flaw)、疏忽(mista…...

vue2中 vue-count-to组件让数字从某个数字动态的显示到某个数字(后附vue3的用法)

1、首先安装 npm install vue-count-to2、使用 2.1、先导入组件 import countTo from ‘vue-count-to’2.2、注册组件 components: { countTo },2.3、使用组件 <countTo> <template><div class"home"><countTo class"count-to&qu…...

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…...

在线生成论文的网站有哪些?分享5款AI一键原创论文免费网站

一、千笔-AIPasspaper 千笔-AIPasspaper是一款备受推荐的AI写作助手&#xff0c;它集成了多种功能&#xff0c;包括论文大纲生成、内容填充、文献引用和查重修改等。这款工具基于最新的自然语言处理技术&#xff0c;能够帮助用户快速生成高质量的论文内容。 AI论文&#xff0…...

考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)

考研论坛平台小程序 目录 基于java和微信小程序的考研论坛平台小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂…...

Pandas 时间序列处理

Pandas 时间序列处理 说明&#xff1a; 请回答以下问题&#xff0c;以展示您对 pandas 中时间序列处理的全面理解。请在适用时提供代码示例。 问题 1 如何将日期字符串列表 [2023-01-01, 2023-01-02, 2023-01-03] 转换为 pandas 的 DatetimeIndex&#xff1f; 问题 2 给定一…...

PCL 1.8.1 + VTK 1.8.0 + QT5.14.2+ VS2017 环境搭建

先看看效果: PCL 1.8.1下载安装: Tags PointCloudLibrary/pcl GitHub 安装完成后: 如果VTK想重新编译的,可以看我的这篇博客:...

微信小程序和抖音小程序的分享和广告接入代码

开发完成小程序或者小游戏之后&#xff0c;我们为什么要接入分享和广告视频功能&#xff0c;主要原因有以下几个方面。 微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因&#xff1a; 用户获取与增长&#xff1a;分享功能可以帮助用户将小程序内容传播给更多人&…...

中断系统的原理

一、介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的。中断是指‌CPU在正常运行程序时&#xff0c;由于内部或外部事件的发生&#xff0c;导致CPU中断当前运行的程序&#xff0c;转而去执行其他程序的过程。‌ 中断可以是硬件产生的&#xff0c;也可以是…...

安装Rust

Rust 是一种系统级编程语言&#xff0c;旨在提供高性能和内存安全&#xff0c;同时避免常见的编程错误。 由 Mozilla Research 推出&#xff0c;Rust 自推出以来因其独特的设计理念和强大的功能而在开发者社区中迅速获得了广泛的关注和采用。 curl --proto ‘https’ --tlsv1.2…...

vite学习教程05、vite+vue2构建本地 SVG 图标

文章目录 前言一、构建本地SVG图标详细步骤1、安装开发依赖2、配置vite2.1、配置vite.config.js2.2、封装vite引入插件脚本 解决报错&#xff1a;can not find package fast-glob imported 二、实际应用应用1&#xff1a;未封装&#xff0c;直接vue应用应用2&#xff1a;封装vu…...

机器学习——自监督学习与无监督学习

# 机器学习中的自监督学习与无监督学习 在机器学习的世界中&#xff0c;监督学习、无监督学习和自监督学习都是重要的学习方法。本文将聚焦于自监督学习与无监督学习&#xff0c;探讨它们的原理、应用场景以及技术细节&#xff0c;并通过大量代码示例来揭示这些方法的内在工作…...

2003经典绝版100%仿盛大服务端火炬引擎原版

;中国游戏制作 本版本为中国游戏制作小组推出的第一个版本&#xff0c;有什么不完美的地方还请大家多多指教&#xff01;&#xff01;&#xff01; 与盛大逼真&#xff01;&#xff01;&#xff01; 本版本M2Server采用“梦幻风”以及“冰眼”M2Server修改器修改的 2004/1/…...

银河麒麟服务器:更新软件源

银河麒麟服务器&#xff1a;更新软件源 1、使用场景2、操作步骤3、注意事项 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 1、使用场景 当需要安装最新软件或修改软件源配置后&#xff0c;需更新软件源以获取最新软件包信息。 2、操作步…...

字节跳动收购Oladance耳机:强化音频技术,加速VR/AR生态布局

字节跳动收购Oladance耳机&#xff1a;加码VR/AR领域布局 近日&#xff0c;字节跳动宣布已完成对开放式耳机品牌Oladance的收购&#xff0c;实现了对该品牌的100%控股。这一收购标志着字节跳动在AI硬件领域的进一步扩展和深化&#xff0c;特别是对其VR/AR领域布局的重要加码。 …...

Android SystemUI组件(11)SystemUIVisibility解读

该系列文章总纲链接&#xff1a;专题分纲目录 Android SystemUI组件 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节持续迭代之前章节思维导图&#xff0c;主要关注左侧最上方SystemUiVisibility解读部分即可。 本章节主要讲解SystemUiVisibility的概念及其相…...

JSON 全知全解:深入探索 JSON 的奥秘

目录 一、JSON 基础认知&#xff08;一&#xff09;JSON 的定义与历史&#xff08;二&#xff09;JSON 的语法规则&#xff08;三&#xff09;JSON 与 JS 对象的关系 二、JSON 在不同语言中的用法&#xff08;一&#xff09;JavaScript 中的 JSON 操作&#xff08;二&#xff0…...

CSS | 响应式布局之媒体查询(media-query)详解

media type(媒体类型)是CSS 2中的一个非常有用的属性&#xff0c;通过media type我们可以对不同的设备指定特定的样式&#xff0c;从而实现更丰富的界面。media query(媒体查询)是对media type的一种增强&#xff0c;是CSS 3的重要内容之一。随着移动互联网的发展&#xff0c;m…...

并查集的模拟实现

简化版本 class UnionFindSet { public:UnionFindSet(size_t n):_ufs(n, -1){}void Union(int x1, int x2){int root1 FindRoot(x1);int root2 FindRoot(x2);// 如果本身就在一个集合就没必要合并了if (root1 root2)return;// 控制数据量小的往大的集合合并if (abs(_ufs[roo…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...