java的小蜜蜂射击游戏--终于有人把游戏的原理讲清了--【课程设计】

关于毕业设计这个没有总目录,请自行在去毕业设计的这个版块查看
基于jsp的企业员工信息管理系统的设计与实现–【毕业论文】 这里列了一些,其它的请自行查找
在这里插入图片描述
JAVA的有代码可能叫【课程设计】
SSM或JAVAWEB(JSP)的【唐诗300首】
springBoot 的叫【JSB项目实战】
PHP的项目叫【白嫖项目】
其它的有可能叫【课程设计】或【毕业设计】

本系列校训

互相伤害互相卷,玩命学习要你管,天生我才必有用,我命由我不由天!

毕设的技术铺垫

语言选择收录专辑链接卷的程度
C张雪峰推荐选择了计算机专业之后-在大学期间卷起来-【大学生活篇】★★★✫✰
JAVA黑马B站视频JAVA部分的知识范围、学习步骤详解★★★★★
JAVAWEB黑马B站视频JAVAWEB部分的知识范围、学习步骤详解★★★★★
SpringBootSpringBoot知识范围-学习步骤【JSB系列之000】★★★★★
微信小程序详细解析黑马微信小程序视频–【思维导图知识范围】★★★✰✰
python详细解析python视频选择–【思维导图知识范围】★★✫✰✰
phpPHP要怎么学–【思维导图知识范围】★★★✫✰

环境及工具:

本系列环境

环境win11
工具idea 2017/idea 2018
jdk1.8
数据库
maven
项目导入方式打开目录
数据库前端工具

项目说明

这个游戏工作量比较小,也比较粗糙。当做学习还是相当的不错的。当毕业设计就有点拿不出手了。

总体功能

飞机大战主要需要我方飞机和敌方飞机(蜜蜂),还有子弹,特殊nPC,开始背景,结束背景,以及背景音乐。我方飞机可以随意移动,敌方飞机无规律出现。游戏玩家通过鼠标移动控制飞机移动,我方飞机在游戏开始时就一直能发射子弹,当我方子弹碰到敌方飞机时,敌方飞机消失。当玩家飞机碰到敌方子弹时,生命值减一,直到玩家飞机生命值为一时,游戏结束。(未实现,现在的版本玩家飞机无敌)
基于Java的飞机大战游戏的设计与实现有以下几个模块:
(1)游戏状态控制功能模块
(2)游戏难度的调整模块
(3)游戏界面绘画功能模块
(4)玩家游戏控制功能模块
4.2 功能模块设计
4.2.1 游戏状态控制功能模块
游戏的状态控制包括运行及结束游戏,首先进入游戏的开始页面,在游戏进行时,玩家必须躲避或者击落敌方飞机,玩家飞机的生命值降低为0的时候游戏就会结束,弹出游戏结束界面。
4.2.2 游戏难度的调整模块
玩家玩的时间越长游戏的难度越高,敌方飞机的数量越多、敌方飞机出现的频率越高,玩家保证飞机的存活的难度越高,操作难度相应也高。
4.2.3 游戏界面绘画功能模块
左上角会显示玩家飞机当前生命值,游戏时间,当前分数,其他地方用来输出玩家对我方飞机的控制与敌方飞机的动作显示
4.2.4 玩家游戏控制功能模块
玩家可以通过控制鼠标或者键盘来控制方飞机(Hero airplane)的移动。
4.3 游戏难点分析
4.3.1 绘图美化
清新靓丽的游戏界面将给用户带来愉悦的美感。因此,在这个游戏中,主要参考原始的游戏画面,敌我飞机的形象也应该是美丽的。
4.3.2 多线程技术的实现
应用程序线程机制的基石,实现了游戏,游戏的刷架的控制,装上各种角色的资源和背景(如飞机,机友)的要求,以实现整个游戏实现自动控制线程 控制。
4.3.3 防碰撞问题的解决
例如,敌方飞机与玩家飞机防碰撞,敌方飞机与玩家飞机防碰撞,等等。防碰撞检测技术实现在不同情况下,有不同的防碰撞检测方法。
4.3.4 动画的实现
用图片的阵列,动画切片变换形成。图像阵列,千变万化的图像画在画布标,使动画,这是一个图像的形成阵列。使用切片来实现动画,所有的帧都放置在相同的图像中,以达到爆炸的效果。

代码部分

文件编码问题。不太熟悉JAVA的同学请不要随意怀疑本程序运行出错,或不能运行,盲目修改文件
在这里插入图片描述

