项目——超级马里奥——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)
一、游戏开发思路: 1.Frame--->BackGround--->Obstacle---->BufferedImage,人物等 2.BackGround的构造函数: 只要记住窗口里边的每一个场景,只要游戏一开始就已经出现在屏幕里边的,都是在构造函数里边 3.绘…...

测试-BUG篇
文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办(高频考题) 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 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部署这个词儿大家肯定不陌生,可能有些小伙伴还不是很清楚这个是干嘛的,但总归是耳熟能详了。 近些年来,在深度学习算法已经足够卷卷卷之后,深度学习的另一个偏向于工程的方向–部署工业落地,才开始被谈论的多了起来…...

在线生成论文的网站有哪些?分享5款AI一键原创论文免费网站
一、千笔-AIPasspaper 千笔-AIPasspaper是一款备受推荐的AI写作助手,它集成了多种功能,包括论文大纲生成、内容填充、文献引用和查重修改等。这款工具基于最新的自然语言处理技术,能够帮助用户快速生成高质量的论文内容。 AI论文࿰…...

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

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

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

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

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

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

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

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

2003经典绝版100%仿盛大服务端火炬引擎原版
;中国游戏制作 本版本为中国游戏制作小组推出的第一个版本,有什么不完美的地方还请大家多多指教!!! 与盛大逼真!!! 本版本M2Server采用“梦幻风”以及“冰眼”M2Server修改器修改的 2004/1/…...

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

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

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

JSON 全知全解:深入探索 JSON 的奥秘
目录 一、JSON 基础认知(一)JSON 的定义与历史(二)JSON 的语法规则(三)JSON 与 JS 对象的关系 二、JSON 在不同语言中的用法(一)JavaScript 中的 JSON 操作(二࿰…...

CSS | 响应式布局之媒体查询(media-query)详解
media type(媒体类型)是CSS 2中的一个非常有用的属性,通过media type我们可以对不同的设备指定特定的样式,从而实现更丰富的界面。media query(媒体查询)是对media type的一种增强,是CSS 3的重要内容之一。随着移动互联网的发展,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…...

如何高效删除 MySQL 日志表中的历史数据?实战指南
在处理高并发的物联网平台或者其他日志密集型应用时,数据库中的日志表往往会迅速增长,数据量庞大到数百GB甚至更高,严重影响数据库性能。如何有效管理这些庞大的日志数据,特别是在不影响在线业务的情况下,成为了一项技…...

请散户股民看过来,密切关注两件大事
明天股市要开市,不仅散户股民期盼节后股市大涨,上面也同样想在节后来上一个“开门红”。 为此,上面没休假,关起门来办了两件大事,这两天发布消息已提前预热了。 两件大事如下: 一是,上交所10…...

设计模式之外观模式(Facade)
一、外观模式介绍 外观模式( Facade Pattern),也叫门面模式,是一个 “结构型” 设计模式。 外观模式的原始定义是:为子系统中的一组接口提供统一的接口。它定义了一个更高级别 的接口,使子系统更易于使用。 外观模式,是…...

解锁 Python 嵌套字典的奥秘:高效操作与实战应用指南
文章目录 前言🍀一、 什么是 Python 字典?1.1 字典的语法 🍀二、 字典的基本操作2.1 字典的创建2.2 访问字典中的值2.3 添加或修改键值对2.4 删除字典中的键值对 🍀三、 字典的遍历操作3.1 遍历字典的键3.2 遍历字典的值3.3 同时遍…...

联想服务器配置阵列、安装操作系统
文章目录 [toc]1.配置阵列2.制作启动盘3.安装系统 1.配置阵列 1.根据提示进入BIOS设置(F1) 2.系统设置 3.存储 4.第四步可以看到raid卡信息 5.Main Menu 6.Configuration Management 7.Create Virtual Drive 8.Select RAID Level raid5 9.Select Drives…...

【深度强化学习】DDPG实现的4个细节(OUNoise等)
文章目录 前言一、论文内容简述创新点(特点,与DQN的区别):可借鉴参数:细节补充: 二、细节1:weight_decay原理代码 三、细节2:OUNoise原理代码 四、细节3:ObsNorm原理代码…...

算法工程师重生之第二十二天(递增子序列 全排列 全排列 II 重新安排行程 N皇后 解数独 总结 )
参考文献 代码随想录 一、非递减子序列 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素,如出现两个整数相等,也可以视作…...

css的选择器及优先级
一、css选择器 CSS选择器是用来选择HTML文档中的元素,并为它们应用样式规则的工具。CSS选择器有很多种,可以根据元素的类名、ID、属性、伪类、伪元素、标签等来选择元素。以下是一些常见的CSS选择器及其用法: 1. ID选择器: 根据…...

JavaScript中的数组不改变原数组的方法
数组 var a [1, 2, 3, 5, 8, 13, 21] 不改变原数组的方法 length 数组元素的长度 继承自原型 concat(arrayX,arrayY) 合并两个或多个数组,返回新数组 合并,a.concat(b) var a[1,2,3],b[4,5,6],c[7,8,9]; a.concat(b,c); //[1, 2, 3, 4, 5, 6, 7…...

Go语言实现长连接并发框架 - 路由分组
文章目录 前言接口结构体接口实现项目地址最后 前言 你好,我是醉墨居士,我们上篇博客实现了任务执行流的路由模块,接下来我们实现一下对任务执行流进行任务 接口 trait/router_group.go type RouterGroup interface {RouterGroup(flow ..…...