本文根据《代码本色》前四章的内容进行撰写,涉及简单的java继承、多态知识,processing的部分函数调用以及动力学基本知识。
一、开发环境
processing IDE(需要安装java并配置路径)
二、开发背景
阅读《代码本色》之后,粒子系统一章令我印象深刻,随即决定利用粒子系统一章编写出一个射击类小游戏,其灵感来源于网站openprocessing中的一个demo,原地址为:https://www.openprocessing.org/sketch/528480,有兴趣可以去玩一下。此demo上手很容易,操作简单,但是趣味无穷,可以感受到玩游戏的乐趣——在快节奏的操作中肾上腺素飙升的快感。如果你沉迷于快节奏的操作快感,这款游戏一定会令你惊喜。
三、内容综述
主要实现了粒子的产生与消失、加速系统、运动检测系统、射击系统等。
四、实现过程
1.创建两个基本类:Particle类、ParticleSystem类(抽象类)
class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float lifetime;
int sizeX, sizeY;
Particle(PVector l, PVector v, PVector a, float lifeTime, int sizex, int sizey) { //s=0, ellipse;s=1, rect;s=2, angle.
velocity = v.get();
location = l.get();
acceleration = a.get();
lifetime = lifeTime;
sizeX = sizex;
sizeY = sizey;
}
int getSize(){
return sizeX;
}
PVector getLocation(){
return location;
}
void run() {
update();
display();
}
void update() {
velocity.add(acceleration);
location.add(velocity);
if(lifetime != 255){
lifetime -= 2.0;
}
}
void display() {
stroke(153, 77, 82);
strokeWeight(3);
fill(217,116,43);
ellipse(location.x, location.y, sizeX, sizeY);
}
boolean isDead() {
if (lifetime < 0.0) {
return true;
} else {
return false;
}
}
}
import java.util.Iterator;
ArrayList <Particle> particles;
abstract class ParticleSystem {
PVector l, v, a;
float lifeTime;
int s, sizex, sizey;
ParticleSystem() {
particles = new ArrayList<Particle>();
}
void run() {
}
}
2.继承这两个类得到三个类:Boss类(继承自Particle)、Player(继承自Particle)、FastBall(继承自ParticleSystem)
class Boss extends Particle {
final int bossBlend = 100;
int leftBlood;
Boss() {
super((new PVector(random(0, 1)*width, random(0, 1)*height)), (new PVector(random(-1,1), random(-1,1))), (new PVector(0, 0)), 255, 100, 100);
leftBlood = bossBlend;
}
void setVelocity(){
super.velocity.add(new PVector(random(-1,1) / 10, random(-1,1) / 10));
}
void display() {
stroke(177, 20, 20);
strokeWeight(3);
fill(117, 22, 22);
rectMode(CENTER);
ellipse(location.x, location.y, sizeX, sizeY);
}
void run(){
if(isDead()){
println("you win");
return;
}
setVelocity();
judgeOut();
super.run();
}
int getBlood(boolean isHit){
if(isHit){
leftBlood--;
}
return leftBlood;
}
void judgeOut() {
float x = super.location.array()[0];
float y = super.location.array()[1];
if (x < -50) {
x += (width + 100);
} else if (x > width + 50) {
x -= (width + 100);
}
if (y < -50) {
y += (height + 100);
} else if (y > height +50) {
y -= (height + 100);
}
super.location.set(new PVector(x, y));
}
boolean isDead(){
if(leftBlood < 0){
return true;
}else{
return false;
}
}
}
class FastBall extends ParticleSystem {
int timePassed;
PVector pos;
PVector playerLocation;
FastBall() {
super();
super.lifeTime = 506;
super.sizex = 20;
super.sizey = 20;
}
void getPlayerLocation(PVector l) {
playerLocation = l;
}
void setGoal(PVector p) {
pos = p;
}
void run() {
super.l = new PVector(width*random(0, 1), height*random(0, 1));
float temp = sqrt(pos.array()[1]*pos.array()[1]+pos.array()[0]*pos.array()[0]);
super.v = new PVector((pos.array()[0]-super.l.array()[0])/temp, (pos.array()[1]-super.l.array()[1])/temp);
super.a = new PVector(super.v.array()[0]/5, super.v.array()[1]/5);
timePassed = millis();
if (timePassed % 40 == 0) {
particles.add(new Particle(super.l, super.v, super.a, super.lifeTime, super.sizex, super.sizey));
}
Iterator <Particle> it = particles.iterator();
while (it.hasNext()) {
Particle p = it.next();
p.run();
if (p.getSize()==20 &&sqrt(pow((p.getLocation().array()[0] - playerLocation.array()[0]), 2)+pow((p.getLocation().array()[1] - playerLocation.array()[1]), 2)) < 20) {
println("you failed");
exit();
}
if (p.isDead()) {
it.remove();
}
}
}
}
class Player extends Particle {
Player(PVector l) {
super(l.get(), (new PVector(0, 0)), (new PVector(0, 0)), 255, 30, 30);
}
PVector getLocation(){
return super.location;
}
void setVelocity(PVector v) {
super.velocity = v;
}
void display(){
stroke(107,194,53);
strokeWeight(3);
fill(174, 221, 129);
ellipse(location.x, location.y, sizeX, sizeY);
}
void run() {
judgeOut();
super.run();
}
void reducedVelocity(){
float vX, vY;
if(super.velocity.array()[0] != 0){
vX = -super.velocity.array()[0] / 100;
}else{
vX = 0;
}
if(super.velocity.array()[1] != 0){
vY = -super.velocity.array()[1] / 100;
}else{
vY = 0;
}
setVelocity(new PVector(vX, vY));
}
void judgeOut() {
float x = super.location.array()[0];
float y = super.location.array()[1];
if (x < -15) {
x += (width + 30);
} else if (x > width + 15) {
x -= (width + 30);
}
if (y < -15) {
y += (height + 30);
} else if (y > height +15) {
y -= (height + 30);
}
super.location.set(new PVector(x, y));
}
}