推箱子游戏设计与实现

毕业设计(论文)

课题名称基于swing开发的推箱子游戏

学生姓名吕季干

学号 0840819035 系、年级专业理学与信息科学系2008级信息与计算科学

指导教师戴亚滨

职称讲师

2012 年 5 月 25 日

摘要

在现今电子信息高速发展的时代,电子游戏已经深入人们的日常生活,成为娱乐方式。但是游戏设计结合了日新月异的技术,在一个产品中整合了复杂的设计、艺术、声音和软件。

推箱子游戏是一款很有趣味的游戏,它由英雄、魔王、笼子、墙和地板组成,然后存储在一个数组中,用户根据键盘的向上、向左、向右和向下键操作。其开发过程有一定的技巧和方法,其中涉及到二维数组、键盘操作以及图形化函数等方面的知识。此次设计是在Microsoft Windows 7系统下,以java为开发语言,在eclipse平台上进行游戏的设计与实践。

关键词:游戏设计、数组、开发语言

Abstract

In the current era of rapid development of electronic information, electronic games has been deeply People's Daily life, be enjoyed by young and old form of entertainment. But the game design combined with tomorrow's technology, in a product integration of complex design, art, sound and software, so not well-known.

Pushed box game is a very interesting game, it achieved by Hero,Devil,Cage,Floor and Wall, and then stored in an array , users according to the keyboard four the direction up, left, right and down operation to control. Pushed box game development process has certain skills and methods, which involves a two dimensional array, keyboard and graphical function and other aspects. This design is in Microsoft Windows 7 system, with JA V A for development of language, Ecplise platform game design and practice.

Keywords: Game design, array, Development language

目录

摘要.......................................................................................................... I Abstract ..................................................................................................... II 前言 (1)

1可行性分析 (2)

1.1要求 (2)

1.2目标 (2)

2 项目开发计划的任务分解 (2)

3 概要设计 (2)

3.1游戏界面 (2)

3.2游戏四种基本图形 (2)

3.3英雄走向图形 (3)

3.4 箭头图片 (3)

4 需求规格说明 (3)

4.1运行环境 (3)

4.2功能需求 (3)

4.3运行需求 (4)

5 详细设计 (4)

5.1 系统模块 (4)

5.2 任务执行流程 (5)

5.3 小人移动流程 (5)

6界面实现 (5)

6.1 界面区 (5)

6.2 游戏区 (8)

6.3 图片加载区 (11)

6.4 英雄变化区 (11)

6.5 地图绘画区 (19)

7 结束语 (23)

参考文献 (24)

附录 (25)

致谢 (26)

前言

随着社会的发展,人类的生产、生活越来越离不开信息。谁拥有了更多更有效的信息,谁就将在竞争中处于有利的地位。信息产业正在成为一个国家的支柱。只有拥有了先进的技术和知识,才能有效地管理好浩如烟海的信息,并从中提取出对自己有用的信息来加以利用。

推箱子游戏是目前比较流行的游戏之一,很多操作系统或者流行软件都会带有这种游戏。它既能锻炼思维的严密性,又有很多乐趣。我个人也比较喜欢玩这个游戏,因此,我就借这个机会将这个推箱子游戏用java语言实现了出来,其中的界面使用了swing中的工具,当然,我也借鉴了前人的一些技巧经验。

然而Swing是什么? Swing是一个用于开发Java应用程序用户界面的开发工具包。它以抽象窗口工具包为基础使跨平台应用程序可以使用任何可插拔的外观风格。Swing开发人员只用很少的代码就可以利用Swing丰富、灵活的功能和模块化组件来创建优雅的用户界面。

通过本次游戏的设计,综合自己在校期间所学的理论知识,设计开发推箱子游戏,使自己熟悉应用系统的开发过程,培养独立思考能力,检验学习效果和动手能力,初步掌握软件工程的系统理论,进一步巩固和加强自身对java, swing基础知识的理解,提高自己的编程水平,从而达到理论与实践相结合的目的。由于时间仓促和本人水平有限,此游戏的制作显得有些粗糙,我以后将会再接再厉。