项目文件目录如下:
在这里插入图片描述

关键核心代码:
应用软件的核心代码是指这个程序最关键部分的代码。例如WinRAR,它的核心代码就是压缩算法部分,而诸如用户界面、操作系统移植等部分就无足轻重了。
商城类的核心代码是指业务层的代码,比如你商城的核心代码就是:商品、购物车、创建订单、支付这些代码就是核心代码。

作为程序员,我们经常需要看懂别人的代码。特别是在开源社区中,我们需要理解许多优秀的开源项目的代码。而在Gitee这样的代码托管平台上,我们如何快速有效地看懂别人的代码呢?本文将为大家介绍一些方法。

1.阅读README和项目介绍

在Gitee上,许多开源项目都会有自己的README文件或项目介绍。这些文件一般会介绍项目的背景、功能、使用方法等内容,可以帮助我们快速了解这个开源项目的基本情况。如果我们能够从这些文件中找到与自己相关的内容,就可以快速入手这个开源项目的代码。

2.了解项目结构和代码组织

在阅读代码之前,我们需要先了解这个开源项目的代码结构和代码组织方式。通常,开源项目会将不同的功能模块封装到不同的代码文件中,并按照一定的目录结构组织起来。如果我们能够了解这个开源项目的代码组织方式,就能更加快速地找到所需的代码。

3.利用IDE和工具

IDE和一些代码阅读工具可以帮助我们更快速、更高效地阅读代码。例如,Java开发者可以使用Eclipse或IntelliJ IDEA这样的IDE,可以快速打开代码文件、查看类、方法和变量等信息。另外,一些代码阅读工具,如Source Insight、CodeCompare等,可以帮助我们更方便地查看代码的结构和关系,以及快速跳转到相关代码。

4.关注代码注释和文档

良好的代码注释和文档可以帮助我们更快速地理解代码。因此,在阅读别人的代码时,我们可以将注意力放在代码注释和文档上。有些开源项目会提供详细的文档,有些则注重代码注释。如果我们能够针对代码注释和文档有一个系统的阅读和理解,就能更快速地掌握别人的代码。

5.跑通测试和运行项目

如果我们想更深入地了解别人的代码,可以试着跑通相关的测试,或者直接运行这个开源项目。通过跑测试和运行项目,我们可以更加直观地了解代码的实现细节和具体的业务逻辑。

总结:

以上就是在Gitee上快速理解他人代码的一些方法,希望对大家有所帮助。当然,阅读代码是一件需要耐心和细心的事情,需要我们多花一点时间和心思。只有沉下心来,慢慢阅读每一行代码,才能真正理解它们的含义和作用。
当然了,本例的代码没有那么多,都是核心代码:)

主面板

//Java RPG 游戏开发中地图的初步构建
//文件:Example1.Java

import java.awt.Container;
import javax.swing.JFrame;

public class MainFrame extends JFrame {
    public MainFrame() {
        // 默认的窗体名称
        setTitle("飞行射击类游戏");
        // 获得我们自定义面板[地图面板]的实例
        GamePanel panel = new GamePanel();
        Container contentPane = getContentPane();
        contentPane.add(panel);
        // 执行并构建窗体设定
        pack();
    }
    public static void main(String[] args) {
        MainFrame e1 = new MainFrame();
        // 设定允许窗体关闭操作
        e1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 显示窗体
        e1.setVisible(true);
    }
}



游戏面板


