由 nature of code 第九章GA的最终范例 Evolution EcoSystem 改编.
组织结构参考范例World类重写,子弹类参考范例Food类重写, 浮靶类参考范例Bloop类重写.
浮靶每秒产生一个,最大上限64个,被击中后显示血槽两秒.
飞船操作键位改到了[W][S][A][D].
(比较习惯以GBA游戏做参考分辨率设为320*240…适当调大可以降低难度)
[Q]键退出.
[J]键发射子弹.
[K]键启动力场.力场启动后对自机有减速效果,对力场判定内浮靶造成范围伤害.力场伤害较子弹小,力场击坠浮靶得分较子弹低.
– 问题:在地图边缘镜头还是抖动 <-飞船撞边不能全速移动,但镜头仍按全速反转,应该单独计算飞船的绝对速度.
– 问题:有时子弹的发射方向和飞船不平行
– 问题:子弹仍是点圆判定,速度慢了容易多判,半径小了容易漏弹,应该改成直线判定
– 问题:每帧耗时计算在 draw() 循环里面直接取两点 millis() 做减法能不能计算出?? 调大分辨率后卡顿明显,但差值并没有明显加大.(但范例的 Topic/Shaders/Landscape 里貌似也是用同样原理算的??)
//--
int pbLeRoller=0;
PVector pbTheOrigin;
//--
EcMap pbTheMap= new EcMap();
Spaceship ship = new Spaceship(pbTheMap);
EcCordinator pbTheCord= new EcCordinator(pbTheMap,ship,3);
//--
void setup() {
size(320, 240);
frameRate(32);
pbTheOrigin=new PVector(width/2,height/2);
}//--
void draw() {background(0);pbLeRoller++;pbLeRoller&=0x1F;
//--
int lpMillisA=millis();
//--
fsCheckCamera();
pbTheMap.ccUpdate();
pbTheCord.ccUpdate();
ship.ccRefresh();
//--
if(pbLeRoller==7){pbTheCord.ccNewDummy();}
//--
fill(0x77,0xEE,0x77);if(pbLeRoller<16){
fnTextString("[W][S][A][D]to move ship...",2);
fnTextString("[J]to fire beam [K] activate barrier...",3);}
fnTextFloat("cameraX:",pbTheMap.cmPos.x,11);
fnTextFloat("cameraY:",pbTheMap.cmPos.y,12);
fnTextFloat("shipX:",ship.location.x,13);
fnTextFloat("shipY:",ship.location.y,14);
fnTextFloat("speed:",ship.velocity.mag(),26);
fnTextInt("bullets:",pbTheCord.cmBulletList.cmPos.size(),28);
fnTextInt("dummies:",pbTheCord.cmDummyList.size(),29);
//--
textAlign(RIGHT,TOP);text("Score:"+nf(pbTheCord.cmScore,6),width-5,2);textAlign(LEFT,TOP);
//--
if (keyPressed) {switch(key){
case 'a':ship.turn(-0.15);ship.cmTurnPlus = true;break;
case 'd':ship.turn( 0.15);ship.cmTurnMinus = true;break;
case 'w':ship.thrust( 1);ship.thrusting = true;break;
case 's':ship.thrust(-1);ship.backThrusting = true;break;
case 'k':case 'f':ship.cmBarrier = true;break;
default:break;
}}
//--
int lpMillisB=millis();
fnTextInt("ms/f:",lpMillisB-lpMillisA,27);
//--
}//+++
void keyPressed(){switch(key){
case 'j':case 'e':pbTheCord.cmBulletList.ccShoot(ship.location,ship.heading);break;
case 'q':fsPover();break;
default:break;
}}//+++
void fsPover(){
//--
exit();
//--
}//+++
void fsCheckCamera(){
PVector lpDist=PVector.sub(ship.cmAbsolutePos,pbTheOrigin);
if(lpDist.mag()>32){
lpDist.normalize();
lpDist.mult(ship.velocity.mag());
pbTheMap.cmPos.sub(lpDist);
}
}//+++
void fnTextFloat(String pxTitle, float pxVal, int pxLine){boolean lpRight=pxLine>(height/16);
text(pxTitle+nfc(pxVal,2),lpRight?width/2+16:16,16*(lpRight?pxLine-height/16:pxLine));
}//+++
void fnTextInt(String pxTitle, int pxVal, int pxLine){boolean lpRight=pxLine>(height/16);
text(pxTitle+nf(pxVal,4),lpRight?width/2+16:16,16*(lpRight?pxLine-height/16:pxLine));
}//+++
void fnTextString(String pxTitle, int pxLine){boolean lpRight=pxLine>(height/16);
text(pxTitle,lpRight?width/2+16:16,16*(lpRight?pxLine-height/16:pxLine));
}//+++
class EcMap{
PVector cmPos;
PVector cmDia;
int cmColorSet;
EcMap(){
cmPos=new PVector(32,32);
cmDia=new PVector(1400,1400);
cmColorSet=0x77;
}
//--
void ccUpdate(){
fill(cmColorSet,cmColorSet);rect(cmPos.x,cmPos.y,cmDia.x,cmDia.y);
float lpDiv=cmDia.x/8;
fill(255-cmColorSet);
for(int i=0;i<64;i++){
text(nf(i,3),i%8*lpDiv+cmPos.x,i/8*lpDiv+cmPos.y);
}
}
//--
}//+++
class Spaceship {
//--
EcMap cmMap;
//--
PVector cmAbsolutePos;
//--
PVector location,velocity,acceleration;
float damping,topspeed,heading,r;
boolean thrusting,backThrusting;
//--
boolean cmTurnMinus,cmTurnPlus;
//--
boolean cmBarrier;
//--
Spaceship(EcMap pxMap) {
//--
cmAbsolutePos = new PVector();
location = new PVector(99,99);
velocity = new PVector();
acceleration = new PVector();
cmMap=pxMap;
damping=0.995;
topspeed=8;
heading=2;
r=8;
thrusting=false;
backThrusting=false;
cmTurnMinus=false;
cmTurnPlus=false;
cmBarrier=false;
//--
}
//--
void ccRefresh(){update();display();}
void update() {
damping=cmBarrier?0.950:0.995;
velocity.add(acceleration);velocity.mult(damping);velocity.limit(topspeed);
location.add(velocity);
location.x=constrain(location.x,0,cmMap.cmDia.x);
location.y=constrain(location.y,0,cmMap.cmDia.y);
acceleration.mult(0);
}
//--
void applyForce(PVector force) {PVector f = force.get();acceleration.add(f);}
void turn(float a) {heading += a;thrust(a*0.3);}
//--
void thrust(float pxDirect) {
float angle = heading - pxDirect*PI/2;
PVector force = new PVector(cos(angle),sin(angle));
force.mult(0.3);
applyForce(force);
}
//--
void display() {
//--
cmAbsolutePos=PVector.add(location,cmMap.cmPos);
//--
pushMatrix();translate(cmAbsolutePos.x,cmAbsolutePos.y);rotate(heading);rectMode(CENTER);
//--
if(cmBarrier&&(frameCount%3==1)){fill(0xEE,0xEE);ellipse(0,0,128,128);};
fill(thrusting?color(0x77,0x77,0xFF):color(0x33,0x11));rect(-r/2,r,r/2,2*r);rect(r/2,r,r/2,2*r);
fill(backThrusting?color(0x77,0x77,0xFF):color(0x33,0x11));rect(-r*3/4,-r/2,r/4,r);rect(r*3/4,-r/2,r/4,r);
fill(cmTurnMinus?color(0x77,0x77,0xFF):color(0x33,0x11));rect(-r,-r,10,r/4);rect( r,0,10,r/4);
fill(cmTurnPlus?color(0x77,0x77,0xFF):color(0x33,0x11));rect( r,-r,10,4/4);rect(-r,0,10,r/4);
//--
fill(175);stroke(0);beginShape();
vertex(-r,r);vertex(0,-2*r);vertex(r,r);
endShape(CLOSE);
rectMode(CORNER);noStroke();
popMatrix();
//--
thrusting=false;backThrusting=false;
cmTurnMinus=false;cmTurnPlus=false;
cmBarrier=false;
}
}//+++
class EcCordinator{
//--
EcMap cmMap;
Spaceship cmProtagon;
//--
ArrayList<EcDummy> cmDummyList;
EcBulletList cmBulletList;
//--
int cmScore;
//--
EcCordinator(EcMap pxMap,Spaceship pxShip,int pxInitDummyAmount){
//--
cmMap=pxMap;
cmProtagon=pxShip;
//--
cmDummyList=new ArrayList<EcDummy>();
cmBulletList= new EcBulletList(cmMap);
for(int i=0;i<pxInitDummyAmount;i++){cmDummyList.add(new EcDummy(cmMap));}
cmScore=0;
}
//--
void ccNewDummy(){if(cmDummyList.size()>63){return;}
cmDummyList.add(new EcDummy(cmMap));
}
void ccUpdate(){
cmBulletList.ccUpdate();
for (int i = cmDummyList.size()-1; i >= 0; i--) {
EcDummy lpDummy=cmDummyList.get(i);
lpDummy.ccUpdate();
lpDummy.ccCheckShots(cmBulletList,cmProtagon);
if(lpDummy.ccIsDestroyed()){cmDummyList.remove(i);cmScore+=cmProtagon.cmBarrier?2:10;}
}
}
//--
}//+++
class EcDummy{
//--
EcMap cmMap;
//--
PVector cmRelativePos;
float cmNoiseX,cmNoiseY;
float cmMaxSpeed;
//--
int cmExplodeTimer;
int cmShowsHpGaugeTimer;
//--
float cmHP;
float cmScale;
//--
EcDummy(EcMap pxMap){
cmMap=pxMap;
cmRelativePos=new PVector(random(cmMap.cmDia.x),random(cmMap.cmDia.x));
cmNoiseX=random(999);
cmNoiseY=random(999);
cmMaxSpeed=4;
cmExplodeTimer=0;
cmShowsHpGaugeTimer=0;
cmHP=192;
cmScale=2;
}
//--
void ccUpdate(){
float lpNoiseX=map(noise(cmNoiseX),0,1,-cmMaxSpeed,cmMaxSpeed);cmNoiseX+=0.01;
float lpNoiseY=map(noise(cmNoiseY),0,1,-cmMaxSpeed,cmMaxSpeed);cmNoiseY+=0.01;
PVector lpSpeed = new PVector(lpNoiseX,lpNoiseY);
cmRelativePos.add(lpSpeed);
cmRelativePos.x=constrain(cmRelativePos.x,0,cmMap.cmDia.x);
cmRelativePos.y=constrain(cmRelativePos.y,0,cmMap.cmDia.y);
float lpAbsoX=cmMap.cmPos.x+cmRelativePos.x;
float lpAbsoY=cmMap.cmPos.y+cmRelativePos.y;
//--
cmExplodeTimer--;if(cmExplodeTimer<0){cmExplodeTimer=0;}
cmShowsHpGaugeTimer--;if(cmShowsHpGaugeTimer<0){cmShowsHpGaugeTimer=0;}
cmScale+=0.5;if(cmScale>10){cmScale=10;}
//--
pushMatrix();translate(lpAbsoX,lpAbsoY);rotate(lpSpeed.heading());rectMode(CENTER);
stroke(0);fill(0xEE);rect(0,0,cmScale,cmScale*2);
noStroke();fill(0x33);rect(0,-cmScale/2,cmScale/2,cmScale/2);
rectMode(CORNER);
if(cmExplodeTimer!=0){fill(0xEE,0x77,0x77,0xAA);ellipse(random(8),random(8),16,16);}
popMatrix();
//--
if(cmShowsHpGaugeTimer!=0){
fill(0x33);rect(lpAbsoX-10,lpAbsoY-10,20,4);
fill(0x33,0xEE,0x33);rect(lpAbsoX-10,lpAbsoY-10,map(cmHP,0,200,1,20),4);
}
//--
}
//--
void ccCheckShots(EcBulletList pxList,Spaceship pxShip){
ArrayList<PVector> lpList=pxList.ccGetList();
PVector lpProtagonPos=pxShip.location.get();
for (int i = lpList.size()-1; i >= 0; i--) {
PVector lpBullet = lpList.get(i);
float lpDist = PVector.dist(cmRelativePos,lpBullet);
if(lpDist<20){ccDamaged(16);}
}
float lpProtagonDist = PVector.dist(cmRelativePos,lpProtagonPos);
if(lpProtagonDist<80 && pxShip.cmBarrier){ccDamaged(4);}
}
//--
boolean ccIsDestroyed(){return cmHP<5;}
//--
void ccDamaged(int pxDamage){
cmExplodeTimer=7;cmShowsHpGaugeTimer=32;
cmHP-=pxDamage;
}
}//+++
class EcBulletList{
//--
EcMap cmMap;
ArrayList<PVector> cmPos;
ArrayList<PVector> cmSpeed;
//--
EcBulletList(EcMap pxMap){
cmPos = new ArrayList();
cmSpeed = new ArrayList();
cmMap=pxMap;
}
//--
void ccUpdate(){for(int i=cmPos.size()-1;i>=0;i--){
PVector lpPos=cmPos.get(i);
PVector lpSpeed=cmSpeed.get(i);
float lpHeading=lpSpeed.heading();
float lpAbsX=cmMap.cmPos.x+lpPos.x;
float lpAbsY=cmMap.cmPos.y+lpPos.y;
lpPos.add(lpSpeed);
//--
pushMatrix();translate(lpAbsX,lpAbsY);rotate(lpHeading);
fill(0xFF,0x77,0x77);ellipse(20,0,3,3);rect(0,-1,24,2);
popMatrix();
//--
if(lpPos.x<0 || lpPos.x>cmMap.cmDia.x ||
lpPos.y<0 || lpPos.y>cmMap.cmDia.y
){cmPos.remove(i);cmSpeed.remove(i);}
//--
}}
//--
ArrayList ccGetList(){return cmPos;}
void ccShoot(PVector pxPos, float pxHeading){
cmPos.add(pxPos.get());
float lpHeading = pxHeading -PI/2;
PVector lpSpeed = new PVector(cos(lpHeading),sin(lpHeading));
//--
lpSpeed.mult(16);
cmSpeed.add(lpSpeed.get());
}
//--
}//+++
//EOF
- 本文固定链接: http://iprocessing.cn/2017/09/01/习作ac_在场景地图里射击浮靶的喷气飞船/
- 转载请注明: constrain 于 Processing编程艺术 发表