当前位置: 首页 > article >正文

半成品 贪吃蛇项目

看看图片

视频链接20_【尚学堂】贪吃蛇游戏项目_游戏关卡的设置_哔哩哔哩_bilibili,他里面有章身体的没有讲到,所以我就学不下了。

还是讲讲代码吧

gamewine代码

package game;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

import obj.bodyobj;
import obj.foodobj;
import obj.head;
import utils.gameutils;

public class gamewin extends JFrame {
    Image offscreenImage = null;

    // 蛇头对象
    head headObj = new head(gameutils.rightimg, 30, 560, this);
    public List<bodyobj> bodyobjs=new ArrayList();
    //食物
    public foodobj foodobj=new foodobj().getFoodobj();

    private void launch() {
        this.setVisible(true);
        this.setSize(600, 600);
        this.setLocationRelativeTo(null);
        this.setTitle("我是一条贪吃蛇");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 设置重绘的定时器
        Timer timer = new Timer(250, e -> repaint());
        timer.start();
     
    }

    @Override
    public void update(Graphics g) {
        // 初始化离屏图像
        if (offscreenImage == null) {
            offscreenImage = createImage(600, 600);
        }
        Graphics gOffscreen = offscreenImage.getGraphics();
        paint(gOffscreen);
        g.drawImage(offscreenImage, 0, 0, this);
    }

    @Override
    public void paint(Graphics g) {
//        super.paint(g);
        // 绘制背景
        g.setColor(Color.GRAY);
        g.fillRect(0, 0, 600, 600);

        // 绘制网格线
        g.setColor(Color.BLACK);
        for (int i = 0; i < 20; i++) {
            g.drawLine(i*30,0,i*30,600);
      
        }
        for (int i = 0; i < 20; i++) {
            g.drawLine(0,i*30,600,i*30);      
        }

        // 绘制蛇头
        headObj.paintself(g);
        foodobj.paintself(g);
    }

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

上述代码是实现窗口等绘制,

注意点

这里的双缓存不能像往常一样了,以前的话这里线条会重叠,导致粗细不同,用了

public void update(Graphics g) {

// 初始化离屏图像

if (offscreenImage == null) {

offscreenImage = createImage(600, 600);

}

Graphics gOffscreen = offscreenImage.getGraphics();

paint(gOffscreen);

g.drawImage(offscreenImage, 0, 0, this);

}

可以实现以前线条的去除,这里的update也是自动触发的

重绘定时

// 设置重绘的定时器

Timer timer = new Timer(250, e -> repaint());

timer.start();

snake head .java类

package obj;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import game.gamewin;
import utils.gameutils;

public class head extends gameobj{
	//方向是上下左右
	private String direction="right";

	 public head(Image img, int x, int y, gamewin frame) {
		super(img, x, y,frame);
		this.frame.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				changedirction(e);	}
			
		}
		
				
				);
		
		// TODO Auto-generated constructor stub
	}
	 public void changedirction(KeyEvent e) {
		 
		 
		 switch (e.getKeyCode()) {
		case KeyEvent.VK_A:
			if (!"right".equals(direction)) {
				direction="left";
				img=gameutils.leftimg;
				
			}
			
			break;
		case KeyEvent.VK_W:
			if (!"down".equals(direction)) {
				direction="up";
				img=gameutils.upimg;
				
			}
			
			break;
		case KeyEvent.VK_S:
			if (!"up".equals(direction)) {
				direction="down";
				img=gameutils.downimg;
				
			}
			
			break;
		case KeyEvent.VK_D:
			if (!"left".equals(direction)) {
				direction="right";
				img=gameutils.rightimg;
				
			}
			
			break;

		default:
			break;
		}
		
	}
	public String getDirection() {
		return direction;
	}
	
	//蛇头移动
	public void move() {
		switch (direction){
		case "up": {
			
			y-=height;
			
			break;
		}
		case "down":
			y+=height;
			break;
			
		case "left":
			x-=width;
			break;
		case "right":
			x+=width;
			break;
			default:
				break;
		
		}
		
	}

	@Override
	public void paintself(Graphics g) {
		// TODO Auto-generated method stub
		super.paintself(g);
		foodobj food=this.frame.foodobj;
		//用xy条件判断蛇头与食物是否重合
		if (this.x==food.x && this.y==food.y) {
			//将新的随机生成的foodobj对象给窗口的foodobj
			this.frame.foodobj=food.getFoodobj();
			
		}
		move();
		//越界处理
		if (x<0) {
			x=570;			
		}
		else if (x>570) {
			x=0;			
		}
		else if (y<30) {
			y=570;
			
		}
		else if (y>570) {
			y=30;
			
		}
	}
	
	

}

