这是本人第一次写博客,是写给自己看的吧,标志着我下定决心开始走程序媛这条路了。
而且这也是我第一次用Processing写小游戏,算是纪念了。
首先帖一张运行初始界面图:
我们可以看到最下面那个警察是玩家,上面有4只僵尸,一只狙击手还有一个杀手。
医生是横着走而且超出界面后不会返回。
然后我们要对每个NPC定义它特有的属性,它是横着走还是竖着走,速度怎么样还有它和玩家相碰之后的结果。
下面是僵尸、狙击以及杀手的特性:
碰到僵尸后游戏不会结束,但是要找医生才能解除屏幕上的提示,当医生不在后如果再碰到僵尸游戏立刻结束。
PImage img=new PImage();
float speed; //将速度定义为全局变量
Enemy enemy1_1,enemy1_2,enemy1_3,enemy1_4; //4只僵尸
class Enemy
{
float img_x,img_y;
Enemy(float x, float y,float sd)
{
img_x=x;
img_y=y;
speed=sd;
}
void movel1()
{ img_x+=speed;
if(img_x>width-80) //僵尸是来回走的
{
img_x=40;
}
}
void movel2()
{ img_x-=speed;
if(img_x<40)
{
img_x=width-80;
}
}
boolean contact() //检测是否和僵尸碰到
{
float Offset = dist(img_x,img_y,X,Y); //距离
boolean bContact =false ;
if(Offset<=55) //如果两个距离小于55说明相碰返回true
{
bContact=true;
}
return bContact;
}
void display()
{
image(img,img_x,img_y);
if(life==1)
{
color c=color(255,204,0);
pushStyle();
fill(c);
textFont(font,25);
text("You have to find the doctor!",width/2-140,height/2);
//生命值为1说明和僵尸相碰了
popStyle();
}
}
}
PImage img6=new PImage(); //狙击
Juji juji;
class Juji
{ float img6_x,img6_y;
Juji(float x, float y,float sd)
{
img6_x=x;
img6_y=y;
speed=sd;
}
void display()
{
image(img6,img6_x,img6_y);
}
void movel3()
{
img6_y+=speed;
if(img6_y>450)
{
img6_y=150;
}
}
boolean contact() //检测是否和狙击碰到
{
float Offset = dist(img6_x,img6_y,X,Y); //distance
boolean bContact =false ;
if(Offset<=55)
{
bContact=true;
}
return bContact;
}
}
PImage img3=new PImage(); //杀手
Shashou shashou;
float speed1=0.1;
class Shashou
{
float angle=0.0;
float offset=270;
float scalar=30;
float sha_x,sha_y;
Shashou()
{
}
void move() //这里是定义了杀手以怎样的方式移动,大概是画圈的形式
{
sha_x= offset+cos(angle)*scalar;
sha_y= (offset+sin(angle)*scalar-180)*1.5;
angle+=speed1;
}
void display()
{
image(img3,sha_x,sha_y);
}
}
然后下面是医生的特性
/**
本页是有关医生的函数及定义
**/
Doctor doctor;
PImage img5=new PImage(); //医生
boolean disapper=false;
int doctor_speed=5;
class Doctor
{
float img5_x,img5_y;
Doctor(float x, float y)
{
img5_x=x;
img5_y=y;
}
void movel()
{
img5_x+=doctor_speed;
if(img5_x>width)
{
disapper=true;
}
}
void display()
{
image(img5,img5_x,img5_y);
}
boolean contact() //检测是否和医生碰到
{
float Offset = dist(img5_x,img5_y,X,Y); //distance
boolean bContact =false ;
if(Offset<=35)
{
bContact=true;
}
return bContact;
}
}
基本和前面敌人的定义方式差不多所以就不多说了。
还有最重要的玩家:
PImage img2=new PImage(); //警察
int X;
int Y;
int life;
boolean arrive=false;
class Player{
Player(int XX,int YY) {
X=XX;
Y=YY;
life=2;
}
void move()
{
if(mousePressed&&life!=3)
{
X+=(mouseX-X)/2.000;
Y+=(mouseY-Y)/2.000;
}
if(mousePressed&&mouseButton==RIGHT)
{
X=mouseX-10;
Y=mouseY-5;
}
if(life==0)
{
X=width/2-20;
Y=height-70;
speed=0;
speed1=0;
color c=color(255,204,0);
fill(c);
textFont(font,25);
text("Game Over,you failed!",width/2-120,height/2);
drawbutton(width/2-30,height/2+20);
player.close();
}
if((X>width/2-50)&&(X<width/2+30)&&(Y>120)&&(Y<175))
{
arrive=true; //判断是否到达目的地
}
else
{
arrive=false;
}
}
void drawbutton(int xx,int yy) //在游戏结束时弄一个类似按钮的东西,点击一下退出游戏
{
noFill();
rect(xx,yy,40,20);
stroke(204, 102, 0);
textSize(15);
text("EXIT",xx+8,yy+14);
if(mousePressed&&(mouseX>xx)
&&(mouseX<xx+40)&&(mouseY>yy)&&(mouseY<yy+20))
{
exit();
}
}
void display()
{
image(img2,X,Y);
}
void update()
{
}
}
编到中后期的时候才想说把字体换一下,用默认的太丑了,而processing的字体是要下载的,在这里顺便说一下换字体的方法:
点击 【工具】->【创建字体】,然后选一个自己喜欢的字体,复制好它的名字如AxureHandwriting-Italic-38.vlw,然后按确认。
调用代码可以这样写:
PFont font;
font = loadFont("AxureHandwriting-Italic-38.vlw");
textFont(font,25);
text("hello,girl!",width/2-120,height/2);
大家还可以像我游戏中那样定义一个颜色什么的。
最后是主界面的绘制以及那些写好的函数的调用:
/**
本页是调用函数
其中包含初始界面、背景音乐以及玩家敌人的调用
**/
import ddf.minim.*;
Minim minim;
AudioPlayer player;
int diameter;
Time timer;
PFont font;
int situation=0;
PImage img4=new PImage(); //背景1
int rectX,rectY; //按钮的长宽
int rectSize=90;
color rectColor;
color currentColor;
boolean rectOver=false;
Player protagonist;
void setup()
{
size(640,680);
timer=new Time(40);
font = loadFont("AxureHandwriting-Italic-38.vlw");
img = loadImage("僵尸1.png");
img2=loadImage("警察.png");
img3=loadImage("杀手.png");
img4=loadImage("背景1.jpg");
img5=loadImage("医生.png");
img6=loadImage("狙击.png");
minim=new Minim(this);
player=minim.loadFile("background.mp3",560); //音频要事先准备好
player.play();
protagonist = new Player(width/2-25,height-70);//生成主角
enemy1_1=new Enemy(3,120,22); //生成僵尸
enemy1_2=new Enemy(width-200,230,20);
enemy1_3=new Enemy(width/2-30,340,32);
enemy1_4=new Enemy(width/2-10,450,25);
doctor=new Doctor(0,height-130);
juji=new Juji(width/2-20,170,10);
shashou=new Shashou();
}
void drawGameOver1()
{
color c=color(255,0,0);
fill(c);
textFont(font,25);
text("Congratulations,You win!",width/2-120,height/2);
}
void drawGameOver3()
{
color c=color(255,204,0);
fill(c);
textFont(font,25);
text("Time is up,you failed!",width/2-120,height/2);
}
void draw()
{
frameRate(10);
image(img4,0,0);
if(situation==0)
{
pushStyle();
textSize(20);
text(millis()/1000,10,height-10);
popStyle();
}
protagonist.display();
protagonist.move();
enemy1_1.display();
enemy1_1.movel1();
enemy1_2.display();
enemy1_2.movel2();
enemy1_3.display();
enemy1_3.movel1();
enemy1_4.display();
enemy1_4.movel2();
doctor.display();
doctor.movel();
juji.display();
juji.movel3();
shashou.display();
shashou.move();
if(enemy1_1.contact()||enemy1_2.contact()
||enemy1_3.contact()||enemy1_4.contact()) //如果遇到的是僵尸,
{
life=1; //碰到僵尸后生命值为1
speed=0;
if(disapper) //如果碰到了僵尸且医生不在了
{
life=0;
situation=1;
}
}
if(juji.contact())
{
life=0;
doctor_speed=0;
situation=1;
}
if(doctor.contact())
{
life=2;
speed=22;
}
if(timer.isFinished())
{
if(arrive&&life!=1) //如果没到时间且到达终点且生命值不为1
{ //life==1表示遇到了丧尸,即使到了目的地也不能算赢
situation=1;
life=3; //如果赢了将生命置为3,这样就不能拖动玩家了
speed=0;
speed1=0;
doctor_speed=0;
player.close();
drawGameOver1();
protagonist.drawbutton(width/2-30,height/2+20);
}
}
else if(!timer.isFinished()&&life!=0)
{ situation=1;
life=3;
speed=0;
speed1=0;
doctor_speed=0;
player.close();
drawGameOver3();
protagonist.drawbutton(width/2-30,height/2+20);
}
}
细致的你们应该会发现我还弄了一个计时的,我定义的游戏时间是40s,如果到时间了你没能到达目的地就算输;还有如果碰到了僵尸但是你没能找到医生救你就算到了目的地也不会显示赢;还有当游戏结束了所有的都不能动,时间也不会显示,你也不能拖动玩家了,为了解决这些问题我就设了life,situation,speed,arrive等全局变量。
所以之间的逻辑还是有点复杂的,我也是弄了好久才理清;
下面是Time 这个类:
class Time{
int totaltime;
Time(int temptotaltime) //将40s传递给totaltime
{
totaltime=temptotaltime;
}
boolean isFinished()
{
int passedtime=millis()/1000;
if(passedtime>totaltime)
{
return false; //如果过去的时间大于40s返回false
}
else
{
return true;
}
}
}
时间到了之后会提示,并且游戏结束:
大家可以看到医生已经看不见,移出界了。
在显示时间的时候一开始我也是懵逼的,因为我想着是用second(),但是时间总是显示不对,而且就算把游戏叉掉再打开运行,它的时间也不是从零开始算而是接着前面的时间。
后来我才发现要用millis()。
整个游戏有4个类外加一个调用的:
由于接触processing不多,一开始连怎样引用音频、改字体、用中文写注释、添加类等等这些很简单的东西都不会,但是自己一点一点摸索还是弄出了这个游戏。而且代码不够精炼。
不过还是想吐槽一下processing,它不像vs,eclipse等编辑器那样给你提示哪个函数有问题,应该怎样写等等,比如我写textSize时写成了textsize,它也只会显示红线而不会说改成什么,我觉得这点很不好。而且它的有些错误提示本身就是错的。
最后还是感谢一下“爱上processing”这篇文章。
如果有人能看到这篇博客,也希望它能在你使用processing时对你有点帮助~