1可行性分析

1.1要求

在eclipse的开发环境下,利用所学java语言相关知识,开发一个推箱子小游戏,实现游戏界面规划、英雄走动、魔王动向等功能。建立一个java projec t工程,实现游戏的编程设计。

1.2目标

可包括:

a. 人力与设备费用的节省:单独开发

b. 界面友好美观:自绘技术实现

c. 游戏的可操作性,通过键盘的方向键实现

d. 游戏界面的游戏区

e. 等等

2 项目开发计划的任务分解

a. 建立一个java project工程

b. 建立一个Hero包

c. 画出游戏区域

d. 调整游戏窗口大小

e. 加载游戏相关图片

f. 计算游戏结果,判断是否进入下一关

3 概要设计

3.1游戏界面

背景图片如下:

3.2游戏四种基本图形

在游戏中相对应的图片分别为:

3.3英雄走向图形

图片如下:

3.4 箭头图片

3.5游戏操作

操作如下:

方向键左:左移

方向键右:右移

方向键上:上移

方向键下:下移

箱子只可以推, 不可以拉, 而且一次只能推动一个,胜利条件就是把所有的箱子都推到目的地。

4 需求规格说明

4.1运行环境

Microsoft Windows XP Microsoft Windows7 Eclipse

4.2功能需求

a. 图形左右移动

b. 图形上下移动

c. 实现开始,结束按钮的功能

d. 使游戏窗口最大化失效

4.3运行需求

硬件和软件接口:

1.cpu :1.6GHz以上

2.内存:256M以上

3.操纵系统:Micorsoft Windows XP Microsoft Windows 7

4.运行软件:Eclipse

5 详细设计

5.1 系统模块

本程序包括5个模块,分别是初始化模块、画图模块、移动箱子模块、移动小人模块和功能控制模块。各个模块的功能描述如下:

(1)初始化模块。

该模块包括屏幕初始化和游戏第一关的初始化。屏幕初始化用于输出欢迎

信息和操作提示,游戏每一关的初始化是构建每一关的关卡。

(2)画图模块。

该模块主要是被其它模块调用,用于画墙、在空地画箱子、在目的地画箱

子、画小人和画目的地。

(3)移动箱子模块。

该模块用于移动箱子,包括目的地之间、空地之间和目的地与空地之间的箱子移动。

(4)移动小人模块。

该模块用于控制小人移动,从而推动箱子到目的地。

(5)功能控制模块。

该模块是几个功能函数的集合,包括屏幕输出功能和指定位置状态判断功能。

5.2 任务执行流程

游戏从第一关开始,按上下左右方向键控制小人移动来推动箱子,可以在游戏中的按退出按钮进行退出。如果游戏无成功希望,可以按空格键回到当前任务的开始状态;如果成功完成当前关,则进入下一关。

5.3 小人移动流程

小人移动的方向有4个,moving()函数(处理小人移动的函数)对这4个方向移动的处理都一致,只是调用函数时的参数有所不同。首先判断小人移动的方向,然后根据小人所处世的当前状态、下一步状态或者下下一步状态进行适当的处理。

6界面实现

6.1 界面区

这个区域主要负责窗体的大小,背景,名称以及窗体不可改变等元素。

a.界面大小: this.setSize(540 + 4, 440 + 62);

b.界面背景: this.setBackground(Color.BLACK);

c.界面大小不可改变: this.setResizable(false);// 不能改变窗体大小

d.界面名称: this.setTitle("英雄传说II---吕季干");

e.界面的实现如下:

f.界面区总代码:

