目录
一 、应用介绍
Owl是一个动画交互小游戏,游戏中有四种角色:猫头鹰、炸弹、胡萝卜、骷髅:
游戏设定是:天空中会随机下落骷髅、炸弹和胡萝卜,他们的运动轨迹随机,猫头鹰会随时间逐渐变小,鼠标可以控制猫头鹰的移动,吃掉胡萝卜,猫头鹰会长大,吃掉骷髅,猫头鹰会变小,缩小至消失或者遇到炸弹则游戏结束,存活40秒则游戏成功。在界面当中有三个躲避区域——安全区,骷髅和胡萝卜遇到该区域的右上边界,会自动弹走,但是炸弹可以穿过安全区。
二 、效果展示
三 、项目结构
四 、技术探讨
1、猫头鹰与鼠标的交互
猫头鹰不是简单的随着鼠标移动,而是“跟随鼠标的趋势”移动,朝着鼠标的位置加速;
猫头鹰与鼠标的交互运动主要运用了Processing中的向量。鼠标拖拽猫头鹰时,通过速度向量控制猫头鹰跟随鼠标,_Center.addSelf( _Velocity)代码中,若鼠标指定不动,且_Velocity向量大小不变,则重心向量会匀速移向鼠标点;若此时以控制速度_DecreaseSpd来控制向量速度_Velocity,则可实现猫头鹰变速移向鼠标。
void update(float deltaTime)
{
_Center.addSelf( _Velocity.scale(deltaTime));
_Radius -= deltaTime * _DecreaseSpd;
}
void dragTo(Vec2D pos)
{
Vec2D Offset =pos.sub(_Center);
_Velocity=Offset.scale(exp(-_Radius / 55.0f) *_dragSpd);
_dragged = true;
}
void dragOff()
{
_dragged = false;
}
速度向量_Velocity计算公式:(与猫头鹰大小和鼠标拖拽速度有关)
2、角色的生成
定义role类,包含的属性有: _Center(位置重心), _Radius(大小),_DecreaseSpd(缩放程度) ,_Velocity(速度向量), _dragSpd(拖拽速度) , _dragged(是否拖拽) ,_Img(角色图片),并定义有关角色运动以及形变的方法。
玩家(猫头鹰)是role类的一个对象,胡萝卜、骷髅和炸弹都是继承自role类的Arole和Brole的对象;
Arole类,是正常下落的萝卜、骷髅和炸弹:
class Arole extends role{
Arole(Vec2D _ctr, float _radius, PImage _img, Vec2D _vel,float _decrease){
super(_ctr,_radius,_img,_vel,_decrease);
}
void update(float deltaTime)
{
_Center.addSelf( _Velocity.scale(deltaTime));
}
}
Brole类是悬浮在画面上方的萝卜和骷髅,他们不下落,通过改变速度向量的方向(_Velocity.rotate(random(2.0)*1300.0f*deltaTime);),来达到悬浮抖动的效果,跟随背景音乐一起律动:
class Brole extends role{
Brole(Vec2D _ctr, float _radius,PImage _img, Vec2D _vel,float _decrease){
super(_ctr,_radius,_img,_vel,_decrease);
}
void update(float deltaTime)
{
_Velocity.rotate(random(2.0)*1300.0f*deltaTime);
_Center.addSelf( _Velocity.scale(deltaTime));
}
}
3、猫头鹰与其他角色的交互
猫头鹰是玩家角色,要求根据碰撞的角色类型改变大小或者死亡,主要根据Arole和Brole中的img属性来判断碰撞关系:
void absorb(role another)
{
boolean bContact = contact(another);
if (bContact)
{
another.resetPosVel();
boolean increase=(another._Img==img13);
changeRadius(increase);
}
}
void absorb2(role another)
{
boolean bContact = contact(another);
if (bContact)
{
_Radius=0;
}
}
void changeRadius(boolean increase)
{
float amount = 30.0f / _Radius;
if (increase)
{
_Radius +=5.4*amount;
}
else
{
_Radius -= 5.0f*amount;
}
}
4、角色与安全区的碰撞
安全区并不是一个简单封闭的矩形,它的四个边缘中,右边缘和上边缘有阻挡能力,左边缘不能阻挡。这种渐变图形绘制方法如下:
PImage img = createImage(80, 80, ARGB);
img.loadPixels();
for (int i = 0; i < img.pixels.length; i++) {
img.pixels[i] = color(0, 90, 102, i % img.width * 2);
}
img.updatePixels();
image(img, 350.0, 150.0);
image(img, 150.0, 350.0);
image(img, 550.0, 350.0);
noStroke();
安全区有一个碰撞的检测,骷髅和胡萝卜会被安全区的边缘“弹走”
void reachBarrier(float x,float y,float w,float h){
Rect mBarrier1=new Rect(x,y,w,h);
if(_Center.isInRectangle(mBarrier1)){
_Velocity.invert();
}
}
for(int i=0;i<mBalls.size();i++){
mBalls.get(i).update(deltaTime);
PlayerBall.absorb(mBalls.get(i));
mBalls.get(i).init();
mBalls.get(i).reachBarrier(350.0, 150.0,80.0,80.0);
mBalls.get(i).reachBarrier(150.0, 350.0,80.0,80.0);
mBalls.get(i).reachBarrier(550.0, 350.0,80.0,80.0);
}
五 、参考资料
《代码本色》