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

news2024/12/24 17:13:02

一、游戏开发思路:

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*600
        this.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();
    }

    @Override
    public 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);

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public 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=2
            for (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));
                }
            }
            //绘制砖块A
            for (int i = 120; i <=150; i+=30) {
                obstacleList.add(new Obstacle(300,i,7,this));
            }
            //绘制砖块B-F
            for (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));
                }
            }
            //绘制砖块G
            for (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();//启动线程
    }

    //马里奥向左移动
    //马里奥向右移动
    //马里奥向左停止
    //马里奥向右停止

    @Override
    public 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;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2194465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

就业市场需求分析:基于前程无忧岗位数据分析

背景介绍&#xff1a;在前程无忧网站&#xff0c;以"数据分析师""武汉"作为搜索关键词&#xff0c;爬取50页岗位数据合计980条。以该数据为基础&#xff0c;从岗位搜索匹配度、HR活跃度、不同区域/行业/企业的岗位数量和薪资分布等角度进行分析。 1、原始数…

自动驾驶 车道检测实用算法

自动驾驶 | 车道检测实用算法 车道识别是自动驾驶领域的一个重要问题&#xff0c;今天介绍一个利用摄像头图像进行车道识别的实用算法。该算法利用了OpenCV库和Udacity自动驾驶汽车数据库的相关内容。 该算法包含以下步骤&#xff1a; 摄像头校准&#xff0c;以移除镜头畸变&…

百度所有网页都打不开,可能是这个原因

今天笔记本连着手机热点在使用浏览器&#xff0c;突然百度的网页就打不开了&#xff0c;不管是百度一下、百家号、百度汉语、百度经验&#xff0c;只要是百度旗下的网页全都打不开,浏览器直接显示下图这个样子。但是别的网页都能正常打开。 然后我赶紧试了一下ping命令&#xf…

cnn突破五(三层bpnet网络公式)

三层网络反向传播公式推导&#xff1a; X【196】-》HI【80】/HO【80】-》YI【10】/YO【10】&#xff0c;期望是d【10】 X&#xff0c;HI之间用w1【196&#xff0c;80】 HO&#xff0c;YI之间用w2【80,10】 k10;j80;i196 (yo[k]-d[k])*ds(yo[k])*ho[j]; (yo[k]-d[k])*ds(yo[…

推荐一款强大的书签管理工具,让你的网址不在落灰

在信息爆炸的互联网时代&#xff0c;我们每天都会浏览大量的网页&#xff0c;收藏各种各样的网址。然而&#xff0c;随着时间的推移&#xff0c;这些杂乱无章的书签往往让我们感到头疼。别担心&#xff0c;今天我要向你推荐一款强大的书签管理工具&#xff0c;它将帮助你轻松整…

训练验证器解决数学应用题

人工智能咨询培训老师叶梓 转载标明出处 数学问题解决不仅要求模型能够理解问题的语言表述&#xff0c;还要求其能够准确地执行一系列数学运算&#xff0c;每一步的准确性都至关重要。遗憾的是&#xff0c;现有的语言模型在这一领域的性能远远未能达到人类的水平&#xff0c;它…

小绿书开启副业模式(保姆级教程)

大家好&#xff0c;我是凡人。 是一个不黑、不吹、不跟风、有知识、有骨气的五好小号主。 好多小伙伴给我私信&#xff0c;问我有最近没有非常火爆的副业项目&#xff0c;现在很多赛道人满为患&#xff0c;有没有值得推荐的&#xff0c;别说还真有&#xff0c;可能大家都没注…

理解Spring中静态代理

参考https://blog.csdn.net/weixin_43005654/article/details/109317773 无论是静态代理还是动态代理&#xff0c;都有四大角色&#xff1a; 抽象角色&#xff1a;一般会使用接口或者抽象类来解决真实角色&#xff1a;被代理的角色代理角色&#xff1a;代理真实角色&#xff0…

ultralytics yolo pose 示例:加载官方pose模型进行推理

Ultralytics YOLO 是计算机视觉和 ML 领域专业人士的高效工具。 安装 ultralytics 库&#xff1a; pip install ultralytics 官方YoLo Pose 模型列表信息&#xff1a; 实现代码如下&#xff1a; from ultralytics import YOLO import cv2 # Load a model ckpt_dir "…

基于PHP的校园二手书交易管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的校园二手书交易管理系统 一 介绍 此二手书交易管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注…

3. BBP系列运动控制板(飞控板)简介

3.1. 概述 Bread Board Pilot(简称BBP) 是在积累了前期 Single Pilot 及 PH7 飞控板大量设计及使用经验的基础上&#xff0c;全新基于PH47代码框架开发的高灵活性&#xff0c; 高性能&#xff0c; 超低成本的最新一代飞控板设计。 目前&#xff0c;因为其使用便捷灵活&#xf…

D30【python 接口自动化学习】- python基础之输入输出与文件操作

day30 F-strings输出 学习日期&#xff1a;20241007 学习目标&#xff1a;输入输出与文件操作&#xfe63;-42 F-strings-如何通过定义好的格式进行输出&#xff1f; 学习笔记&#xff1a; F-strings 介绍 F-strings 的计算功能 F-strings 宽度和精度调整 练习 # 宽度为10个…

【计算机网络 - 基础问题】每日 3 题(二十九)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

platformio.ini工程配置文件入门

主要参考资料&#xff1a; “platformio.ini” (Project Configuration File): https://docs.platformio.org/en/latest/projectconf/index.html 目录 简介语法[platformio]: PlatformIO配置选项[env]:配置环境 简介 .ini是一个配置文件&#xff0c;它可以设置开发环境&#x…

4.循环结构在存储过程中的应用(4/10)

引言 在数据库管理中&#xff0c;存储过程是一种强大的工具&#xff0c;它允许将一组SQL语句封装为一个独立的、可重用的单元。存储过程不仅可以提高数据处理的效率&#xff0c;还可以增强代码的安全性和可维护性。在复杂的数据库操作中&#xff0c;循环结构扮演着至关重要的角…

面试系列-淘天提前批面试

00-淘天提前批面试 在牛客上看到了淘天提前批的面试题目&#xff0c;这里分析一下淘天面试的问了有哪些内容&#xff0c;面试的重点 是偏向哪些方面 项目相关 1、秒杀架构如何设计&#xff1f; 问了秒杀的架构如何设计&#xff0c;对于秒杀的设计&#xff0c;秒杀符合 写多读少…

【cpp/c++ summary 工具】Visual Studio 2022 安装与cmake项目配置

Visual Studio 2022安装 https://visualstudio.microsoft.com/zh-hans/free-developer-offers/下载后选择c桌面开发安装即可&#xff1a; Visual Studio 2022创建cmake项目 Visual Studio 2022打开cmake项目 点击打开带有cmakelists.txt的项目文件夹 配置缓存&#xff1a;点…

【操作系统考研】2进程管理(1)

在翻看操作系统知识框架的时候&#xff0c;对一些概念的理解还比较模糊&#xff0c;现在我来理清他们的关系。 操作系统、处理器、进程、线程、内存、存储器、设备、文件的关系 咱们可以把计算机系统想象成一个大工厂&#xff0c;来理解这些概念之间的关系。 操作系统&#xf…

小目标检测利器:YOLOv8+SAHI使用教程

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

软考系统分析师知识点三:应用数学

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;34天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…