import java.awt.Toolkit;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class GameFrame extends JFrame {

private GamePanel gp = new GamePanel();

private ImageUtil iu = new ImageUtil();// 加载图片的工具

public GameFrame() {

init();

}

public void init() {

this.add(gp);// 加入画纸

this.setSize(540 + 4, 440 + 62);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setCursor(Toolkit.getDefaultToolkit().createCustomCursor( iu.getImage("cursor.png"), new Point(26, 29), "aaa"));

this.setResizable(false);// 不能改变窗体大小

this.setResizable(false);

this.setTitle("英雄传说II---吕季干");

// 加一个监听器,保镖,匿名类:匿名类的格式new 接口名(){ 接口中的方法的实现}

this.addKeyListener(new KeyListener() {

@Override

public void keyPressed(KeyEvent arg0) {

// TODO Auto-generated method stub

switch (arg0.getKeyCode()) {

// 0=向下1=向左2=向右3=向上

case 39:// System.out.println("英雄向右");

gp.setHeroF(2);

break;

case 40:// System.out.println("英雄向下");

gp.setHeroF(0);

break;

case 38:// System.out.println("英雄向上");

gp.setHeroF(3);

break;

case 37:// System.out.println("英雄向左");

gp.setHeroF(1);

break;

}

}

@Override

public void keyReleased(KeyEvent arg0) {

// TODO Auto-generated method stub

}

@Override

public void keyTyped(KeyEvent arg0) {

// TODO Auto-generated method stub

}

});

this.setVisible(true);

}

public static void main(String[] args) {

// TODO Auto-generated method stub

new GameFrame();

}

}

6.2 游戏区

这个区域主要完成游戏界面的大小等元素。

a.界面大小:this.setSize(600, 500);

b.界面实现如下图:

c.游戏区总代码:

package frame;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Image;

import javax.swing.JPanel;