import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements Runnable, KeyListener {

	/** 屏幕的宽高* */
	private int mScreenWidth = 320;
	private int mScreenHeight = 480;
	/** 游戏主菜单状态* */
	private static final int STATE_GAME = 0;
	/** 游戏状态* */
	private int mState = STATE_GAME;
	/** 游戏背景资源 两张图片进行切换让屏幕滚动起来* */
	private Image mBitMenuBG0 = null;
	private Image mBitMenuBG1 = null;
	/** 记录两张背景图片时时更新的Y坐标* */
	private int mBitposY0 = 0;
	private int mBitposY1 = 0;
	/** 子弹对象的数量* */
	final static int BULLET_POOL_COUNT = 15;
	/** 飞机移动步长* */
	final static int PLAN_STEP = 10;
	/** 没过500毫秒发射一颗子弹* */
	final static int PLAN_TIME = 500;
	/** 敌人对象的数量* */
	final static int ENEMY_POOL_COUNT = 5;
	/** 敌人飞机偏移量* */
	final static int ENEMY_POS_OFF = 65;
	/** 游戏主线程* */
	private Thread mThread = null;
	/** 线程循环标志* */
	private boolean mIsRunning = false;
	/** 飞机在屏幕中的坐标* */
	public int mAirPosX = 0;
	public int mAirPosY = 0;

	/** 敌机对象数组* */
	Enemy mEnemy[] = null;
	/** 子弹对象数组* */
	Bullet mBuilet[] = null;
	/** 初始化发射子弹ID* */
	public int mSendId = 0;
	/** 上一颗子弹发射的时间* */
	public Long mSendTime = 0L;
	Image myPlanePic[];/** 玩家飞机所有图片* */
	public int myPlaneID = 0; /** 玩家飞机当前帧号* */

	/**
	 * 构造方法
	 */
	public GamePanel() {
		setPreferredSize(new Dimension(mScreenWidth, mScreenHeight));
		// 设定焦点在本窗体并付与监听对象
		setFocusable(true);
		addKeyListener(this);
		init();
		setGameState(STATE_GAME);
		/** 启动游戏主线程* */
		mIsRunning = true;
		mThread = new Thread(this);// 实例线程
		mThread.start();
		setVisible(true);

	}

	protected void Draw() {
		switch (mState) {
		case STATE_GAME:
			renderBg();// 绘制游戏界面(包括背景、敌我飞机、子弹)
			updateBg(); // 更新游戏
			break;
		}
	}

	private void init() {
		/** 游戏背景* */
		try {
			mBitMenuBG0 = Toolkit.getDefaultToolkit().getImage(
					"images\\map_0.png");

			mBitMenuBG1 = Toolkit.getDefaultToolkit().getImage(
					"images\\map_1.png");
			// Toolkit.getDefaultToolkit().getImage("pic\\t0.jpg");
			ImageIO.read(new File("images/map_1.png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/** 创建主角飞机动画对象* */
		// mAircraft = new Animation(mContext,new int[]_);
		/** 第一张图片津贴在屏幕00点,第二张图片在第一张图片上方* */
		mBitposY0 = 0;
		mBitposY1 = -mScreenHeight;

		/** 初始化飞机的坐标* */
		mAirPosX = 150;
		mAirPosY = 400;
		myPlanePic = new Image[6];
		for (int i = 0; i < 6; i++)
			myPlanePic[i] = Toolkit.getDefaultToolkit().getImage(
					"images\\plan_" + i + ".png");
		/** 创建敌人对象* */
		mEnemy = new Enemy[ENEMY_POOL_COUNT];

		for (int i = 0; i < ENEMY_POOL_COUNT; i++) {
			mEnemy[i] = new Enemy();
			mEnemy[i].init(i * ENEMY_POS_OFF, i * ENEMY_POS_OFF-300);
		}

		/** 创建子弹类对象* */
		mBuilet = new Bullet[BULLET_POOL_COUNT];
		for (int i = 0; i < BULLET_POOL_COUNT; i++) {
			mBuilet[i] = new Bullet();
		}
		mSendTime = System.currentTimeMillis();
	}

	private void setGameState(int newState) {
		mState = newState;
	}

	public void renderBg() {
		// Graphics g=this.getGraphics();
		myPlaneID++;
		if (myPlaneID == 6)
			myPlaneID = 0;
		repaint();
	}

	public void paint(Graphics g) {
		/** 绘制游戏地图 * */
		// ImageIcon icon=new ImageIcon("C://rear.gif");
		// Image mBitMenuBG0=icon.getImage();
		// g.clearRect(0, 0, mScreenWidth, mScreenHeight);
		g.drawImage(mBitMenuBG0, 0, mBitposY0, this);
		g.drawImage(mBitMenuBG1, 0, mBitposY1, this);
		/** 绘制自己飞机动画* */
		g.drawImage(myPlanePic[myPlaneID], mAirPosX, mAirPosY, this);
		// mAircraft.DrawAnimation(g, mAirPosX, mAirPosY);
		/** 绘制子弹动画 */
		for (int i = 0; i < BULLET_POOL_COUNT; i++)
			mBuilet[i].DrawBullet(g, this);

		/** 绘制敌人动画* */
		for (int i = 0; i < ENEMY_POOL_COUNT; i++) {
			mEnemy[i].DrawEnemy(g, this, i );
		}
	}

	private void updateBg() {
		/** 更新游戏背景图片实现向下滚动效果 * */
		mBitposY0 += 10;
		mBitposY1 += 10;
		if (mBitposY0 == mScreenHeight) {
			mBitposY0 = -mScreenHeight;
		}
		if (mBitposY1 == mScreenHeight) {
			mBitposY1 = -mScreenHeight;
		}

		/** 更新子弹动画 * */
		for (int i = 0; i < BULLET_POOL_COUNT; i++) {
			/** 子弹出屏后重新赋值* */
			mBuilet[i].UpdateBullet();

		}
		/** 绘制敌人动画* */
		for (int i = 0; i < ENEMY_POOL_COUNT; i++) {
			mEnemy[i].UpdateEnemy();
			/** 敌机死亡 或者 敌机超过屏幕还未死亡重置坐标* */
			if (mEnemy[i].mAnimState == Enemy.ENEMY_DEATH_STATE
					&& mEnemy[i].mPlayID == 6
					|| mEnemy[i].m_posY >= mScreenHeight) {
				mEnemy[i].init(UtilRandom(0, ENEMY_POOL_COUNT) * ENEMY_POS_OFF,
						0);
			}

		}

		/** 根据时间初始化为发射的子弹* */
		if (mSendId < BULLET_POOL_COUNT) {
			long now = System.currentTimeMillis();
			if (now - mSendTime >= PLAN_TIME) {
				mBuilet[mSendId].init(mAirPosX-5, mAirPosY-40);
				mSendTime = now;
				mSendId++;
			}
		} else {
			mSendId = 0;
		}

		// 更新子弹与敌人的碰撞
		Collision();

	}

	public void Collision() {
		// 更新子弹与敌人碰撞
		for (int i = 0; i < BULLET_POOL_COUNT; i++) {
			for (int j = 0; j < ENEMY_POOL_COUNT; j++) {
				if (mBuilet[i].m_posX >= mEnemy[j].m_posX
						&& mBuilet[i].m_posX <= mEnemy[j].m_posX + 30
						&& mBuilet[i].m_posY >= mEnemy[j].m_posY
						&& mBuilet[i].m_posY <= mEnemy[j].m_posY + 30

				) {
					mEnemy[j].mAnimState = Enemy.ENEMY_DEATH_STATE;
				}
			}

		}
	}

	/**
	 * 返回一个随机数
	 * 
	 * @param botton
	 * @param top
	 * @return
	 */
	private int UtilRandom(int botton, int top) {
		return ((Math.abs(new Random().nextInt()) % (top - botton)) + botton);
	}

	public void run() {
		while (mIsRunning) {
			/** 绘制 */
			Draw();
			// 延时0.1秒
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	// 在这里检测什么键被按下
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		int key = e.getKeyCode();
		System.out.println(key);
		if (key == KeyEvent.VK_UP)// 假如是向上键被按下
			mAirPosY -= PLAN_STEP;
		if (key == KeyEvent.VK_DOWN)// 假如是向下键被按下
			mAirPosY += PLAN_STEP;
		if (key == KeyEvent.VK_LEFT)// 假如是向左键被按下
		{
			mAirPosX -= PLAN_STEP;
			if (mAirPosX < 0)
				mAirPosX = 0;
		}
		if (key == KeyEvent.VK_RIGHT)// 假如是向右键被按下
		{
			mAirPosX += PLAN_STEP;
			if (mAirPosX > mScreenWidth - 30)
				mAirPosX = mScreenWidth - 30;
		}
		System.out.println(mAirPosX + ":" + mAirPosY);
	}

	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}
	// public static void main(String[] args) {
	// GamePanel frame = new GamePanel();
	// }
	// public void surfaceDestroyed(SurfaceHolder arg0) {
	// // surfaceView销毁的时候
	// mIsRunning = false;
	//	}
}

敌方飞机(蜜蜂)


import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

//敌机类
//2012-7-05
public class Enemy {
    /**敌机存活状态**/
   public static final int ENEMY_ALIVE_STATE = 0;  
    /**敌机死亡状态**/
   public static final int ENEMY_DEATH_STATE = 1;    
    /**敌机行走的Y轴速度**/
    static final int ENEMY_STEP_Y = 5;    
 
    /** 敌机的XY坐标 **/
    public int m_posX = 0;
    public int m_posY = 0;     
    /**敌机状态**/
    public int mAnimState = ENEMY_ALIVE_STATE;  //敌机最初为存活状态
    private Image enemyExplorePic[] = new Image[6]; // 敌机爆炸图片数组
    /** 当前帧的ID **/
    public int mPlayID = 0;
    public Enemy() {
    	for (int i = 0; i < 6; i++) 
    		enemyExplorePic[i] = Toolkit.getDefaultToolkit().getImage(
    					"images\\bomb_enemy_" + i + ".png");
    }
    
    /**初始化坐标**/
    public void init(int x, int y) {
	m_posX = x;
	m_posY = y;
	mAnimState = ENEMY_ALIVE_STATE;
	mPlayID = 0;
    }
    
    /**绘制敌机动画**/
    public void DrawEnemy(Graphics g,JFrame i)
	{
    	Image pic;
		try {
			pic = ImageIO.read(new File("images/e1_1.png"));
			g.drawImage(pic,m_posX,m_posY,(ImageObserver)i);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
					
	}
    public void DrawEnemy(Graphics g,JPanel i)
	{
	    //当敌机状态为死亡并且死亡动画播放完毕 不在绘制敌机
	    if(mAnimState == ENEMY_DEATH_STATE && mPlayID<6) {
	    	g.drawImage(enemyExplorePic[mPlayID],m_posX,m_posY,(ImageObserver)i);
	    	mPlayID++;
	    	return;
	    }
	    //当敌机状态为存活状态
    	Image pic = Toolkit.getDefaultToolkit().getImage("images/e1_2.png");
		g.drawImage(pic,m_posX,m_posY,(ImageObserver)i);					
	}

	public void DrawEnemy(Graphics g,JPanel i, int j)
	{
		//当敌机状态为死亡并且死亡动画播放完毕 不在绘制敌机
		if(mAnimState == ENEMY_DEATH_STATE && mPlayID<6) {
			g.drawImage(enemyExplorePic[mPlayID],m_posX,m_posY,(ImageObserver)i);
			mPlayID++;
			return;
		}

		//当敌机状态为存活状态
		Image pic = Toolkit.getDefaultToolkit().getImage("images/e1_"+j%4+".png");
		g.drawImage(pic,m_posX,m_posY,(ImageObserver)i);
	}
    /**更新敌机状态**/
    public void UpdateEnemy() {
	    m_posY += ENEMY_STEP_Y;
    }
}


子弹

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;
import javax.swing.JPanel;

//子弹类
public class Bullet {
    /**子弹的X轴速度**/
    static final int BULLET_STEP_X = 3;    
    /**子弹的Y轴速度**/
    static final int BULLET_STEP_Y = 15;   
   
    /**子弹图片的宽度**/
    static final int BULLET_WIDTH = 40;
    
    /** 子弹的XY坐标 **/
    public int m_posX = 0;
    public int m_posY = 0;
    
    /**是否更新绘制子弹**/
    boolean mFacus = true;
    private Image pic[] = null; // 子弹图片数组
    /** 当前帧的ID **/
    private int mPlayID = 0;

    public Bullet() {
        pic = new Image[4];
    	for (int i = 0; i < 4; i++) 
    			pic[i] = Toolkit.getDefaultToolkit().getImage(
    					"images\\bullet_" + i + ".png");
    }
    
    /**初始化坐标**/
    public void init(int x, int y) {
	m_posX = x;
	m_posY = y;
	mFacus = true;
    }
    
    /**绘制子弹**/
    public void DrawBullet(Graphics g,JPanel i)
	{
    	g.drawImage(pic[mPlayID++],m_posX,m_posY,(ImageObserver)i);
    	if(mPlayID==4)mPlayID=0;
    }
    /**更新子弹的坐标点**/
    public void UpdateBullet() {
	if (mFacus) {
	    m_posY -= BULLET_STEP_Y;
	}

    }
    
}

这里的一个关键是,本游戏设计的多款小蜜蜂,怎么能让其显示不同的图片呢?
在这里插入图片描述

一个很容易想到的办法就是在绘制飞机的时候,使用不同的图片,这里要注意的是要使用PNG格式哦, 这样背影 才会自然。不然的话,哼哼。
但是,如果这里设计是画飞机,会出现一个问题,同一个飞机,在不同的时间,会来回变来变去。
为什么呢?

帧频

游戏运行时每秒所运行的帧数(简称FPS,Frames Per Second) 和视频一样,FPS越大,在屏幕上的视频就越来越平滑,直到一个临界点(大约是100FPS),超过这个临界点,再高的FPS都只是一个令人惊奇的数值,400FPS和100FPS在人的视觉中几乎没有差别。
人眼分辨编辑 播报
关于“人眼不能分辨超过每秒30帧的画面”,以下是其中的科学根据:
【说法1】是因为人眼的视觉残留特性:是光对视网膜所产生的视觉在光停止作用后,仍保留一段时间的现象,其具体应用是电影的拍摄和放映。原因是由视神经元的反应速度造成的。其时值是二十四分之一秒。是动画、电影等视觉媒体形成和传播的根据。 [2-3]
【说法2】当物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像1/24秒左右的图像,这种现象被称为视觉暂留现象。是人眼具有的一种性质。人眼观看物体时,成像于视网膜上,并由视神经输入人脑,感觉到物体的像。但当物体移去时,视神经对物体的印象不会立即消失,而要延续1/24秒左右的时间,人眼的这种性质被称为“眼睛的视觉暂留”。就是说,无论你游戏帧率有多高,60帧或120帧,最后我们仅仅能分辨其中的30帧而已。

而小游戏的流行就不得不提及adobe的flash 。
网页三剑客,是一套强大的网页编辑工具,最初是由美国的Macromedia公司开发出来的。由Dreamweaver,Fireworks,Flash三个软件组成,俗称网页三剑客。
后来被Adobe 公司收购

2011年底,Flash被Adobe公司合并,最新版本为2013年宣布的:Adobe Flash Creative
Cloud(CC),播放器也更名为Adobe Flash Player。 [1]

Flash–帧的概念
在Flash中,帧 指的就是图片或画面。一帧就是一张图片或一张画面。Flash中时间轴上的小格子都表示帧,它们有待开发者进行开发。

Flash中的帧有两种类型:普通帧和关键帧。

关键帧:用来定义动画中的变化。在任意时候,用户想要改变动画发生改变,必须插入关键帧。关键帧又分为以下两种:

关键帧:有图像的关键帧,用实心小圆点表示。
空白关键帧:无图像的关键帧,用空心小圆点表示。
最后,介绍一下帧速率。帧速率的单位是 fps (frame per second)。表示单位时间内播放的画面或图片的数目。帧速率越大,表示画面播放的速度越快;帧速率越慢,表示画面播放的速度越慢。

也就是说
程序绘制的是每隔一段时间的所有的画面
因为位置连续的变动一点,这样人眼就看上去是动画(游戏)了。
在这里插入图片描述
那么,每一帧的动作是。
先画背景(其实,这是一种懒人的做法,因为大多数是不需要的,但是有的时候,当初学者判断不出来啥时候需要的时候,还不如每次都画)
在这里插入图片描述
然后是每一帧的一个判断,主要是位置,以及状态,比如敌人飞机被“子弹撞击” --击落
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
碰撞的部分如上图。
这里没有优化,使用的是最简的双重循环判断法。判断每一个子弹,与每一个飞机。
如果有想进一步优化的,可以参考有关游戏优化的书籍。基本上都是流行分格法,即不在一个格子里的物体不可能碰撞,这样减少算法复杂度。
这也是现在的游戏,为什么贴图错误的时候,显卡是“某一块的图”错乱,因为后台就是不停的绘制一块一块的。

界面

在这里插入图片描述

总结

其实,这是某学校的学员作品,当然了,是早期的学员的。所以JDK还是用的6.0的版本(我把这部分给重置了),从类名大小写不分,方法名大小写不分,就可以看出不是一个成熟的程序员,开始的时候,我还想把这个“简单的错误” 更正一下,后来我一想,这不就是现在的人与以前的人的心态差别么?以前的学习的人,没有那么正规,但是潜下心写代码。现在的人呢?除了各种网络的BBLL,真心写代码的还能找不到工作?每个人都是springBoot ,甚至springcloud 起步,但是实际的分析能力真的是…也正如2023年的IT现状一样,会springBoot全套,会VUE,工资只有2000左右。而以前的985学校的学生,不会SSM,不会SpringBoot的刚一毕业10K,工作2年的一般都20K左右。当然了,现在的也是一毕业10K左右,不过,现在都会SpringBoot了。差别只是一种是指别人的项目会,一种是指着自己的项目会。
有的时候,真的要思考一下,现在的人取巧 到底是不是巧。

论文参考
基于java的坦克大战游戏的设计与实现–毕业论文–【毕业论文】
https://blog.csdn.net/dearmite/article/details/131962993

配套资源

java的小蜜蜂射击游戏–终于有人把游戏的原理讲清了–【课程设计】

https://download.csdn.net/download/dearmite/88217932

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

项目花园范德彪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值