安卓平板游戏编程入门指南(全)
原文:Beginning Android Tablet Games Programming
协议:CC BY-NC-SA 4.0
一、为 Java 开发设置 Android 3.0
这本书教你为 Android 3.0 平板电脑创建自己的游戏。在阅读并完成其示例后,您将对许多新型平板电脑的传感器、触摸屏、网络功能和处理能力有所了解。这听起来令人生畏吗?它不是。不用去做开发定位商店或赠送优惠券的乏味的企业应用的苦差事,你将知道如何制作有趣和吸引人的游戏。如果你过去做过一些游戏开发,你可能会惊喜地发现,与传统的 PC 和主机游戏开发相比,Android 系统让这个过程变得如此简单。
虽然没有任何一本书可以让你从新手变成游戏编程大师,但本书中介绍的基础知识可以让你将 2D 游戏中的任何想法变成现实。这本书使编程尽可能简单,以便专注于游戏开发中更具创造性的方面。
安卓是什么?
Android 非常特别,当你开始编程时,你会对它更加欣赏。许多手机制造商开发运行 Android 操作系统的平板电脑的运动为你将要制作的游戏创造了一个巨大的市场。这一节给你一个 Android 的功能和历史的纲要。
Android 的开端
2003 年,Android 作为一家硅谷的小型创业公司成立,旨在为智能手机创造一个更具互动性和更有帮助的界面。谷歌在 2005 年迅速收购了该公司,作为其进军手机市场的一部分。在谷歌收购它之后,第一个 Android 操作系统很快在 2007 年发布。在随后的几年里,Android 经历了多次修改(超过七次重大变化),使其成为智能手机的主要操作系统之一,有人说 Android 拥有近 50%的移动设备。
Android 的修订对于理解开发如何工作非常重要。谷歌努力确保其 Android 版本的向后兼容性;然而,应用通常被设计为适用于选定的几个 Android 版本,以保证**的性能和用户体验。名为 Froyo 的版本仍然是最受开发者欢迎的,但随着平板电脑等更现代的设备需要更强大的操作系统,后来的版本也越来越受欢迎。
下面的 Android 版本列表,以及它们当前的市场份额,说明了哪些版本仍然受欢迎,因此是开发者感兴趣的。谷歌给每个版本起的创意名就在版号旁边。开发者经常使用这些名字,而不仅仅是数字。请记住,除了 Android 3.0,所有版本的操作系统都是专为手机设计的:
- 1.5 Android cupcakes (2.3%)
- Android 1.6 donuts (3.0%)
- 是阿云 2.1 闪电(24.5%)
- Android 2.2 Froyo (65.9%)
- Android 2.3 gingerbread (1.0%)
- Android 2.3 gingerbread (3.0%)
- Android 3.0 Honeycomb (0.3%)
如果您有兴趣查看各种版本的当前市场份额,请前往developer.android.com/resources/dashboard/platform-versions.html。
在检查了这个列表后,许多人会说你应该为 Froyo 制作游戏,因为它在市场份额上比其他版本领先很多。Froyo 流行的原因是它安装在许多更简单的旧手机上,这些手机只能通过复杂的过程获得更新版本。随着新版本占据中心舞台,这些设备将慢慢变得无关紧要。某种程度上,为广大用户做游戏是有意义的;然而,每天都有新用户购买使用最新版本的更现代的手机。此外,也许最重要的一点是,成千上万的应用可以在 Froyo 版本上玩,而且越来越难脱颖而出。
也就是说,这本书教你为最新版(蜂巢)设计游戏有两个原因。首先,Honeycomb 是唯一针对平板电脑优化的版本,比任何智能手机都更具沉浸感和乐趣。其次,随着越来越多的公司发布可以与苹果 iPad 竞争的平板电脑,Android 平板电脑正在以巨大的速度增长。随着 webOS 的失败,Android 和 iOS 是平板电脑市场唯一的竞争者。微软也推出了自己的操作系统,但还没有获得很大的市场份额。谷歌经常被引用的关于每天有 50 万台 Android 设备注册的声明让你感受到这个市场扩张的速度有多快。
安卓 3.0 的特性
Honeycomb 相对于之前的 Android 版本是一个巨大的进步。Android 3.0 旨在利用更大的屏幕和更强大的处理器,让开发人员扩展他们通常适度的智能手机游戏。许多新功能都是用户界面的变化,使用户可以通过比智能手机屏幕大几倍的屏幕访问桌面。例如,典型的手机有两到三英寸的屏幕,而平板电脑拥有令人印象深刻的九到十英寸的屏幕。这些更新很方便;然而,游戏开发商更关注更新更快的图形渲染和操作系统的新传感器和网络能力。
并非所有游戏都使用所有这些功能,但在设计独特的游戏时,考虑它们的重要性是至关重要的。更大的屏幕本身就是一个值得注意的更新。高分辨率屏幕需要可缩放且视觉上吸引人的艺术品。很多安卓平板都登陆了 1280 × 800 作为屏幕尺寸。这与许多计算机屏幕仍在使用的分辨率相当。在这种情况下,图形必须接近计算机游戏中使用的图像。
表 1-1 列出了游戏开发者特别感兴趣的 Android 3.0 的主要变化。
在整本书中,我给出了如何充分利用 Android 平板电脑新功能的建议。如果你想把自己制作游戏作为一种爱好,那么请留意我的笔记,看看哪里可以免费获得高质量的声音和图像。我为我的游戏制作音乐和图形的工具也将在第二章中详细解释。
我希望在熟悉 Android 之后,你已经准备好开始使用了。不过,请仔细阅读下一部分,以确保你拥有为 Android 开发游戏的适当技能和硬件。
制作安卓游戏需要什么
那么,如何才能成为一名 Android 游戏开发者呢?让我们来看看你需要从本书中获得最多的技能,以及你需要通过它的例子来工作的系统。
你需要知道的事情
安卓游戏编程有多难?这真的取决于你对 Java 和 Android 操作系统的经验。如果你有扎实的 Java 知识,那么这本书对你来说再合适不过了。如果你以前为 Android 写过代码,那么你可能不会被这里的任何代码所挑战,你可以自由地享受你的体验。在继续之前,请仔细阅读这一部分,这样您就能确切地知道您需要什么。
一般来说,有兴趣学习在安卓系统中为平板电脑创建游戏的人来自三种不同的背景。每一个背景都为你准备了本书中的例子,但是它们都需要一个稍微不同的方法。
如果你既懂 Java 又懂 Android,你就可以开始了。这里的代码类似于您以前看到的,但是它侧重于图形、游戏循环和对用户输入的快速响应,这些您可能没有处理过。不管你做过什么,这本书帮助你掌握平板电脑游戏的创作。
也许你对 Java 很熟悉,但是你从来没有用过 Android。这很好。阅读示例和代码不会有太大的困难。请记住,对于任何新的环境和 API,您都应该定期查找提供的函数和类。熟悉 Android 需要时间,但努力是值得的。
你可能从来没有用 Java 编写过一个语句,更不用说用 Android 了。如果是这样的话,你还是可以用这本书,但是你得弄一本 Java 入门。我强烈推荐杰夫·弗里森(Apress,2010)的《学习 Android 开发的 Java》。当你有了 Java 的参考资料,熟悉 Java 的工作原理,然后直接进入本文。你在学习过程中学习语言。
理解 XML 是有益的;然而,XML 相对容易理解,您应该可以轻松掌握本书中对它的基本用法。资质不在话下,是时候考虑游戏创作使用的环境了。
您需要什么样的平台
是时候动手了,看看开发 Android 游戏到底需要什么。幸运的是,你不应该买任何软件!唯一的费用是当你准备把你的游戏放到安卓市场时,要交 25 美元的注册费。首先,检查以确保您的计算机支持 Android 开发:
- Windows XP (32 bit), Vista (32 bit or 64 bit) or Windows 7 (32 bit or 64 bit)
- Mac x 10.5.8 or later (x86 only)
- Linux(在 Ubuntu Linux、Lucid Lynx 上测试)
这个列表是根据 Android 自己的系统需求编制的。查看developer.android.com/sdk/requirements.html了解最低系统标准的最新变化。
虽然满足最低要求的系统可以让你创建 Android 应用,但是测试你的程序可能会相当慢。一般来说,如果你能在电脑上玩现代电子游戏,那你应该没问题。但是,如果你有更慢的机器,不要绝望;你完全有能力编写 Android 游戏,但你应该在 Android 平板电脑上测试它们,而不是在电脑上的模拟器上。
你不需要一台 Android 平板电脑来完成本书中的任何练习或程序,但在真实设备上测试你的创作是无可替代的。随着市场上平板电脑供过于求,更便宜的型号会让你花费大约 500 到 700 美元。如果你像我一样发现游戏编程令人上瘾,那么这些投资是非常值得的。摩托罗拉和三星生产一些最受欢迎的平板电脑;寻找他们的产品,以了解 Android 平板电脑方面的顶级产品。
如果你对自己的技能很有信心,并且已经决定在哪台机器上投入游戏开发,那么你已经准备好获得工具并配置你的开发环境了。
设置您的 Android 平板电脑编程环境
您就要进入有趣的部分了,但首先您必须确保您的计算机设置正确。您必须为您的工作下载并安装三个软件包:
- Java development kit (JDK)
- Eclipse, also known as Integrated Development Environment (IDE)
- Android Java SDK
如果您是 Java 开发人员,那么您可能有最新版本的 JDK,甚至可能安装了 Eclipse。在这种情况下,请跳到以下说明的 Android SDK 部分。如果您遇到问题,请仔细阅读前两节,因为您可能使用了错误的 JDK 或 Eclipse 版本。
在接下来的几节中,您将逐步安装这些软件包。完成后,您就可以创建您的第一个 Android 平板电脑程序了。在你准备好出发之前,整个过程不会超过 20 分钟。
安装 Java JDK
第一步是为您的机器下载并安装最新版本的 JDK。以下是如何:
- To find the JDK required by your system, please go to . You need JDK to allow you to use Java language on your computer. Find the big Java icon in the upper left corner of the page and select the JDK link, as shown in in Figure 1-1. This link will take you to the JDK SE download page.
- 在 Java SE 下载页面的下载选项卡上,如图图 1-2 所示,接受许可协议,选择适合您操作系统的软件包,点击链接下载。
图 1-2。许可协议和爪哇版本选择
- After the file is downloaded, run the installer. On some computers, the installer will start automatically. If this doesn't happen, please find the folder where you downloaded the files and sort the folders by the modification date. The last file is this installer. Double-click it, and you can start.
- A welcome dialog box of Java wizard installation appears, as shown in figure and figure 1-3 . Click the next button and follow the wizard prompts to complete the installation.
图 1-3。 JDK 安装向导
现在您已经准备好设置 Eclipse,这是您在本书中用来构建游戏的开发环境。如果没有 Eclipse,您将被迫使用命令行编译代码。开发环境为您节省了大量时间。
安装 Eclipse IDE
安装 JDK 后,您现在可以设置您的开发人员环境。您将使用 Eclipse,这是一个免费的软件包,为 Java 和 Android 开发人员提供了很多强大的支持。请遵循以下步骤:
- To find the Eclipse package for your system, please go to . On the Eclipse download page, as shown in in Figure 1-4, use the small drop-down menu to match your operating system. Then select Eclipse IDE for Java Developers and click the link of the required version of the operating system. You will be taken to a download page.
- Download the compressed folder containing the selected version and unzip it. Click Install executable file. During the installation process, make sure that you select the check box to create Eclipse shortcuts on your desktop, so that we can access Eclipse conveniently in the future.
- After installation, you can start Eclipse by shortcut. You should see something similar to Figure 1-5 . This means that everything is working.
图 1-5。Eclipse 开始了
安装好开发平台后,您就可以添加 Android SDK 了,它为您提供了构建游戏所需的库和工具。到目前为止,您只研究了基础知识,包括 Java 语言和开发环境。
安装 Android SDK
您的平台需要的最后一个软件包是 Google 的 Android SDK:
- 要找到您的系统需要的软件包,进入developer.android.com/sdk/index.html,如图图 1-6 所示,点击链接选择为您的操作系统制作的 Android SDK 软件包。完成后,相应的文件开始下载。
图 1-6。 Android SDK 下载页面
- 下载完文件夹或安装程序后,找到文件双击运行。出现 Android SDK 工具安装向导的欢迎页面,如图 1-7 所示。
图 1-7。 Android SDK 安装向导
注意记住你安装软件开发工具包(Software Development Kit)的位置。我更喜欢用.无论您使用的是哪种操作系统,请记下它的安装位置。当我们将它连接到黯然失色时,我们将在接下来的步骤中需要它的位置
- 点击下一步按钮,按照向导的提示安装 SDK。最终,你看到了最后一页。应选中启动 SDK 管理器复选框,如图图 1-8 所示。这将导致 SDK 管理器在安装完成后立即启动。
图 1-8。 Android SDK 工具安装向导结束
- 当 Android SDK 和 AVD 管理器对话框打开后,如图图 1-9 所示,点击左侧导航面板中的可用软件包链接,然后点击安装选定的按钮。这一步接受并安装 Google 推荐的游戏默认 Android 包。如果不安装这些,您将无法使用一些工具和示例应用。
图 1-9。 Android SDK 管理器。请注意所选的默认包点击安装选定项时,会出现如图 1-10 所示的对话框,显示安装进度(这可能需要几分钟)。
图 1-10。包和档案的安装
现在你有了 Java 语言、开发环境和 Android 工具。剩下的唯一步骤是将所有这些部分集成在一起。
向 Eclipse 添加 Android 工具和虚拟设备
你要做的最后一项工作是让 Eclipse 与新的 Android 工具和程序相适应。这样做可以让您将代码输入到 Eclipse 中,然后从 Eclipse 本身进行测试。否则,你必须保存你的代码,并使用不同的程序来测试应用。请遵循以下步骤:
- 要用将要使用的 Android 工具安装你的 Eclipse,打开 Eclipse 并选择帮助安装新软件。出现 Eclipse 安装对话框,如图图 1-11 所示。每次需要向 Eclipse 添加更多功能时,都要返回到这个安装对话框。
图【月食】1-11 日的安装对话框.
- 你首先需要让 Eclipse 知道在哪里寻找你想要添加的工具。在安装屏幕上,单击右上角的添加按钮。添加存储库对话框打开,如图图 1-12 所示。
图 1-12。用于向黯然失色添加机器人工具的名称和位置框
- Do the following:
- In the name box, type Android tools , which is the name of the tool you will use to refer to this step.
- For location, enter the URL dl-ssl.google.com/android/eclipse/ , which is the location of the tool you are adding.
- 完成后,点击确定按钮,返回到图 1-13 所示的安装对话框。
图 1-13。开发者工具软件
- Select the developer tools check box and follow the prompts to install the update. Doing so can increase the tools needed for Android tablet development. Restart Eclipse when prompted by the dialog box.
- 在 Eclipse 中,选择窗口首选项。打开侧窗格上的 Android 选项卡。你的屏幕应该看起来像图 1-14 。您将把 Eclipse 指向您的 Android SDK 的安装。这允许您在 Eclipse 中编译程序。
图 1-14。月食中机器人的配置选项在 SDK 位置字段中输入你下载 Android SDK 的准确位置名称。我的例子使用了。
应用这些更改后,您就完成了设置过程!
从现在开始,你要专注于实际的 Android 应用的结构,以及如何实现你对游戏的愿景。这种背景使你很容易在游戏中尝试各种不同的工具和技术。能够快速地改变你的代码并看到你努力的结果,在你的努力中是无价的。
测试你的工具
到目前为止,你可能正在急切地期待一些有形的 Android 游戏。这一节讲述了如何使用你已经安装的工具来使用 Android 内置的示例程序库。它还介绍了设计应用外观的基础知识。未来的章节将对这些项目进行扩展,以制作一个全功能的游戏。
你的每一款 Android 游戏都将被开发成一个 Eclipse 项目,在一个位置保存所有的图像、声音和代码。随着您的深入,您将对 Eclipse 有更好的理解。了解资源的存储以及如何在这种环境中访问文件是您需要掌握的一项关键技能。
即使对于最高级的程序员来说,示例程序也是一个极好的资源。你编写的任何游戏所需要的大部分基本功能已经在这些程序中的一个或多个中实现了,而且很可能是免费的。网上粗略看一下,可以为你以后节省几十个小时的工作时间。可悲的是,大多数应用都是为旧版本的 Android 编写的,因此它们在大型平板电脑屏幕上显得非常小。作为补偿,您可以将他们的一些代码合并到您的项目中,但自己处理图形。
在本节的其余部分,您将逐步了解为平板电脑创建 Android 游戏的步骤。至少从头开始一次是很重要的,这样你才能看到一个游戏最基本的框架。首先用 Eclipse 创建第一个 Android 项目。
创建 Android 项目
构建任何 Android 游戏的第一步是创建一个 Eclipse 项目:
- 在 Eclipse 中,选择文件新建项目,选择 Android 文件夹下的 Android 项目,进入新建 Android 项目界面,如图图 1-15 所示。
图 1-15。填写好的新机器人项目表
- Fill in the missing information:
- Type the name firstapp or any project name you want.
- Keep the default values of other parts unchanged until you reach the construction target part. Here, you can decide which version of Android you want your application to be suitable for. Choose Android 3.0 because you want your application to run on the latest tablet. When you test your game, this name becomes crucial, and you want to make sure that it works well on the analog tablet, not on the small screen of the mobile phone.
- 应用名称一般与项目名称相同。重新键入 FirstApp 或您为项目使用的名称。Java 开发人员对 Package Name 字段很熟悉,但是如果您不熟悉它,可能会感到困惑。这里你声明名字为 。
包是爪哇组织代码的一种方式,使得使用以前编写的文件变得容易。你可以在java.sun.com/docs/books/jls/third_edition/html/packages.html阅读更多关于爪哇包的内容,但是这对你来说并不重要。当您准备好稍后与世界分享您的应用时,您可以再次访问此页面.将
- 写成 Main 作为你希望项目创建的活动。
活动对于机器人程序来说是必不可少的,稍后我会更深入地讨论它们。现在,把这个活动看作是应用的主要功能。它被调用来设置游戏,然后通过处理输入和指导精灵的移动来运行游戏。活动应该根据它们的角色来命名,所以最初的活动通常被称为主要、主要活动或类似的名称.
- 用编号 11 填写 Min SDK 版本字段。这意味着 Android 要求设备运行 Android 版本 11 才能正常运行你的游戏。
你可能很好奇为什么我会突然跳到数字 11,当我之前谈到安卓 3.0 是最新的更新时。嗯,安卓有一个疯狂的版本命名系统。3.0 级指的是平台版本,它遵循正常的软件惯例,小的更新增加十分之一位,大的修订得到一个新的数字。为了保持一致,安卓为每个平台版本关联了一个代码安卓 3.0。被分配了 11,而安卓 2.3.3 得到了 10。因为您的项目是为最新版本的机器人设计的,所以您键入 11 作为最低软件开发工具包(Software Development Kit)版本
- Figure 1-15 shows a completed new Android project form. Check your name to make sure it is the same, because the remaining code and examples use the name provided in this walkthrough. When you're done, click Finish. You will see a blank Eclipse screen with a project folder on the far left.
现在让我们看看 Eclipse 创建的文件和代码。
探索 Eclipse 中的 Android 项目
要查看项目创建了哪些文件,请展开文件夹。然后进一步将扩展到到。双击在 Eclipse 编辑器中显示文件(中间的大查看窗格)。这是你游戏的核心;然而,目前它是一个基本的骨架。您看到的代码应该类似于清单 1-1 中的代码。
清单 1-1。??
`package com.gameproject.firstapp;
public class Main extends Activity {
/ Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}`
清单 1-1 中的代码创建了一个新的类,然后让这个类更新用户看到的视图。前三行定义包,然后导入应用需要使用的类。注意,这两个导入都引用了属于 Android SDK 的类。当你制作更多的功能游戏时,你将导入许多其他的类,让你执行各种各样的动作。
让我们一行一行地仔细看看清单中的代码:
这个简单的介绍指定这个文件是包的一部分。包是 Java 对同一程序的文件进行分组的方式。
Import 语句向项目中添加功能。实际上,这些是您想要使用的其他包。包括处理应用运行的方法。是为您的应用存储信息的一种特定方式。
这里,类被赋予了 Android 类拥有的所有函数和变量。每当一个类扩展另一个类时,新的类继承或接收对其他类的所有功能的访问。
这里定义的函数实际上来自于类。它处理应用启动时必须完成的所有过程。参数保存应用的先前状态。第一次启动 app 的时候是。
调用类的方法。这将导致程序启动应用。注意函数前面的关键字。关键字意味着程序正在从 Android SDK 调用原来的方法,而不是您之前在代码行中创建的新的方法。
最后,应用通过将 Android 屏幕设置为一个 XML 文件来执行第一个真正的任务。是表示资源的标识符,指定资源的类型,表示文件的名称。很快您就可以编辑文件来改变程序的外观。
是时候运行这个程序了,看看它能做什么。不过,在此之前,您必须创建一个虚拟的 Android 设备来测试它。如果你有一台运行 Android 3.0 的 Android 平板电脑,你可以直接在上面测试程序。要了解如何做到这一点,请前往附录 A 。
创建虚拟 Android 设备
在 Eclipse 中,创建自己的虚拟设备是一个非常简单的过程:
- On the Eclipse main menu bar, select windows Android SDK and AVD manager. An Android SDK and AVD manager screen similar to that shown in Figure 1-8 opens.
- 因为您没有列出任何设备,点击左上角的新建按钮。弹出一个创建新的 Android 虚拟设备(AVD)对话框,让你定义新的模拟器,如图图 1-16 所示。完成表格如下:
- The device name doesn't matter; I chose the original name tablet _ device .
- Your target Android version is Android 3.0.
- For most applications, you don't need to worry about the size of SD card. However, if your game requires you to store high scores or other data on the device, please specify the size of the onboard data storage.
- And the skin and hardware parts do not need to be changed. However, it is worth noting the hardware specifications. When you make graphics for games, you should definitely use the LCD density of 160 (which is quite standard) to determine the resolution of your images. Compared with many tablet computers, the device RAM size of the simulator is actually quite low. However, the simulator cannot accurately represent the capabilities of RAM or processor. In order to truly show how your game will work, you must try it on a real device.
图 1-16。创建机器人虚拟设备(AVD)
- Click the Create AVD button, and you can run your application.
如果你期待一个模拟器出现,你会失望的;新的虚拟设备仅在您运行应用时启动。下一部分启动设备。
运行应用
按照以下快速步骤运行应用:
- In the center of the toolbar near the top of the Eclipse screen is a green play button. Click it, and your program will open a big black screen. This is your new simulator. After a while, when it is loaded, the word Android will be displayed on the screen. Then, with the completion of loading, the word Android with larger font scrolls upwards.
- When the loading screen is finished, move the small round knob to the right. If you wait long enough, the application may start automatically. In this case, the word hello world, Main! appears. If not, please continue to the next step. There is a Google search bar in the upper left corner of the main screen and several buttons at the bottom. Real devices use touch gestures to select applications, but the simulator lets you use the mouse cursor. To run your own program, click the application icon in the upper right corner of the screen.
- A list of all programs on the device appears. Your application uses the universal Android robot as its icon; The application name (FirstApp) appears below the icon. Click on it, and the screen will soon display Hello World, Main!
尽管可能很简单,但您已经启动了您的第一个 Android 应用。当你陶醉其中时,点击左下角指向屏幕左侧的箭头。你回到了桌面家庭。现在尝试模拟器中的其他一些应用。您可能会惊讶地发现,浏览器、电子邮件和其他程序的功能与您预期的完全一样。
AVD 与真实的东西非常相似,甚至允许你测试传感器和 GPS 数据。要测试这个模拟器的速度,你可以制作你自己的令人难以置信的应用。请看下一节,了解如何处理代码。
对应用进行首次更改
尽管从技术上来说,你确实创建了自己的应用,但除了自动创建的应用之外,你并不需要操作代码。现在是时候改变程序的文本了:
在
- Open the folder. You should find a file (strings.xml) there; Double-click it to display it in the viewing pane.
- List two string resources. One is the application name, and the other is called . Click to change the value to any string you want.
- Save your changes and rerun the program. When you open the FirstApp, you should see that you have changed the text on the screen.
要理解这是如何工作的,你需要知道资源的重要 Android 主题。您刚刚编辑的文件是一个资源。大的文件夹中的每个文件也是如此。
如果你还记得文件,我在代码中提到了一个资源文件:,在布局部分。您需要对此文件进行一些更改:
5.要查看文件,请展开文件夹并双击。出现一个 WYSIWYG 编辑器,在右上角有一个小屏幕和您创建的字符串。
6.不幸的是,屏幕是为手机设计的。您可以使用顶部带有 2.7 英寸 QVGA 的菜单快速更改这一点。向下滚动列表,直到到达 10.1 WXGA。这就使得屏幕布局十寸多一点,对于平板电脑来说很正常。
7 .。使用编辑器更新布局非常容易。左侧的窗格已经有几个不同的项目可以拖到应用上。试着在你写的文字下面放一个按钮。
8.尽管 WYSIWYG 编辑器很方便,但对于制作游戏来说并不是非常有用。您需要进入图像背后的实际文件。要查看这一点,点击(靠近屏幕底部,图形布局旁边)。
清单 1-2 显示了你在布局中添加一个按钮后应该看到的代码。
清单 1-2。??
如果您不熟悉 XML,那么这可能看起来像希腊语,但实际上非常容易理解。第一行声明了您正在使用的 XML 类型。下一节创建一个特殊的布局类型,称为。其中,简单的指令告诉设备如何定位应用,以及它相对于整个设备屏幕的大小。接下来,一个对象被创建为(扩展以适合整个空间),然后被定义为,这将视图限制为仅需要的数量。
最后,通过调用名为的字符串资源将文本插入到屏幕中。这是您已经编辑过的字符串。
下一部分是您拖到应用上的信息。重要的是要记住,XML 布局并不创造功能,而仅仅是程序的外观。例如,点击你的按钮不会做任何事情,除非你专门设计了一个响应程序。
总结
这一章在让你的开发环境启动和运行方面肯定涵盖了很多内容。您讲述了 Android 背后的概念以及如何创建游戏。在接下来的章节中,你将会彻底地检查布局以及如何为游戏创建一个吸引人的背景。然后你创建精灵,并开始通过在屏幕上移动玩家来给你的应用添加一些味道。后面的章节添加用户输入、声音和人工智能来完成你的创作。
二、使用精灵和动作创造简单的游戏
祝贺您,您已经成功地设置了您的开发环境,并准备好继续进行更具创造性的游戏开发活动。当你想到你最喜欢的游戏时,你可以马上想象出它的样子,无论是怪物向你跑来还是汽车在赛道上跑来跑去。在本章中,您将为平板电脑屏幕注入活力。市场上有成千上万的游戏,你的游戏的外观和感觉可以决定它有多成功。
本章介绍在平板电脑屏幕上显示图像,然后移动图像的基础知识。你了解了精灵的概念。为了本章的目的,精灵是任何在游戏中可以移动的游戏物体。游戏中的主角或敌人通常是精灵,但游戏的背景却不是。
这一章的内容进展相当快,引入了许多新概念。
处理图像
精灵是游戏的基础,在你创建游戏之前,你需要能够在屏幕上画出它的卡片、角色和其他物体。在本节中,您将学习 Android 3.0 图形显示的基本组件。我们还将计算出精灵的组成部分,并在屏幕上移动我们的图像。这将成为我们未来项目的基础。看看图 2-1 看看我们的游戏会是什么样子。这个启动精灵实际上是来回跳动的。
图 2-1。完成的图形程序。
注如果你迷路了,从与这本书相连的谷歌代码项目中复制代码。然后回到课程中,你将能够通过操作它的某些方面来理解程序是如何工作的。
创建图像显示表面
要开始,您需要打开一个新的 Eclipse 项目。在上一章中,您在 Eclipse 中创建了一个名为 FirstApp 的新项目。那个代码对你来说已经没用了。从一个全新的项目开始:
- Select File New Project Android Project from the Eclipse main menu.
图 2-2。图形测试的项目创建窗口..
- Your app name is GraphicsTest. Make sure that the completed form looks like in Figure 2-2. Getting used to creating new projects in Eclipse is very important, because if something goes wrong, this is usually the easiest way to start from scratch.
- When the form is finished, click Finish. If you need help filling in other fields, please refer to Chapter 1.
在平板电脑上显示图像之前,您需要一个画布来渲染图像。您在程序主例程中构建曲面。请遵循以下步骤:
第一个项目中的文件可能仍在您的主编辑面板中打开。通过右键单击文件选项卡旁边的并选择全部关闭来关闭它们。这不会删除代码,而是关闭显示代码的编辑屏幕。* 在 Eclipse Package Explorer(位于屏幕左侧)中打开 GraphicsTest 项目的文件树。您想检查 Java 代码,所以打开文件夹,然后继续展开,直到看到。图 2-3 显示了文件的位置。
清单 2-1。??
`package com.gameproject.graphicstest;
public class GameView {
}`
您可以添加到这个原始源代码中,将图像文件绘制到屏幕上。但是,在开始之前,您必须了解 Android 中视图和显示的基础知识。
Android 视图类是如何工作的
到目前为止,您只在项目中使用了两个 Android 类:和。活动包含处理应用的创建、运行和关闭的功能。它们是任何安卓游戏的命脉。类仅仅是保存程序当前状态的一种方法。
然而,现在你看看类。应用运行时,视图处理屏幕的图形和外观。你所有的游戏都将创建一个类来扩展类并给你这个功能。通常,你的类中的代码比类中的多得多,因为游戏的大部分内容都是操纵屏幕上的对象。
所有函数类必须有两个不同的部分。第一个是构造函数方法。像任何类一样,当您创建它的实例时,您需要调用一个函数来定义对象的各个方面。在类中,你可以加载你的图像并决定所有精灵的起始位置。
类的下一个关键部分是将图像呈现到屏幕上的方法。每次移动图像时都会调用这个函数,因为图像必须在新的位置重新绘制。
尽管这是一种抽象的查看类的方式,但它有助于您理解代码。然而,在深入研究之前,让我们来看看实际获取一个文件并将其显示在屏幕上的机制。
提示如果你对类或任何其他 Android 类感到好奇,访问developer.android.com/reference/packages.html并找到你正在寻找的包。在这里,Android 提供了关于如何使用这些类以及每个类包含的各种方法的文档。
Android 如何渲染图像
类只是将图像呈现到屏幕上的整个方法的一部分。其他构建块包括图像、存储图像的方式、绘制图像的方法以及屏幕上的最终结果。
图像存储在项目中。下一节将介绍如何添加图像。一旦图像存储在应用中,你就可以通过将它分配给一个位图来访问它。位图是你描述图像的一种方式,并准备好将其传送到屏幕上。
在显示之前,必须通过画布进行渲染。画布包含绘制图像的方法。在视图内部,您调用画布来处理绘制过程。视图是他们控制的屏幕的指定部分。在您的例子中,视图拥有整个屏幕。然后画布将图像绘制到屏幕上。
渲染一幅图像
为了真正理解 Android 中的类是如何工作的,让我们用它来显示一个图像:
- 你需要一个图像文件加载到屏幕上。您可能已经准备好了一个图像文件,或者您可能需要创建一个。您电脑上任何扩展名为或的图像都可以。
- 如果你有一个现成的图像,确保它不超过 500 × 500 像素。
- 如果你想画自己的图像,我通常使用 Inkscape ( inkscape.org/)或 GIMP ( )作为我的图形编辑器,因为这两个都是免费的。如果你喜欢自己的图形编辑器,那也很好。
- 将文件拖到 GraphicsTest 项目的 文件夹中。Eclipse 问你要不要复制;单击是,您就可以开始了。
- 如果您仔细查看项目的文件夹,您会看到它包含三个以单词开头的文件夹。这些都指定了设备上图形的特定分辨率。对于为平板电脑构建的游戏,您使用中等清晰度文件夹;但是如果你是为手机开发的,你会希望每张图片都有三种分辨率的不同版本,以确保大多数手机能够尽可能快地渲染它们。
- 在编辑窗格中打开文件,用清单 2-2 中显示的代码替换清单 2-1 中的代码。这段代码将您的图像呈现到平板电脑的屏幕上。之后我会解释每一部分的作用。
清单 2-2。??
`package com.gameproject.graphicstest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;class GameView extends View {
public GameView(Context context) {
super(context);
}@Override
public void onDraw(Canvas canvas) {
Bitmap star = BitmapFactory.decodeResource(getResources(), R.drawable.star);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(star, 10, 10, null);
}
}importViewContextViewViewGameViewonDraw@OverrideonDrawViewonDraw()CanvasBitmapstar.pngstarstar.pngCanvasblackcanvas.drawColor(Color.argb(0, 100, 100, 100));argbdrawBitmap(Bitmap bitmap, float left, float top, Paint paintPaintnullnMainActivityGameViewMainActivity.javaGameViewMainActivity.javasetContentView(R.layout.main);main.xmlGameView.java`. This is readily done by adding the statement in Listing 2-3 inside the MainActivity constructor.
这个结果肯定不是很令人兴奋,所以你的下一个目标是移动屏幕上的图像。
与精灵一起工作
你可以在屏幕上移动一个图像,你必须给它起个名字。游戏不会四处移动图像或形状,而是使用精灵——屏幕上的对象由图像表示,但其方法和属性提供了您需要控制和跟踪它们的功能和状态。创建一个专用的类有很多好处。你可以很容易地添加动画序列和旋转,甚至跟踪每个精灵的生命或弹药。在你创建一个类之前,让我们研究一个更好的方法来显示精灵和一个更高级的游戏循环来处理它们的一致移动和更新。
渲染精灵
您需要对您创建的类做一些重大的修改。首先,让我们使用类而不是类。这是一个微妙的区别,但是类具有加快渲染速度的优势。当你在下一章看动画时,你会了解到类的来龙去脉。清单 2-4 显示了的新代码。将您的当前代码更改为这个新版本。它为你更高级的图像和精灵应用奠定了基础。
清单 2-4。
`package com.gameproject.graphicstest;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
setFocusable(true);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
}
}`
现在,除了使画布变黑之外,不执行任何有意义的操作。您从类中移除了绘图函数,以便以后可以在您的和类中实现它们。新的类的第一个重要部分是它现在实现了。这是负责控制表面,并使您能够从它被创建时开始绘制,直到它被破坏。这样,您就有了三种可以覆盖的方法:、和。你很快就可以用处理精灵和游戏循环的指令填充其中的一些。
当您需要初始化您的类的实例时,您也可以使用的构造方法。在代码的最后,你有和函数。在这一章的前面,你使用了把你的图像放到屏幕上,所以看起来应该很熟悉。功能新增;您可以用它来调用每个 sprite 来更新自己。有了处理图像的能力,你现在可以探索游戏是如何运行的。
构建游戏循环
要运行好游戏,你需要利用 Java 的类的能力。如果你用现代语言编程过,你可能以前遇到过线程。一个线程是设备执行的独立例程。在所谓的多线程中,线程几乎总是与其他线程一起使用。这基本上意味着线程是自主存在的,并且通常由一个程序同时运行以执行不同的功能。一个例子是在一个线程中运行游戏的图形,而在另一个线程中处理物理。显然,这两件事必须同时发生,所以你多线程的程序。
要构建 Android 游戏,您需要使用 Java 类。您可以在中找到类的源代码。您不必导入它,因为假设它是可用的;然而,记住这是您正在使用的类是很重要的。对于您的目的来说,线程非常简单。你创建一个扩展的类,然后你覆盖方法,把你的游戏循环放在那里。从那里,您可以改变视图或处理碰撞或收集输入。
既然您已经看到了我们在中所做的更改,让我们创建类的所有重要扩展:
- 在 Eclipse 中新建一个类,命名为。因为处理游戏的外观,所以处理幕后的计算才是合适的。
提示当你创建越来越多的源代码文件时,给类起一个非常具体的名字会很有帮助。如果你的游戏包含不同类型的精灵或物体,不要给类标上、等等。我总是试图根据一个类的确切功能来命名它,比如或者.
- Listing 2-5 shows the entire listing of . Similar to the implementation of your class, the current code is spartan. Copy the code in Listing 2-5 and replace the original code in .
清单 2-5。
`package com.gameproject.graphicstest;
public class GameLogic extends Thread {
private SurfaceHolder surfaceHolder;
private GameView mGameView;
private int game_state;
public static final int PAUSE = 0;
public static final int READY = 1;
public static final int RUNNING = 2;
public GameLogic(SurfaceHolder surfaceHolder, GameView mGameView) {
super();
this.surfaceHolder = surfaceHolder;
this.mGameView = mGameView;
}
public void setGameState(int gamestate) {
this.game_state = gamestate;
}
public int getGameState(){
return game_state;
}
Canvas canvas;
while (game_state == RUNNING) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.mGameView.update();
this.mGameView.onDraw(canvas);
}
}
finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}`
这里列出了的重要方法以及每个方法的功能:
- : Create a means to manipulate the canvas. In the code of function, it locks and unlocks the canvas you draw. Locking the canvas means that only this thread can write. You unlock it and allow any thread to use it.
- : Create an instance of your class and use it to call the and methods you saw in the previous section.
- : Create a system to store the state of the game at any given time. Later, you can use this when you have a pause screen or want to display a message when the player wins or loses the game. The game state also determines the time when you execute the game loop.
- : When the game is running, try to lock the canvas, then perform the operation you need, release the canvas, and prepare to restart the process.
虽然可能看起来很简单,但它并没有解决游戏中的许多问题。首先,没有合适的计时系统。该循环将按照处理器允许的速度运行,因此快速的平板电脑将运行得很快,而较慢的平板电脑将具有明显较低的速度。稍后,这一章用一个非常简单的方法来解决这个问题,当你的目标是每秒 30 帧(fps)左右时,调节精灵的移动量。
也不处理任何任务,如输入或碰撞检测,这些将在以后实现。目前,是一个重复执行操作的工具,不会使类复杂化。
创建精灵
构建游戏的下一步是创建类。虽然你的游戏只需要一个和的实例,但是你的游戏里可以有几十个小精灵;所以代码必须是通用的,但是允许你在精灵上执行所有必要的操作。
因为在任何 Android 包中都没有真正的类的基础,所以您从头开始创建代码。基本变量是你的类的根。例如精灵的 x 和 y 坐标以及精灵的图像本身。您还想存储精灵在每个方向上的速度。最终,你的精灵的生命值和其他方面也会被保存在这里。为了保持类的原始性,您将所有这些变量标记为,并使用一个函数来更改它们的值和检索它们的值。这是常见的做法,可以防止您在想要检索这些值时无意中更改它们,反之亦然。
清单 2-6 展示了你的类的代码。经历在 Eclipse 中创建新类的正常过程,然后用这段代码填充它。该代码执行一些非常简单的任务,因此理解它应该不会有太大的困难。
清单 2-6。??
`package com.gameproject.graphicstest;
private Bitmap bitmap;
private int x;
private int y;
private int x_move = 5;
private int y_move = 5;
public SpriteObject(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() /
2), null);
}
}
}`
这个类的最后两个方法——和——是最有趣的。在中从游戏循环中调用功能。在将图像渲染到屏幕上之前,使用操作来增加 x 和 y 坐标。请注意,您可以通过手动改变变量来改变移动速度,或者您可以创建函数,让您根据碰撞或用户输入等事件来改变精灵的速度。
运行游戏
通过对你的类做一些快速的修正,你可以拥有一个完整的应用,它将你的精灵投射到屏幕上。首要任务是在中创建和类的实例,这样您就可以利用新创建的类了:
- Open the class so that you can add some code to it.
- 将你的类的两个实例(如清单 2-7 所示)放在构造函数之前。
??清单 2-7。创建你的类的实例
- 在类里面,你调用两个类的构造函数。然而,要格外注意论点的结构。最后一行让您能够使用设备。将清单 2-8 中的代码添加到构造函数中。
清单 2-8。构造新的类
- Take the coordinates of bitmap and sprite. The method of obtaining bitmap resources is the same as what you did in the first example of this chapter. Take a and a . The function is a part of the class, which allows you to send the current holder to the method.
- 现在你可以利用函数中的新对象了。清单 2-9 显示了应用一创建表面就开始游戏循环的代码。
??清单 2-9。开始游戏循环
- 随着你游戏的肉开始,你要把你的方法放进和的套路里,如清单 2-10 所示。注意类没有调用这些函数;它们是从类中调用的。
清单 2-10。使用游戏中的物品
`public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.draw(canvas);
}public void update() {
sprite.update();
}`- The method gets sprite to draw itself, and then the function lets sprite execute its function. Separating the method from the method reduces the confusion within the class. Whenever a specific task must be executed, complete it in a separate function to keep your main code clean and tidy. All your code is ready and the game can be executed now. Make sure that all Java source codes are saved, and then click the green Eclipse play button to start the simulator.
注意如果您收到找不到类的错误消息,您可能已经在不同的文件夹中创建了 Java 文件。在左窗格的文件树中,确保所有四个文件都在文件夹中。
如果一切顺利,您应该会看到图像从左上角到右下角快速穿过屏幕。正如你之前注意到的,根据运行该程序的计算机或设备,精灵可能会快速或缓慢地移动。有了控制精灵移动的能力,你可以改变和的值来加速或减速。接下来的部分是清理用户界面,为一些激烈的游戏做准备。
获得专业形象
游戏意味着尽可能沉浸其中。要在平板电脑或任何设备上实现这一点,你必须移除所有提醒玩家游戏之外世界的栏和菜单。Android 有一些功能使这变得有效,但是 Android 3.0 包括了实际上要求系统栏总是可见的功能。不管怎样,您可以在文件中用一行简单的代码隐藏动作栏。清单 2-11 显示了应该紧跟在命令之后的语句。
清单 2-11。移除动作条
如果你现在运行这个项目,带有 Android 机器人图标的顶栏就会消失。图像应该正常地在屏幕上移动。为了让你的游戏看起来更专业,你可以把默认图标改成更适合你游戏的图标。当玩家想要打开你的游戏时,他们会进入他们的主页并选择应用。提供一个充满活力的图标来吸引他们的注意力是很重要的。
在创建你自己的图标之前,记下图标的尺寸。你需要有 72 × 72,48 × 48,32 × 32 的版本。在您的图形编辑器中,创建一个最大尺寸的图标,然后将其缩小以显示其他尺寸。当你有了这三个文件后,将它们命名为,并替换文件夹下每个分辨率类别中的其他图标文件。
现在,唯一要做的工作就是在你的代码上加一个头文件,就像清单 2-12 中所示的那样,这样你就可以发布你的游戏,而不用担心别人在不认可你的情况下拿走你的作品。诚然,网上发布的任何东西都可能被不当使用,但是在你的作品上签名可以帮助人们向你提问,或者至少在该表扬的地方给予表扬。
清单 2-12。代码上方的示例注释头
如果你真的对保护你的作品感兴趣,你可以在许可下发布代码。例如,Android 代码本身是在 Apache License Version 2.0 下发布的,这非常自由,允许用户将代码主要用于他们可以想象的任何项目。如果你在网上发布你的代码,准备好在一个许可下提供它,保持它的开源,让其他人在上面开发。
提示关于知识共享许可和开源项目如何工作的更多信息,请访问creativecommons.org/。
实现定时和复杂运动
现在,您可以继续创建一个系统,使您能够准确地设置游戏运行的速度。游戏循环将不再受制于设备的突发奇想。要做到这一点,你可以使用一个计时器,然后根据经过的时间调整移动。这意味着,如果一个周期花费很长时间,而另一个周期花费很短时间,精灵将根据该值移动一定的距离。查看代码是理解这种方法的最好方式。请遵循以下步骤:
- 用清单 2-13 中的代码替换中块中的代码。
清单 2-13。测试恒定英国制药学会会员游戏
`try {
Thread.sleep(30);
}
catch (InterruptedException e1) {
}long time_interim = System.currentTimeMillis();
int adj_mov = (int)(time_interim - time_orig);
mGameView.update(adj_mov);
time_orig = time_interim;
this.mGameView.onDraw(canvas); `- At first, the whole clip looked strange. In fact, it performs several simple tasks:
- [-] blocks tell the tablet to wait 30 milliseconds before continuing. This operation may result in an exception that you cannot handle.
- Previously, in the function declared next to object, you created two long variables named and . Use to set to the current system time. Now, you set as time and determine how long it has passed. You store it in the integer , which represents the adjusted movement of . The function in the class was changed to accept the integer as a parameter. After completion, the original time is set to the current time, and the view is refreshed by calling the method.
- 将清单 2-14 中的代码添加到中的方法中。
清单 2-14。的与修改后的功能
- 清单 2-15 显示了变量被传递给精灵,以便它被合并到运动中。
清单 2-15。的与修改后的功能
java零基础自学游戏
- In this case, the sprite method multiplies and by the change of time. I changed the speed constant to in order to keep the movement at a reasonable speed. This makes sense, because if the calculation takes a long time, the movement will be multiplied by a larger number. If the processing speed is fast, the wizard won't move that far. The idea of controlling the number of frames per second in a game has many meanings, which you can use in future projects.
虽然你可能会想象大多数游戏都想要有时间元素,但是许多应用可以不用担心这个问题。想想象棋或井字游戏。在回合制游戏中,时机不是一个重要的方面。
注意示例程序可从 Android 的参考指南中获得,你可以从不同类型的游戏中寻找灵感。查看该页面的代码源:developer.android.com/resources/browser.html?tag=sample。需要注意的是,大多数程序是为早期版本的 Android 编写的,比如 2.2 或 2.3。如果您真的对示例感兴趣,您可能想创建一个特定于该版本的仿真器。将它们移植到 Android 3.0 并不困难;你可以通过放大图片和屏幕尺寸来实现。
检测碰撞
虽然你没有收集用户的输入,但你可以通过处理与平板电脑墙壁的简单碰撞来给游戏注入一定的响应能力。清单 2-16 中显示了一个快速简单的实现。
清单 2-16。碰撞代码
将这段摘录添加到文件的方法中。在调用之前做这件事很重要,因为你必须在增加精灵的位置之前处理任何方向的改变。
您可能会注意到,您引用了一个尚未创建的函数。为了让这个函数工作,类需要两个函数,分别叫做和。这些的基本代码如清单 2-17 所示。
清单 2-17 。碰撞功能
在你运行这个程序之前,我手动将改为 0,这样你就可以消除任何上下移动。当你播放程序时,精灵会在屏幕的左右两边来回跳动。不过,这个运动应该有些奇怪:当精灵到达屏幕的最右侧时,它几乎消失了,因为你在精灵的位置上引用了你的碰撞,这是由其中心给出的。您可以通过考虑精灵的实际大小和尺寸来消除任何消失。
如果你想试验必要的改变,继续操作语句来反映精灵的绝对左和绝对右。第七章深入讨论碰撞;您使用元素来精确地找到不同精灵和墙壁或地板之间的交叉点。
注意碰撞检测几乎是任何游戏的一个重要方面,有多种方法可以实现。当您稍后想要使用项目符号或其他不规则形状时,您可以使用各种多边形来寻找精灵的交集。快速搜索不规则碰撞检测会产生大量信息来继续这个话题。
总结
这一章讲述了渲染图像的方法,你制作了一个框架来管理精灵并以一致的速度在屏幕上移动它们。通过这项工作,大多数游戏应该可以在你当前的系统上运行。在接下来的几章中,添加用户输入和声音将使高质量的游戏成为可能。当您使用 OpenGL 来加速复杂游戏的图形并向您的类添加动画框架时,您将在稍后处理高级图形主题。所有这些代码都是以可重用和适用于任何数量的游戏为目标而编写的。
作为本章的结尾,请确保所有代码和示例都能在您的系统上正常运行。如果你犯了任何错误,你可以从这本书的相关网站下载第二章的代码。在继续前进之前,你需要理解这些信息,这样你就可以轻松地处理人工智能和高级物理学,它们根据时间表扩展了一致运动的思想。
下一章涵盖了一个完全不同的主题:用户输入。你的精灵可以活过来,对用户的行为做出反应。这是游戏开发中非常令人兴奋的部分,因为它是交互性的核心。否则你会设计一部复杂的电影。
三、收集用户输入
到目前为止,你的作品缺乏游戏的互动性,主要是因为你没有办法让玩家与精灵和角色互动。在这一章中,你将解锁几种你最终用来控制游戏外观和动作的输入形式。这也是你在 Android 3.0 中解锁平板游戏编程的一些惊人特性的地方。以前,大多数这样的工作适用于旧的 Android 手机,但现在程序员严重依赖大触摸屏来收集触摸输入。
平板电脑的独特之处在于,用户可以进行大量选择;而作为开发者,你需要为此做好准备。除了这种显而易见的交互方法,您还会看到一些更不寻常的输入,比如加速度计数据和手势。除了输入,您还将介绍事件队列如何帮助您简化游戏。但让我们先来快速概述一下大多数 Android 平板电脑上的输入设备。
了解平板电脑输入选项
为了理解你的选择,你需要知道平板电脑在收集用户行为数据方面提供了什么。以下是许多平板电脑中存在的传感器的一个相当全面的列表。一些平板电脑不具备所有这些功能,而其他平板电脑则具备额外的功能:
- Touch screen: Most tablet computers have a multi-touch interface that allows you to input on the screen with several fingers at a time. Precision screens now allow you to create very small elves, and users can still drag them because of the precision of the screens. For most games, this is a user-controlled method. Almost every game needs this as its menu.
- Microphone: Tablet PCs running Android 3.0 often have built-in microphones that can be used as input. Examples include changing the height of the helicopter according to the pitch or volume of sound samples. Although there are many interesting applications, it is not used in most games.
- Accelerometer: This sensor measures the orientation change of the tablet computer. When you rotate the tablet from landscape to portrait, you may be familiar with this: the screen usually adjusts itself according to the accelerometer data. In flight games and racing games, this is an interesting way for users to control vehicles.
- Gyroscope: Similar to accelerometer, gyroscope measures the rotation rate along three axes of motion. This is for precise movement and can tell you the exact mode of rotation. Games that use accelerometers can also use gyroscopes.
- Proximity: The proximity sensor measures the distance between the object and the mobile phone. These are usually inaccurate and are mainly used to turn off the screen near your cheek (when you make a phone call with a touch-screen phone). However, few games use this.
虽然这个列表包括了游戏从玩家那里收集数据的大多数方式,但是您可以访问描述玩家所在区域和周围环境的其他传感器。这不能代替用户交互,但是它增加了游戏的真实性。以下是大多数平板电脑提供的获取这些信息的方式:
- GPS: The GPS positioning of a device can make the game map an image of the surrounding area or change the scene or characters of a game. It is not possible to consider all the different locations where a device may be located, but later you will study how to incorporate this point.
- Ambient light: This sensor is mainly used to adjust the brightness of the screen according to external light, but it does provide some advantages for game developers. If the user is in a dark place, one way to integrate it is to change the game to night scene.
- Barometer: This sensor is a joke rather than what it is. But in reality, the game may use it to estimate the altitude and adjust the game accordingly. I haven't seen a game that successfully integrates this sensor.
了解了平板电脑上可以找到的各种内部传感器,您也可以开始考虑可能想要连接到它的其他输入设备。Android 3.0 自带对任何 Android 版本蓝牙输入的**支持。每一个新版本都可能继续扩展这一点。虽然蓝牙输入可能令人兴奋,但为平板电脑编写游戏的目的是为用户提供独特的体验。如果他们仍然必须连接他们的游戏控制台,那么他们也可以使用电视。也就是说,Android 现在对操纵杆、键盘和游戏控制器提供了原生支持。
注意随着运行 Android 和 Chrome 混合操作系统的电视的出现,将平板电脑用作控制器成为可能。将平板电脑连接到运行 Android 的电视上,可以让电视屏幕显示游戏,同时平板电脑还可以充当地图和控制器。Android 越广泛地用于驱动设备,你在输入方面就有越多的机会。
您几乎已经准备好为您的游戏设置一些输入了。然而,首先你要回顾一下收集信息背后的一些理论。快速获得输入对游戏来说至关重要,而传统应用(例如地图或地址簿)不需要这种速度。
了解平板电脑输入
对于传统的应用,程序通常依赖于输入事件。这意味着,在用户与应用交互之前,什么都不会发生。大多数应用有许多不同的菜单和文本,用户一按下按钮,代码就负责筛选。在这些情况下,传统的游戏循环是不必要的,因为在触摸事件发生之前没有任何事情要做。同样的原则也适用于没有触摸屏的手机的旧程序。
如果你想制作这种应用,Android 可以让你非常简单地为屏幕上的各种按钮和图像添加监听器。通过在按钮被按下时执行特定的动作,您可以操纵程序的屏幕和动作。令人惊讶的是,这种用平板电脑工作的方式与游戏有一定的关联。以回合制策略游戏(如国际象棋)为例:在玩家移动精灵之前,什么都不会发生。
所有收集用户输入的方法都不可避免地涉及到非常重要的游戏过程。这是应用经历的事件循环。有多少种游戏类型,就有多少种游戏过程。这些循环都处理输入,确定物理,并给用户反馈(通常通过改变游戏的显示)。图 3-1 显示了一款回合制策略游戏的游戏流程。
图 3-1。依赖输入游戏的游戏过程
注意如果你对回合制游戏感兴趣,你可以在网上查看几个例子。一个非常简单但优雅的演示是一个井字游戏的 Android 示例。可以在这里下载源码:developer.android.com/resources/samples/TicTacToeMain/index.html。
因为大多数现代游戏都是快节奏和输入密集型的,所以你在处理输入事件的同时还要执行图形和逻辑操作。为了做到这一点,你收集输入并处理它,以便不中断游戏的流程。你可能认为这是同时做不同的事情;但是更实际的情况是,您注意到一个输入事件,然后等待在进入下一个游戏周期时处理它。图 3-2 显示了输入事件是如何存储的,直到你准备好处理它们。
在第二章的中讨论的类在处理输入事件中起着很大的作用。然而,类是注册输入事件的方法的地方。事实上,类有几个方法,您可以覆盖它们来执行您自己的触摸事件工作。
您实质上改变了您的类,因为您已经有了像和这样的方法,一旦输入事件发生,您就可以操纵 sprite。你创建新的事件来改变精灵的速度和方向。稍后,一个触摸事件可能会导致精灵重新装填弹药或施放特殊法术。在本章结束时,你将使用某些事件来产生一个全新的精灵。
为了清楚地了解示例游戏是如何工作的,图 3-2 展示了如果用户开始快速点击屏幕,你如何处理输入事件而不使游戏停止。请注意图 3-1 和图 3-2 之间的差异。
你使用的游戏流程版本有两个在回合制游戏中没有的附加功能,如图 3-1 所示。首先,应用路径不是线性的:输入事件在需要时被添加到游戏中。第二,游戏循环管理整个过程,而回合制游戏中的处理循环由输入控制。这是一个关键的区别,因为不管用户在做什么,你的游戏都需要继续,而图 3-1 中的游戏必须等待用户交互。
你的游戏的图形渲染也是不同的,因为它经常发生。在回合制游戏中,图形会在用户输入事件发生后改变。但是,即使什么都没有改变,您也将在循环的每个周期中更新图形。
图 3-2。连续游戏的游戏循环
图 3-2 显示了一个通过图形和用户输入循环的连续游戏过程。任何不需要用户输入而继续的游戏循环都可以被称为游戏循环。请注意,一个输入事件会导致一个输入队列,事件会存储在该队列中,直到您准备好接受并响应它。因为您的游戏以每秒高帧数运行,所以您在输入响应方面不会有任何明显的延迟。
对触摸做出反应
Android 可以在各种设备上运行,因此它有办法收集所有类型的输入。然而,对你来说,最重要的事情是与触摸屏的互动。你的首选方法如下:
这个方法是从类继承的,为了执行自己的操作,您可以覆盖它。这个函数的关键是它包含的参数。A 是 Android 中的一个对象,描述了与平板电脑的各种交互。您可以通过调用类中的方法来找到关于该事件的很多信息。这个类有许多选项,但是重要的函数会在您使用它们时指出。如果你很好奇,可以在 Android 文档中查找该类:。
同样,这个方法和其他几个方法是从您的类中调用的,因此您可以快速地将相关的更改传递给您的和进程。您可能会用到的其他输入功能包括、和。如果您有兴趣使用它们,它们的实现方式几乎与处理一般触摸事件的方式相同。这些方法都返回一个布尔值。这意味着当您完成处理时,您返回,以释放程序来收集下一个输入。
你可以想象,对于平板电脑来说,一次屏幕滑动对玩家来说可能相对简单;但是你的应用可能会将其误解为几个小动作,或者完全错过这个动作。随着游戏的进行,你要练习更复杂的手势,并确保即使是新玩家也能掌握游戏的控制。
让我们仔细看看如何处理触摸屏上的用户输入。在 Eclipse 中创建一个新项目来演示用户输入:
- Create a new project Android project . Type the name of the new project as input test , and make sure that the title of the activity is main activity . It is common practice to put items in the same root package.
- Because you will largely reuse the earlier classes, open the folder tree of GraphicsTest and copy all four files to the folder of the InputTest project. Also close the window of each class in the editing panel to make sure that you are editing the file of the new project. Open all the classes of the InputTest project, and it's almost ready to start.
- If you still want the same image, please move the image file from to the folder of the new project. If you like, you can create a new image for this project, as long as you reference it correctly in the code.
- 你已经知道输入收集发生在类中,所以把清单 3-1 中的函数添加到游戏视图中。将此部分放在方法的正下方。
注意许多讨论的主题都需要在代码顶部添加额外的语句。每个列表的标题包括必要的语句。请确保将这些内容放在文件的顶部,否则将无法运行该应用
清单 3-1。添加输入采集到()
- 这是的完整实现;但是,它目前不执行任何有意义的操作。将清单 3-2 中所示的代码片段添加到语句之前的函数代码中。
清单 3-2。基于触摸事件操纵精灵
- This code uses your and functions to move the sprite to the place where the touch event stopped or the last position of the finger. is a method to retrieve the position of the last motion event. It returns a floating-point number, so you can convert it into an integer to satisfy your method.
- 因为你的精灵一直在屏幕上快速移动,所以你移除了精灵的移动。清单 3-3 停止类中被改变的方法。
清单 3-3。停止精灵运动
`public void update(int adj_mov) {
if (sprite.getX() > = getWidth()){
sprite.setMoveX(0);
}
if (sprite.getX() <= 0){
sprite.setMoveX(0);
}
sprite.update(adj_mov);}`
- You must also stop the movement in the class by setting the value of the sprite-movement variable to zero.
- Your backstage work is finished. Save all files and run the application. If you click on the screen, the wizard will appear in the position where you moved last time.
也可以试着在数位板上拖动光标。你会看到精灵疯狂地试图跟上,即使如果你使用模拟器,它会明显滞后。真实设备的运动相当流畅。图 3-3 显示了你的工作结果。
图 3-3。通过在屏幕上拖动,将精灵移动到不同的位置。
当您在屏幕上移动光标时,您可能会注意到无论您从哪里开始移动,精灵都会移动。大多数允许你移动精灵的游戏都有几个精灵,所以你必须通过触摸来选择你想要移动的精灵。这就把你带到了触摸屏输入的主要话题之一:手势。尽管拖动事件本质上很简单,但它被认为是一种手势,因为它涉及持续的交互。其他手势包括滚动、挤压、旋转等。接下来,您将学习如何在游戏环境中创建手势并对其做出响应。
回应手势
要做到这一切,你需要对 Android SDK 中的类非常友好。在您在代码中使用它之前,让我们在 Android 开发团队创建的示例程序中体验一下手势。你可以在模拟器中访问这个应用:它被称为手势生成器。但是,在此之前,您必须对模拟器进行一些更改:
- GestureBuilder writes files into SD card of tablet. If your simulator doesn't have this, you can easily add it. Select the window Android SDK and AVD manager.
- 点击平板设备,并点击屏幕左侧的编辑按钮。弹出一个对话框(如图 3-4 所示),输入设备的内存大小。我一般用 1000 兆。
图 3-4。为手势生成器应用设置仿真器
- Click edit AVD.
- 你被带回 Android SDK 和 AVD 管理器。单击开始按钮;或者,如果开始按钮不可用,首先选择仿真器名称,如图图 3-5 所示。您从这里启动模拟器,因为您希望能够选择应用,而不是让应用默认启动。
图 3-5。从安卓 SDK 和主动脉瓣疾病管理器启动模拟器
- When the simulator is up and running, go to the icon labeled Apps. Then, click the Gesture Generator program. Play with this application for a while and see how it works. Make a new gesture and give it a name. Do a series of slides to create your gestures. This application gives you a feeling of what a gesture looks like.
如果您创建了一个真正伟大的手势,并希望在游戏中使用,您可以从 SD 卡中获取该手势,并在您的游戏代码中引用它。这是一个高级话题,你现在只想体验手势;要完成这个过程,请遵循 Android 文档中的说明:developer.android.com/resources/articles/gestures.html。
图 3-6 显示了我创建的一个星形手势。尽管你可以用多种方式画一颗星星,但手势是特定的,因为笔画的顺序非常关键。平板电脑正在寻找正确的序列。
图 3-6。做出独特的明星姿态
Android 开发小组有自己的名为 GestureDemo 的程序,可以让你做出手势,让应用识别。这一章没有详细介绍这个应用是如何工作的,因为它与大多数游戏的相关性有限。不过,还是值得简单看一下,因为你可以看到手势是如何被识别的。通过改变手势的方式,你会发现平板电脑识别手势的准确度有多高:
7.从code.google.com/p/apps-for-android/downloads/detail?name=GesturesDemos.zip&can=2&q=下载项目。解压缩文件夹,并注意记住所有内容都是从哪里提取的。
8.打开 Eclipse,选择 File Import General 将已有的项目导入工作区。
9.找到您下载的文件夹,并填写表格。当您单击 Finish 时,您的工作区中就会有一个新项目。要了解这个项目的更多信息,可以访问网页。
10.运行新项目,并开始表演手势。如果你做一个闪电手势,它应该在底部显示雷霆咒语。
如果你在这个项目上玩的时间足够长,你可能会注意到它在识别一些手势方面不是很准确。这是意料之中的,也是创建自定义手势不常见的原因之一。人们已经熟悉的著名手势,如捏和拖,很容易被 Android 计算出来,导致更少的混乱。尽管如此,当你可以像在现实生活中一样用手做动作时,一些游戏还是非常令人兴奋的。你可以在 Android 文档中查找手势库来更好地理解手势,因为这是一个太复杂的主题,本章无法完全涵盖。
提示如果你创造了自己的手势,让它们简单而夸张。此外,将你的游戏限制在一两个彼此非常非常不同的新手势,以避免错误。
使用输入队列
早些时候,这一章讨论了大量的用户输入是如何冻结游戏并导致其停止的。您可以使用非常方便的类来解决这种可能性。基本上,当输入事件发生时,您试图限制主线程上的压力。回想一下图 3-2 展示了你如何在响应输入事件之前保持它们。这正是你在这里做的。您不必等待锁定整个线程,而是在后台完成大部分工作。
这个系统最初是由罗伯特·格林介绍给我的,它非常有效和简单,从那以后我一直在使用它。(你可以在阅读罗伯特关于 Android 开发和其他沉思的博客。)An 负责输入处理的繁重工作。这基本上是一种存储对象并在以后遍历它们的方法。要使用一个,您需要在使用它的每个 Java 文件的顶部导入它,如下所示:
为了使用这种存储输入事件并在以后处理它们的方便方法,在 InputTest 项目中创建一个名为的新类。从现在开始,你引用 s 而不是 s 来获取关于发生了什么类型的事件的信息。除了加快处理速度之外,创建这样一个类还有多种原因。当您开始响应输入时,您会注意到处理有时很复杂的事件变得更加容易。
让我们试试这个技巧:
- 创建类,并用清单 3-4 中的代码填充它。
清单 3-4。??
`import java.util.concurrent.ArrayBlockingQueue;
import android.view.KeyEvent;
import android.view.MotionEvent;public class InputObject {
public static final byte EVENT_TYPE_KEY = 1;
public static final byte EVENT_TYPE_TOUCH = 2;
public static final int ACTION_KEY_DOWN = 1;
public static final int ACTION_KEY_UP = 2;
public static final int ACTION_TOUCH_DOWN = 3;
public static final int ACTION_TOUCH_MOVE = 4;
public static final int ACTION_TOUCH_UP = 5;public ArrayBlockingQueuepool;
public byte eventType;
public long time;
public int action;
public int keyCode;
public int x;
public int y;public InputObject(ArrayBlockingQueue
pool) {
this.pool = pool;
}/p>
p>public void useEvent(KeyEvent event) {
eventType = EVENT_TYPE_KEY;
int a = event.getAction();
switch (a) {
case KeyEvent.ACTION_DOWN:
action = ACTION_KEY_DOWN;
break;
case KeyEvent.ACTION_UP:
action = ACTION_KEY_UP;
break;
default:
action = 0;
}
time = event.getEventTime();
keyCode = event.getKeyCode();
}
/p>
p>public void useEvent(MotionEvent event) {
eventType = EVENT_TYPE_TOUCH;
int a = event.getAction();
switch (a) {
case MotionEvent.ACTION_DOWN:
action = ACTION_TOUCH_DOWN;
break;
case MotionEvent.ACTION_MOVE:
action = ACTION_TOUCH_MOVE;
break;
case MotionEvent.ACTION_UP:
action = ACTION_TOUCH_UP;
break;
default:
action = 0;
}
time = event.getEventTime();
x = (int) event.getX();
y = (int) event.getY();
}
/p>
p>public void useEventHistory(MotionEvent event, int historyItem) {
eventType = EVENT_TYPE_TOUCH; action = ACTION_TOUCH_MOVE;
time = event.getHistoricalEventTime(historyItem);
x = (int) event.getHistoricalX(historyItem);
y = (int) event.getHistoricalY(historyItem);
}
/p>
p>public void returnToPool() {
pool.add(this);
}
}KeyEventMotionEventuseEvent()ArrayBlockingQueueInputObjectuseEventHistory()getHistoricalEventTime()getHistoricalX()actionInputObjectGameView.javaGameView` class, create the following variable shown in Listing 3-5.
/p>
pre>
/pre>
ol>
你需要再导入一个安卓库。为此,将清单 3-13 中的代码添加到文件中。 清单 3-13。获取传感器数据
You may notice that these imports are about hardware-specific information. The device running the game may lack the correct sensor. 在你的类中实现类。为此,直接在行后添加。当出现错误消息时,双击它创建两个事件,如列表 3-14 所示。 清单 3-14。自动生成传感器方法
`@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub}
@Override
public void onSensorChanged(SensorEvent arg0) {
// TODO Auto-generated method stub} `
This is quite self-evident: create a and two methods, which register when the sensor changes its accuracy or its value. You are most concerned about because you are looking for data. In addition, there are many other functions that you can use when you want to get very specific information from the sensor. 将清单 3-15 中的行放在中的方法之上。 清单 3-15。创建传感器对象
用方法初始化这些传感器对象,如清单 3-16 所示。 清单 3-16。初始化传感器对象
要处理传感器,您需要添加两个基本方法,这两个方法在每个活动中都已经可用:和。您在这里需要它们,因为当设备已经处于某种睡眠模式时,您不想继续搜索传感器输入。清单 3-17 中的代码处理了这个问题。 清单 3-17。 和
`protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}`你可以查看修改后的来确定俯仰、滚转和方位角的值。作为参考,方位角为绕 z 轴旋转,俯仰为绕 x 轴旋转,滚动为绕 y 轴旋转。为了表达加速度计的值,您引入了一种针对 Eclipse 和 Android 的调试技术。在顶部,导入。然后将更改为清单 3-18 中所示的代码。 ??清单 3-18。??
float R[] = new float[9];
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);Log.d("azimuth",Float.toString(orientation[0]));
Log.d("pitch",Float.toString(orientation[1]));
Log.d("role",Float.toString(orientation[2]));}`
Basically, you create two arrays to store numerical values. Then call the sensor manager to get the direction of the device. Finally, get the direction array and print out the value. The function may seem novel to you, but it is just a way to send data to the debugger. Before running the program, you can set the view for reading these values by selecting the window Display View Other Android Logcat. /ol>
img src="https://gitee.com/OpenDocCN/vkdoc-android-pt2-zh/raw/master/docs/begin-andr-tablet-game-prog/img/0307.jpg" alt="images" loading="lazy">
em>
图 3-7。记录设备的方位、俯仰和滚动
/em>
em>
清单 3-19。实例
/em>
em>
清单 3-20。发送传感器数据
/em>
br> public void onSensorChanged(SensorEvent event) {
br> float orientation[] = new float[3];
br> for(int i = 0; i < 3; i++){
br> orientation[i] = event.values[i];
br> }
br> Log.d("pitch",Float.toString(event.values[1]));
br> Log.d("role",Float.toString(event.values[2]));
br> }
em>
清单 3-21。处理传感器数据
/em>
br> if (roll < -40) {
br> sprite.setMoveX(2);
br> } else if (roll > 40) {
br> sprite.setMoveX(-2);
br> }
em>
清单 3-22。让精灵自由移动
/em>
br> if (sprite.getX() >= getWidth()){
br> //sprite.setMoveX(0);
br> }
br> if (sprite.getX() <= 0){
br> //sprite.setMoveX(0);
br> }
br> sprite.update(adj_mov);
img src="https://gitee.com/OpenDocCN/vkdoc-android-pt2-zh/raw/master/docs/begin-andr-tablet-game-prog/img/0308.jpg" alt="images" loading="lazy">
em>
图 3-8。安卓平板电脑的坐标轴
/em>
img src="https://gitee.com/OpenDocCN/vkdoc-android-pt2-zh/raw/master/docs/begin-andr-tablet-game-prog/img/square.jpg" alt="images" loading="lazy">
strong>注
/strong>过去,游戏开发商不愿在音效上花费时间和金钱,因为他们认为手机游戏玩家希望能够安静地玩游戏。随着平板电脑的出现,游戏已经转变为一个更加多人和社交的场合,多人可以在屏幕上同时玩游戏;因此,噪音不再是一个问题。然而,游戏必须让玩家有可能关掉声音。
em>Raw
/em> 是您为任何非版面或图像文件的媒体或杂项文件指定的名称。
ol>
Download a sound file that you find interesting, and temporarily store it on your desktop or a place that you can easily access. Open Eclipse IDE and follow the steps to create a new project. It was named sounds test . Open the InputTest project you built in chapter 2 of , and copy all its files to the corresponding folders in SoundsTest, including images and all codes. Make sure that and are in the file you copied. Close the old source code in the edit pane and open the file from the new project. To incorporate new sounds into the SoundsTest project construction, you need to create a new file in its folder. Remember, layout data and images are stored in this folder; But now you are dealing with different file formats for storing media files, so you use a new folder for it. Right-click the folder, select New Folder, and create a new folder. Name the folder . Find your audio file, copy and paste it into the folder. As mentioned above, the folder is used to store resources such as sound and video files. /ol>
em>
清单 4-1。获得媒体播放能力
/em>
em>
清单 4-2。运动事件发生时播放声音
/em>
em>
清单 4-3。??
/em>
br> import android.graphics.BitmapFactory;
br> import android.graphics.Canvas;
br> import android.graphics.Color;
br>
strong>import android.media.AudioManager;
/strong>
br>
strong>import android.media.SoundPool;
/strong>
br> import android.view.MotionEvent;
br> import android.view.SurfaceHolder;
br> import android.view.SurfaceView;
br> SurfaceHolder.Callback {
br> private GameLogic mGameLogic;
br> private ArrayBlockingQueue
inputobject> inputObjectPool;
p>Download Give me a chance (or the song of your choice) to your desktop. Note that if you have your own MIDI file, Android is very picky about using extension instead of . In the future, Android may support both of them, but this was a common source of problems in the past.
/p>
p>Just like a sound effect, drag or copy the file to the folder of your project. Before you do this, please give it a reasonable name that is easy to retype. I now rename the file .
/p>
p>With the resource stored correctly, you can view the simple code for running it. First, create a private variable at the beginning of the class:
/p>
p>Add the bold code below to the method. This is how you instruct the tablet to start playing music immediately after creating the screen image: `@Override
public void surfaceCreated(SurfaceHolder holder) {
mGameLogic.setGameState(mGameLogic.RUNNING);
mGameLogic.start();
/p>
p> mp = MediaPlayer.create(getContext(), R.raw.background_music);
mp.setLooping(true);
mp.start();
}`
/p>
p>Because you have already handled a media player, this code should be self-evident. Create the object by loading the appropriate file and passing the application context. You are doing this to prepare the music to be played. Then tell to cycle the sample before starting.
/p>
p>To clean up after completion, modify the function with the following code:
/p>
p>That's all.
/p>
p>Run the SoundsTest application, and you should hear music at the beginning of the game. If you drag the cursor on the screen, the sound from will play along with the music. When you want to play music files in the game, you can use the method you created.
/p>
p>Download the Python version suitable for your computer at .
/p>
p>按照下载的安装程序的说明进行操作。在安装过程中,您可以选择 Python 的安装位置。参见图 4-1 。
/p>
p>
图 4-1。一定要记住你把你的计算机编程语言发行版放在哪里.正确安装了 Python 的/p>
p>wxPython: needs to be installed. Select the version suitable for your computer again and start the installation process.
/p>
p>在安装向导中,将 wxPython 指向您的 Python 安装,如图图 4-2 所示。
/p>
p>
图 4-2。如果简介找不到您的计算机编程语言安装位置,您可能需要将它指向您安装中的文件夹.??
/p>
p>注 WxPython 是计算机编程语言编程语言中用于图形用户界面的工具。如果没有它,您将被迫在命令提示符下完成所有工作.
/p>
p>Start JET Creator. To do this, please go to in the Android installation directory and double-click . The dialog box shown in Figure ?? and Figure 4-3 ?? appears.
?? ?? 】 Figure 4-3. If you don't see the folder path in the open Jet file dialog box, don't worry about clicking the import button on the far right in the open jet file dialog box.
/p>
p>Find the path . Select the ZIP folder named .
/p>
p>When prompted, the folder is allowed to decompress in the default location, usually in the folder. You will see the JET Creator program, which lists several different MIDI files.
/p>
strong>all together
/strong> .
p>在顶部创建四个基本状态作为整数(见清单 5-5 )。
/p>
p>
清单 5-5。代表精灵状态的常数/p>
p>
/p>
p>我个人的偏好一直是将赋值为 0,因为你经常会有默认状态等于 0,为了让精灵活下来而执行某种动作(比如初始化关卡)是有意义的。国家的另一个重要方面是它们应该是排他性的。这意味着角色不能同时处于一种以上的状态。在初始化之前,角色一开始总是死的。从那时起,他们默认是活着的,直到一个动作被执行,如跳跃或被杀死..你需要创建两个快速函数来处理精灵状态。将清单 5-6 中显示的函数放入中。
/p>
p>
清单 5-6。 getstate()和 setstate()函数/p>
p>`
public intgetstate(){
return
state;
}
/p>
p>
public voidsetstate(
ints){
state = s;
}`
/p>
p>These functions should look familiar, because this is how you access the X and Y coordinates of the wizard.
/p>
p>因为你定义的状态是公共整数,你可以用清单 5-7 中的代码在中测试一个 sprite 是否死了。将此代码添加到函数中。
/p>
p>
清单 5-7。如果角色死了就重置角色/p>
p>
/p>
p>Pay attention to how simple it is to deal with basic information, such as what is happening to elves at present. It becomes more and more important when you see a complicated state like jumping. The elf was the fastest when he first left the ground. Then it gradually decreases until sprite reaches its peak height, and then it gradually accelerates. The change speed of sub-picture must be controlled within function. You need to find out what state the elves are in, so as to change at the right rate. For example, a normal jump will last for a predictable period of time. But what if the jump is interrupted by hitting the platform? You use the status to quickly evaluate the new situation.
/p>
p>In order to completely merge the states in the game, put the code lines in Listing 5-8 into statement to test the collision between characters and bombs. This is an alternative method to reset the position of the character when the bomb is hit, rather than being executed immediately in the conditional collision test.
/p>
br>
integer name="blocknumber">3
/integer>
br>
item>300
/item>
br>
item>600
/item>
item>900
/item>
br>
br>
item>200
/item>
br>
item>200
/item>
br>
item>200
/item>
br>
strong>清单 6-6
/strong>:
strong>清单 7-1。
/strong>
strong>清单 8-1。
/strong>码头平台位置
br> <integer name=
em>"blocknumber"
/em>>32
strong>清单 8-3。
/strong>建造码头
strong>清单 8-5。
/strong>创建地面和城堡
strong>图 8-2。
/strong>图像图层
strong>清单 8-11。
/strong>改变加农炮计数的数值
strong>图 8-8。
/strong>海港保卫者运行时出错
strong>.
/strong>????
In most cases, you only need to pay attention to the previous error line. In this case, when the cannon is pulled out, the function fails. The reason is that I commented out the initialization of the cannon elf. This is a common problem when you deal with a game where elves are created and destroyed. Please make sure that all the wizards you refer to for drawing or updating really exist. The last suggestion for handling errors is to make your simulator smaller. If you have a relatively small screen size, then your simulator may occupy most of the screen. This can prevent you from looking at at work. To solve this problem, choose to run Run_configuration. Then go to the target tab and scroll down. In the command line option, type scale.8 . This reduces the simulator to 80% of its original size.
注意如果你解决问题的最大努力没有成功,尝试在 stack overflow()上搜索解决方案。不过,将来在测试之间做些小的改变。通过这种方式,您可以回到以前的工作状态。准备好总是回到你知道有效的事情上来。
下一章涉及到游戏的许多不同的修正和更新。最值得注意的是,你使用户能够移动和旋转大炮。在你以前的游戏中,玩家从来没有这么多的选择,这将是一个独特的练习。
另一个增加的是一个积分系统,玩家每摧毁一艘船就获得奖励。物理也必须更新,因为一旦船撞上城堡,你需要结束游戏,而不是让船直接通过。
你还得担心一个新的因素:不恰当的用户交互。对于用户来说,点击码头的一部分来放置大炮是有意义的,但是如果他们错过了码头而点击了海洋呢?这就要求你快速有效地评估每一个输入,并立即对用户做出反应,同时还要防止大炮出现在不该出现的地方。
为了完成你的工作,你添加输入和逻辑来润色游戏的整体外观。
总结
你已经经历了设置一个真实游戏的过程。有了这些元素,你就可以添加让游戏成为有趣的用户体验的特性了。你应该习惯于计划一个游戏和组织处理精灵和组成它的物体的方式。
当你展望未来时,你会更加关注玩家的体验,而不是你技术能力的极限。为一个游戏创作美术作品通常也是一个限制因素,但是一个有趣和有创意的游戏可以弥补许多缺点。现在,让我们为您的游戏部署做好准备。
九、单人策略游戏第二部分:游戏编程
有了框架,现在你可以编写代码来创建一个可玩的游戏。这里的诀窍是让你的代码尽可能高效。当游戏变得越来越复杂,涉及到更多的精灵时,它们可能会因为处理器难以跟上而开始变慢。你可以用一些巧妙的技术来减轻负担,从而避免这种情况。
随着你的进展,牢记最终目标也很重要,因为你必须有一个正常运行的游戏,然后才能添加使你的工作与众不同的附加功能。事实上,以我的经验来看,知道何时停止开发一款游戏并发布它总是最棘手的部分。太简单的游戏和不可玩的游戏之间有一条细微的界限,因为它的功能和附加功能太多了,普通用户没有时间去学习。
注意当你阅读本章中的代码时,回想一下,将语句放入代码中有助于澄清正在发生的事情和正在调用的函数。有些代码可能相当复杂,我仍然使用这种技术来帮助我逐步完成这些方法,尤其是当我没有得到想要的行为时。
以下是你必须在本章中完成的功能列表,以便拥有一个可用的游戏:
- Augmented elf object
- Shoot a bullet from a cannon
- Destroy the hit ship.
- Restart the game when the ship hits the castle.
其中一些——比如当子弹击中一艘船时降低它的健康——很容易完成,但是其他的需要一些思考和聪明的编码。为了简化你的编辑,我已经贴出了这一章的全部方法。这样可以保证你之前的作品正是最终游戏所需要的。这也有助于您了解每个函数如何调用其他函数,以及它们之间共享哪些信息。
下一节从我们对的改进开始。您只做了很少的修改,但是您所做的更改将会简化您在中的工作。
增强游戏精灵
在这个游戏中,你对你的精灵要求很多。为了处理新功能,您需要一些所有精灵都使用的新方法和变量。虽然实际上只有一个精灵可以利用一个特定的特性,而不是创建额外的类,但是你可以让每个游戏精灵从继承,因为精灵在很大程度上是相同的——没有必要混淆项目。
然而,如果你扩展游戏,你想让船能够开火还击,改变方向,或者产生更小的船,那么你可能想创建一个特殊的船类来体现这些能力。每当一个精灵或对象使用两个或更多独特的函数时,我通常会为它创建一个新类。
按照以下步骤修改:
1.清单 9-1 显示了要添加的新变量以及你赋予它们的值。将这段代码添加到的顶部。
清单 9-1。 变数
2.清单 9-1 中变量的使用在清单 9-2 中所示的函数中显而易见。在的末尾键入所有这些代码。新方法被你的精灵们自由地使用。
清单 9-2。新增功能为
`public boolean cursor_selection(int cursor_x, int cursor_y){
int sprite_right = (int)(getBitmap().getWidth() + getX());
int sprite_bottom = (int)(getBitmap().getHeight() + getY());
if(cursor_x > getX() && cursor_x < sprite_right && cursor_y > getY() && cursor_y <
sprite_bottom){
return true;
}
else{
return false;
}
}
public void setStacked(boolean s){
stack = s;
}
public boolean getStacked(){
return stack;
}public void diminishHealth(int m){
health -= m;
}
public int getHealth(){
return health;
}
public void setOrientation(int o){
Orientation = o;
}
public int getOrientation(){
return Orientation;
}`
函数是一个非常强大的方法,如果用户触摸了一个 sprite,它将返回 true,如果用户没有触摸,它将保持 false。它基本上是一个简单版本的方法,但是它只关心用户给出的输入。您通过用户选择要添加的加农炮类型来实现它。
与子画面是否堆叠相关的函数用于确定一块桥墩上是否已经有大炮。如果那里有一门加农炮,你要阻止用户在它上面放置另一门。有些地方比其他地方更好,所以让玩家放置大炮是不公平的。
添加两个函数来处理精灵的健康状况。游戏中唯一健康的精灵是船。当他们被击中三次时,他们将被移出游戏。
3.你需要修改 函数来检查一个精灵是否已经失去了所有的健康。用清单 9-3 中的代码替换现有代码。
清单 9-3。改变方法
最后一个加法检查精灵面向哪个方向。你用这个装大炮。例如,如果一门大炮朝下,你必须向屏幕底部发射子弹,而一门指向右边的大炮应该向屏幕右侧发射子弹。
让我们把这些功能付诸行动吧!
创建用户控件
的构造器方法有几个新人。本节剖析了主要用于用户交互的新精灵,并向您展示了一个新概念。不是创建四个不同的指向所有主要方向的大炮图标,而是为四个不同的精灵旋转一个图像。这可以节省机器上的空间,但也会在启动时导致一些额外的处理器工作。
为了证明这一点,主炮都是不需要旋转的独立精灵。在这种情况下,您使用的方法取决于您的资源和磁盘空间。
请遵循以下步骤:
1.在开始使用新精灵之前,必须先在构造函数之前声明对象。将清单 9-4 中的代码放到中。
清单 9-4。 s 为海港保卫者
2.在构造函数中,初始化、和图标,如清单 9-5 所示。这三个精灵创建了用户控件的基础。在屏幕右下角,有一个存放选项的 dock。在码头的前面是垃圾桶,让用户摧毁他们建造的大炮。标记精灵在图标后面跳来跳去,向玩家显示当前选择的是哪一个。
清单 9-5。设置图标
3.下一步是创建小炮图标。将清单 9-6 中的代码添加到构造函数中。这是你的码头的基础。
清单 9-6。制作微型大炮图标
`Bitmap bcannonupsmall = BitmapFactory.decodeResource(getResources(),
R.drawable.cannonupsmall);
int w = bcannonupsmall.getWidth();
int h = bcannonupsmall.getHeight();
Matrix mtx = new Matrix();
mtx.postRotate(90);
Bitmap bcannonrightsmall = Bitmap.createBitmap(bcannonupsmall, 0, 0, h, w, mtx, true);
Bitmap bcannondownsmall = Bitmap.createBitmap(bcannonrightsmall, 0, 0, w, h, mtx, true);
Bitmap bcannonleftsmall = Bitmap.createBitmap(bcannondownsmall, 0, 0, h, w, mtx, true);
cannonrightsmall = new SpriteObject(bcannonrightsmall, 110, 650);cannonleftsmall = new SpriteObject(bcannonleftsmall, 180, 650);
cannondownsmall = new SpriteObject(bcannondownsmall, 240, 650);
cannonupsmall = new SpriteObject(bcannonupsmall, 300, 650);`
如果你觉得这段代码有点像希腊语,不用担心。你创建了微型加农炮精灵,并收集其高度和宽度。然后你启动一个新的矩阵,旋转 90 度。通过旋转三次创建三个新位图。然后用新图像创建精灵。位置非常具体,将所有图标放在屏幕左下方的小 dock 上。
4.要使 dock 有用,您需要用变量存储用户的选择(换句话说,如果用户选择正面朝下的大炮,您需要知道如何创建该类型的大炮)。你可以通过将清单 9-7 中的变量放在的顶部来实现。存储用户的选择。
清单 9-7。存储用户选择的变量
5.您已经创建了一个不错的 dock,有几个选项供用户选择,但是您需要跟踪用户指向的位置。您使用四个变量来引用用户的选择。将清单 9-8 中的变量添加到的顶部。
清单 9-8。收集关于最后一次触摸事件的位置的数据
6.编辑看起来像清单 9-9 中的代码。这包含了您在步骤 5 中声明的前三个变量。
清单 9-9。存储用户的输入
`public void processMotionEvent(InputObject input){
selection_changed = true;
cursor_x = input.x;
cursor_y = input.y;
}`
有了这些代码,当平板电脑上发生触摸时,将设置为,并用变量和存储触摸的位置。
7.在函数中,您使用来自步骤 6 的数据来确定是否需要处理用户输入事件以及用户在哪里交互。将清单 9-10 中的代码添加到的方法中。这就是处理用户输入的方式。
清单 9-10。在功能中处理用户输入
`if(selection_changed){
selection_changed = false;
if(trash.cursor_selection(cursor_x, cursor_y)){
user_choice = TRASH;
marker.setX(50);
addboat = false;
}
if(cannonrightsmall.cursor_selection(cursor_x, cursor_y)){
user_choice = CANNON_RIGHT;
marker.setX(110);
addboat = true;
}
if(cannonleftsmall.cursor_selection(cursor_x, cursor_y)){
user_choice = CANNON_LEFT;
marker.setX(180);
addboat = true;
}
if(cannondownsmall.cursor_selection(cursor_x, cursor_y)){
user_choice = CANNON_DOWN;
marker.setX(240);
addboat = true;
}
if(cannonupsmall.cursor_selection(cursor_x, cursor_y)){
user_choice = CANNON_UP;
marker.setX(300);
addboat = true;
}
else if(addboat){
if(cannon_count < 10){
for(int i = 0; i < pier_count; i++){
if(pier[i].cursor_selection(cursor_x, cursor_y)){
if(pier[i].getStacked() == false){
switch(user_choice){
case 2:
cannon[cannon_count] = new
SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.cannonleft),
(int)pier[i].getX(), (int)pier[i].getY());
case 3:
cannon[cannon_count] = new
SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.cannonright),
(int)pier[i].getX(), (int)pier[i].getY());
cannon[cannon_count].setOrientation(cannon[cannon_count].RIGHT); break;
case 4:
cannon[cannon_count] = new
SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.cannonup),
(int)pier[i].getX(), (int)pier[i].getY());
case 5:
cannon[cannon_count] = new
SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.cannondown),
(int)pier[i].getX(), (int)pier[i].getY());
cannon[cannon_count].setOrientation(cannon[cannon_count].DOWN);
break;
}
cannon_count++;
pier[i].setStacked(true);
}
else if(pier[i].getStacked() == true){
if(user_choice == 1){
for(int u = 0; u < cannon_count; u++){
if(cannon[u].getX() ==
pier[i].getX() && cannon[u].getY() == pier[i].getY()){
cannon[u].setstate(cannon[u].DEAD);
}
}
}
}
}
}
}
}
}`
这段代码处理的是 dock 图标。用户交互的另一面是船在屏幕上的实际位置。当玩家选择任何一艘船或垃圾桶时,他们设置到。这意味着你需要寻找用户在游戏中做什么。变量存储用户选择的最后一个停靠图标。
处理器循环通过墩件;当它发现用户触摸了墩块时就停止。然后,它会询问码头是否堆叠。你早些时候看到,在这种情况下,被堆叠意味着码头已经容纳了一门大炮。如果不是,那么用户可以自由添加一门大炮到那个码头。然后代码进入一个语句。
的事例编号对应于您在构造函数方法中分配的变量(例如,大炮是否指向左边)。当你找到玩家想要的加农炮的方向时,你使用码头的位置创建新的精灵。很重要的一点是,你的码头和大炮要占同一个面积(100 × 100)。这使得定位变得很简单。
然而,放置大炮并不是玩家唯一能做的事情。他们还可以选择值为 1 的垃圾桶。垃圾的表现与你之前看到的相反:它寻找一个堆放的墩块,找到放在那里的大炮,然后移走它。
就这样。用户现在可以控制你的游戏了。接下来的部分将为你的子弹和船只添加新的功能。
把一切都显示在屏幕上
现在你已经有了很多很棒的特性,比如你的用户界面控件和船只,你需要把它们添加到屏幕上。为此,功能需要调整。清单 9-11 包含了这个函数的全部代码。
确保你的 onDraw 函数看起来与清单 9-11 中的完全一样,否则图像不会被绘制到屏幕上。
清单 9-11。??
`@Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
ground.draw(canvas);
//the user controls
dock.draw(canvas);
marker.draw(canvas);
trash.draw(canvas);
cannonleftsmall.draw(canvas);
cannonrightsmall.draw(canvas);
cannondownsmall.draw(canvas);
cannonupsmall.draw(canvas);
for(int i = 0; i < pier_count; i++){
pier[i].draw(canvas);
}
for(int i = 0; i < boat_count; i++){
boat[i].draw(canvas);
}
for(int i = 0; i < cannon_count; i++){
cannon[i].draw(canvas);
}
for(int i = 0; i < 50; i++){
bullets[i].draw(canvas);
}
castle.draw(canvas);
}`
查看标题为“用户控件”的精灵组。这些图标包括用户可以选择的 dock、标记以及垃圾桶和大炮图标。这里需要注意的是,dock 显然是先画的,然后是标记,然后是图标。这样就可以一直在背景中看到 dock。然后,标记可以自由地从后面高亮显示所有图标。图 9-1 显示了码头的样子。
图 9-1。包含用户控件的 dock,用户可以与之交互
在函数的最后,四个循环遍历精灵列表。最后画出城堡。
你总是画出每一颗子弹,即使它们可能正在移动,也可能不在移动。这是由类负责的,它在绘制精灵之前检查以确保精灵是活的。随着子弹准备摧毁船只,我们必须创造和跟踪即将到来的敌人。下一节将介绍操纵船只的来龙去脉。
部署和管理攻击艇
清单 9-12 包含了处理船只的整个 方法的代码..如果你不明白它的一部分,键入它的全部并运行游戏。你可以根据游戏的行为来看它是如何工作的。
1.确保您的 update()方法包含这里的所有代码。上市后,你会发现它的解释。
清单 9-12。在功能中设置船只
`public void update(int adj_mov) {
for(int i = 0; i < boat_count; i++){
if((int)boat[i].getX() > 950){
boat[i].setMoveX(0);
boat[i].setMoveY(3);
boat[i].setBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.boatdown));
}
}
if(check_boat > 97 && boat_count < 12){
int previous_boat = boat_count - 1;
if(boat_count == 0 || boat[previous_boat].getX() > 150){
boat[boat_count] = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.boat), 100, 150);
boat[boat_count].setMoveX(3);
boat_count++;
}
}`
来自清单 9-12 的代码在第八章中完成..第一个循环确定船只是否向右移动过多。如果有,那么使用一个新的精灵图像,它开始沿着屏幕向城堡移动。
下一个块处理随机船的创建。最重要的部分是使用一个语句来确保前一艘船与新船充分分离。同样,你增加船只的数量,并设置新船上路,如清单 9-12 所示。
现在我们将检查与城堡的碰撞,这将导致玩家的损失。
2.在 update()方法中添加清单 9-13 中的 for 循环。
清单 9-13。测试与城堡的碰撞,重置游戏
如果用户失败,船撞上了城堡,那么你调用一个名为的新函数。你看一下这个简单的函数做了什么。(我本可以在这里包含所有的代码,但是我发现添加额外的函数来处理不同的任务在视觉上更容易。)
随着船只的航行和子弹的准备发射,我们需要研究我们的大炮。没有它们你无法打败船。看看下一节,我们如何操纵和使用加农炮。
开炮
在用户输入之后,子弹是游戏中最复杂的部分。跟踪 50 个可以向四个不同方向移动的精灵是一件棘手的事情,这些精灵目前可能活着,也可能不活着。大炮将会变得更加精彩。在本节中,您将添加子弹并编写代码来处理大炮如何以及何时发射炮弹。
请遵循以下步骤:
1.将清单 9-14 中的代码添加到构造函数中。这个代码处理大炮发射的新子弹。为了简单起见,屏幕上的项目符号数量限制为 50 个。有两个数组:一个包含子弹精灵(),另一个包含当前没有使用的子弹列表()。
清单 9-14。
`available_bullet = new int[50];
for(int i = 0; i < 50; i++){
available_bullet[i] = i;
}
bullets = new SpriteObject[50];
for(int i = 0; i < 50; i++){
bullets[i] = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.bullet), 10, 10);
bullets[i].setState(bullets[i].DEAD);
}`
您声明了一个整数数组,其中包含所有可用的子弹,因为您知道还没有子弹射出。项目符号精灵也被初始化。您将它们的状态设置为,因为您不希望子弹没有发射就出现。
2.将清单 9-15 中的代码添加到方法中。首先,你设置数组等于零;这将使你进行计算时更容易。然后你创建了一个非常重要的变量:。用于指定哪些项目符号可用,哪些不可用。
清单 9-15。重置可用子弹列表
`for(int f = 0; f < 50; f++){
available_bullet[f] = 0;
}
int g = 0;`
3.在清空数组后,立即将清单 9-16 中的代码放到方法中。
清单 9-16。处理子弹的变化
`for(int i = 0; i < 50; i++){
if(bullets[i].getY() > 800 || bullets[i].getX() > 1280 || bullets[i].getY() < 0 || bullets[i].getX() < 0){
bullets[i].setstate(bullets[i].DEAD);
}
for(int b = 0; b < boat_count; b++){
if(bullets[i].collide(boat[b])){
boat[b].diminishHealth(1);
bullets[i].setstate(bullets[i].DEAD);
}
}
bullets[i].update(adj_mov);if(bullets[i].getstate() == bullets[i].DEAD){
available_bullet[g] = i;
g++;
}
}`
每个子弹精灵都有一个循环。第一个语句检查子弹是否已经离开屏幕;如果有,就将其状态设置为。这意味着它可以在下一次迭代中作为可用的项目符号被重用。一个回路处理船只碰撞。如果船被击中,那么它的健康就会下降一,你就摧毁了子弹。同样,子弹现在可以重复使用。一个简单的调用根据它的和改变了子弹的位置。
如果子弹是死的,那么你把它列为可用子弹。如果仔细观察语句,您会注意到第一个失效的项目符号被赋予了数组中的第一个位置,被递增,下一个失效的项目符号被赋予了下一个位置。
4.子弹准备好了,该担心发射机制了。五十次迭代的函数从比赛场上的每一门大炮中释放一颗子弹。清单 9-17 中的代码通过调用新函数来执行这些操作,这个函数有四个参数。将这段代码放在已经添加到方法中的代码之后的方法中。
清单 9-17。计算何时发射一排子弹
这段代码创建了变量,它跟踪哪颗子弹已经发射。第一门大炮发射第一轮,第二门大炮发射第二轮,以此类推。这一系列的语句使用了您在中创建的新的函数。然后将每门加农炮炮管末端的 x 和 y 坐标传递给方法。得到坐标需要一些计算,因为你知道枪管在大炮的中心。
子弹的结构在中更有意义,你将在下一节中写它;清单 9-17 中的代码只是将必要的信息发送给那个方法。因为你已经初始化了所有的子弹精灵,这不会浪费处理时间,因为你只是在更新精灵。
5.要完成方法,确保调用了各种精灵的函数,如清单 9-18 所示。
清单 9-18。包括基本的功能
`castle.update(adj_mov);
ground.update(adj_mov);
for(int i = 0; i < boat_count; i++){
boat[i].update(adj_mov);
}
}`
接下来的部分通过处理游戏重置和发射子弹来解决遗留问题。
管理游戏结果
当玩家输掉游戏,一艘船撞上城堡,你呼叫。这是一个简单快捷的功能。
请遵循以下步骤:
1.将清单 9-19 中的代码添加到中其他函数的下面。
清单 9-19。 法
`private void reset(){
for(int i = 0; i < boat_count; i++){
boat[i].setstate(boat[i].DEAD);
}
boat_count = 0;
}`
你所做的就是毁掉那些船。这实际上重新开始了游戏,因为船又一次被随机创建了。你不移除大炮,因为没有必要担心它们。如果用户愿意,他们可以删除它们。如果您想向用户显示一条消息,您可以创建一个 sprite 并在此时将其绘制在屏幕上。在功能中,等待大约 30 个周期,然后删除消息。
2.方法有点复杂,正如你在清单 9-20 中看到的,但它绝对是可管理的。把这个方法直接放在函数下面。
清单 9-20。 法
`private void createBullet(int x, int y, int direction, int r){
if(r >= 0){
int index = available_bullet[r];
if(direction == bullets[index].RIGHT){
bullets[index].setMoveX(10);
bullets[index].setMoveY(0);
bullets[index].setX(x);
bullets[index].setY(y);
bullets[index].setstate(bullets[index].ALIVE);
}
if(direction == bullets[index].LEFT){
bullets[index].setMoveX(-10);
bullets[index].setMoveY(0);
bullets[index].setX(x);
bullets[index].setY(y);
bullets[index].setstate(bullets[index].ALIVE);
}
if(direction == bullets[index].UP){
bullets[index].setMoveY(-10);
bullets[index].setMoveX(0);
bullets[index].setX(x);
bullets[index].setY(y);
bullets[index].setstate(bullets[index].ALIVE);
}
if(direction == bullets[index].DOWN){
bullets[index].setMoveY(10);
bullets[index].setMoveX(0);
bullets[index].setX(x);
bullets[index].setY(y);
bullets[index].setstate(bullets[index].ALIVE);
}
}
}`
子弹精灵是对称的,所以你不用担心它们的方位,只需要担心它们移动的方向。别忘了每个块的最后一行,让子弹活起来。否则,它们将永远不会被绘制出来,并且您将很难找出哪里出错了。
你终于完成了游戏项目。下一节给你一些未来计划的想法。
分析游戏
如果你还没有,运行游戏。当船开始来的时候,放置你的大炮保卫城堡。祝你在战斗中好运。
以下是您用来构建 Harbor Defender 的功能和技术列表。为你在代码、错误和工作中坚持不懈的努力感到自豪:
- Game cycle
- Multiple elves
- Draw an image on the screen
- Bitmap manipulation
- User interaction
- Some AI
- Collision detection
- XML data parsing
- And more.
写完整个游戏后,你可以放松,把游戏改成你想要的样子。如果你做了足够多的改变,也许你可以在 Android 市场上赚点钱。本书的最后一章讨论了这种可能性。
拥有一款可扩展的游戏至关重要。如果游戏开发商不得不从头开始制作每一款游戏,他们永远不会发布足够的游戏来支付租金。相反,他们将框架转化为许多独特的、看似不同的创造。你所做的有潜力转化为迷宫游戏,平台游戏,回合制策略游戏,或者其他许多可能性。
类是完全可重用的,并且可以很容易地调整成其他类型。如果你需要想法,我觉得浏览其他游戏开发书籍并为 Android 创建它们的样本很有趣。任何语言的任何游戏都可能在 Android 上创建。如果游戏是为电脑设计的,并且使用键盘控制,这可能是一个挑战。要有创造性,我相信你能写出一些非常不同的程序。
图 9-2 显示完成的游戏。看看你能否想象它被转化成十几个不同的项目。
图 9-2。你完成的项目
总结
你的辛苦完成了,你也学到了很多。在本章的最近部分,你看到了如何使用矩阵来旋转位图。您还了解了如何跟踪 50 个精灵并维护另一个列表,其中列出了哪些精灵已经死亡并准备再次创建。这一章也标志着你第一次尝试创建一个用户界面,它包括几个图标和一个标记来显示用户当前选择的内容。
如果你厌倦了代码,有一个好消息:下一章处理发布你的游戏,提供更新,并处理业务结束。你看看什么游戏卖得好,平板电脑如何改变计算领域。当你理解了商业方面,就轮到你创造自己的杰作了!
十、发布游戏
你的游戏已经为大众做好了准备,但是在应用被大众消费之前,你还有几个步骤。对代码有几处修改,可以用来润色您的工作。然后这一章讲述了出售或赠送游戏的步骤。最后,您将了解如何确保在竞争激烈的移动应用市场中取得成功。
制作一款高质量的游戏只是在 Android 应用市场获得畅销地位的第一步。到目前为止,你所做的一切都可以融入到你展示最终产品的过程中。这款应用的图形、声音和外观都融入了你向消费者销售的方式中。
打磨应用
虽然你的游戏可以玩,但它可能需要一些润色。欢迎屏幕将是一个很好的补充,这样玩家可以在进入游戏之前了解游戏。当谈到添加这个功能时,你有很多选择,但制作一个基本的入口屏幕很容易,你可以针对每个游戏进行微调。在本节中,您将添加一个屏幕,然后添加一个按钮来启动游戏。
添加闪屏
因为负责实际的游戏及其外观,所以你的启动页面由处理。不是设置屏幕显示,而是呈现一个快速布局,然后给用户进入游戏的能力。这使您的工作更专业,对用户来说也更容易。为了扩展这个概念,你可以播放一小段视频来介绍这个游戏,但是我会留给你自己去想象。
看看图 10-1 看看你的闪屏是什么样子的。如果你想要一个更完整的介绍界面,这一节将讨论添加特性和项目的方法。
图 10-1。游戏简介
为了达到图 10-1 中的效果,让我们回到第一章中的概念。应用的外观是在中生成的,在这里你可以通过拖动按钮和文本到屏幕上来创建界面。然后编辑文本和元素。以下步骤显示了如何做到这一点:
- Navigate to the folder: to find your main.xml file in the Harbor Defender project.
- Open and select "10.1-inch WXGA" from the drop-down menu near the top. The first task is to check the code of the main.xml file.
- Select on the small tab near the bottom of the screen. Replace the existing code with the code in Listing 10-1 .
清单 10-1 。
`
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
`
你用一个替换现有的。这两者都是可以添加布局元素的框架。然而,让您快速指定元素的确切位置,而将所有项目向左对齐。当您添加欢迎屏幕的各个部分时,这一点非常重要。
5.选择屏幕底部的小图形布局选项卡,返回图形布局。
6.您可以使用左侧的项目面板来创建您的布局。图 10-2 显示了这将会是什么样子。将一个和一个拖到您的屏幕上。它们现在包含填充文本,但是您很快就会编辑它。
图 10-2。使用左边的调色板拖动和对象到屏幕上
7.是时候回到代码的视图了。选择屏幕底部的选项卡。您应该观察到两个新元素(和)已经出现在您的元素中。
8。您需要插入文本并更改按钮的。查看清单 10-2 中的粗体代码。您可以使用不同的词,但重要的是记住您分配给按钮的的名称或其他标识符。
清单 10-2 。
`
<AbsoluteLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:text="Start Game"
android:layout_width="wrap_content"
android:id="@+id/startgame"
android:layout_height="wrap_content"
android:layout_x="557dip"
android:layout_y="249dip">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="When you are ready to begin this game, please click on the button above."
android:id="@+id/textView1"
android:layout_x="310dip"
android:layout_y="361dip">
`
和行指定项目的位置。如果您想要精确地确定按钮和文本的位置,您可以编辑这些值。您使用标签来引用代码中的对象,就像您在下一节中所做的那样。
响应开始游戏按钮的按下
现在你已经有了一个很好的展示给用户,你需要让它具有交互性。让玩家快速开始游戏至关重要。这对于一个回归的玩家来说尤其重要。请记住,如果这个人回来玩你的游戏,他们希望很快开始玩,不希望看到说明或被介绍视频打扰。
为了显示你的新布局,然后让用户导航到真正的游戏,让我们回到。这里你做一个简单的输入测试,然后展示实际的游戏。然而,最初你需要把而不是作为游戏的视图。请遵循以下步骤:
- Open in the edit pane of Eclipse.
- Add the following statement to the top of the file:
3.更改的方法,使其看起来像清单 10-3 中的。粗体部分是对你之前作品的修改。你必须进口才能让它工作。
清单 10-3。??
`@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGameView = new GameView(this);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
final Button button = (Button) findViewById(R.id.startgame);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setContentView(mGameView);
}
});
}`
第一个告诉应用加载作为布局。按钮部分监听按钮的点击。一旦发生这种情况,你调用另一个在屏幕上显示。这是你用来初始化游戏的简单方法。
当你给按钮赋值时,使用函数;作为参数,您使用按钮的。这就是为什么你要把按钮设计成一个很容易识别的启动游戏的物品。
4.运行游戏,你会看到一个欢迎界面。按下开始游戏按钮继续,应用正常运行。
恭喜你:你终于完成了这本书的代码部分!下一部分处理游戏的最终编译和发行的准备工作。您离与其他用户共享您的创作越来越近了。
包装游戏
在游戏完成并准备发布之前,你必须注意几件事情。这一节讲述了如何清理代码,并最终将产品编译成一个 APK 文件,以备分发。APK 是包含所有游戏代码、图像和资源的包装。
请遵循以下步骤:
- The first thing to do is to delete any statements in the code. I usually perform global search and replacement to delete them. You don't want the retail version to waste processing power and send our debugging warning. You must fix the code version in the Android manifest file. Find this file by going to the root directory of folder and opening . The code should be similar to the tag shown in Listing 10-4 .
清单 10-4。??
`
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gameproject.harbordefender"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="11" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<action android:name=
"android.intent.action.MAIN" />
<category android:name=
"android.intent.category.LAUNCHER" />
注意粗体部分。你可以设置自己的版本代码和版本名称,但这是惯例,因为这是你的第一个游戏,使用 1.0 作为版本。还要确保 SDK 的最低版本是 11。
3.在 Eclipse 中选择文件>导出。
4.选择导出 Android 应用作为您要执行的导出类型。
5.在下一页,输入你最终项目的名称: Harbor Defender 。
6.您必须创建一个密钥库,这是保护您的应用的安全性所必需的,并且被 Android 应用市场用作标识符。选择创建新的密钥库,如图图 10-3 所示,并使用浏览按钮打开一个窗口,让您将文件放入文件夹中..键入类似于 harbordefenderkey 的文件名,并接受默认位置。
图 10-3。生成密钥的提示
7.创建一个唯一且难懂的密码来保护自己,如图图 10-3 所示。
8.在图 10-4 所示的密钥创建页面中填写适用信息。(图为我是如何完成的。)密码可以与您在上一页中使用的密码相同。
图 10-4。填写开发商信息
9.下一页是最后一页。单击浏览,并输入 HarborDefender 作为 APK 目的地。关闭对话框,并完成该过程。
就这样,你完成了这个项目。下一节将讨论如何将这个项目引入应用市场并送到消费者手中。你还将讲述如何在拥挤的应用市场中做最好的营销和工作。
部署游戏
我希望你对你的游戏感到满意,并且相信其他人也会喜欢它。本节介绍如何使用 Android 应用市场。您将了解如何上传应用以及营销和定价的基本原理。有了这些信息,您就可以继续制作更多的待售应用。
首先,看一下图 10-5 ,图中显示了market.android.com/的 Android 应用市场主页。
图 10-5。安卓应用市场
在这个页面上,Android 移动设备和平板电脑的用户可以下载和购买应用。特别值得注意的是标签上写着特色平板电脑应用。Android 正在大力吸引平板电脑的买家,因此它将专门为平板电脑设计的应用与手机应用分开。这对你来说是个好消息,因为你面临的竞争少了很多。
在如何提供课程方面有很大的自由。你可以为你的应用设定一个介于 1 美元到 200 美元之间的价格,或者免费赠送。当一个顾客买了它,你得到了销售额的 70%;剩下的就是将应用发送到设备上的费用。谷歌不收取任何收益,但设备制造商和在线分销商收取处理交易的费用,就像信用卡公司对每笔交易收取费用一样。iPhone 和 iPad 应用只给开发者 60%的收入,所以从这个意义上说,Android 比苹果应用商店还有一个优势。
安卓市场上 57%的应用是免费的。竞争应用商店的免费应用比例要低得多。对你的暗示是,你必须意识到,要求用户付费的节目必须表现出优越的质量,并提供许多小时的播放时间。
你现在知道了应用市场的基本情况。您必须创建一个 Android 应用市场帐户,才能看到您自己的作品。下一节将介绍如何创建帐户并上传您的第一个应用。
开设谷歌开发者账户
没有什么比看到自己的工作掌握在他人手中更让应用开发人员高兴的了。在这里,您可以创建您的 Android 应用市场帐户,并向全世界发布您的程序:
- Go to market.android.com/. At the bottom of the screen, click Developer.
- Select the option to publish the application.
- Log in to your Google account, or create a new account. You should create a new account specifically for your application business, which is different from your regular email or Google+ activities.
- The next screen is shown in Figure 10-6 . Fill in with accurate and professional information. If you don't have a website, that's fine, but you might want one. ?? * ?? 】 Figure 10-6. Create your robot application market account*
- You are prompted to pay the registration fee. This is $25, which must be paid through Google checkout.
注册完成后,您的帐户就有了一个分类配置文件。你可以做很多事情,从添加一个谷歌结账账户以便获得付款,到上传一个应用。
现在你可以将你的游戏上传到谷歌市场了。
上传游戏到谷歌市场
虽然大多数开发人员都想出售他们的应用,但这一部分介绍了如何将您的应用免费上传给公众。如果你想收到付款并为你的工作收费,请访问这个关于市场的惊人指南:www . Google . com/support/androidmarket/developer/bin/topic . py?topic=15866 。
在完成上传游戏的简单过程之前,您必须准备好几个项目,包括:
- Include applications
- Two beautiful application screenshots of APK file highlight its characteristics.
- A high-resolution icon that users choose to play your game.
上传游戏是一个简单的命题。在您的在线开发人员控制台上,单击上传应用。在这里,您将看到一个向导,询问刚才列出的项目。在您存储文件的目录中找到这些文件。
关键是要有一个有吸引力的截图和描述,以及任何你想显示的附加图表;你的成功将关系到你的游戏吸引了多少用户。下一部分着眼于如何准备在市场上取得最大的成功。
营销您的游戏
营销你的应用需要将你的产品展示给尽可能多的人。如果你创造了一个像样的游戏,那么如果人们有机会看到它,他们就会购买。第一个问题是如何让你的应用脱颖而出。与 iPads 和 iPhones 的应用商店不同,Android 程序可以从任何网站下载,而不仅仅是谷歌官方市场。这意味着拥有自己网站的开发者更容易销售他们的产品,因为他们不会与市场上过多的类似应用混淆。用户可以直接来到他们的网站,看到视频、图片和程序说明,这些在 Android Market 上的简短描述中是不可能的。
利用这一事实,创建自己的网站,吸引潜在买家。创建一个脸书页面或推特账户也能增加关注度。不要把读者引向你在 Android 应用市场上的页面,而是把他们引向你自己网站上的一个页面,这样就不会那么混乱了。
如果你做过网上营销,你就会知道邮件列表有多有用。在您的网站上,为访问者提供注册更新您的应用和免费附加服务的机会。这样,即使他们没有立即购买,你也可以继续吸引他们,说服他们购买你的产品。看看 AWeber ( )网站,它提供了一个很棒的邮件系统,你可以用它来向你的用户分发时事通讯。它每月收费,但许多营销人员发现,客户从简讯中获得的收益超过了成本。
最后,通过将你的公司或游戏放入更传统或可信的媒体来解决营销问题。请关注技术的杂志对其进行评论,或将相关信息发送给在线新闻来源。当你这样做的时候,确保你的游戏提供一些非常独特的东西。也许输入控制是完全创新的,或者游戏发生在零重力室内。让应用有新闻价值。这也可以由你的公司整体来做。举例来说,如果你所有游戏中的艺术作品都来自一位著名的画家,那绝对是一个值得一个网站谈论的独特故事。
所有这些技术都可以追溯到广告中使用的基本漏斗方法。它在各种各样的初级营销和公共关系书籍中有所阐述,但也需要包括在这里。你吸引的用户越多,时间越长,你的销售额就越多。图 10-7 显示了这是如何工作的。
图 10-7。将你的访客引向买家
这就是营销技巧。通过反复试验,你会找到最适合你的方法。我发现在应用市场上的成功很少是在你的第一款甚至第二款游戏上实现的。你必须坚持下去,在获得金牌之前,建立对你的产品的期待和兴奋。
总结
恭喜你!你已经完成了这本书。你从发现什么是 Android 以及如何在其中编程,到编写一个完整的游戏,再到将你的工作投入应用市场。
这是一本有趣的书,我希望你也喜欢。从事一项发展如此迅速的技术工作既令人畏惧又令人振奋;理想情况下,这本书给了你一些关于如何为 Android 平板电脑创建自己的游戏的想法。
凭借 Android 过去的成功和光明的未来,我相信平板电脑对更好游戏的需求将会持续很长一段时间。确保你在那里抓住这个令人兴奋的浪潮。
十一、在真实设备上测试 Android 游戏
如果你打算为 Android 平板电脑制作游戏,你肯定需要在真实的东西上测试它们。Android 有一个内置的方法来做到这一点,消除了开发人员过去在视频游戏机和其他移动平台上测试他们的创作时遇到的许多障碍。应用市场很难容忍那些有缺陷或问题的程序,而这些缺陷或问题在产品测试中很容易被修复。
本附录指导您快速设置平板电脑进行测试。要跟进,你需要一台 Android 3.0 平板电脑。在我写这篇文章的时候,市场上有很多平板电脑,每周都会有更多的上市,所以不可能一一列出。当我选择设备时,我很少寻找最先进的平板电脑,而是寻找最受欢迎的一款。如果大多数人使用你所使用的设备,那么你的结果将与大多数用户的结果相似。
选择一款拥有广泛认可的品牌名称和众多追随者的平板电脑。如果你有平板电脑的朋友,你应该在所有的平板电脑上测试你的应用。这里描述的过程不需要很长时间,所以你应该没有问题。
因为您将进行调试,所以硬件接口要求您将应用指定为可调试的。您可以通过在 Android 清单文件中设置一个参数来实现这一点。当您在 Eclipse project explorer 中查看您的项目文件夹时,您不会在其中看到清单文件。图 AppA-1 显示了在哪里可以找到这个文件。
图 AppA-1。安卓清单文件
向 XML 中添加一个非常简单的参数,将项目定义为可调试的程序。清单 AppA-1 包含整个清单的代码,必须插入的部分用粗体显示。
清单 AppA-1。安卓清单文件
`
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gameproject.firstapp"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="11" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="true">
<activity android:name=".Main"
android:label="@string/app_name">
<action android:name=
"android.intent.action.MAIN" />
<category android:name=
"android.intent.category.LAUNCHER" />
接下来的步骤因设备而异。谷歌推荐去平板上的文件夹,然后去文件夹,选择 USB 调试。如果这对你的平板电脑不起作用,快速搜索一下,看看如何打开这种类型的调试。
现在你需要一个特定 USB 设备的驱动程序。这与您在将平板电脑连接到电脑进行常规使用时安装的不同。你需要从谷歌 Android 开发者页面的 USB 驱动列表中选择一个:developer.android.com/sdk/oem-usb.html。安装这些的过程非常简单。
以我拥有的摩托罗拉平板电脑为例。我点击链接进入摩托罗拉的开发者驱动主页。因为我在 64 位版本的 Windows 上运行程序,所以我选择了最新的手机 USB 驱动程序。(平板电脑是否是手机尚有争议,但驱动因素是一样的。)我按照设置流程做好了准备。
注意如果你正在麦金塔电脑上开发,你不需要担心 USB 驱动程序:你已经准备好了。然而,Linux 用户手头有些工作要做。有关更多信息,请查看 Android 官方文档,了解如何设置开发设备:
developer.android.com/guide/developing/device.html#setting-up。
如果您正确地遵循这些指示,现在您可以在设备上测试您的程序。进入 Eclipse,像往常一样运行程序。您应该可以在添加的设备和模拟器之间进行选择,而不是默认使用模拟器。选择你插入的设备,你就可以像你的用户一样与你的应用互动。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/19562.html