java游戏第六天——总结

news/2024/10/27 23:19:46/

开始

我们先在这里创建五个java文件,后面创建一个文件夹存储图片,我就按照这几个文件作用展开描述

bg.java

package common;
import common.game_pic;import java.awt.Color;
import java.awt.Graphics;
public class bg {public void paintself(Graphics g){g.drawImage(game_pic.bgimgage, 0,0 ,1440,900,null);switch (newgame.state) {case 0: {game_pic.drawworld(g, "开始", Color.red, 80	, 500, 600);
//		System.out.println("");}case 1:{game_pic.drawworld(g, "积分"+game_pic.score,Color.orange, 50	, 300, 120);game_pic.drawworld(g, "难度"+game_pic.level, Color.red, 50	, 600, 120);game_pic.drawworld(g, "等级"+myfish.level, Color.red, 50	, 100, 120);}}
}
}

代码解释

先看看这些包

import java.awt.Color;

import java.awt.Graphics;,这两个是图像类

在bg.java中我们主要是实现一开始的背景加载功能,而又在类中创建一个paintself方法,这是为后面加载图像提供简便的实现。我们可以看到实现的是

public void paintself(Graphics g)

g.drawImage(game_pic.bgimgage, 0,0 ,1440,900,null);

switch (newgame.state) {

case 0: {

game_pic.drawworld(g, "开始", Color.red, 80 , 500, 600);

// System.out.println("");

}

case 1:{

game_pic.drawworld(g, "积分"+game_pic.score,Color.orange, 50 , 300, 120);

game_pic.drawworld(g, "难度"+game_pic.level, Color.red, 50 , 600, 120);

game_pic.drawworld(g, "等级"+myfish.level, Color.red, 50 , 100, 120);

这里传入的是Graphics g,这个是绘制图像的,一开始的时候加载我们的背景图像

然后呢在switch (newgame.state)来判断newgame.state,就是游戏现在的状态,一般游戏的时候前面都是有开始的画面

game_pic.drawworld(g, "开始", Color.red, 80 , 500, 600);

然后又安装一个公共的方法,这个主要是为了便于绘制文字

case 1:{

game_pic.drawworld(g, "积分"+game_pic.score,Color.orange, 50 , 300, 120);

game_pic.drawworld(g, "难度"+game_pic.level, Color.red, 50 , 600, 120);

game_pic.drawworld(g, "等级"+myfish.level, Color.red, 50 , 100, 120);

}

game_pic.java

package common;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;public class game_pic {//分数统计static int score=0;//敌方鱼类集合public static List<fish> enny_l=new ArrayList<fish>();//List<ennamy_l>: 这指定了变量的类型。List 是一个接口,它提供了操作对象集合(特别是序列)的方法。尖括//号 <> 中的 ennamy_l 是一个泛型参数,它告诉编译器这个列表只能包含 ennamy_l 类型的对象。//背景图类public static Image bgimgage=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\sea.png");//敌方鱼类public static Image dirmgage1=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fish_l.png");public static Image dirmgager=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fish_r.png");public static Image myfish_l=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fissl.gif");public static Image myfish_r=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fissr.gif");public static Image ffdir=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fish3.png");public static Image ffdil=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\fiss3.png");public static Image bossImage=Toolkit.getDefaultToolkit().createImage("D:\\programing\\javaide\\new_game\\src\\picture\\boss.png");static boolean up=false;static boolean down=false;static boolean left=false;static boolean right=false;//关卡等级设置,到了积分就设置不同的关卡难度static int level=0;//绘制文字的工具类public static void drawworld (Graphics g,String str,Color color,int size,int x,int y) {g.setColor(color);g.setFont(new Font("仿宋", Font.BOLD,60));g.drawString(str,x,y);}
} 	
/*在Java中,这段代码是创建并初始化一个静态`Image`对象的实例。这个对象`bgimage`被设置为使用`Toolkit`类加载并创建的一个图像。下面是对代码的逐行解释:
- `public static Image bgimage`: 这是在一个类中声明一个名为`bgimage`的公共静态变量,它的类型是`Image`。`Image`是AWT(Abstract Window Toolkit)包中的一个类,用于表示图像数据。
- `Toolkit.getDefaultToolkit()`: `Toolkit`类是一个抽象类,它提供了一种抽象的方式来处理本地图形和用户输入。`getDefaultToolkit()`是一个静态方法,它返回当前平台默认的工具包实例。
- `.createImage('image/sea.png')`: `createImage`是`Toolkit`类的一个方法,用于创建一个图像。它接受一个图像文件的路径作为参数。在这个例子中,路径是`'image/sea.png'`,这意味着它试图加载当前工作目录下`image`文件夹中的`sea.png`文件。
所以,整行代码的意思是:
声明一个名为`bgimage`的静态`Image`变量,并将其初始化为通过默认工具包加载的位于`image`文件夹中的`sea.png`文件。
不过,这段代码有几个潜在的问题:
1. 单引号`'`通常用于字符字面量。在Java中,字符串应该使用双引号`"`。因此,正确的路径应该是`"image/sea.png"`。
2. `createImage`方法可能不会立即加载图像,它可能返回一个异步加载的图像。因此,在使用图像之前,你可能需要确保图像已经完全加载。
3. 如果`sea.png`文件不存在或者路径不正确,`createImage`方法将返回一个不包含任何图像数据的`Image`对象。
正确的代码应该是:
```java
public static Image bgimage = Toolkit.getDefaultToolkit().createImage("image/sea.png");
```
在使用`bgimage`之前,你可能还需要确保图像已经加载完毕。这可以通过实现`ImageObserver`接口或使用`MediaTracker`类来实现。
*/

在这个java中主要实现的对于一些公共属性的封装

bgimgage=          
dirmgage1=
dirmgager=
   myfish_l=T
myfish_r=T
ffdir=Tool
ffdil=Tool
bossImage,对这些图片加载显现

up=fa
down=
left=
right这是对上下左右的实现逻辑

public static void drawworld (Graphics g,String str,Color color,int size,int x,int y) {

g.setColor(color);

g.setFont(new Font("仿宋", Font.BOLD,60));

g.drawString(str,x,y);

}

}这个是封装了g.drawString方法,不然的话每次都要写几遍

fish.java

package common;
import java.awt.*;
import common.game_pic;
public class fish {//定义图片Image img;//定义坐标int x;int y;int width;int height;//移动速度int speed;//方向定义int dir=1;//类型int type;//分值int count;//距离,用于检测自身//距离,用于碰撞检测public Rectangle getrec () {return new Rectangle(x,y,width,height);//就相当于是返回一个对象}public void paintself(Graphics g ) {g.drawImage(img,x,y,null);//背景面}}//敌方鱼左边的鱼
class ennamy_l extends fish{
//	ennamy_l(){
//		
//	}构造方法public ennamy_l() {// TODO Auto-generated constructor stubthis.x=5;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=10;this.count=5;this.img=game_pic.dirmgage1;}}class ennamy_r extends fish{public ennamy_r() {// TODO Auto-generated constructor stubthis.x=1400;dir=-1;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=10;this.count=5;this.img=game_pic.dirmgager;}}class ennamy_3 extends fish {public  ennamy_3() {// TODO Auto-generated constructor stu() {// TODO Auto-generated constructor stubthis.x=5;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=15;this.type=2;this.img=game_pic.ffdir;}@Overridepublic Rectangle getrec () {return new Rectangle(x+40,y+30,width+5,height+5);//就相当于是返回一个对象}}
class ennamy_3r extends fish {// TODO Auto-generated constructor stu() {// TODO Auto-generated constructor stubpublic  ennamy_3r() {// TODO Auto-generated constructor stu() {// TODO Auto-generated constructor stubthis.x=1400;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=15;this.type=2;this.dir=-1;this.img=game_pic.ffdil;}@Overridepublic Rectangle getrec () {return new Rectangle(x+40,y+30,width+5,height+5);//就相当于是返回一个对象}}
class enn_bos extends fish{public enn_bos() {this.x=-1000;this.y = (int)(Math.random() * 700 + 100);this.width=340;this.height=340;this.speed=20;this.type=10;this.img=game_pic.bossImage;// TODO Auto-generated constructor stub}}

在这里是我们的fish类,把这几个敌方的鱼构建

我们先创建一个公共鱼类,这个公共鱼类是敌方鱼类共有的

public class fish {//定义图片Image img;//定义坐标int x;int y;int width;int height;//移动速度int speed;//方向定义int dir=1;//类型int type;//分值int count;//距离,用于检测自身//距离,用于碰撞检测public Rectangle getrec () {return new Rectangle(x,y,width,height);//就相当于是返回一个对象}public void paintself(Graphics g ) {g.drawImage(img,x,y,null);//背景面}}

所以后面我们把那些敌方类都继承到这个敌方公共类

敌法类

class ennamy_l extends fish{
//	ennamy_l(){
//		
//	}构造方法public ennamy_l() {// TODO Auto-generated constructor stubthis.x=5;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=10;this.count=5;this.img=game_pic.dirmgage1;}}

然后又是类继承

class ennamy_r extends fish{public ennamy_r() {// TODO Auto-generated constructor stubthis.x=1400;dir=-1;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=10;this.count=5;this.img=game_pic.dirmgager;}}

class ennamy_3 extends fish {public  ennamy_3() {// TODO Auto-generated constructor stu() {// TODO Auto-generated constructor stubthis.x=5;this.y = (int)(Math.random() * 700 + 100);this.width=45;this.height=69;this.speed=15;this.type=2;this.img=game_pic.ffdir;}@Overridepublic Rectangle getrec () {return new Rectangle(x+40,y+30,width+5,height+5);//就相当于是返回一个对象}}

这样我们在需要不同等级下的不同敌方类的时候生成不同的鱼子

在boss类构建时

class enn_bos extends fish{

public enn_bos() {

this.x=-1000;

this.y = (int)(Math.random() * 700 + 100);

this.width=340;

this.height=340;

this.speed=20;

this.type=10;

this.img=game_pic.bossImage;

// TODO Auto-generated constructor stub

}

}

然后又是myfish,即我自己的鱼类

myfish.java

package common;
import java.awt.*;
import common.game_pic;
public class myfish {Image img=game_pic.myfish_l;//坐标int x=700;int y=500;int width=50;int height=50;//速度int speed=20;//等级static int level=3;public void paintself(Graphics g) {logic();//判断下是哪个图片,后面再更改g.drawImage(img,x,y,width+game_pic.score,height+game_pic.score,null);}public void logic() {if (game_pic.up) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直//接访问,但是非静态成员必须通过类的实例来访问。y=y-speed;}if (game_pic.down) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直//接访问,但是非静态成员必须通过类的实例来访问。y=y+speed;}if (game_pic.left) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直//接访问,但是非静态成员必须通过类的实例来访问。x=x-speed;img=game_pic.myfish_l;}if (game_pic.right) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直//接访问,但是非静态成员必须通过类的实例来访问。x=x+speed;img=game_pic.myfish_r;}if (newgame.state==3) {x=700;y=500;}}//检测矩形的方法,用碰撞检测public Rectangle setRec() {return new Rectangle(x,y,width+game_pic.score,height+game_pic.score);}}

我们在这个类中也是又paintself方法的

public void paintself(Graphics g) {

logic();//判断下是哪个图片,后面再更改

g.drawImage(img,x,y,width+game_pic.score,height+game_pic.score,null);

}

因为我们的鱼是要上下左右移动的,所以我们用logic来判断下

public void logic() {

if (game_pic.up) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直

//接访问,但是非静态成员必须通过类的实例来访问。

y=y-speed;

}

if (game_pic.down) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直

//接访问,但是非静态成员必须通过类的实例来访问。

y=y+speed;

}

if (game_pic.left) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直

//接访问,但是非静态成员必须通过类的实例来访问。

x=x-speed;

img=game_pic.myfish_l;

}

if (game_pic.right) {//错误消息 “Cannot make a static reference to the non-static field game_pic.up” 表示您正在尝试在一个静态上下文中引用一个非静态字段 game_pic.up。在 Java 中,静态成员(方法或变量)可以在没有类实例的情况下直

//接访问,但是非静态成员必须通过类的实例来访问。

x=x+speed;

img=game_pic.myfish_r;

}

if (newgame.state==3) {

x=700;

y=500;

}

},这里我们是用左右键的左右图片表达这种看法。而上下是用y的上下实现。那么

public Rectangle setRec() {

return new Rectangle(x,y,width+game_pic.score,height+game_pic.score);

}是用于碰撞检测的

new game.java

package common;
import javax.swing.Timer;import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Iterator;import javax.swing.JFrame;
import javax.swing.WindowConstants;public class newgame extends JFrame {int width=1440;int height=900;//游戏状态static int state=0;bg bgg=new bg();Image offimagescreen;//敌方鱼类装载fish ennFish,boss;//随机生成鱼的数量,速度不要太快,控制生成double random;int time=0;//记录重绘次数fish enfis;myfish myfis=new myfish();boolean isbooss=false;public void launch() {this.setVisible(true);this.setSize(width,height);this.setLocationRelativeTo(null);//如果setLocationRelativeTo的参数是null,//则窗口会相对于整个屏幕居中显示。如果参数是一个特定的组件this.setResizable(false);//设置可调解大小的this.setTitle("这是一个长久项目");this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);this.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {super.mouseClicked(e);if (e.getButton()==1&&state==0) {state=1;repaint();//重新绘制/*总的来说,repaint 方法属于 Component 类,这是所有Swing组件的父类。因此,所有继承自 Component 类的Swing组件,* 如 JButton, JPanel, JFrame 等,都有 repaint 方法。repaint 是Swing组件更新显示的一个关键方法,用于确保用户界面能够反映组件的最新状态。* repaint() 调用的位置是正确的,它位于状态改变之后,这样就可以确保组件在状态改变后能够重新绘制自己,以反映新的状态。*/}if (e.getButton()==1&&state==2||state==3) {regame();}}});//键盘移动this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stubsuper.keyPressed(e);if (e.getKeyCode()==87) {game_pic.up=true;}if (e.getKeyCode()==83) {game_pic.down=true;}if (e.getKeyCode()==65) {game_pic.left=true;}if (e.getKeyCode()==68) {game_pic.right=true;}//空格键实现暂停功能if (e.getKeyCode()==32) {//用switch实现转换switch (state) {case 1: state=4;//这个时候进行提示语game_pic.drawworld(getGraphics(), "游戏暂停", Color.red, 50, 600, 400);break;case 4 :state=1;}}}@Overridepublic void keyReleased(KeyEvent e) {// TODO Auto-generated method stubsuper.keyReleased(e);if (e.getKeyCode()==87) {game_pic.up=false;}if (e.getKeyCode()==83) {game_pic.down=false;}if (e.getKeyCode()==65) {game_pic.left=false;}if (e.getKeyCode()==68) {game_pic.right=false;}}});//在Java中,this.addKeyListener(new KeyAdapter() { }); 这行代码是用于为当前组件(通常是窗口或者面板)添加键盘事件监听器。这里使用了KeyAdapter类,它是一个适配器类,用于简化键盘事件监听器的实现,因为//它为KeyListener接口中的所有方法提供了空实现。Timer tim=new Timer(100, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {time++;// TODO Auto-generated method stubrepaint();}} );tim.start();	//		while (true) {
//			repaint();
//			try {
//				Thread.sleep(400);
//			} catch (InterruptedException e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//			}}}/** DO_NOTHING_ON_CLOSE:当用户试图关闭窗口时,不执行任何操作。这通常用于在关闭窗口之前需要确认的情况。
HIDE_ON_CLOSE:当用户试图关闭窗口时,只隐藏窗口,但不会终止程序。这是 JFrame 的默认操作。
DISPOSE_ON_CLOSE:当用户试图关闭窗口时,会释放窗口的资源并隐藏窗口。如果所有窗口都被dispose,程序将结束。
EXIT_ON_CLOSE:当用户试图关闭窗口时,会退出应用程序。这通常用于程序的主窗口。*/@Overridepublic void paint(Graphics g) {//		  super.paint(g);//createImage(width, height) 是一个方法调用,它创建了一个指定宽度和高度的空图像缓冲区。这个方//法可以在 Component 类中找到,因此任何从 Component 继承的类(比如 Applet 或 JPanel)都可以使用这个方法。if (offimagescreen == null) {offimagescreen = createImage(width, height);}Graphics gimage=offimagescreen.getGraphics();//Graphics gimage = offimagescreen.getGraphics(); 这行代码是用来获取之前//创建的屏幕外图像缓冲区(offimagescreen)的Graphics对象,这样你就可以在这个图像上进行绘制操作了// 调用父类的paint方法来确保其他组件也被绘制// 确保图像已经被加载// 正确的方式是使用静态变量//			  try {g.drawImage(game_pic.bgimgage,0,0,null);//这个是绘制底板,缓存区域
//				  
//				
//			
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}switch (state) {case 0:bgg.paintself(gimage);//背景面这些是将底板都加到缓存区域上
//				
//				gimage.setColor(Color.pink);//设置笔为粉红
//	//			gimage/设置字体
//				gimage.setFont(new Font("仿宋", Font.BOLD,60));
//				gimage.drawString("hello world",700,500);break;case 1:bgg.paintself(gimage);//定义分数
//				gimage.setColor(Color.red);
//				gimage.setFont(new Font("仿宋", Font.BOLD,60));
//				String str = "开始!"+game_pic.score; // 示例文本
//				int x = 200; // 示例 x 坐标
//				int y = 120; // 示例 y 坐标
//
//				gimage.drawString(str, x, y);logic();//加载//				System.out.println(ennFish.x);
//				ennFish.x+=30;myfis.paintself(gimage);
//				取出小鱼for (fish enl:game_pic.enny_l) {enl.paintself(gimage);}if (isbooss) {boss.x=boss.x+boss.dir*boss.speed;boss.paintself(gimage);}break;//				/** 在这个例子中,fruits 是一个包含三个字符串的数组。增强型 for 循环将遍历数组中的每个元素,并且每次迭代都将当前元素赋值给变量 fruit。然后,可以在循环体内使用 fruit 变量。以下是增强型 for 循环的一般语法:for (声明语句 : 表达式) {// 循环体
}
声明语句:用于声明一个局部变量,该变量的类型必须与集合中元素的类型相同,或者是可以兼容的类型。
表达式:这个表达式必须是一个数组或者是一个实现了 Iterable 接口的集合。增强型 for 循环在处理集合时非常方便,因为它简化了代码并减少了出错的可能性(比如索引越界错误)。不过,它也有一些限制,比如你不能在循环中使用索引来访问元素,也不能直接修改集合的结构(比如添加或删除元素)。如果需要这*///			System.out.println(ennFish.x);
//			break;case 2:game_pic.drawworld(gimage,"失败",Color.orange,50,700,500);if (isbooss) {boss.paintself(gimage);}break;case 3:	myfis.paintself(gimage);gimage.setColor(Color.red);gimage.setFont(new Font("仿宋", Font.BOLD,60));gimage.drawString("积分"+game_pic.score, 200, 500);gimage.drawString("胜利", 600, 500);break;case 4:return;}g.drawImage(offimagescreen,0,0,null);//这里将所有缓存的一次加载到图片上
//			g.drawImage(game_pic.dirmgage1,0,0,null);}void logic() {//将添敌方小鱼添加到队列中//管卡难度逻辑判断if (game_pic.score<20) {myfis.level=1;}
//		  else if ( game_pic.score<100 &&game_pic.score>20) {
//			
//			game_pic.level=1;
//			  myfis.level=2;
//
//		
//		}
//		else if (game_pic.score<50) {
//					
//			game_pic.level=2;
//			myfis.level=2;else if (game_pic.score>20) {game_pic.level=2;myfis.level=4;}else if (game_pic.score>300) {state=3;//游戏胜利并显示胜利}random=Math.random();//随机概率//来看时间判断switch (game_pic.level) {case 4:if(time%160==0) {if (random<0.5) {boss=new enn_bos();isbooss=true;}}break;case 0:{		if(time%11==0) {if (random<0.5) {enfis=new enn_bos();}else {enfis=new ennamy_r();}  //需要不同等级生成不同的鱼game_pic.enny_l.add(enfis) ;  }}break;case 1:{if (time%20==0) {System.out.println(game_pic.level);if (random>0.5) {enfis=new ennamy_3();}else {enfis=new ennamy_3r();}game_pic.enny_l.add(enfis) ;  }}break;//对每个鱼的添加移动,有移动方向}for (fish enl:game_pic.enny_l) {enl.x=enl.x+enl.dir*enl.speed;//我方鱼类与对方鱼类进行碰撞检测	if (isbooss) {if (boss.getrec().intersects(enl.getrec())) {enl.x=-200;enl.y=-200;}if (boss.getrec().intersects((myfis.setRec()))) {state=2;}}if (myfis.setRec().intersects(enl.getrec())) {if (myfish.level>=enl.type) {enl.x=-200;enl.y=-200;//通过坐标实现消失game_pic.score=game_pic.score+enl.count;}else {state=2;}//这里判断
//				System.out.println("开始判断了");}//获取两个的交集}}//对于鱼类批量出来的/** 在Java Swing中,paint 方法通常不需要手动调用,因为它是自动调用的。当你创建一个窗口(例如 JFrame)并设置为可见时,Swing 的绘图系统会在必要时调用 paint 方法来绘制组件。在你提供的代码中,paint 方法被覆盖了,这意味着当Swing框架决定需要重绘窗口时(例如,窗口首次显示、窗口大小改变、窗口被遮挡后又重新显示等),它会自动调用这个方法。*/public void regame() {game_pic.enny_l.clear();time=0;myfis.level=1;game_pic.score=0;myfis.x=700;myfis.y=500;myfis.width=50;myfis.height=50;boss=null;isbooss=false;}public static void main(String[] args) {newgame gamewine=new newgame();gamewine.launch();}}

在这里的时候是我们主要实现的

先导入包

package common;

import javax.swing.Timer;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.util.Iterator;

import javax.swing.JFrame;

import javax.swing.WindowConstants;

我们这些导入的类有awt,有事件触发

这里的一个总类是

public class newgame extends JFrame {

JFrame,

int width=1440;

int height=900;

//游戏状态

先初次加载这些类

static int state=0;

bg bgg=new bg();

Image offimagescreen;

//敌方鱼类装载

fish ennFish,boss;

//随机生成鱼的数量,速度不要太快,控制生成

double random;

int time=0;//记录重绘次数

fish enfis;

myfish myfis=new myfish();

boolean isbooss=false;

	public void launch() {this.setVisible(true);this.setSize(width,height);this.setLocationRelativeTo(null);//如果setLocationRelativeTo的参数是null,//则窗口会相对于整个屏幕居中显示。如果参数是一个特定的组件this.setResizable(false);//设置可调解大小的this.setTitle("这是一个长久项目");this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);this.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {super.mouseClicked(e);if (e.getButton()==1&&state==0) {state=1;repaint();//重新绘制/*总的来说,repaint 方法属于 Component 类,这是所有Swing组件的父类。因此,所有继承自 Component 类的Swing组件,* 如 JButton, JPanel, JFrame 等,都有 repaint 方法。repaint 是Swing组件更新显示的一个关键方法,用于确保用户界面能够反映组件的最新状态。* repaint() 调用的位置是正确的,它位于状态改变之后,这样就可以确保组件在状态改变后能够重新绘制自己,以反映新的状态。*/}if (e.getButton()==1&&state==2||state==3) {regame();}}});//键盘移动this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stubsuper.keyPressed(e);if (e.getKeyCode()==87) {game_pic.up=true;}if (e.getKeyCode()==83) {game_pic.down=true;}if (e.getKeyCode()==65) {game_pic.left=true;}if (e.getKeyCode()==68) {game_pic.right=true;}//空格键实现暂停功能if (e.getKeyCode()==32) {//用switch实现转换switch (state) {case 1: state=4;//这个时候进行提示语game_pic.drawworld(getGraphics(), "游戏暂停", Color.red, 50, 600, 400);break;case 4 :state=1;}}}@Overridepublic void keyReleased(KeyEvent e) {// TODO Auto-generated method stubsuper.keyReleased(e);if (e.getKeyCode()==87) {game_pic.up=false;}if (e.getKeyCode()==83) {game_pic.down=false;}if (e.getKeyCode()==65) {game_pic.left=false;}if (e.getKeyCode()==68) {game_pic.right=false;}}});//在Java中,this.addKeyListener(new KeyAdapter() { }); 这行代码是用于为当前组件(通常是窗口或者面板)添加键盘事件监听器。这里使用了KeyAdapter类,它是一个适配器类,用于简化键盘事件监听器的实现,因为//它为KeyListener接口中的所有方法提供了空实现。Timer tim=new Timer(100, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {time++;// TODO Auto-generated method stubrepaint();}} );tim.start();	//		while (true) {
//			repaint();
//			try {
//				Thread.sleep(400);
//			} catch (InterruptedException e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//			}}}

我们这里是一个主要实现方法

然后其他判断方法

//		  super.paint(g);//createImage(width, height) 是一个方法调用,它创建了一个指定宽度和高度的空图像缓冲区。这个方//法可以在 Component 类中找到,因此任何从 Component 继承的类(比如 Applet 或 JPanel)都可以使用这个方法。if (offimagescreen == null) {offimagescreen = createImage(width, height);}Graphics gimage=offimagescreen.getGraphics();//Graphics gimage = offimagescreen.getGraphics(); 这行代码是用来获取之前//创建的屏幕外图像缓冲区(offimagescreen)的Graphics对象,这样你就可以在这个图像上进行绘制操作了// 调用父类的paint方法来确保其他组件也被绘制// 确保图像已经被加载// 正确的方式是使用静态变量//			  try {g.drawImage(game_pic.bgimgage,0,0,null);//这个是绘制底板,缓存区域
//				  
//				
//			
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}switch (state) {case 0:bgg.paintself(gimage);//背景面这些是将底板都加到缓存区域上
//				
//				gimage.setColor(Color.pink);//设置笔为粉红
//	//			gimage/设置字体
//				gimage.setFont(new Font("仿宋", Font.BOLD,60));
//				gimage.drawString("hello world",700,500);break;case 1:bgg.paintself(gimage);//定义分数
//				gimage.setColor(Color.red);
//				gimage.setFont(new Font("仿宋", Font.BOLD,60));
//				String str = "开始!"+game_pic.score; // 示例文本
//				int x = 200; // 示例 x 坐标
//				int y = 120; // 示例 y 坐标
//
//				gimage.drawString(str, x, y);logic();//加载//				System.out.println(ennFish.x);
//				ennFish.x+=30;myfis.paintself(gimage);
//				取出小鱼for (fish enl:game_pic.enny_l) {enl.paintself(gimage);}if (isbooss) {boss.x=boss.x+boss.dir*boss.speed;boss.paintself(gimage);}break;//				/** 在这个例子中,fruits 是一个包含三个字符串的数组。增强型 for 循环将遍历数组中的每个元素,并且每次迭代都将当前元素赋值给变量 fruit。然后,可以在循环体内使用 fruit 变量。以下是增强型 for 循环的一般语法:for (声明语句 : 表达式) {// 循环体
}
声明语句:用于声明一个局部变量,该变量的类型必须与集合中元素的类型相同,或者是可以兼容的类型。
表达式:这个表达式必须是一个数组或者是一个实现了 Iterable 接口的集合。增强型 for 循环在处理集合时非常方便,因为它简化了代码并减少了出错的可能性(比如索引越界错误)。不过,它也有一些限制,比如你不能在循环中使用索引来访问元素,也不能直接修改集合的结构(比如添加或删除元素)。如果需要这*///			System.out.println(ennFish.x);
//			break;case 2:game_pic.drawworld(gimage,"失败",Color.orange,50,700,500);if (isbooss) {boss.paintself(gimage);}break;case 3:	myfis.paintself(gimage);gimage.setColor(Color.red);gimage.setFont(new Font("仿宋", Font.BOLD,60));gimage.drawString("积分"+game_pic.score, 200, 500);gimage.drawString("胜利", 600, 500);break;case 4:return;}g.drawImage(offimagescreen,0,0,null);//这里将所有缓存的一次加载到图片上
//			g.drawImage(game_pic.dirmgage1,0,0,null);

同样是逻辑判断

	  void logic() {//将添敌方小鱼添加到队列中//管卡难度逻辑判断if (game_pic.score<20) {myfis.level=1;}
//		  else if ( game_pic.score<100 &&game_pic.score>20) {
//			
//			game_pic.level=1;
//			  myfis.level=2;
//
//		
//		}
//		else if (game_pic.score<50) {
//					
//			game_pic.level=2;
//			myfis.level=2;else if (game_pic.score>20) {game_pic.level=2;myfis.level=4;}else if (game_pic.score>300) {state=3;//游戏胜利并显示胜利}random=Math.random();//随机概率//来看时间判断switch (game_pic.level) {case 4:if(time%160==0) {if (random<0.5) {boss=new enn_bos();isbooss=true;}}break;case 0:{		if(time%11==0) {if (random<0.5) {enfis=new enn_bos();}else {enfis=new ennamy_r();}  //需要不同等级生成不同的鱼game_pic.enny_l.add(enfis) ;  }}break;case 1:{if (time%20==0) {System.out.println(game_pic.level);if (random>0.5) {enfis=new ennamy_3();}else {enfis=new ennamy_3r();}game_pic.enny_l.add(enfis) ;  }}break;//对每个鱼的添加移动,有移动方向}for (fish enl:game_pic.enny_l) {enl.x=enl.x+enl.dir*enl.speed;//我方鱼类与对方鱼类进行碰撞检测	if (isbooss) {if (boss.getrec().intersects(enl.getrec())) {enl.x=-200;enl.y=-200;}if (boss.getrec().intersects((myfis.setRec()))) {state=2;}}if (myfis.setRec().intersects(enl.getrec())) {if (myfish.level>=enl.type) {enl.x=-200;enl.y=-200;//通过坐标实现消失game_pic.score=game_pic.score+enl.count;}else {state=2;}//这里判断
//				System.out.println("开始判断了");}//获取两个的交集}}//对于鱼类批量出来的

又实现重新开始的功能

	public void regame() {game_pic.enny_l.clear();time=0;myfis.level=1;game_pic.score=0;myfis.x=700;myfis.y=500;myfis.width=50;myfis.height=50;boss=null;isbooss=false;}

main方法总类,总类的实现

public static void main(String[] args) {newgame gamewine=new newgame();gamewine.launch();}}

这里我们来解释一下

流程

  1. launch类加载
  2. int width=1440;

    int height=900;

    //游戏状态

    static int state=0;

    bg bgg=new bg();

    Image offimagescreen;

    //敌方鱼类装载

    fish ennFish,boss;

    //随机生成鱼的数量,速度不要太快,控制生成

    double random;

    int time=0;//记录重绘次数

    fish enfis;

    myfish myfis=new myfish();

    boolean isbooss=false;。将这些初始属性加载下

  3. 调用launch方法。launch方法中

    this.setVisible(true);

    this.setSize(width,height);

    this.setLocationRelativeTo(null);//如果setLocationRelativeTo的参数是null,

    //则窗口会相对于整个屏幕居中显示。如果参数是一个特定的组件

    this.setResizable(false);//设置可调解大小的

    this.setTitle("这是一个长久项目");

    this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);先把窗口初步设置下,然后增加监听事件this.addMouseListener(new MouseAdapter() {,在个里面是对state的一个判断,重新绘制,因为图像是要变化的

  4. 键盘事件的监听

    this.addKeyListener(new KeyAdapter() {

    @Override

    public void keyPressed(KeyEvent e) {

    // TODO Auto-generated method stub

    super.keyPressed(e);

    if (e.getKeyCode()==87) {

    game_pic.up=true;

    }

    if (e.getKeyCode()==83) {

    game_pic.down=true;

    }

    if (e.getKeyCode()==65) {

    game_pic.left=true;

    }

    if (e.getKeyCode()==68) {

    game_pic.right=true;

    }

    //空格键实现暂停功能

    if (e.getKeyCode()==32) {

    //用switch实现转换

    switch (state) {

    case 1:

    state=4;

    //这个时候进行提示语

    game_pic.drawworld(getGraphics(), "游戏暂停", Color.red, 50, 600, 400);

    break;

    case 4 :

    state=1;

    }

    }

    }这里就是利用键盘上的不同对game_pic.left=实现更改,从而实现图片替换

  5. @Override

    public void keyReleased(KeyEvent e) {

    // TODO Auto-generated method stub

    super.keyReleased(e);

    if (e.getKeyCode()==87) {

    game_pic.up=false;

    }

    if (e.getKeyCode()==83) {

    game_pic.down=false;

    }

    if (e.getKeyCode()==65) {

    game_pic.left=false;

    }

    if (e.getKeyCode()==68) {

    game_pic.right=false;

    }

    }这个就是放开按键后变化

  6. 实现定时重绘

    Timer tim=new Timer(100, new ActionListener() {

    @Override

    public void actionPerformed(ActionEvent e) {

    time++;

    // TODO Auto-generated method stub

    repaint();

    }

    } );

  7. public void paint(Graphics g) {

    方法,双缓存图片机制实现

    if (offimagescreen == null) {

    offimagescreen = createImage(width, height);

    }

    Graphics gimage=offimagescreen.getGraphics();//

  8. switch (state) {

    case 0:

    bgg.paintself(gimage);//背景面这些是将底板都加到缓存区域上

    //

    // gimage.setColor(Color.pink);//设置笔为粉红

    // // gimage/设置字体

    // gimage.setFont(new Font("仿宋", Font.BOLD,60));

    // gimage.drawString("hello world",700,500);

    break;

    case 1:

    bgg.paintself(gimage);

    //定义分数

    // gimage.setColor(Color.red);

    // gimage.setFont(new Font("仿宋", Font.BOLD,60));

    // String str = "开始!"+game_pic.score; // 示例文本

    // int x = 200; // 示例 x 坐标

    // int y = 120; // 示例 y 坐标

    //

    // gimage.drawString(str, x, y);

    logic();//加载

    // System.out.println(ennFish.x);

    // ennFish.x+=30;

    myfis.paintself(gimage);

    // 取出小鱼

    for (fish enl:game_pic.enny_l) {

    enl.paintself(gimage);

    }

    if (isbooss) {

    boss.x=boss.x+boss.dir*boss.speed;

    boss.paintself(gimage);

    }

    break;

    判断加载不同的鱼类,这里也有个logic判断

  9. 然后进行logic方法构建,通过

    if (game_pic.score<20) {

    myfis.level=1;对分数的不同更改myfis.level的变更,后面

    switch (game_pic.level) {

    case 4:

    if(time%160==0) {

    if (random<0.5) {

    boss=new enn_bos();

    isbooss=true;

    }

    }

    break;

    case 0:{

    if(time%11==0) {

    if (random<0.5) {再用来通过game_pic.level)困难程度实现鱼类变化

  10. 鱼类添加

    if(time%11==0) {

    if (random<0.5) {

    enfis=new enn_bos();

    }

    else {

    enfis=new ennamy_r();

    } //需要不同等级生成不同的鱼

    game_pic.enny_l.add(enfis) ;

    是通过enny_l这里的原先指定的列表添加

  11. for (fish enl:game_pic.enny_l) {

    enl.x=enl.x+enl.dir*enl.speed;

    //我方鱼类与对方鱼类进行碰撞检测

    if (isbooss) {

    if (boss.getrec().intersects(enl.getrec())) {

    enl.x=-200;

    enl.y=-200;

    }

    if (boss.getrec().intersects((myfis.setRec()))) {

    state=2;

    }}把列表中每个成员拿出来,把这些enl.x=enl.x+enl.dir*enl.speed;对其x进行x方面的移动,我们再到这里if (myfis.setRec().intersects(enl.getrec())) {。来和矩形判断接触的距离,这样的话我们就能够实现吃不吃。就这样

    enl.x=-200;

    enl.y=-200;//通过坐标实现消实现了它的消失。

  12. 我们的regame是重新开始,就是重置选分

    public void regame() {

    game_pic.enny_l.clear();

    time=0;

    myfis.level=1;

    game_pic.score=0;

    myfis.x=700;

    myfis.y=500;

    myfis.width=50;

    myfis.height=50;

    boss=null;

    isbooss=false;

    }

好了,我的表达太混乱了


http://www.ppmy.cn/news/1542465.html

相关文章

汽车免拆诊断案例 | 2019 款奥迪 A6L 车行驶中偶发熄火

故障现象  一辆2019款奥迪A6L车&#xff0c;搭载2.0T发动机&#xff0c;累计行驶里程约为9万km。车主反映&#xff0c;车辆行驶中偶发熄火&#xff0c;故障频率较高。 故障诊断  接车后试车&#xff0c;起动发动机&#xff0c;可以正常起动着机。使用故障检测仪检测&#x…

【大模型理论篇】主流大模型的分词器选择及讨论(BPE/BBPE/WordPiece/Unigram)

1. 背景分析 分词是将输入和输出文本拆分成更小单位的过程&#xff0c;使得大模型能够处理。token可以是单词、字符、子词或符号&#xff0c;取决于模型的类型和大小。分词可以帮助模型处理不同的语言、词汇和格式&#xff0c;并降低计算和内存成本。分词还可以通过影响token的…

多eSIM配置文件(MEP)

根据在fediverse上的一个回复&#xff0c;Google Pixel 7和8都应该支持MEP&#xff08;多eSIM配置文件&#xff09;。这一信息在Reddit上的一个帖子中似乎得到了确认&#xff0c;该帖子讨论了eSIM MEP和双eSIM功能。 如果您想进一步研究并检查是否可以通过DIAG&#xff08;诊断…

R语言笔记(二):向量

文章目录 一、Data structure: vectors二、Indexing vectors三、Re-assign values to vector elements四、Generic function for vectors五、Vector of random samples from a distribution六、Vector arithmetic七、Recycling八、Element-wise comparisons of vectors九、Comp…

【笔记】apt源设置为阿里云源

目录 1. 备份现有的源列表&#xff08;可选&#xff0c;但推荐&#xff09;&#xff1a;2. 编辑 sources.list 文件&#xff1a;3. 替换内容为阿里源&#xff1a;4. 保存并退出&#xff1a;5. 更新软件包索引&#xff1a; 在 Ubuntu 系统中&#xff0c;将 APT 源设置为阿里云源…

【C++单调栈 贡献法】907. 子数组的最小值之和|1975

本文涉及的基础知识点 C单调栈 LeetCode907. 子数组的最小值之和 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 109 7 。 示例 1&#x…

Word 删除空白页:亲测有效的方法

# Word 删除空白页&#xff1a;亲测有效的方法 在使用Microsoft Word编写文档时&#xff0c;有时会遇到空白页的问题&#xff0c;这可能会影响文档的排版和可读性。以下是几种有效的方法来删除Word文档中的空白页。 ## 一、检查段落标记和分页符 ### 1. 显示/隐藏段落标记 -…

深入理解JAVA虚拟机(四)

介绍对象Mark Word里面锁状态的流转 线程真正有四个状态&#xff1a;无锁状态 &#xff08;标识01&#xff0c;是否偏向0&#xff09;、偏向锁&#xff08;标识01、是否偏向1&#xff09;、轻量级锁&#xff08;标识00&#xff09;、重量级锁&#xff08;标识&#xff1a;10&a…