基于Java的愤怒的小鸟游戏的设计与实现
摘 要
Java语言是一门面向对象的编程语言,它不但汲取了C++语言的各种精髓,而且还抛弃了C++语言里晦涩难懂的多继承和指针等概念,所以Java语言具有的特征便是:功能超强和易用实用。
Jbox2D中不仅集成了大量物理运动学和机械运动学计算,而且也将物理仿真包集成到类对象中,同时对象也应用在开发人员与用户的交互界面中。所以我们只需要调用对象或者使用相应的功能,就可以模拟出现实生活中的速度、加速度、抛物线运动、重力、碰撞、反弹等各种各样真实的物理运动。
愤怒的小鸟游戏的视角是横向版本的水平视角。背景是为了报复偷鸡蛋的猪,鸟将自己的身体作为武器,就像炮弹一样从弹弓上发射而出,撞向绿猪搭建的堡垒,以达到摧毁绿猪的目的。游戏非常简单,小鸟跳上弹弓,发射角度和强度的改变导致小鸟的落点的不同,玩家需要良好的整体计算,适当的调节强度和角度,从而更准确地击中绿猪。每次击中绿猪,便可获得一定的分数,积累足够的分数便可以通关,游戏设计的体现了放松的情调,乐观的风格。
本文将介绍使用Java语言实现经典的益智类游戏作品“愤怒的小鸟”的开发。游戏将主要实现以下几个功能:游戏玩法功能、页面管理功能、难度和级别功能、碰撞功能、鸟类管理功能、玩家管理功能和备份功能等。此游戏不仅可以给玩家带来欢乐,也会使玩家对开发游戏产生极大地兴趣,让玩家切身体会到Java语言在生活方面的无处不在。
关键词 :Java;C++;Jbox2D;物理运动;愤怒的小鸟
Abstract
Java language is an object-oriented programming language, it not only draws the essence of the C + + language, but also abandoned the C + + language obscure multi-inheritance and pointer concepts, so the Java language has the following characteristics: Super and easy to use practical.
Jbox2D not only integrates a large number of physical kinematics and mechanical kinematics calculations, but also the physical simulation package into the class object, while the object is also used in the developer and user interface. So we only need to call the object or use the appropriate function, you can simulate real life in the speed, acceleration, parabolic movement, gravity, collision, rebound and other real physical movement.
The type of game is horizontal horizontal view of the version. The background is to retaliate to steal the eggs of the pig, the birds will be their own body as a weapon, like shells from the slingshot thrown into the green pig fortress. The game is very simple, the birds on the slingshot, the angle of the pop-up and strength by the player's finger control, pay attention to a good overall calculation, the appropriate adjustment of strength and angle, and thus more accurately hit the pig. Each time hit more green pigs, will get a lot of scores, the game style is full of fun and humor, the game design reflects the relaxed atmosphere, optimistic style.
This article will introduce the use of Java language to achieve the classic puzzle game "angry bird" development. The game will mainly achieve the following functions: gameplay function, page management functions, difficulty and level function, collision function, bird management function, player management function and backup function. This program is intended to stimulate the use of the game to stimulate the use of players and learning interest, so that players experience the Java language in the life of countless.
Key words : Java; C++;Jbox2D; Physical movement; angry birds
1 绪论
1.1 游戏开发的背景
游戏如今已经成为人们生活中不可或缺的一部分,无论是处于童趣中的小孩、还是繁忙工作中的成人,游戏无疑在每一个人生活中起着非常重要的调剂作用。不管是实体玩具还是如今的电子游戏,它们都能给我们留下很多美好的回忆。
本人对Java语言有很大的兴趣爱好,大学期间便对其一直进行学习,而且游戏的制作同时也是我非常感兴趣的一个方面,在此之前也进行过一些小游戏的开发。经此次毕业设计机会,使得我想在专业导师的指导下通过这次毕业设计,来提高自己的Java语言水平,为以后的工作打下坚实的语言基础。
游戏名称是“愤怒的小鸟”,英文称为“AngryBird”。“愤怒的小鸟”是著名游戏公司Rovio偶然间开发出来的益智游戏,从2009年12月上市到iOS。,讲述了鸟类和猪因为猪偷鸟蛋反生的一系列故事。游戏的类型版本是横向版本的水平视角,背景是为了报复偷鸡蛋的猪,鸟将自己的身体作为武器,就像炮弹一样从弹弓射出抛到绿猪搭建的堡垒,并将其摧毁。游戏非常简单,小鸟跳上弹弓,发射角度和强度由玩家的自行控制,游戏中需要良好的整体计算,适当的调节强度和角度,从而更精确地击中猪。每次击中更多的绿猪,将获得大量的分数。游戏风格充满乐趣和幽默,游戏设计的体现了放松的情调,乐观的风格。
愤怒的小鸟这款游戏内容包含着丰富的人机交互:不管游戏本身设计的难度如何,只要玩家学会基本的游戏使用方法,大多数人都可以经过不断训练来打到通关这一目的。这一款益智类游戏的开发,目的是为了使人们更多了解物理引擎游戏所带来的与众不同。在今天如此复杂多样的游戏环境中,这一款游戏所带来的新鲜感让人为之疯狂,极大展现了Java语言在开发物理运动游戏方面独有的魅力,也极大促进了Java语言在游戏方面的发展。
1.2 典型的Java游戏介绍
1.2.1 Minecraft介绍
Minecraft是近乎是沙盒游戏的鼻祖,是由瑞典Mojang AB公司和4J Studios联合开发,发行于2009年,最后在2014年冬季被microsoft以25亿美金收购。
1.2.2 Super Mario Bros介绍
Super Mario Bros是任天堂游戏公司开发的,相信我们小时候都玩过这一款游戏,它几乎是所有红白机游戏中最畅销的一款,游戏风格是横版过关类型,这个游戏几乎移植到了所有已知的游戏平台,为游戏爱好者广泛而知。
1.2.3 The Sims介绍
这是一款由Electronic Arts,简称EA开发的以模拟一个人生活中各种事情为主的模拟养成类游戏,。在这个模拟的世界中,玩家可以操作游戏人物进行近乎于现实生活的行动,仿造真实的情境,控制生理和精神的需求。
1.3 游戏开发的意义
随着计算机科学的发展,游戏的发展已经取得非常显著的成果。图形计算、应用数学、数据结构、算法设计,甚至网络安全都已经应用在强大的游戏引擎中,而且由于快速做出原型是游戏开发的重要组成部分,所以应该学习如何高效率编写可重用的代码是一个很值得关注的问题。即使游戏没有为他人做出贡献,但至少它给了我很多的灵感,让我认识到作为一个程序员的兴趣所在,我可以继续为未来所需的知识量而努力。况且,游戏已经影响到人类生活的方方面面,成为生活不可或缺的一部分。甚至来说,游戏作为一种产业,已经跻身到互联网这个巨大的利益链的前列。目前,中国的游戏产业已然成为一个新的经济增长,极大地刺激了中国经济的发展,成为了中国六大支柱产业之一。
游戏的发展不仅带来了经济的利益,同时也极大地丰富了人类的生活,增强人们的幸福感,但游戏也存在不可避免的弊端,所以积极宣传中国传统文化,引导青少年健康游戏、快乐游戏应该是,每个游戏工作者的责任和义务。
2 开发环境
2.1 开发语言
Java语言是一种面向对象的编程语言,它不仅拥有着C++语言的长处,而且也将C++中的多重继承和指针等概念进行摒弃,Java语言不仅具有易用实用的特征,同时也是一种功能强大的编程语言。
Java语言的特征大致可以分为以下一些:简单性、面向对象、分布式开发、稳健性、安全性、平台独立性、可移植性和多线程以及动态特性。这些特性以及Java语言本身的强大,是Java语言得以风靡全球的根本原因。
Java语言从外部看起来确实很像C++语言,但是为了使Java语言不那么晦涩难懂和难于学习,开发设计人员将很多原本用于C++语言的功能进行选择性删除。比如:Java语言将重载和多个继承功能中的重载运算符排除在外,并且去除主文件,从而消除了预处理器。再由于Java语言准确的是没有结构的,并且字符串数组是对象,所以指针存在也是不必要的。去除C++语言的糟粕后,Java语言可以自动管理参考对象和间接引用、自动垃圾收集,这些功能都可由使用户不必担心内存管理问题,从在将更多的时间和精力投入到研发开发当中,无疑是大大提升了编程开发效率。
如图2-1为Java语言总体特点:
由于Java语言是面向对象的语言。所以对于程序员来说,这意味着数据必须在方法中声明和操纵,笼统来说,程序员只需要学习对方法的熟悉和使用,而不是严格的创造方法过程。Java语言的特点使得语句不单单依赖于实现的方面,这种特殊的特点使得Java环境本身对新的硬件平台和操作系统是可移植的,并且起重要作用的Java编译器也是用Java语言所编写的,而且还包括用ANSIC语言编写的Java运行时系统。Java语言旨在适应进化,这说明它是一种动态语言。
由于Java语言的本质,Java游戏不会受到太多来自软件运行平台的诸多限制。假如我们以Java语言进行开发时,哪怕要重新编译成千上万个类,也只不过是花费很少的时间便可以办到的事情,这是CPP编译速度所无法企及的。而Java语言语法在一定程度上要比C语言或者C++语言简洁方便很多,开发者只需要掌握一些基本语法,久而久之的学习,绝大多数人都可以使用Java语言轻易地进行开发程序。本文将以电脑为基础,采用Java语言来编写一款叫做“愤怒的小鸟”的游戏。
2.2 开发工具
Eclipse是一个将源代码的开放、基于Java语言的具有可扩展性的编程开发平台。就其本身而言,它仅仅只有一个框架与一组服务,将其通过插件组件来构建成一个开发环境。比较需要注意的是,Eclipse 还附带着一个标准的插件集,插件集中包含了各种开发工具,比如用于Java语言开发的Java开发工具(Java Development Kit,JDK)。Eclipse是著名的跨平台开发环境和自由集成开发环境的组合。它最初主要是用于Java语言的开发,在Eclipse中通过安装不同的插件,使得Eclipse具有可以支持不同的计算机语言的特性,比如C++语言和Python语言等开发语言。Eclipse简单来说,它本身仅仅只是一个框架平台,但是各种各样插件的支持使得Eclipse具有其他功能死板IDE软件所难以拥有的方便灵动性,这一特性让许多软件开发公司都将以Eclipse作为基本框架来开发属于自己的IDE。
Eclipse起始于1999年4月,它最开始是由OTI和IBM这两家巨头公司的IDE产品开发项目组合力创建,。Eclipse基础代码最初是由IBM提供的,其中包括JDT 、PDE 和Platform。Eclipse项目经由IBM发起,经过这么多年的发展, Eclipse这一当初小小的项目已然发展成为了一个巨大的Eclipse联盟,目前为止,大概有140多家软件公司先后参与到Eclipse开发项目中,其中包括Red Hat和Sybase等公司。Eclipse本身作为一个开源的项目,它的初衷作为是作为Visual Age for Java的替代品,所以Eclipse的界面效果与早期版本的Visual Age for Java相差不大,后来随着开放源代码,任何开发人员不仅可以免费得到Eclipse,而且可以在它的基础上进行各自插件的开发,这一缘由导致Eclipse受到越来越多的人的欢迎。在此之后还有包括Oracle等在内的许多软件大公司也先后加入了该项目,使得Eclipse到目前为止已经成为任何语言开发的IDE集成者,也是Java语言开发使用最广泛的平台。
2.3 JDK介绍
JDK是Java语言的软件开发工具包(Java Development Kit),它在java语言开发中占有核心的地位,它包括Java的运行环境,java的基本工具和java的基础库等。 JDK包含的基本组件包括:
-
javac编译器 :javac编译器自动读取由java语言编写而成的类和接口的定义等,并将它们编译成字节代码(class文件)
-
jar打包工具 :将相关的类文件整合为一个文件
-
javadoc文档生成器 :从源码中将注释提取为一个文档
-
jdb debugger :调试工具
-
jav :可将编译后的java程序(.class后缀的程序)运行
-
appletviewer :可在脱机环境的情况下运行applet
-
Javah :创建一个可以被Java程序所调用的C过程的头文件
-
Javap :一种进行反编译的工具
-
Jconsole :Java中可以对系统进行监控和调试的工具
2.4 Java Awt介绍
AWT(Abstract Window Toolkit),中文翻译是:抽象窗口工具包,该包提供了一个GUI交互的接口,Java提供了用于创建和配置Java GUI的基本工具。AWT中图形操作函数与系统中图形功能之间提供了一对一的关系,称为peeres,当开发者使用AWT编写图形用户界面时,实际上是使用本地操作系统所提供的图形库。由于各种操作系统的风格和功能不同,所以提供的图形库不一样,在一个平台上可能存在的功能反而在另一个平台不存在。为了实现“写一次(编写一次,任意平台都可以运行”)Java语言的概念,AWT必须以牺牲独立平台功能为代价,由各种系统提供的AWT图形功能的交集来作为awt图形功能的可用功能。
如下图为awt的几种基本布局:
AWT在基础组件(components)的GUI应用于提供JavaApplet和Java Application。由于Java是一种独立于平台的编程语言,而是通常将GUI链接到特定的平台,Java技术允许使用相应的AWT可以提供一个平台接口独立应用于某个机器,这保证了相同的程序操作GUI 在不同的机器上具有相似的界面效果(但是并不能保证一定相同)。
来自AWT Java1.0(旧AWT)的和AWT Java1.1(新AWT)之后的有着截然不同的情况,新的AWT相比于旧的AWT有这更显着的改进并且摒弃了很多缺点,从而新的AWT可以更加方便的使用,这篇论文主要是讨论新的AWT,但不可否认在Java1.1中更旧版本的AWT程序也可以运行。
Abstract Window Toolkit(AWT)使用Java语言来操纵位图显示窗口,为一个图形过程库。最后,扩展设计人员将AWT扩充为AWT Window Alternative Toolkit和Applet Widget Toolkit。最新的图形界面叫做Swing,扩展了AWT,Swing应用程序开发人员可以使用它来生成独立的GUI平台对象。
2.5 JavaSwing 介绍
Java Swing 作为一个GUI工具包,是专门为Java设计与使用的,也是Java基础类的一部分,其中包含的一些组件如文本框、分割窗格、表格、按钮等
Java Swing可以提供的屏幕显示元素,在某种程度上要比Java Awt提供的要好的多。由于Java Swing使用纯Java语言编写的,在这一点上不与AWT相同,所以Java Swing拥有与Java语言一样的可扩展性,可以在多种平台上使用,并且Java Swing也是JFC的一部分。Java Swing可以对面板和主题进行变更(操作系统中存在着默认的主题,不同操作系统的主题不尽相同),这并不是真正的去使用这种操作系统的设备,只是在一定程度上在表面上模仿。这些特殊的功能导致程序猿可以可以使用Java的任何面板,并且不需要操作系统的限制。如下图2-4为Java swing 基本组成:
-
JFrame : java中的GUI是以JFrame为基础的一种基本思路,它是屏幕上创建window的对象,通过调用一些特定的方法,可以实现界面的最大化、最小化、关闭
-
JPanel :作为Java GUI 下的swing中的面板容器类,它包含在javax.swing 包中,使用的时候可以对其进行嵌套,它的功能是在窗体的使用中对其具有相同逻辑功能的组件进行整合,同时也是是一种轻量级容器,使用中可以加入到JFrame窗体中
-
JLabel :JLabel 对象的功能是可以将文本、图像进行显示或同时对二者进行显示。它有垂直和水平两种对齐方式,可以指定标签显示区中的标签内容在任意一处进行对齐。通常默认情况下,标签默认在显示区域内居中垂直对齐,而且,显示文本的标签是开始一种边对齐,显示图像的标签则是居中水平对齐
-
JTextField :它可以进行编辑单行文本,是一个轻量级的组件
-
JPasswordField :功能是让我们输入了一个文本框类似于输入框,但是在输入密码的时候讲密码进行隐藏,类似替换成*符号
-
JButton :JButton 类的实现类,功能是在面板中创建按钮,可以对齐进行点击之类的操作。比如我们经常使用的登录、注册按钮
2.6 Java语言开发平台搭建
首先登陆到官方网站 http://www.oracle.com ,之后跳转到JDK下载页面下载Java JDK ,版本选择最新的jdk1.8.0_131进行下载,下载界面如下图2-5所示:
下载完成后安装JDK,安装路径为F:\Java\jdk1.8.0_131,安装路径如下图2-6所示:
安装完成JDK之后登陆网址 https://www.Eclipse.org ,进行下载Eclipse,下载界面如下图2-7所示:
下载后,安装完成打开Eclipse,点击菜单栏上的window-preference进行配置JDK,之后便可以使用Eclipse进行编程开发,配置方式如下图2-8所示:
如下图2-9位Eclipse的基本使用界面,通过多次使用来进行熟悉即可。
3 系统需求分析
3.1 可行性分析
可行性分析是要求以经济方法和效益为核心进行全面的系统分析,围绕影响项目的各种因素、收集大量数据分析论证项目的可行性。对整个项目进行可行性研究是为了对项目进行分析和评估,突出项目的优缺点和讨论如何对项目进行改进。为了结论的可行性,经常还需要添加一些配件,如测试数据、演示材料、电子表格、图纸等,以提高可行性研究的严谨性,使其更具有说服力。
3.1.1 技术可行性
技术可行性是从重要技术项目执行实施的角度,合理设计技术解决方案,进行比较评估不同行业和不同深度的大型技术可行性研究项目。这一款软件开发,在硬件方面不存在特殊要求,只需要在普通的硬件配置中便可以轻松实现,但必须保证系统的正常运行,并提高效率。如果硬件特别弱、性能差从而使得系统效率低下,导致整个系统不顺畅。但对于如今的个人PC的一般配置,进行软件开发是很容易满足条件的。因此,该系统的开发在硬件方面完全可行。操作系统选择WINDOWS操作系统,开发软件为Eclipse,该系统的设计实现在软件方面是可行的。因此可以看出,该系统的开发是没有问题的。
3.1.2 经济可行性
经济可行性是在资源配置、区域经济发展目标、经济资源有效配置、增加供给、创造就业机会、改善环境、改善生活等方面,对项目的价值进行评估。本基于Java开发的愤怒的小鸟游戏,需要的软硬件环境,在市场上都是很方便可以购买得到,开发人员主要是进行软件开发和简单的维护。所以人力和财力资源开发方面没有问题,开发周期长,经济可行性很大。
3.1.3 操作可行性
操作可行性是设想项目验证是可行的,它提出了各种方案的实施,并解释了不同方案的优缺点。该系统使用基于Java语言编写,使用个人PC安装Eclipse来进行访问和操做,并且界面简单易用,只要用户稍加以学习和多试几次,完全可以熟悉访问和操作。这一款愤怒的小鸟游戏,有着界面上易于管理和良好的互动操作等各种优点。
3.1.4 发展可行性
软件生命周期的观点:随着中国游戏方面还处于成长期,这类游戏软件将会被广大用户提出需求。因此,这是游戏软件长寿的主要原因,开发一款游戏软件,合理的运营将会使它和谐的发展,而且这并不是一个太难的开发项目,它不仅可以在PC端进行操作使用,甚至可以跨平台传播,而且用户操作简单,使用起来非常方便,绝大多数用户都可以不用花费大量的时间便可以完全上手,这不仅是适应用户对游戏的追求,同时适应当前的游戏发展趋势。
3.2 性能需求分析
为了保证愤怒的小鸟程序的长期、稳定和有效的运作,必须保证系统的发展。在开发基于Java语言的愤怒的小鸟程序的过程中,系统必须确保使用适当方法来保证程序的安全性和有效性。我们必须充分考虑以下几点:
-
安全性 :在信息时代,信息是确保信息安全的重要资产,特别是个人信息也需要强大的安全性,所以在游戏个人信息保存方面,应该确保安全性是第一位
-
超前性 :结合当今时尚潮流,开发满足用户需求,让用户总是可以第一时间获得超前的游戏体验,获得新鲜感,获得新的乐趣
-
可扩展性 :基于Java的愤怒的小鸟游戏不仅可以在PC端进行使用,由于Java语言的可扩展性,注定这个游戏也可以进行多平台使用,更加方便的获取以及更加方便的操作
3.3 功能需求分析
需求分析是对用户需求和要求的分析。需要准确评估用户需求的结果从而反映实际用户需要,这将直接影响整个设计的流程,也会对系统的使用产生影响。关注需求评估来完成调查收集和研究,可能会受到数据管理和信息安全过程的影响。一般用户相对于开发者来说,绝大部分用户都是缺少计算机相关知识,并且无法确定计算机是否可以为自己做到或者做不到一些事情,准确表达他们的需求是需要的,必须通过跟用户的深入了解来获取用户的需求从而准确的确定计算机的功能。
搜索用户分析和细化特征等用户的描述的信息是必要的。它是软件开发过程的第一阶段主要部分,主要任务是了解您需要什么,需要做个什么样的系统,使完整的目标系统拥有清晰准确的功能,并且可以进行书面表达。
- 游戏玩法功能
- 能实现发射器创建、发射角度、发射力度等
- 可以实现小鸟飞行功能,包括小鸟飞行抛物线、小鸟飞行悬停
- 实现游戏中猪的移动功能,包括猪的根据级别不同改变移动速度、猪在哪里移动
-
碰撞功能:实现小鸟与障碍的碰撞、小鸟与猪的碰撞、鸡蛋与障碍物的碰撞、鸡蛋与猪的碰撞、猪与障碍物的碰撞
-
页面管理功能 :实现各个页面功能,包括主界面、载入游戏界面、控制帮助界面、跳转界面功能等
-
难度、级别功能 :实现游戏难度功能,难度不同猪的移动速度不同,实现级别功能,级别不同地图难易程度也不同
-
实体类管理功能 :创建游戏中各种实体类,包括鸟的种类、猪、障碍物、草地等
-
玩家管理功能和备份功能 :实现玩家信息管理以及游戏信息保存的功能
3.4 系统UML分析
UML是在面向对象的方法Booch,TMO,OOSE等基础上开发的方法,以及根据许多其他方法和材料的基础从而衍变出来的。UML符号是为各种图形符号表示,消除混淆、冗余符号或很少使用以及容易导致的图形符号,同时添加一些新的图形符号。
UML是统一建模语言的缩写,也称为统一建模语言。它是用于可视化建模的一种语言。 UML是开发人员用于建模事物的客观标记,同时也为开发人员了解什么样的系统工作以及整个过程做出了准备工作。现在我们在这个基础上对愤怒的小鸟进行建模分析,UML用例图如下图3-2所示:
UML界面用例图
UML游戏操作用例图
3.5 界面需求分析
目前,界面设计已成为软件质量评估的重要指标,良好的用户界面能提高用户操作系统的信心和增加兴趣、提高效率。客户界面是指与用户与机器进行交互的软件系统界面,通常覆盖界面格式输出,输入和其他人机对话。
-
输出设计 :输出是游戏程序解决基本信息的输入,产生高质量的正确信息,并使其具有一定的格式,供管理人员使用,这是发布设计和目标的主要责任和目标。与系统开发过程的实现不同,不是从输入设计到输出,而是输处设计到输入到设计。这是因为输出表与用户直接链接,应设计为确保用户可以方便地使用输出表格,及时将有用的信息可以反映在各个部门
-
输入设计 :收集和输入输出数据更加不方便,需要大量的人力物力,而且经常出错。一旦不正确的数据输入系统,处理后的输出会扩大这些错误,所以输入数据的准确性对系统的整体性能起决定性的作用。输入设计有以下几点原则:
- 输入量必须最小程度的满足处理要求。输入数据越少,错误率会越小,数据准备时间也较少
- 如果可能的话,尝试尽可能方便的准备和输入过程,以减少更多的发生错误发生率
- 尽早检查输入数据(尽可能靠近原始数据生成点),及时进行纠错更改
- 可能会尽可能早地将输入数据记录所需的处理形式进行记录,以防止从一个介质传输到另一个介质而可能发生的转录数据错误
4 系统设计
4.1 系统流程设计
在设计开发基于Java语言的愤怒的小鸟的时候,必须先进行需求分析,这样才可以对系统总体进行概括性规划,从而进行系统功能模块的设计、测试、基于Java语言的愤怒的小鸟的总体设计流程图, 如下图4-1所示:
该程序在游戏概念和属性中使用面向对象的模型。运行程序后,用户可以选择运行选项菜单,屏幕刷新屏幕重新设计一定频率,实时反映游戏状态。
如下图3-2显示了游戏控制的流程图。首先,当游戏运行时会成为测试的关键角色,同时响应方向。这是对鸟类在屏幕的主要方向的响应,同时检测释放的鸟类的强度。如果你摧毁对象超过一个固定的分数,导致游戏结束。当物体被鸟类摧毁时,根据物体的破坏得到不同的分数。
同时,还有其他检测键,主要用于检测菜单键。菜单按钮包括检测输出和返回参数。当游戏检测到退出按钮时,游戏结束。当检测到游戏的返回键时,游戏将返回到主屏幕。
4.2 系统架构设计
系统架构设计模型采用MVC经典建模模型,使用面向对象设计思想来帮助实现。 MVC全名模型视图控制器(Model-View-Controller),M、V、C分别是指逻辑模型、指视图模型、控制器。MVC已经开发成了用于图形用户界面中常规映射输入,处理和输出逻辑功能的独特结构。
我们参考的模型是一个对应于多个逻辑模型的视图模型,我们使用这个模型将视图模型的代码和逻辑模型的代码分开,以便我们可以以不同的形式实现相同的程序,然后控制台的控制着两者同时工作,其中一个变化,另一个应该同时更新。
用户对此模型的最大优势是根据自己的方式选择更加适合自己的方式来浏览数据。对于那些开发人员来说,这种模式的最大优点就是分离界面和应用程序的逻辑层,这个界面和程序员的设计者可以在格子的领域工作,而不会互相干扰。
Model(模型) :
-
GameModel() :实现游戏主要功能,包括碰撞、发射、得分
-
Level() :实现游戏难度、地图功能
-
LevelNumber() :存储地图功能
-
ListChangedEvent()、ListListener() :碰撞功能的监听
-
Player() :玩家备份功能
-
Entity()、Bird()、Block()、Egg()、Enemy()、EntityThread()、Grass()、HummingBird()、Pig()、Pigeon()、Sparrow() :定义游戏中各种模型的实体类
View(视图) :
-
GameView() :实现游戏中发射皮筋功能
-
GameViewMenu() :实现背景界面及标题功
-
MenuDifficultyView() :实现难度选择界面
-
MenuHomeView() :实现主界面
-
MenuLevelView() :实现级别选择界面
-
MenuLoadView() :实现确认及删除界面
-
MenuNewView() :实现增加玩家信息界面
-
MenuOptionsView() :实现控制帮助
Controller(控制器) :
-
eController() :实现监听事件(键盘,鼠标,更改实体列表)
-
nuController() :实现菜单控制界面跳转等功能
5 详细设计
5.1 主界面实现
(见图5-1)当玩家开始游戏时,共有4个选择:开始一个新游戏,加载一个保存的游戏,了解游戏控制或离开游戏。如果启动新游戏,则需要输入其名称,以创建备份。如果决定加载保存的游戏,玩家从已经备份的名称中进行选择。如果点击控制帮助选项,玩家将会看到游戏控制的帮助内容,以便更好的了解游戏、更容易上手。如果选择退出游戏,则游戏会立刻关闭。
部分代码以及相应的页面布局 :
```java
public class MenuHomeView extends GameViewMenu
{
private JButton newButton,loadButton,optionsButton,exitButton;
public MenuHomeView() {
newButton = new JButton("新游戏");
newButton.setSize(250,40);
newButton.setLocation(frameWidth/2-115, 150);
loadButton = new JButton("载入游戏");
loadButton.setSize(250,40);
loadButton.setLocation(frameWidth/2-115, 225);
optionsButton = new JButton("控制帮助");
optionsButton.setSize(250,40);
optionsButton.setLocation(frameWidth/2-115, 300);
exitButton = new JButton("退出游戏");
exitButton.setSize(250,40);
exitButton.setLocation(frameWidth/2-115, 375);
backButton.setVisible(false);
this.add(newButton,new Integer(1));
this.add(loadButton,new Integer(1));
this.add(optionsButton,new Integer(1));
this.add(exitButton,new Integer(1));
}
public JButton getNewButton()
{
return newButton;
}
public JButton getLoadButton()
{
return loadButton;
}
public JButton getOptionsButton()
{
return optionsButton;
}
public JButton getExitButton()
{
return exitButton;
}
} ```
5.2 游戏玩法实现
(见图5-2及5-3)选择一个级别后游戏开始。 首先玩家必须选择弹出一只鸟(游戏中总共有三只鸟供玩家使用),根据鸟的特点,玩家可以决定在飞行期间是否停止鸟,同时鸟也可以扔一个鸟蛋(鸟蛋的数量取决于不同的鸟的种类)。 玩家可以使用鸟蛋碰撞或直接鸟本身碰撞消灭阻碍物。 最后,玩家还可以借助鸡蛋或鸟类本身杀死绿猪,有时可能需要摧毁阻碍物才能到达消灭某些猪的目的。
图5-3为刚进入游戏时的界面,右上角显示还剩下几种鸟可以使用以及剩余鸟的数量,金色的蛋表示鸟剩余蛋的数量:
图5-4表示鸟在飞行过程中的状态,飞行中可以按S键将小鸟悬停在空中,然后可以按space键释放鸟蛋:
部分代码(创建面板以及地图的代码)以及相应的页面布局 :
```java
public GameView(ArrayList
this.entities = entities;
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(map.getImage(), 0, 0,frameWidth,frameHeight, this);
g2d.drawImage(slingShotImg2, 100,412, this);
int k = 0;
for(int i = entities.size()-1; i >=0;i--) {
Entity e = entities.get(i);
if(e instanceof Bird && e != currentBird) {
g2d.drawImage(e.getImage(), frameWidth-100-k*15, 100,e.getImageWidth(),e.getImageHeight(), this);
k++;
}
if(e == currentBird)
{
Egg egg = new Egg(0,0,28,30);
for (int j = 0; j < currentBird.getEggLeft(); ++j) {
g2d.drawImage(egg.getImage(), frameWidth-100+j*15, 20, this);
}
}
}
for (Entity e : entities) {
if (!(e instanceof Bird))
{
g2d.drawImage(e.getImage(), (int) e.getPosition().getX(), (int) e.getPosition().getY(), this);
}
if(e== currentBird )
{
g2d.setStroke(new BasicStroke(7.0f));
g2d.setColor(new Color(54, 28, 13));
//drawLine()划线的方法
if(!currentBird.isFlying())
g2d.drawLine(135,442, (int)e.getPosition().getX()+e.getImageWidth()/2, (int)e.getPosition().getY()+e.getImageHeight()/2);
g2d.drawImage(e.getImage(), (int) e.getPosition().getX(), (int) e.getPosition().getY(),e.getImageWidth(),e.getImageHeight(), this);
if(!currentBird.isFlying())
g2d.drawLine(120,442, (int)e.getPosition().getX()+e.getImageWidth()/2, (int)e.getPosition().getY()+e.getImageHeight()/2);
}
g2d.setStroke(new BasicStroke(7.0f));
g2d.setColor(new Color(54, 28, 13));
if(currentBird.isFlying())
g2d.drawLine(135,442,120,442);
g2d.setStroke(new BasicStroke(1.0f));
g2d.setColor(new Color(0, 0, 0));
}
g2d.drawImage(slingShotImg1, 100, 412, this);
g.drawString("Highest Score : " + currentHighestScore, 10, 15);
g.drawString("Flying time left : " + currentBird.getFlyingTimeLeft(), 10, 30);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void setEntityList(ArrayList<Entity> entities) {
this.entities = entities;
}
public Level getMap() {
return map;
}
public void setMap(Level map) {
this.map = map;
}
public void setCurrentHighestScore(int highestScore) {
this.currentHighestScore = highestScore;
}
@Override
public void listChanged(ListChangedEvent event) {
entities = event.getEntityList();
currentBird = event.getCurrentBird();
repaint();
}
} ```
5.3 面板管理功能实现
菜单管理通过6个不同的面板进行如图5-5所示:
-
MenuHomeView :游戏启动时的主页
-
MenuNewView :创建新部分的页面
-
MenuLoadView :加载游戏页面
-
MenuControlsView :游戏控制信息页面
-
MenuDifficultyView :游戏选择页面
-
MenuLevelView :级别选择页面
每个面板的实现一个特定的功能,但是它们都继承自GameViewMenu(abstract)类,该类具有所有面板共同的功能,例如Menu背景。GameViewMenu继承自JLayeredPane类,它允许向放置在面板上的元素分配不同的深度,这使得我们将按钮按照自己的意愿放置在在已经创建好背景上。菜单中的导航按钮通过创建鼠标的各种监听来完成,对于返回按钮的设置,使用 “转义”键通过键盘设置了额外的控制(相当于使用按钮“返回”)。 然后,检测窗口和窗口中的先前显示的面板。 在选择面板的时候,可以从新的游戏或者加载游戏等进行面板的访问。接下来的所示一系列图为各个面板:
创建备份面板 :在此处可以输入玩家的用户名,点击确认后可以保存玩家信息:
载入游戏面板 :在此处玩家可以选择之前的存档,然后接着上次游戏内容继续进行游戏:
控制游戏面板 :此处是整个游戏需要学会的操作方式:
难度选择面板 :此处可以对游戏进行难度选择,选择不同的难度,小猪的移动各不相同,随着难度的提高,小猪的移动速度越来越快:
级别选择面板 :此处选择不同的级别,导致进入的关卡不同,随着关卡级别的提高,关卡的地形难度会越来越高:
5.4 等级、级别管理功能实现
创建一个文本文件来管理等级,所有的游戏等级都依赖于这个文本,以下内容为等级管理功能的详细解释:此功能可用于实现某个级别的鸟类、阻碍物以及猪在这个环境中的位置、鸟类列表列在文件的顶部。
鸟类的等级与其出现顺序相同。在行中的字符串和不同类型的鸟的名字对等,以创建相应的鸟,并将其添加到实体的ArrayList。当程序阅读文本时,遇到“地图(Map)”一词时,程序便可以从该文本中知道可用于该级别的鸟类列表是完整的,并且文件同时也包含表示级别的地图。这些是相同大小的文本行,包含将在二维数组中实现的不同字符(文本文件的每一行对应于2D数组中的一行)。每个元素都包含在具有26 * 26像素的相应图像中,并且在此图像对应的尺寸为1200 * 600像素的窗口中,该表的一行包含47个元素,一列包含22.每个字符对应于不同的元素装饰:
-
“0”表示地图上没有任何内容
-
“1”表示地图上现在有一个草块
-
“2”表示地图上现在有一块阻碍物
-
“3”表示敌方猪的起始位置
图5-11所示的为游戏的基本地图:
相应的实体(猪,草块或阻碍物)是通过特定元素(“猪”,“草块”或“阻碍物”)创建的。 该实体通过构造函数创建,取其位置x(使用表的列索引和与实体对应的图像的大小计算)及其位置y(以l为单位计算)使用数组的行索引和 与实体对应的图像的大小)。
部分代码以及相应的页面布局 :
```java
public class Level {
private String backgroundImagePath = "res/images/background.png"; private Image image;
private int tabMap[][];
private int tabMapSizeX = 47;
private int tabMapSizeY = 22;
private int blockSize = 26;
private String grassImagePath = "res/images/grass.png";
private Image grass;
private String blockImagePath = "res/images/block.png";
private Image block;
private boolean isLoaded;
private ArrayList
public Level(String fileMapPath, String difficulty) {
ImageIcon ii = new ImageIcon(backgroundImagePath);
image = ii.getImage();
ImageIcon gr = new ImageIcon(grassImagePath);
grass = gr.getImage();
ImageIcon bl = new ImageIcon(blockImagePath);
block = bl.getImage();
if (difficulty == "easy")
pigSpeed = 0;
if (difficulty == "medium")
pigSpeed = 1;
if (difficulty == "hard")
pigSpeed = 2;
if (difficulty == "extreme")
pigSpeed = 3;
entities = new ArrayList<Entity>();
try {
FileInputStream ips = new FileInputStream(fileMapPath);
isLoaded = true;
InputStreamReader ipsr = new InputStreamReader(ips);
BufferedReader br = new BufferedReader(ipsr);
String line;
line = br.readLine();
while (!line.equals("Map")) {
if (line.equals("Pigeon")){
entities.add(new Pigeon());
}
if (line.equals("Humming Bird")){
entities.add(new HummingBird());
}
if (line.equals("Sparrow")){
entities.add(new Sparrow());
}
line = br.readLine();
}
tabMap = new int[tabMapSizeY][tabMapSizeX];
for (int i = 0; i < tabMapSizeY; i++) {
line = br.readLine();
for (int j = 0; j < tabMapSizeX; j++) {
char car = line.charAt(j);
String st = String.valueOf(car);
tabMap[i][j] = Integer.parseInt(st);
if (tabMap[i][j] == 3)
entities.add(new Pig(j * blockSize, i * blockSize, pigSpeed));
if (tabMap[i][j] == 2)
entities.add(new Block(j * blockSize, i * blockSize, blockSize, blockSize));
if (tabMap[i][j] == 1)
entities.add(new Grass(j * blockSize, i * blockSize, blockSize, blockSize));
}
}
}
catch (Exception e) {
isLoaded = false;
}
}
```
5.5 碰撞管理功能实现
碰撞管理和与其相关的事件在updateEntity()函数中执行。 创建的每个实体都具有hitBox,也就是说,每个图形对象都被一个碰撞矩形包围。 然后,按照实体的处理,通过测试其hitBox是否与其他人的hitBox相交的方式,来进行碰撞的各种处理。
如果一个元素与另一个元素的冲突导致删除两个对象之一,则程序会将一个或多个元素添加到实体列表(toRemove()调用)。 反过来,这在函数结束时遍历,以执行GameModel中实体的删除。 这使得可以在算法中删除相同级别的所有相关实体,并确保在删除它们之前已经执行了实体上的所有进程。 各种管理冲突如下:
- 鸡蛋碰撞
- 与绿猪:当检测到碰撞时,绿猪和当前的鸡蛋被添加到要删除的实体列表中
- 蛋与阻碍物:在要删除的实体列表中涉及到阻碍物和相关蛋的处理
-
与草块:碰撞导致当前的蛋被地添加到toRemove()列表。 草地是坚不可摧的
-
猪碰撞
-
与阻碍物
- 管理碰撞:碰撞的管理是不同的,在这里,因为在阻碍物与猪的碰撞矩形上没有完成。 实际上,猪可以在阻碍物上自由移动,但是当它们从侧面撞击一块阻碍物时,碰撞必须导致猪的方向移动。 必须能够测试块的hitBox的哪个边缘,猪的hitBox相交
- 事件:当猪碰到一块阻碍物的左边缘或右边缘时,猪会改变运动方向(左侧或右侧); 当猪不与其中一块阻碍物(即猪的任何阻碍物上移动)的一个上边缘碰撞时,猪坠落,直到它碰到其中一个块阻碍物或草,则猪会进行反向移动,而块的下边缘猪不会进行改变方向
- 猪:当两头猪相遇时,这两头猪就会改变方向
-
鸟类碰撞
- 阻碍物:当一只鸟与一块阻碍物碰撞时,这两个实体被添加到删除列表中。可以再次证明在功能结束时选择对缺失的处理。只有当鸟类被第一个块的碰撞检测直接攻击时,其他将会崩溃的块将不会被测试
- 与猪一起:鸟和猪的碰撞导致在删除列表中添加这两个实体
在theupdateEntity()函数中,可以看到位置所在的实体(左,右或底部),相关要素被添加到删除列表中。
部分代码以及相应的页面布局 :
```java if(entity == currentBird) { Bird bird = (Bird) entity; if(!bird.isVisible()) toRemove.add(bird); Rectangle hitBoxBird = bird.getHitBox(); for(Entity entity2 : entities) { if(entity2 instanceof Block) { Block block = (Block) entity2; Rectangle hitBoxBlock = entity2.getHitBox(); if(hitBoxBird.intersects(hitBoxBlock)) { toRemove.add(block); toRemove.add(bird); } } } for(Entity entity2 : entities) { if (entity2 instanceof Pig) { Pig pig = (Pig) entity2; Rectangle hitBoxPig = pig.getHitBox(); if(hitBoxBird.intersects(hitBoxPig)) { toRemove.add(pig); toRemove.add(bird); boolean win = true; for (Entity entity3 : entities) { if (entity3 instanceof Pig && !toRemove.contains(entity3)) { win = false; break; } } if (win) {
for (Entity entity3 : entities) {
if (entity3 instanceof Bird)
++score;
}
win();
}
}
}
}
for (Entity entity2 : entities) {
if (entity2 instanceof Bird && !toRemove.contains(entity2)) {
currentBird = (Bird) entity2;
break;
}
}
}
}
for(Entity entity : toRemove)
entities.remove(entity);
for(Entity entity4 : entities){
if(entity4 instanceof Bird)
birdTest++;
if(entity4 instanceof Pig)
pigTest++;
if(entity4 instanceof Egg)
{
eggTest++;
}
}
if(birdTest==0 && eggTest==0 && pigTest!=0){
angryView.repaint();
lose();
}
} ```
5.6 鸟类管理功能实现
-
所有鸟类都继承了抽象类Bird
-
创建当前的鸟 :当前的鸟,位于弹弓上的鸟是通过浏览实体列表顺序找到的第一只鸟。 要将鸟类定义为当前目录,扫描实体列表,当检测到Bird的第一个实例时,将在该实例上放置currentBird指针
-
鸟的状态 :当鸟儿飞行时,他们有两个阶段:第一个准备飞行和一秒钟的飞行。 准备不良:鸟类位于抛石机上,玩家有可能试着对弹弓进行拉伸,以确定初始速度和进行鸟投掷的初始角度。 要做到这一点,玩家必须点击弹弓上的鸟,然后拖动它,同时按住鼠标按钮。 当释放鼠标按钮时,鸟类切换到飞行模式(isFlying布尔值设置为true)
-
飞行阶段 :飞行中的鸟类受到加速度公式,Y中的加速度为9.81(模拟重力)。鸟的位置被修改为时间,角度初始速度和施加的初始速度的函数。 在飞行中,玩家有可能释放鸡蛋(在分配的鸡蛋数量的限制内:eggLeft)。玩家也可以将鸟类允许(鸽子或蜂鸟)悬停。目前的鸟的死亡:当目前的鸟死亡(与块碰撞,与猪碰撞,在窗口中消失或飞行时间用完),鸟被添加到updateEntity函数的删除列表中删除。然后,再次返回列表,以确定新的当前鸟
部分代码以及相应的页面布局 :
```java
public abstract class Bird extends Entity {
protected short flyingTime;
protected int eggLeft;
protected ArrayList
protected boolean isMoving;
private double time;
protected Dimension frameSize;
private double accelX;
private double accelY;
protected int startLocationX;
protected int startLocationY;
private long lastTime;
private long flyingTimeLeft;
public Bird(int width, int height) {
super(100,440,width,height);
isMoving = false;
time = 0.1;
accelX = 0;
startLocationX = 100;
startLocationY = 440;
accelY = 9.81;
flyingTimeLeft = 10000;
}
public int getEggLeft() {
return eggLeft;
}
public void setEggLeft(int i) {
this.eggLeft = i;
}
public int getStartLocationX()
{
return startLocationX;
}
public int getStartLocationY()
{
return startLocationY;
}
public abstract void hovering();
public boolean isFlying() {
return isFlying;
}
public void move() {
if(isFlying){
if(isMoving){
hitBox.x = (int) Math.round(speed*Math.cos(angle)*time+0.5*accelX*time*time+startLocationX);
hitBox.y = (int) Math.round(0.5*accelY*time*time-Math.sin(angle)*speed*time+startLocationY);
time+=0.1;
}
long currentTime = System.currentTimeMillis();
flyingTimeLeft -= (currentTime - lastTime);
lastTime = currentTime;
}
if (hitBox.y > (int) frameSize.getHeight() || hitBox.x > (int) frameSize.getWidth() ||flyingTimeLeft <= 0 )
visible = false;
}
public void launch(){
isMoving = true;
isFlying = true;
lastTime = System.currentTimeMillis();
}
public void moveRight() {
accelX+=0.1;
}
public void moveLeft() {
accelX-=0.1;
}
public long getFlyingTimeLeft() {
return flyingTimeLeft;
}
} ```
5.7 胜利管理功能实现
每个级别都有一些敌人(猪)。 当所有级别的猪都被杀死(从实体列表中删除)时,游戏将获胜。 胜利测试在updateEntity()函数中执行。 当浏览实体列表时,我们更新猪的行为,或者如果实体列表不再包含任何猪实例,则游戏级别完成。 一旦达到这个级别,该程序将进入WIN()函数,这将允许执行胜利的所有条件。 与胜利管理相同的方式,失败事件在upledateEntity()函数中触发,但在这种情况下,事件不是在实体中的鸟的实例中完成的。 当列表中没有更多的鸟类时,将调用lost()函数。 在这种情况下,首先处理猪是重要的,所以当没有更多的鸟或猪时,不会调用lost()函数(对于win()函数的调用将优先进行)。
胜利后的提示信息
失败后的提示信息
部分代码以及相应的页面布局 :
```java public void win() { javax.swing.JOptionPane.showMessageDialog(null, "祝贺你胜利 ,你的分数是: " + score+"."); currentPlayer.finished(currentLevel, difficulty, score); Level lvl = new Level("res/maps/lvl0" + (currentLevel+1) + ".txt",difficulty); if (lvl.isLoaded()) { angryView.setMap(lvl); this.setMap(lvl); this.setCurrentLevel(currentLevel+1); } else { javax.swing.JOptionPane.showMessageDialog(null, "没有此难度的地图!"); } }
public void lose() { javax.swing.JOptionPane.showMessageDialog(null, "游戏结束,再试一次?"); Level lvl = new Level("res/maps/lvl0" + (currentLevel) + ".txt",difficulty); if (lvl.isLoaded()) { angryView.setMap(lvl); this.setMap(lvl); } } ```
5.8 玩家管理和备份管理功能实现
这个功能目的是为了保存玩家的进度,让他恢复之前所成功进行的游戏。 因此,设置了一个“配置文件”系统:保存文件夹包含每个视图页面的备份文件,其中包含他的名字。 该文件包含对应于游戏的对象的序列化。
Player类专门为此而设计。 游戏可以选择从先前保存的配置文件中选择,或者创建一个新的配置文件。
玩家相关数据:对于每个玩家,希望存储他的名字,他成功的水平以及获得的分数。 因此,Player类包含一个名称的String字段和每个难度和级别的两个ArrayLists,一个包含相应文件的解锁级别,另一个包含后续级别的分数。
序列化 :为了在双方之间保存数据,有必要序列化Player类。为此,最简单的方法是使用Java提供的ObjectOutputStream和ObjectInputStream。我们不需要担心对象的序列化实现的细节,或者从文件中读取的细节。这种技术防止备份文件被我们的其他程序读取,但这并不是这个项目的问题。另一个问题可能是游戏的名称:在游戏中,备份文件被命名为“nom.save”,但是在创建新配置文件时输入的名称没有进行验证。 得分:只有最高的分数保留给玩家和给定的水平。当玩家完成一个级别时,Player类的finished()方法被调用,其中级别和score作为参数。完成后检查,看看给定的分数是否是一个新的记录。
部分代码以及相应的页面布局 :
```java
public Player(String name) {
this.name = name;
easy = new ArrayList
easyScores = new ArrayList<Integer>();
mediumScores = new ArrayList<Integer>();
hardScores = new ArrayList<Integer>();
extremeScores = new ArrayList<Integer>();
highestEasyScores = new ArrayList<Integer>();
highestMediumScores = new ArrayList<Integer>();
highestHardScores = new ArrayList<Integer>();
highestExtremeScores = new ArrayList<Integer>();
for (int i = 0; i < LevelNumber.getLevelNumber(); ++i) {
easyScores.add(0);
mediumScores.add(0);
hardScores.add(0);
extremeScores.add(0);
highestEasyScores.add(0);
highestMediumScores.add(0);
highestHardScores.add(0);
highestExtremeScores.add(0);
}
this.save();
}
public static Player loadFromFile(String name) {
try {
FileInputStream fichier = new FileInputStream("save/" + name
+ ".save");
ObjectInputStream ois = new ObjectInputStream(fichier);
Player player = (Player) ois.readObject();
return player;
} catch (java.io.IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public void save() {
try {
File file = new File("save/" + name + ".save");
file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(this);
oos.flush();
oos.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public String toString() {
return name;
}
public boolean isFinished(int level, String difficulty) {
if (difficulty.equals("easy")) {
return easy.contains(level);
} else if (difficulty.
参考文献
- 基于J2EE平台标准的WEB应用开发(福州大学·苏晓玲)
- 基于J2EE的网络环境下游戏运营平台的设计与实现(西安石油大学·郭栋)
- 基于Cocos2d-JS引擎的手机网页游戏设计与实现(武汉邮电科学研究院·赵甜)
- 基于JavaEE计算机资源审批系统(华南理工大学·罗正杰)
- 基于手持移动设备的教学游戏设计与开发(上海师范大学·覃柳思)
- 网络游戏虚拟物品交易系统设计与实现(吉林大学·李云峰)
- 基于MVC模式的Struts框架的研究与应用(武汉理工大学·戴翔宇)
- 基于.NET平台的游戏门户系统设计与实现(电子科技大学·余胜鹏)
- 3D云游戏平台的设计与实现(北京交通大学·闫璐)
- 基于Android平台的手机游戏的设计与开发(云南大学·秦成)
- 基于轻量级J2EE的网络游戏虚拟物品交易系统的设计与实现(北京邮电大学·曹鹃)
- 基于J2EE的学生网上考试系统的设计与实现(山东大学·雷怡然)
- 教育网络游戏的设计与开发(河南大学·张绍宾)
- 基于J2EE的MMORPG手机游戏框架的设计与实现(哈尔滨工业大学·李永金)
- 基于J2EE的手机综合网站的设计与实现(吉林大学·宋微)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码客栈 ,原文地址:https://bishedaima.com/yuanma/35251.html