Android vs. CraigDJ






4.91/5 (24投票s)
我使用HTML5、CSS、Javascript、Node.js和PhoneGap创建了一个Android游戏,这是我的开发过程。
介绍
大家好,欢迎来到我的Android应用项目!
我必须承认,我对原生Android环境几乎一无所知——这是我鲁莽地 dive 到CP的Android版块。我没有去学习一个全新的环境和语言,而是使用HTML5、CSS和Javascript构建了我的游戏,并通过一个名为PhoneGap的开源项目将其移植到Android。随着项目的进展,我一直在更新这篇文章——请继续关注,不要忘了投票和评论!
我的应用想法是什么?
如今,我们的LCD显示器可以显示数百万种颜色,而我们的眼睛也能感知数百万种颜色。我设想了一个极致测试人眼的简单游戏。
有几种方法可以做到这一点,但我脑海中最先浮现的是一种计算机生成的点在屏幕上滑动的画面。想象一下,几乎所有的点都颜色相同,只有少数几个点会被应用程序通过添加或减少一点R、G或B值而略微修改。用户的目标是点击那些颜色不同的点(也许可以将它们滑到屏幕的边缘)。
可以创建几种游戏模式——限时模式、在线模式(与其他玩家对战)、无限玩模式(赚取积分和道具)以及多色模式(增加难度)。
用户可以自定义基础颜色。点还可以与音乐同步。
应用程序可以跟踪用户最擅长识别哪种颜色修改,并在用户个人资料中显示这些信息,以供用户参考。游戏中有几种可收集物品(与点一起下落的物品):颜色增强器(使识别差异更容易)、积分、炸弹(不要收集这些!)以及临时减速。
设置
我是一个坦白的Android新手。假设你也是,以下是你开始所需的一切。
- 你需要一个Java开发工具包(JDK)。在此处下载并安装。
如果你还没有,这个工具包也包含一个完整的JRE。 - 下载并安装Android SDK。SDK没有安装程序,所以我建议你创建一个新文件夹来存放SDK文件(例如,放在Program Files中,或与你的文档/图片/视频旁边)。
- 而且,如果你还没有,我推荐安装GIMP,一个免费且功能强大的图像编辑器。我用它来创建游戏中的一些图形。
查看原生SDK
现在你应该拥有开发Android所需的一切了。现在和我一起花点时间看看SDK,感受一下。
- 打开Eclipse(双击/eclipse/eclipse.exe)。
- 导航到File>>New>>Android Application Project并点击。
- 一路按默认设置完成。
- 你可以连接你的Android设备(如果你有的话),并在上面运行你的第一个应用。我没有Android设备,所以没有执行这一步。
这时,在我的应用进展到这一步时我停了下来。学习一个全新的环境和语言突然变得太过痛苦。我拥有设备,但不知道如何使用它。
HTML5?Node.js?这是什么...?
我真的不想为了写这个应用而学习原生Android开发。我知道可以使用Web技术来构建应用,于是我决定探索这条路。我仍然学到了很多,只是过程没那么痛苦!
以下是对比
原生环境
- 功能极其强大
- 性能优越
- 完全不熟悉(IDE、语言,一切都是新的)
PhoneGap & Friends
- 功能适中(使用PhoneGap,可以使用摄像头、加速计、文件系统、GPS、通知)
- 性能适中
- 相对熟悉(我已经知道HTML等)
我需要证明使用HTML5的理由吗?简短的回答是“不需要”。长长的回答是,Web技术很有趣,而且YOLO(活在当下),所以我就是想用它们。现在开始。欢迎评论。
开始吧——介绍PhoneGap
“PhoneGap是一个开源框架,可以利用HTML5、Javascript和CSS快速构建跨平台移动应用。”——http://phonegap.com/about/
基本上,PhoneGap是一个原生的Web代码包装器,它允许用Web代码编写的应用被移植到原生应用并在应用商店分发。它支持iOS、Android、WebOS、Windows Phone、Symbian、Bada,甚至Blackberry :P。它还允许Web应用访问目标设备的本地功能,如指南针、加速计、摄像头、地理位置和文件系统。它还支持自定义警报、声音和振动。安装PhoneGap
这是创建原生Android应用所需的一切(至少目前我只需要这些)——使用HTML5、CSS和Javascript。
- 如果你还没有,请下载并安装Node.js。
- 现在,正如你在这个链接上看到的,打开Node.js命令行,确保你在C:\目录下,然后输入
npm install -g phonegap
并按回车键。让魔法开始! - PhoneGap安装后,你需要“Ant”。我尝试自己安装Ant但失败了。因此,我强烈建议你使用WinAnt,它是由某个神奇的贡献者编写的。WinAnt将为你处理一切。
- 现在重启你的电脑。
- 现在你需要配置一些环境变量。打开控制面板,在搜索框中输入“envi”(只需输入这些),然后点击“编辑系统环境变量”。现在创建一个名为ANDROID_HOME的新用户变量,将其值设置为你存放SDK的文件夹路径(例如,C:\Users\...\Android\adt-bundle-windows-x86_64-20131030\adt-bundle-windows-x86_64-20131030\sdk)。现在编辑PATH变量,在后面追加“;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools”。
- 再次重启。虽然痛苦,但值得。
- 现在你可以创建你的应用了。打开Node.js命令行,使用
cd
命令导航到你想要创建项目的目录,然后运行phonegap create your-app-name
。
这样就安装好了所有东西,并且创建了我们的第一个应用!启动Eclipse,然后点击Android SDK Manager图标。
现在导航到Tools>>Manage AVDs。我们需要设置一个虚拟Android设备。
转到“Device Definitions”选项卡并选择一个设备。最初,我选择了Nexus 7,但是...
...在使用模拟器一段时间后,我现在强烈建议你使用较小的设备,比如Nexus S。模拟器本身已经相当慢了,选择一个较重的设备可能会让它慢得无法忍受。
现在点击“Create AVD...”。设备将被设置。设置完成后,返回到命令行并运行以下命令:cd your-app-name
,这会进入你的项目目录,然后运行phonegap run android
,这会同时将Android添加到你的项目中并在模拟器上运行你的应用。
这张截图是我用HTML、CSS和JavaScript构建的空白PhoneGap Android应用!
在我们开始之前...
www目录
如果你在文件资源管理器中打开项目的根文件夹,你会看到一个名为“www”的目录。这个目录是我们(在很大程度上)将要用来创建应用的。
关于开发的一点说明
不要在Android模拟器上完成所有的调试和测试,这是一个非常缓慢的过程。使用PhoneGap编译一个应用可能需要几分钟,而Android模拟器本身就非常慢,而且相当不响应。因此,我大部分的调试工作都是在桌面Chrome和Windows Phone上完成的。为了最有效地做到这一点,我将这段代码片段添加到了每个页面的head标签中,并在编译Android版本时将其移除。
<!--Delete this later-->
<meta name="viewport" content="user-scalable=no, width=device-width"/>
<meta name="msapplication-tap-highlight" content="no" />
开发我的应用想法
在本节中,我将简要解释这个游戏是如何工作的。
页数
我游戏中最关键的部分之一是导航UI。整个游戏只在一个HTML页面(index页面)上运行,所以我将HTML分割成可视化的“页面”,放在一个大的容器中,就像这样
<div id="container" onresize="updateWidths()">
<div id="header">
<h1 id="hdrWplText">OcularHues</h1>
<a href="#" id="hdrButton">Back</a>
</div>
<div id="Page1" class="Page">
<div class="content">
<h2>Total Points Scored</h2>
<p id="tlt_points"></p>
<div class="menuList">
<ul>
<li><a href="#" id="a_unlimited">Play as long as you like...<span class="li_i"><img src="img/arrowright.png"/></span></a></li>
<li><a href="#" id="a_limited">Timelimit (2 mins)...<span class="li_i"><img src="img/arrowright.png"/></span></a></li>
</ul>
<ul>
<li><a href="#" id="a_userstats">Your Stats...<span class="li_i"><img src="img/arrowright.png"/></span></a></li>
<li><a href="#" id="a_about">About...<span class="li_i"><img src="img/arrowright.png"/></span></a></li>
</ul>
</div>
</div>
</div>
<!--Etc-->
</div>
页面是这样在CSS中定义的...
.Page { position: absolute; display: none; }
然后使用Javascript,所有Page div都被设置为设备的宽度,并且它们的left属性被设置为device width,这样所有的页面都会在屏幕的右侧不可见。但是,活动页面,即用户正在使用的页面,会被捕获并设置为“display: block”和“left: 0”。
$(document).ready(function () {
$(".Page").css("top", 46);
$("#Page5").css("top", 0);
updateWidths();
loadPositions();
$('#hdrButton').click(function (event) {
event.preventDefault();
$('#hdrButton').css('background-color', '#C5D4E2');
slide(previouspage);
});
}); function loadPositions() {
//All pages except the root page should be directly off to the right of the screen
$(".Page").css("left", width());
$(activepage).css("left", 0);
$(activepage).css("display", "block");
$('#hdrButton').css("display", "none"); //It's the home scren. Can't go back.
}
我还用下面的代码动画化了页面过渡。这个函数使得从一个页面移动到另一个页面就像调用slide("#PageX")
一样简单。
function unit(pageno) {
var soFar = $(pageno).css("left").slice(0, -2);
if (width() / 2 < soFar)
return width() / 8;
else
return Math.pow(soFar, .85);// / 10;
}
function slide(pageno) {
if (issliding) { return; }
window.scrollTo(0, 0);
$(pageno).css("display", "block"); //display the page to the right.
issliding = true;
nextIncrement(pageno);
} function nextIncrement(pageno) {
var current = $(activepage).css("left").slice(0, -2);
var nextCurrent = current - unit(pageno);
$(activepage).css("left", nextCurrent.toString() + "px");
$(pageno).css("left", (nextCurrent + width()).toString() + "px");
if (nextCurrent + width() < 0 || unit(pageno) < .1) {
//We're done.
$(activepage).css("display", "none");
$(activepage).css("left", width());
//Change the active page
activepage = pageno;
$(activepage).css("left", 0);
//Page-specific actions
if (activepage == "#Page1") {
document.getElementById('hdrWplText').innerHTML = "OcularHues";
$('#hdrButton').css("display", "none");
}
else {
$('#hdrButton').css("display", "block");
}
//etc for each page as needed
issliding = false;
if (codeToRunAfterwards != "") {
var _store = codeToRunAfterwards;
setTimeout(_store, 1);
codeToRunAfterwards = "";
}
}
else {
setTimeout(function () { nextIncrement(pageno) }, 10);
}
}
Canvas元素
我使用了HTML5的canvas元素来创建这个游戏。它是以这种方式以编程方式创建的
var view;
var canvas;
$(document).ready(function () {
//Create the drawing board
$('#Page5').prepend('<canvas id="view" width="' + width() + '" height="' + height() + '">Your browser does not support the canvas element.</canvas>');
canvas = document.getElementById("view");
view = document.getElementById("view").getContext("2d");
});
创建点颜色
关卡越高,区分点的难度应该越大。这个函数根据游戏关卡生成颜色。
var R = 255;
var G = 0;
var B = 0;
var mainColor = "";
var adjustedColor = "";
function setGameColors() {
mainColor = "rgb(" + R + "," + G + "," + B + ")";
var g = G;
var b = B;
var dd = getRandomInt(2, 3);
isblue = (dd == 3);
if (dd == 2) { g += (11 - level) * 10; }
if (dd == 3) { b += (11 - level) * 10; }
adjustedColor = "rgb(" + R + "," + g + "," + b + ")";
}
一个函数统治一切,一个函数把它们联系起来...
很有讽刺意味的是,整个游戏中最重要的函数之一却是最小的。这个函数循环运行游戏。
function runGame() {
//Update game situation
UpdateMovements(); //Adjust items on the screen
DrawGame(); //Visually render the adjusted items unto the screen
if (is_playing)
setTimeout("runGame()", 20);
}
创建点
我可以复制粘贴更多的代码,但这篇文章已经很长了。相反,我只想说,点的坐标存储在数组中,一个数组存储X值,另一个数组存储Y值。实际上只有15个正常的(“坏”)点,以及五个不寻常的、颜色不同的点。在UpdateMovements()
中,这些点以稳定的速度向下移动,直到它们被点击或穿过屏幕底部。在这两种情况下,它们都会被重新分配新的X值,并放置在屏幕上方,最多比屏幕顶部高一个设备高度,然后它们将再次开始向下滑动。
如果你想看代码,随时可以从本文顶部下载源代码。
星星
与点一样,星星的X和Y坐标也存储在数组中。当游戏开始时,会调用LoopStars()
,直到游戏结束,它会启动以下循环。
function CreateStar() {
var postY = getRandomInt(-1 * height(), 0);
var postX = getRandomInt(_r, width() - _r);
while (overlaps(postX, postY)) {
postY = getRandomInt(-1 * height(), 0);
postX = getRandomInt(_r, width() - _r);
}
s_X[stars] = postX;
s_Y[stars] = postY;
++stars;
}
function LoopStars() {
//Skip the very first time.
if (!first_star)
CreateStar();
first_star = false;
if (is_playing) {
var wait = getRandomInt(50000, 120000); //50-120 sec
star_timeout = setTimeout(function () { LoopStars(); }, wait);
}
}
肾上腺素模式
我想在游戏中增加一些东西来打破点在屏幕上滚动的单调。在肾上腺素模式期间,屏幕会变成紫色,速度会增加三倍。在肾上腺素模式期间点击的点比正常游戏玩法中点击的点值钱得多。肾上腺素模式由这个循环控制,通过StartAdrenalineMeter(true)
启动。
function doAdrenaline() {
isadren = true;
fatfinger = 2; //It's harder to be accurate during adrenaline mode.
//End it in 10 sec
var wait = 10000;
adren_timeout = setTimeout(function () { StartAdrenalineMeter(false); }, wait);
}
function StartAdrenalineMeter(varcheck) {
if (!varcheck) {
//Finished
isadren = false;
fatfinger = 1.3;
//Now Start again
adren_timeout = StartAdrenalineMeter(true);
}
else {
//Start again
if (is_playing) {
var wait = getRandomInt(10000, 40000); //10-40 sec
adren_timeout = setTimeout(function () { doAdrenaline(); }, wait);
}
}
}
创建限时模式
我们快完成了!创建限时模式非常容易。每次游戏开始时,我都通过运行这段代码来做到这一点...
//Let's do this!!
if (istimelimit) {
d_Date = new Date();
startTime = d_Date.getTime();
time_checker = setInterval(function () {
d_Date = new Date();
var t_now = d_Date.getTime();
if (t_now - startTime > 120000) {
if (navigator.notification) {
navigator.notification.alert("Two minutes have elapsed.", null, "Time's Up!", "OK");
} else {
alert("Time's Up! Two minutes have elapsed.");
}
QuitGame();
}
}, 5000);
}
存储用户统计数据
我不会复制粘贴所有用于这部分应用的代码,但我会用一个非常基本的例子来展示我是如何做到的。
我使用了一个新的HTML5功能,称为Localstorage。Localstorage的使用方式如下
if (!localstorage.stored)
{
localstorage.foobar = 10;
localstorage.stored = "true";
}
else
{
alert(localstorage.foobar);
}
//Imagaine the page closes. Then the user opens it again...
//<--Imagining--->
//Result: 10
所以,保存用户统计数据就像监控积分和点击次数一样简单,并将这些数据存储在localstorage中。同样,如果你想要完整的代码,随时可以下载源代码。:-)
出版
代码就完成了!现在是签名和发布时间...
- 打开www目录下的config.xml,并更新其中的详细信息。我的应用ID是app.lufroloc.ocularhues(lufroloc是colorful的倒序)。保存。
- 在你的项目目录中,导航到platforms/android目录并打开AndroidManifest.xml
- 将
android:debuggable
设置为false
。 - 保存。还记得本文开头我们在Android IDE中创建的Android项目吗?在Eclipse中再次打开它。
- 在Package Explorer中,屏幕右侧,右键单击你的项目目录。
- 然后选择Android Tools>>Export Signed Application Package。
- 按照步骤创建一个密钥库和密钥。你需要它们来签名你的应用。
- 确保你记住了密码和别名!更新和签名应用时都需要它们!
- 现在去build.phonegap.com,登录或创建一个账户。
- 当被要求上传.zip文件时,压缩你的整个项目目录(不仅仅是www文件夹),然后上传。
- PhoneGap的网站会处理接下来的事情。它相当直观。完成后,你应该就能下载编译和签名的APK文件了。
已知问题
我知道我的应用目前存在一些问题。如果你发现更多问题,请随时在下方评论:-)
- 模拟器性能不佳。
我不确定这有多大程度上是我的应用的问题,有多大程度上是模拟器的问题。模拟器本身已经非常慢了……所以如果我能在实际设备上运行我的应用,我会对真实性能有更好的了解。 - 声音不工作。
不知何故,应用中的声音似乎不起作用。
总结
就是这样!感谢你一直以来的支持!希望你喜欢我的Android提交。如果你有Android设备,请随时安装我的应用(可以从页面顶部下载.zip文件)。任何反馈都将不胜感激。:-)
历史
- 2013/12/23 - 第一个版本。
- 2013/12/28 - 第二个版本。创建了游戏的alpha版本。
- 2013/12/31 - 第三个版本。至少目前完成了应用。
- 2014/01/13 - 修复了一些拼写错误,润色了文本。