public class GamePanel extends JPanel {

private static final long serialVersionUID = 6792476564904637059L;

private Image backImage; // 背景图片

private Image me;

private ImageUtil iu = new ImageUtil();// 加载图片的工具

private Hero hero = new Hero(this);

private Maps map = new Maps(this);

public Maps getMap() {

return map;

}

public void setMap(Maps map) {

this.map = map;

}

public GamePanel() {

this.setSize(600, 500);

this.setBackground(Color.BLACK);

backImage = iu.getImage("back1.jpg"); // 初始化背景图片

// heroImage = iu.getImage("role1.gif"); //英雄的图片

// me=iu.getImage("慧灵.jpg");

new D().start();// 启动线程

}

@Override

public void paint(Graphics g) {

g.drawImage(backImage, 0, 0, Color.BLACK, this);// 画出背景图片

g.drawImage(me, 0, 0, null);

boolean yes6 = map.draw(g);// 画地图

if (yes6) {

// 到下一关

map.setMap();

map.draw(g);// 画地图

}

// 画英雄

hero.draw(g);// 调用英雄的的画的方法,将并将画笔g传递过去,画出英雄

}

// 该方法用于改变英雄运行的方向

public void setHeroF(int f) {

hero.setF(f);// 将方向的改传给英雄

hero.setMoving(true);// 因为按了键所以可以移动

}

// 使用线程来完成,内部类:写在类里面的类

class D extends Thread {

public void run() {// 方法必须这么写

while (true) {

try {

Thread.sleep(40);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

GamePanel.this.repaint(); // 调用这个D对象外面的repaint()

}

}

}

public Hero getHero() {

return hero;

}

public void setHero(Hero hero) {

this.hero = hero;

}

}

6.3 图片加载区

这个区域主要负责加载各类型的图片,使界面变得美观等条件。

图片加载区总代码:

package frame;

import java.awt.Image;

import java.awt.Toolkit;

import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageUtil {

public Image getImage(String imageUrl) {

Image image = null;

try {

// 会将图片加载在内存中

image = ImageIO.read(this.getClass().getClassLoader()

.getResourceAsStream("image/" + imageUrl));

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return image;

}

}

6.4 英雄变化区

这个区域主要负责英雄的变化,如下:

a.英雄的起始坐标:

// 存放英雄起始位置的坐标

private int heroX = 200;

private int heroY = 200;

b.英雄起始的方向:

private int f = 0;// 0=向下1=向左2=向右3=向上

c.画英雄的方法:

public void draw(Graphics g) {

if (isMoving) {

moving();// 移动英雄

}

// g.drawImage(heroImage, 0, 0, 32, 32, 200, 200, 232, 232, this);

// 在屏幕上的左上角的X,Y和屏幕上的右下角X,Y,之间,

// 图片的左上角X,Y,图片上右下角

// g.drawImage(heroImage, heroX, heroY, heroX+32,

heroY+32,0,0,32,32,

// null);//向下

g.drawImage(heroImage, heroX, heroY, heroX + 32, heroY + 32, 0,

32 * f,

32, 32 * (f + 1), null);// 控制上下左右的图片

}

d.英雄坐标改变的方法:

public void moving() {

switch (f) {

case 0:

if (peng()) {

heroY += 32;

}

break;

case 1:

if (peng()) {

heroX -= 32;

}

break;

case 2:

if (peng()) {

heroX += 32;

}

break;

case 3:

if (peng()) {

heroY -= 32;

}

break;

}

isMoving = false; // 每移动一次就停止

// System.out.println("现在英雄的坐标是:"+heroX+"--"+heroY);

}

e.碰撞检测的方法,返回能走还是不能走

public boolean peng() {

// 1. 得到英雄在地图中的位置

int row = (heroY - 100) / 32;

int column = (heroX - 100) / 32;

// 2. 根椐英雄的位置及行进的方向,判断地图上是否可以行走

switch (f) {

// 0=向下1=向左2=向右3=向上

case 0:

// 得到地图对象中的地图数组

if (gp.getMap().getMap()[row + 1][column] == 2

|| gp.getMap().getMap()[row + 1][column] == 6) {

return true;

}

if (gp.getMap().getMap()[row + 1][column] == 10) { // 前面是魔王

if (gp.getMap().getMap()[row + 2][column] == 2) { // 前面前面是地板

gp.getMap().getMap()[row + 1][column] = 2;

gp.getMap().getMap()[row + 2][column] = 10;

return true;

}

if (gp.getMap().getMap()[row + 2][column] == 6) { // 前面前面是笼子

gp.getMap().getMap()[row + 1][column] = 2;

gp.getMap().getMap()[row + 2][column] = 14;

return true;

}

}

if (gp.getMap().getMap()[row + 1][column] == 14) { // 前面是带笼子魔王

if (gp.getMap().getMap()[row + 2][column] == 2) { // 前面前面是地板

gp.getMap().getMap()[row + 1][column] = 6; // 前面就变成笼子

gp.getMap().getMap()[row + 2][column] = 10; // 前面的前面变成了魔王

return true;

}

if (gp.getMap().getMap()[row + 2][column] == 6) { // 前面前面是笼子

gp.getMap().getMap()[row + 1][column] = 6; // 前面变成笼子

gp.getMap().getMap()[row + 2][column] = 14; // 前面前面变成带笼子的魔王

return true;

}

}

break;

case 1:

if (gp.getMap().getMap()[row][column - 1] == 2

|| gp.getMap().getMap()[row][column - 1] == 6) {

return true;

}

if (gp.getMap().getMap()[row][column - 1] == 10) { // 前面是魔王

if (gp.getMap().getMap()[row][column - 2] == 2) { // 前面前面是地板

gp.getMap().getMap()[row][column - 1] = 2;

gp.getMap().getMap()[row][column - 2] = 10;

return true;

}

if (gp.getMap().getMap()[row][column - 2] == 6) { // 前面前面是笼子

gp.getMap().getMap()[row][column - 1] = 2;

gp.getMap().getMap()[row][column - 2] = 14;

return true;

}

}

if (gp.getMap().getMap()[row][column - 1] == 14) { // 前面是带笼子魔王

if (gp.getMap().getMap()[row][column - 2] == 2) { // 前面前面是地板

gp.getMap().getMap()[row][column - 1] = 6; // 前面就变成笼子

gp.getMap().getMap()[row][column - 2] = 10; // 前面的前面变成了魔王

return true;

}

if (gp.getMap().getMap()[row][column - 2] == 6) { // 前面前面是笼子

相关文档
最新文档