半成品 贪吃蛇项目

看看图片

视频链接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,有多个构造方法的用途

相关推荐
ygl615037311 分钟前
Vue3+SpringBoot3+Sa-Token+Redis+mysql8通用权限系统
java·spring boot·vue
Code哈哈笑13 分钟前
【Java 学习】构造器、static静态变量、static静态方法、static构造器、
java·开发语言·学习
是老余15 分钟前
Java三大特性:封装、继承、多态【详解】
java·开发语言
鸽鸽程序猿16 分钟前
【JavaEE】Maven的介绍及配置
java·java-ee·maven
尘浮生1 小时前
Java项目实战II基于微信小程序的南宁周边乡村游平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·微信小程序·小程序·maven
耀耀_很无聊5 小时前
第1章 初识SpringMVC
java·spring·mvc
麻衣带我去上学5 小时前
Spring源码学习(一):Spring初始化入口
java·学习·spring
东阳马生架构5 小时前
MySQL底层概述—1.InnoDB内存结构
java·数据库·mysql
手握风云-6 小时前
数据结构(Java版)第一期:时间复杂度和空间复杂度
java·数据结构
坊钰6 小时前
【Java 数据结构】时间和空间复杂度
java·开发语言·数据结构·学习·算法