java游戏第六天——总结

开始

我们先在这里创建五个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 stub
		this.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 stub
		this.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 stub
		this.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;

	}
	@Override
	public 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 stub
		public  ennamy_3r() {
			// TODO Auto-generated constructor stu() {
			// TODO Auto-generated constructor stub
			this.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;

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

	}
	@Override
	public 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() {
			@Override
			public 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() {
			
			@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;
					}
					
				}
			}
			
			@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;
				}
			}
		});//在Java中,this.addKeyListener(new KeyAdapter() { }); 这行代码是用于为当前组件(通常是窗口或者面板)添加键盘事件监听器。这里使用了KeyAdapter类,它是一个适配器类,用于简化键盘事件监听器的实现,因为
		//它为KeyListener接口中的所有方法提供了空实现。
		 Timer tim=new Timer(100, new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				time++;
				// TODO Auto-generated method stub
			       repaint();
			}
		} );
		 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:当用户试图关闭窗口时,会退出应用程序。这通常用于程序的主窗口。
		 */
	
	  @Override
		    public 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() {
			@Override
			public 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() {
			
			@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;
					}
					
				}
			}
			
			@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;
				}
			}
		});//在Java中,this.addKeyListener(new KeyAdapter() { }); 这行代码是用于为当前组件(通常是窗口或者面板)添加键盘事件监听器。这里使用了KeyAdapter类,它是一个适配器类,用于简化键盘事件监听器的实现,因为
		//它为KeyListener接口中的所有方法提供了空实现。
		 Timer tim=new Timer(100, new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				time++;
				// TODO Auto-generated method stub
			       repaint();
			}
		} );
		 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;//通过坐标实现消实现了它的消失。

我们的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;

}

好了,我的表达太混乱了

相关推荐
windwind20001 小时前
游戏关卡设计方法的杂感
游戏·关卡设计
白乐天_n14 小时前
腾讯游戏安全移动赛题Tencent2016A
安全·游戏
这是我5815 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
tealcwu16 小时前
【游戏设计原理】21 - 解谜游戏的设计
游戏·游戏策划
清梦202016 小时前
经典问题---跳跃游戏II(贪心算法)
算法·游戏·贪心算法
tealcwu17 小时前
【游戏设计原理】22 - 石头剪刀布
游戏·游戏策划
l1384942745120 小时前
Java每日一题(2)
java·开发语言·游戏
孤留光乩1 天前
从零搭建纯前端飞机大战游戏(附源码)
前端·javascript·游戏·html·css3
王大队长1 天前
Epic游戏使用mod
游戏
tealcwu2 天前
【游戏设计原理】20 - 囚徒困境
游戏