简介
本文介绍的弹幕游戏是参考《代码本色》一书中的前四章,运用其中的向量、力以及粒子系统得以实现。
开发工具
processing3
主要流程
弹幕游戏主要分为敌方(enemy)、玩家(player)以及弹幕机制,由于本文设计的游戏移除了射击元素,并且为玩家的移动加上了物理机制,躲避弹幕会变得难以操作,同时屏幕中会有两个旋涡对玩家的移动进行干扰,玩家撞到边界或陨石后速度会发生变化并扣血,hp为0游戏结束。玩家可以通过WASD四键来对飞船进行移动,移动需要消耗燃料槽,燃料槽在玩家没有操作的时候会自行补充。玩家存活的时间越长,得分越高。
飞船(玩家操控)
飞船由SpaceShip类实现,其中包含的固有属性有:质量(mass)、位置(pos)、加速度(acc)、速度(velocity)、受到推进器的推力(force)、受到旋涡的引力(totalGforce)。和现实中的物理系统一样,质量和位置决定飞船受到的引力,玩家的操纵决定飞船受到的推进力,力之和决定飞船的加速度,加速度改变速度,速度来改变位置,这样我们就可以获得一个在真空状态下,模拟真实物理系统而运动的飞船,同时我们给飞船加一个血条和燃料槽,飞船碰到边界和陨石时,飞船的速度会发生改变(方向大小之类的,这个可以自定义),血条会减少,血条为0游戏就结束。
// SpaceShip
class SpaceShip{
float mass;
PVector pos;
PVector force;
PVector velocity;
PVector acc;
PVector totalGforce;
SpaceShip(float m,int x,int y){
‘’’初始化
}
void setPosition(PVector np){
‘’’设定位置
}
void addThrust(PVector thrust){
‘’’添加推力
}
void addTotalGforce(PVector gforce){
‘’‘添加引力
}
void moveSS(int[] a){
‘’‘移动飞船
}
void boarderCollider(int[] a){
‘’’判断是否越界
}
void showSS(){
‘’’画出飞船
}
void drawShip(){
‘’’定义飞船样式
}
}
陨石
陨石的构成比较简单,初始位置(pos),速度(v)以及贴图就可以了,陨石的运动路径可以自定义,这里我直接简单的设置为直线下落。同时陨石中要有一个判断与飞船是否相撞的方法。
// Stone
class Stone{
PVector pos;
PVector v;
PImage pic;
Stone(PImage p){
‘’’初始化
}
void update(){
‘’‘更新位置
}
void showStone(){
‘’‘显示陨石
}
boolean isOut(){
‘’’判断是否出界
}
boolean isColid(PVector spos){
‘’’判断是否与飞船相撞
}
}
旋涡
旋涡是用粒子系统来实现的,原理是用长扁的椭圆绕着圆心旋转,椭圆有一定的偏转,旋转过程中椭圆的旋转半径越来越小,小到一定程度时,旧椭圆湮灭,生成一个新椭圆,约400个椭圆能到达不错的效果,但由于processing的渲染器很菜,实际过程中会导致掉帧等情况,在游戏中减少为200个。
// Particle2椭圆粒子
PVector pos=new PVector(0,0);
PVector center=new PVector(0,0);
float distance;
float od;
float theta;
float ot;
float radius1;
float radius2;
boolean first=true;
Particle2(float t,float d,PVector c){
‘’’初始化
}
void update(){
‘’’更新位置
}
void showP(){
‘’’显示粒子
}
boolean isDead(){
‘’’判断是否消亡
}
// Bhole 粒子组成旋涡
class Bhole{
int p_num=200;
PVector center;
int dist;
ArrayList<Particle2> plist=new ArrayList<Particle2>();
Bhole(PVector c,int d){
‘’’初始化
}
void show(){
‘’’显示旋涡
}
}
//定义旋涡的位置、质量、半径等。
class Planet{
float mass;
PVector pos;
int radius;
Bhole bh;
Planet(float m,int r,int x,int y){
‘’’初始化
}
void showP(){
‘’’显示旋涡
}
}
喷焰
喷焰同样使用粒子系统生成,将粒子的运动轨迹改为直线即可,同时我们使用高斯随机数来产生粒子,使得整个粒子系统呈现出的效果具有火焰的感觉。
// Particle
class Particle{
PVector pos;
PVector velocity;
PVector acc;
PVector direction;
float lifeSpan;
Particle(PVector origin,PVector vDirection){
‘’’初始化
}
void run(){
‘’’运行
}
void update(){
‘’’更新位置
}
void showParticle(){
‘’’显示粒子
}
boolean isDead(){
‘’’判断是否消亡
}
演示效果
总结
整个游戏最初的目标是做成飞船穿越在星际间的那种样式,但由于种种原因未能实现,比较遗憾。代码编写过程中比较好玩的部分就是粒子系统,我们可以通过调节粒子的运动轨迹来重现各种各样的效果,比如我在上文中实现的火焰和旋涡。
源码
// SpaceShip
class SpaceShip{
float mass;
PVector pos;
PVector force;
PVector velocity;
PVector acc;
PVector totalGforce;
SpaceShip(float m,int x,int y){
mass=m;
pos=new PVector(x,y);
force=new PVector(0,0);
velocity=new PVector(0,0);
acc=new PVector(0,0);
totalGforce=new PVector(0,0);
}
void setPosition(PVector np){
pos.x=np.x;
pos.y=np.y;
}
void addThrust(PVector thrust){
force.set(thrust);
}
void addTotalGforce(PVector gforce){
totalGforce.set(gforce);
}
void moveSS(int[] a){
PVector joinForce=PVector.add(force,totalGforce);
acc.x=joinForce.x/mass;
acc.y=joinForce.y/mass;
velocity.add(acc);
pos.add(velocity);
boarderCollider(a);
}
void boarderCollider(int[] a){
if(pos.x<0||pos.x>width||pos.y<0||pos.y>height){
velocity.x*=-1;
velocity.y*=-1;
a[0]-=10;
}
}
void showSS(){
drawShip();
}
void drawSh