java贪吃蛇小游戏(一)

刚看完java基础课的课程花费了一个星期边看Swing边复习学过的知识边完善程序,还有不少bug,例如,点击帮助后按空格键会开始游戏,贪吃蛇撞到墙后以后再重新开始游戏有一节小蛇没有及时重绘制;先分享出来,写一个详细一点的注释,有时间再慢慢完善。
这个小程序中,我用到的组件有JFrame(窗体)、Jpanel(面板)、JButton(按钮)、Label(标签),实现了基本的贪吃蛇游戏功能(吃食物,计分,改变速度)。下面先说一下大体的思路和核心的步骤:
贪吃蛇是由一组节点构成,使用LinkedList( )集合存储贪吃蛇的节点(LinkedList底层的数据结构为链表,增删方便,便于贪吃蛇变长)贪吃蛇一次移动一个节点的长度,需要依靠JPanel的重绘paint(Graphics g)方法来实现间隔一定的时间来进行重绘,由于间隔时间较短看到的贪吃蛇就近似连续移动了,不必每次刷新移动所有节点,只需要先将头部节点向当前方向移动一个节点的位置,再判断是否吃到食物,吃到食物则在原来头部的位置添加一个节点(也就是集合索引为1的位置);若没有吃到食物,则在原来头部的位置添加一个节点的同时,删除集合最后一个元素(集合索引为size()-1)。这样就实现了贪吃蛇的一次移动。吃到食物后对计分变量++,改变刷新的时间就可以简单的实现计分和改变速度的功能了。对java面向对象的设计模式还不熟练,所以写的类有点乱,等到学习深入了可以考虑一下代码重构。类IndexFrame()继承了JFrame,是游戏的容器该类是游戏的入口,主要包含了窗口的大小,位置等基本属性的设置,并把面板添加到上面;BackgroundPanel类继承了Panel类,里面对游戏界面进行了布置,添加了按钮和标签,重写了paint()方法,定义了存储贪吃蛇节点的集合,提供了贪吃蛇移动的各个方法以及开辟了单独的线程让贪吃蛇移动,便于移动的同时监听键盘和鼠标事件。接下来贴出各个类的源码,在源码上做了尽可能详细的注释,毕竟是新手,也希望自己能够理解的透彻一点,便于以后代码的修改。

(需要注意的是:Swing中的JPanel重绘本身利用了双缓冲流所以不必自己再利用双缓冲流重新方法,AWT中的Panel没有实现双缓冲流,使用这个组件可能会出现刷新不及时,图像掉帧,断开等问题,需要自己按照双缓冲流重写程序)

package  view;

import java.awt.Container;

import javax.swing.JFrame;

import util.LocationSize;
import util.UiUtil;

/*
 * 此页面为首页
 */
public class IndexFrame extends JFrame {
	private static final long serialVersionUID = -4891314929133227453L;
	// 首页的长和宽
    //写了单独的类提供组件的尺寸和位置的字段值,便于修改
	private static final int width = LocationSize.FRAMEW;
	private static final int height = LocationSize.FRAMEH;
	// 创建面板对象
	BackgroundPanel bgp = new BackgroundPanel();
	// 获取JFrame的窗格
	final Container contentPane = getContentPane();
	// 无参构造方法用于数据的初始化
	public IndexFrame() {
		initComponents();
		init();
	}
	private void initComponents() {
		// 将面板添加到窗格中
		contentPane.add(bgp);
		this.setContentPane(contentPane);
	}  
	private void init() {
		// 设置窗体的Undecorated属性为true,阻止窗体采用本机系统修饰,这样窗体就没有标题栏和边框了
		this.setUndecorated(true);
        //设置窗体关闭时程序也关闭,此处也可不需要这个,因为没有窗体关闭按钮
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		this.setResizable(false);
		this.setSize(width, height);
        //设置窗体在居中,需要获取屏幕的尺寸,写了在了操作窗体的工具类中
		UiUtil.setFrameCenter(this);
		this.setVisible(true);
        //监听鼠标拖拽实现窗体的实时移动
		FrameMoveListener moveListener = new FrameMoveListener(this);
		// 监听鼠标事件
		this.addMouseListener(moveListener);
		// 监听鼠标移动事件
		this.addMouseMotionListener(moveListener);
	}
	public static void main(String[] args) {
        //创建窗体对象,程序入口
		IndexFrame idf = new IndexFrame();
	}

}
package view;

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;

/*
 * 鼠标拖动窗口发生移动
 */
public class FrameMoveListener extends MouseAdapter {
	private Point oldPoint;
	private JFrame jf;

	public FrameMoveListener(JFrame jf) {
		this.jf = jf;
	}

    //鼠标点击窗体是存储鼠标此时的坐标
	@Override
	public void mousePressed(MouseEvent e) {
		oldPoint = e.getLocationOnScreen();
	}
    //发生鼠标拖拽后,重新设置窗体坐标,保持窗体相对于鼠标的坐标不变
	@Override
	public void mouseDragged(MouseEvent e) {
		Point newPoint = e.getLocationOnScreen();
		int difX = newPoint.x - oldPoint.x;
		int difY = newPoint.y - oldPoint.y;
		 jf.setLocation(jf.getBounds().x+difX,jf.getBounds().y+difY);

		oldPoint = newPoint;
	}
}

为了使注册监听事件时不必要重新所有的方法,模仿适配器类,新建了适配器类,只重写方法名,不需要具体实现,当组件需要注册监听时可以创建该类的实例重写需要的方法即可。

package view;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MouseEvent;
import org.w3c.dom.views.AbstractView;

public class MyEventListener implements MouseEvent, MouseListener,
		MouseMotionListener, KeyListener {

	@Override
	public AbstractView getView() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getDetail() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void initUIEvent(String typeArg, boolean canBubbleArg,
			boolean cancelableArg, AbstractView viewArg, int detailArg) {
		// TODO Auto-generated method stub

	}

	@Override
	public String getType() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public EventTarget getTarget() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public EventTarget getCurrentTarget() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public short getEventPhase() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean getBubbles() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean getCancelable() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public long getTimeStamp() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void stopPropagation() {
		// TODO Auto-generated method stub

	}

	@Override
	public void preventDefault() {
		// TODO Auto-generated method stub

	}

	@Override
	public void initEvent(String eventTypeArg, boolean canBubbleArg,
			boolean cancelableArg) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

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

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseDragged(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseMoved(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseClicked(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(java.awt.event.MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public int getScreenX() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int getScreenY() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int getClientX() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int getClientY() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean getCtrlKey() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean getShiftKey() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean getAltKey() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean getMetaKey() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public short getButton() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public EventTarget getRelatedTarget() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void initMouseEvent(String typeArg, boolean canBubbleArg,
			boolean cancelableArg, AbstractView viewArg, int detailArg,
			int screenXArg, int screenYArg, int clientXArg, int clientYArg,
			boolean ctrlKeyArg, boolean altKeyArg, boolean shiftKeyArg,
			boolean metaKeyArg, short buttonArg, EventTarget relatedTargetArg) {
		// TODO Auto-generated method stub

	}

}

猜你喜欢

转载自blog.csdn.net/Will_Zhan/article/details/81484367