我们这里对蛇的上下左右控制

这里有监控,按压

 public head(Image img, int x, int y, gamewin frame) {
		super(img, x, y,frame);
		this.frame.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				changedirction(e);	}
			
		}
		

对不同的方向实现不同的蛇头图片

public void changedirction(KeyEvent e) {
		 
		 
		 switch (e.getKeyCode()) {
		case KeyEvent.VK_A:
			if (!"right".equals(direction)) {
				direction="left";
				img=gameutils.leftimg;
				
			}
			
			break;
		case KeyEvent.VK_W:
			if (!"down".equals(direction)) {
				direction="up";
				img=gameutils.upimg;
				
			}
			
			break;
		case KeyEvent.VK_S:
			if (!"up".equals(direction)) {
				direction="down";
				img=gameutils.downimg;
				
			}
			
			break;
		case KeyEvent.VK_D:
			if (!"left".equals(direction)) {
				direction="right";
				img=gameutils.rightimg;
				
			}
			
			break;

		default:
			break;
		}
		
	}

而像

if (!"up".equals(direction)) {

direction="down";

img=gameutils.downimg;

是为了保证蛇不会往反方向移动,然后又将其移动

public String getDirection() {
		return direction;
	}
	
	//蛇头移动
	public void move() {
		switch (direction){
		case "up": {
			
			y-=height;
			
			break;
		}
		case "down":
			y+=height;
			break;
			
		case "left":
			x-=width;
			break;
		case "right":
			x+=width;
			break;
			default:
				break;
		
		}
		
	}

因为我们这个实现的越界后继续循环使用的样子,所以

	public void paintself(Graphics g) {
		// TODO Auto-generated method stub
		super.paintself(g);
		foodobj food=this.frame.foodobj;
		//用xy条件判断蛇头与食物是否重合
		if (this.x==food.x && this.y==food.y) {
			//将新的随机生成的foodobj对象给窗口的foodobj
			this.frame.foodobj=food.getFoodobj();
			
		}
		move();
		//越界处理
		if (x<0) {
			x=570;			
		}
		else if (x>570) {
			x=0;			
		}
		else if (y<30) {
			y=570;
			
		}
		else if (y>570) {
			y=30;
			
		}

x,y坐标的改变

公共属性

package utils;

import java.awt.*;

public class gameutils {
	//蛇头。蛇身
	public static Image upimg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\head.png");
	public static Image downimg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\down.png");
	public static Image leftimg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\left.png");
	public static Image rightimg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\right.png");
	public static Image bodyimg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\body.png");
	public static Image food=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\food.png");
	public static Image bg=Toolkit.getDefaultToolkit().getImage("D:\\programing\\javaide\\snak\\picture\\background.png");


	public void drawword(Graphics g,String string,Color color,int size,int x,int y ) {
		g.setColor(color);
		g.setFont(new Font("仿宋",Font.BOLD,size));
		g.drawString(string, x, y);
		
	}

	

}

对一些能够通用的就放到一起

结语

这个残缺的代码就写好了

与以前对比

java讲究的是对象化,把每个物体看作对象,如大鱼吃小鱼,我方鱼,敌方鱼,大鱼,小鱼,这都是不同的对象。不过又可以定义一个公共的对象,,让这些小对象继承,如

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{

敌方鱼继承,我方鱼继承,或override其属性。在我们的贪吃蛇小游戏项目中,我们有蛇头,蛇身,食物,这三个obj,那么对于一些公共方法,属性的实现我们就可以在这个公共方法中实现了

package obj;
import java.awt.*;

import game.gamewin;
import utils.gameutils;
public class gameobj {
	//图片
	Image img;
	int x;
	int y;
	//物体的宽高
	int width=30;
	int height=30;
	//
	//窗口类的引用
	gamewin frame;
	public Image getImg() {
		return img;
	}
	public int getWidth() {
		return width;
	}
	public int getHeight() {
		return height;
	}
	public gamewin getFrame() {
		return frame;
	}
	public void setImg(Image img) {
		this.img = img;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public void setFrame(gamewin frame) {
		this.frame = frame;
	}
	public gameobj() {
		// TODO Auto-generated constructor stub
	}
	public gameobj(Image img, int x, int y, int width, int height, gamewin frame) {
	
		this.img = img;
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.frame = frame;
	}
	
	
	 public gameobj(Image img, int x, int y,gamewin frame) {
		
		this.img = img;
		this.x = x;
		this.y = y;
		this.frame = frame;

	}
	//绘制自身的方法
	public  void paintself(Graphics g) {
		
//		g.drawImage(img, x, y,null);
		g.drawImage(img, x, y, width, height, null);
		// TODO Auto-generated method stub
		
	}
	public void foodobj() {
		
	}
	
	
}

这里用了多个构造方法以此来适应后期不同的需求,并且注意

this.frame = frame;这是我们以前方法中没有的。gamewin frame目的是指向gamewin这个代码页面,所以在我们head构造器中就没必要重复定义x,y,this.x=x这样的

public head(Image img, int x, int y, gamewin frame) {

super(img, x, y,frame);

head headObj = new head(gameutils.rightimg, 30, 560, this);

时,这个this就是值frame了。那么在head中也能使用frame.x或y了

对判断食物时

@Override

public void paintself(Graphics g) {

// TODO Auto-generated method stub

super.paintself(g);

foodobj food=this.frame.foodobj;

//用xy条件判断蛇头与食物是否重合有个替换

总之、

有this的用途,用逻辑switch,有多个构造方法的用途


http://www.kler.cn/a/378200.html

相关文章:

  • 微控制器(MCU)如何运行存储在Flash的程序???
  • uni-app跨域set-cookie
  • contenteditable实现需要一个像文本域一样的可编辑框
  • 专业网页设计服务重要是什么
  • 1565412310
  • 建立maven项目常见问题解决办法
  • Linux软硬链接
  • C++ 优先算法 —— 查找总价格为目标值的两个商品(双指针)
  • 八、MapReduce 大规模数据处理深度剖析与实战指南
  • 100种算法【Python版】第33篇——Tonelli-Shanks算法
  • vue+element上传图片
  • fmql之Linux以太网
  • chatgpt3.5权重参数有多少MB;llama7B权重参数有多少MB
  • ChatGPT 和 RAG(检索增强生成)的区别;ChatGPT 和 RAG 的联系
  • 【缓存与加速技术实践】Redis 高可用
  • 【AI语音克隆整合包及教程】声临其境,让想象成为现实——第二代GPT-SoVITS引领语音克隆新时代!
  • ChatGPT变AI搜索引擎!以后还需要谷歌吗?
  • 初知C++:继承
  • Ubuntu删除docker
  • Vue 组件生命周期(四)
  • Docker:网络
  • synchronized加锁原理以及锁升级过程
  • 微服务架构深入理解 | 技术栈
  • vue3项目history模式部署404处理,使用 historyApiFallback 中间件支持单页面应用路由
  • 最新指南,如何使用 ChatGPT 提示词指令进行学术写作
  • 人工智能原理实验一:知识的表示与推理实验