《a little challenge》--基于processing的简易射击游戏

演示效果

在这里插入图片描述
在这里插入图片描述

游戏机制

简单的击杀得分,躲避敌人攻击并击杀敌人获得经验升级和分数:在这里插入图片描述
当还有剩余生命时通过按下q键复活,没有时显示最终分数:
在这里插入图片描述
在这里插入图片描述
当敌人被击中后会有0.5秒无敌时间,自己会有两秒无敌。升级会补满血量和能量。
敌人写了两种,一种是固定炮台,当玩家靠近会发射激光。另一种是黑色飞机,会在地图内巡逻,躲避玩家子弹和玩家并跟踪追击玩家:
在这里插入图片描述
wasd控制上下左右,通过鼠标左中右键发射不同子弹和c键发射激光:
在这里插入图片描述

类间关系与简易逻辑实现

在这里插入图片描述
其余ui,map等类就不介绍使用关系了。

敌人逻辑是根据自身血量判断,当血量大于1/2选择根据距离攻击或者追踪,与玩家过近即后退,否则躲避玩家,过远则继续游走。
炮台逻辑更简单,当距离在一定范围内蓄能发射激光,冷却时间内发射普通子弹。

主要代码

玩家类的显示和更新:

class Spaceship { 
  map mymap;
  bullets all_bullet;
  enemies enemies; 
  
  float laser_prepare_time=60;
  float laser_prepare_timer=0;
  float quick_shoot_timer=0;
  float quick_shoot_interval=5;
  float normal_shoot_timer=0;
  float normal_shoot_interval=10;
  boolean Ispreparing_laser=false;
  
  ArrayList<life_variation_text> texts=new ArrayList();
  float max_hp;
  float max_mp;
  float hp;
  float mp;
  float xp=0;
  float xp_limit=800;
  float damage=30;
  int LV=1;
  int life=3;
  int score=0;
  int protected_timer_limit=120;
  int protected_timer=121;
  
  
  float IsSprint;
  
  // All of our regular motion stuff
  PVector position;
  PVector absolutePos;
  PVector velocity;
  PVector acceleration;

  // Arbitrary damping to slow down ship
  float damping = 0.99;
  float topspeed = 6;

  // Variable for heading!
  float heading = 0;

  // Size
  float r = 16;

  // Are we thrusting (to color boosters)
  boolean thrusting = false;
  bar bar=new bar(absolutePos);
Spaceship(map tmap,float hp,float mp,bullets all_bullet) {
    this.hp=hp;
    this.mp=mp;
    max_hp=hp;
    max_mp=mp;
    this.all_bullet=all_bullet;
    IsSprint=0;
    position = new PVector(0,0);
    velocity = new PVector();
    acceleration = new PVector();
    absolutePos=new PVector(0,0);
    mymap=tmap;
  } 

  Spaceship(map tmap,int hp,int mp,bullets all_bullet,enemies enemie) 
  {
    this(tmap,hp,mp,all_bullet);
    this.enemies=enemie;
  } 

  // Standard Euler integration
  void update() {
    xp=xp>xp_limit?xp_limit:xp;
    if(xp>=xp_limit)
    {
    levelup();
    }
    if(all_bullet.get_ship_laser_num()<1&&laser_prepare_timer>=laser_prepare_time&&mp>=50)
    {
    laser_prepare_timer=0;
    }    
    mp+=0.03+(LV-1)*0.01;
    mp=mp>max_mp?max_mp:mp;
    velocity.add(acceleration);
    velocity.mult(damping);
    velocity.limit(topspeed);
    position.add(velocity);
    position.x=constrain(position.x,-mymap.size.x/2,mymap.size.x/2);
    position.y=constrain(position.y,-mymap.size.y/2,mymap.size.y/2);
    absolutePos=PVector.add(position.get(),mymap.pos.get());
    if(protected_timer>=protected_timer_limit&&!IsDead())
    {
    getCollided();
    getShooted();
    IsSprint=acceleration.mag()>0?255:0;
    }else
    {
    protected_timer++;
    IsSprint=20;
    }
    acceleration.mult(0);
  }
 // Draw the ship
  void display(float col,color c) { 
    rectMode(CENTER);
    pushMatrix();
    translate(absolutePos.x,absolutePos.y);
    rotate(heading);
    fill(c,IsSprint);
    // Booster rockets
    stroke(0);
    strokeWeight(0);
    rect(-r/3,r,r/3,r);
    rect(r/3,r,r/3,r);
    
    
    stroke(0);
    strokeWeight(2);
    if(protected_timer>=protected_timer_limit)
    {
      fill(col);
    }else
    {
    fill(col,125);
    }
    // A triangle
    beginShape();
    vertex(-r,r);
    vertex(0,-1.5*r);
    vertex(r,r);
    endShape(CLOSE);
    rectMode(CENTER);
    popMatrix();
    show_hp_change();
    thrusting = false;
  }
  }

子弹类:

