java游戏第六天——总结

ops/2024/10/31 8:19:36/

开始

我们先在这里创建五个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/ops/129810.html

相关文章

测试自动化工具的横向对比

MicroAgent&#xff1a;这个AI智能体一键写代码并且自动测试&#xff01;它比 Aider 更好吗&#xff1f; 待研究&#xff1a;https://blog.csdn.net/gitblog_00054/article/details/139541862 playright&#xff1a;这是一个python驱动的自动化框架&#xff0c;部署简单&#…

相关矩阵图——Python实现

import matplotlib.pyplot as plt import numpy as np# 创建一些正常分布的数据 mean [0, 0] cov [[1, 1], [1, 2]] x, y np.random.multivariate_normal(mean, cov, 3000).T# Set up the axes with gridspec fig plt.figure(figsize(6, 6)) grid plt.GridSpec(4, 4, hspa…

LeetCode 热题 100 回顾28

干货分享&#xff0c;感谢您的阅读&#xff01;原文见&#xff1a;LeetCode 热题 100 回顾_力code热题100-CSDN博客 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标…

获得淘宝app商品详情原数据 API 券后价获取API

item_get_app_pro-获得淘宝app商品详情原数据 通过此API可以实现通过商品id获取商品详情页数据&#xff0c;包括券后价、主图、详情等等。 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameStr…

[数据结构]插入排序(全)

插入排序分为直接插入排序和希尔排序&#xff0c;希尔排序是在直接插入排序的基础上做出的优化版本(原因后面解释)。 代码如下: //直接插入排序 void InsertSort(int arr[], int sz) {for (int i 0; i < sz - 1; i){int mark i;int tmp arr[mark 1];while (mark > …

无人机避障——4D毫米波雷达从PCD点云到二维栅格地图

本文旨在以 4D 毫米波雷达的 PCD 点云格式文件为基础&#xff0c;直接生成可用于后续无人机路径规划、能提供雷达感知环境的 2D 导航地图文件PGM&#xff0c;从而为无人机在相关环境中的飞行路径规划等操作提供有力的基于雷达感知的环境信息支撑。 安装PCD转PGM代码 代码来自…

重生之我在Java世界------学工厂设计模式

文章目录 为什么需要工厂模式&#xff1f;简单工厂模式&#xff1a;第一步改进实际应用场景(常见场景)1. 数据库连接的创建2. 支付方式的处理 工厂模式的优势注意事项总结 在日常开发工作中&#xff0c;我们经常需要创建对象。随着项目的发展&#xff0c;对象创建的逻辑可能变得…

redis详细教程(5.AOP和RDB持久化)

AOF&#xff08;Append Only File&#xff09;日志和RDB&#xff08;Redis Database Backup&#xff09;持久化是Redis中两种重要的数据持久化机制。 RDB持久化机制原理RDB是Redis提供的一种数据快照保存机制&#xff0c;它将某个时间点的数据库状态保存到一个RDB文件中。这个…