class bullet
{
map tmap;
PVector pos;
PVector absolutePos;
PVector direct;
float speed;
float angle;
float damage;
color col;
bullet(PVector pos,float angle,map tmap,float damage,color col,float speed)
{
this.pos=pos;
this.speed=speed;
this.absolutePos=PVector.add(pos.get(),tmap.pos.get());
this.angle=angle;
this.direct=new PVector(sin(angle),-cos(angle));
this.tmap=tmap;
this.damage=damage;
this.col=col;
}

void display()
{
pushMatrix();
fill(col);
translate(pos.x,pos.y);
rotate(angle);
pos.add(direct.get().mult(speed));
rectMode(CENTER);
rect(0,0,3,30);
popMatrix();
}

void display_pos()
{
absolutePos=PVector.add(pos.get(),tmap.pos.get());
pushMatrix();
fill(col);
pos.add(direct.get().mult(speed));
translate(absolutePos.x,absolutePos.y);
rotate(angle);
rectMode(CENTER);
strokeWeight(1);
rect(0,0,3,30);
popMatrix();

}


}

激光类:

class laser
{
map mymap;
PVector Pos;
PVector absolutePos;
float angle;
float launch_time;
float launch_timer;
float duration=60;
float timer=0;
float max_distance=3000;
float max_radius;
float radius;
float distance=200;
float damage;


laser(PVector Pos,float radius,float angle,map mymap,float damage)
{
  this.Pos=Pos;
  this.mymap=mymap;
  this.angle=angle;
  this.max_radius=radius;
  this.radius=max_radius/7;
  this.damage=damage;
  launch_time=max_radius-this.radius;
  launch_timer=0;
  absolutePos=PVector.add(Pos.get(),mymap.pos.get());
}


void display()
{
absolutePos=PVector.add(Pos.get(),mymap.pos.get());
launch_timer+=8;
if(launch_timer<launch_time)
{
radius+=8;

radius=radius>max_radius?max_radius:radius;
}

if(launch_timer>=launch_time&&timer<=duration)
{
timer++;
mymap.shake();
}else if(launch_timer>=launch_time)
{
radius-=4;  
mymap.recover_from_shake();
}
radius=radius<0?0:radius;
distance+=100;
distance=distance>max_distance?max_distance:distance;
pushMatrix();
translate(absolutePos.x,absolutePos.y);
rotate(angle);
strokeWeight(radius);
stroke(60,0,0);
line(0,-radius/2,0,-distance);
popMatrix();
strokeWeight(1);
}


void display_enemy()
{
absolutePos=PVector.add(Pos.get(),mymap.pos.get());
launch_timer+=8;
if(launch_timer<launch_time)
{
radius+=8;

radius=radius>max_radius?max_radius:radius;
}

if(launch_timer>=launch_time&&timer<=duration)
{
timer++;
}else if(launch_timer>=launch_time)
{
radius-=4;  
}
radius=radius<0?0:radius;
distance+=100;
distance=distance>max_distance?max_distance:distance;
pushMatrix();
translate(absolutePos.x,absolutePos.y);
rotate(angle);
strokeWeight(radius);
stroke(30);
line(0,-radius/2,0,-distance);
popMatrix();
}




float dist(PVector target)
{
PVector self=new PVector(sin(angle)*distance,-cos(angle)*distance);
PVector a=subpoint(target);
if(PVector.dot(PVector.sub(a,absolutePos),self)<0)
{
  return 9999;
}else
{ 
  return(abs(PVector.dist(subpoint(target),target)));
}
}

PVector subpoint(PVector target)
{
PVector self=new PVector(sin(angle)*distance,-cos(angle)*distance);
PVector start_target=new PVector(target.x-absolutePos.x,target.y-absolutePos.y);
PVector start_subpoint=self.normalize().mult(PVector.dot(start_target,self.normalize()));

return PVector.add(absolutePos.get(),start_subpoint);
}



}

构思与踩坑点

1.地图,玩家都是相对运动,单用独立坐标无法表示,分别用绝对坐标和相对坐标表示屏幕位置以及彼此关系。
2.敌人与玩家,地图都是相对运动,以地图中心点为(0,0)基准储存相对坐标。
3.子弹显示和击中不好管理所以创建了enemies类和bullets类分别保存应当显示的对应物体,当需要销毁时移除。
4.使用《代码本色》中介绍的随机游走会让物体一直贴着地图边缘走,改用地图中心为基础的随机目标点能比较好地模拟范围内随机移动。

缺陷

1.当地图随着飞机移动时有时候会有卡顿
2.应当考虑将地图分块,考虑同一地图块内物体间的碰撞,每次都遍历整个子弹列表或者敌人列表速度很慢,所以没考虑敌人之间相互避免碰撞。
3.敌人总是扎堆生成,应考虑新的随机方法。

运用到的《代码本色》中相关内容

1.ch0 随机数
2.ch1 向量,速度,加速度
3.ch2 力
4.ch6 自治智能体

参考文章

【1】行为树和Behavior Designer插件https://zhuanlan.zhihu.com/p/29366677
【2】《代码本色》https://natureofcode.com/

同学作品推荐

1 作者:吴彦宏
《Magic Network》-使用processing编写的神经网络交互系统,可以方便地创建任意层数和节点的全连接网络,同时可以观察到运行过程中的结果,可以帮助使用者理解深度神经网络的结构。
在这里插入图片描述
2.作者:周际翔
《Gravity》-使用openFramework编写的游戏,画面清新,游戏操作简单,可玩性强,ui精美,支持手柄操作
在这里插入图片描述

3作者:吕天旭
《动态条形码》-以条形码作为创意点,在简单的黑白条形码上进行艺术加工,可以将条形码作为画板,也有着各种各样的交互方式,看起来十分精美。
在这里插入图片描述

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值