顯示具有 08162412_郑本清 標籤的文章。 顯示所有文章
顯示具有 08162412_郑本清 標籤的文章。 顯示所有文章

2022年1月3日 星期一

ᐇ Week17

 Week17

1.音效

根据week3的内容加上跳跃,bgm,以及死亡音效。

import ddf.minim.*;

Minim minim;

AudioPlayer bgm,jump,gameover;

在setup设定的部分加上以下程式码,可以载入三个档案。

minim = new Minim(this);

gameover = minim.loadFile("gameover.wav");

jump = minim.loadFile("jump.mp3");

bgm = minim.loadFile("bgm.mp3");

在keyPressed的函式中加入以下程式码,能够在跳跃时发出相对音效。

jump.rewind();

jump.play();

在死亡时bgm会暂停,且发出死亡音效。

bgm.pause();

gameover.play();


2.给板子加上上下移动的速度

hboardy[i]+=md[i];

if(hboardy[i]<110) md[i]=abs(md[i]);

if(hboardy[i]>260) md[i]=-abs(md[i]);

以上程式码能让给方块y方向的速度,且控制在110-260范围内,超过范围速度方向会变。

3.跳上板子后会跟着移动

if(onhBoard==true) usery+=md[hboardID];


3.贴图

PImage img1,img2,img3,img4,img5,img6,img7;

在setup部分载入图片

img1=loadImage("bg.jpg");

img2=loadImage("gg.png");

img3=loadImage("good.png");

img4=loadImage("bg2.jpg");

img5=loadImage("bg3.png");

img6=loadImage("start.jpg");

img7=loadImage("block.png");

最后在各个需要的地方贴上贴图

image(img6,0,0,600,400);

image(img1,0,0,600,400);


4.字型处理

PFont myFont;

载入正黑体

myFont = createFont("微軟正黑體",30);

最后用text指令完成输入


5.最终程式码

import ddf.minim.*;//音效

Minim minim;//音效

AudioPlayer bgm,jump,gameover;//音效及三个音档

PImage img1,img2,img3,img4,img5,img6,img7;//贴图图片

PFont myFont;//字型

float []badx,bubblex,bubbley,boardx,boardy,boardw,hboardx,hboardy,hboardw,trix,triy,rx,ry,md,mdt;

int now,score,now2;

int boardID=0;

int hboardID=0;

int rID=0;//部分变数

void setup(){

  size(600,400);

  myFont = createFont("微軟正黑體",30);//字型

  img1=loadImage("bg.jpg");//贴上的图片

  img2=loadImage("gg.png");

  img3=loadImage("good.png");

  img4=loadImage("bg2.jpg");

  img5=loadImage("bg3.png");

  img6=loadImage("start.jpg");

  img7=loadImage("block.png");

  minim = new Minim(this);

  gameover = minim.loadFile("gameover.wav");

  jump = minim.loadFile("jump.mp3");

  bgm = minim.loadFile("BGMG.mp3");//音效

  textSize(40);

  badx=new float[1200];//陷阱x

  badx[0]=350+250;

  for(int i=1;i<1200;i++){

    if(i%5==0 || i%8==0 || i%11==0) {badx[i]=badx[i-1]+random(200,300);}//不让陷阱太密集

    else {badx[i]=badx[i-1]+random(50,55);}

  }

  boardx=new float[200];//板子x

  boardx[0]=380+250;

  for(int i=1;i<200;i++){

    boardx[i]=boardx[i-1]+random(360,440);

  }

  boardy=new float[200];//板子y

  boardy[0]=260;

  for(int i=1;i<200;i++){

    if(boardy[i-1]>=270){boardy[i]=boardy[i-1]-20;}//防止板子太高或太低

    else if(boardy[i-1]<=230){boardy[i]=boardy[i-1]+20;}

    else boardy[i]=boardy[i-1]+random(-20,10);

  }

  boardw=new float[200];//板子宽度

  boardw[0]=140;

  for(int i=1;i<200;i++){

    boardw[i]=boardw[i-1]+random(-20,10);

    if(boardw[i-1]<=80){boardw[i]=boardw[i-1]+30;}

  }

  hboardx=new float[190];//更高的板子x

  //hboardx[0]=boardx[2]+160;

  for(int i=0;i<190;i++){

    //hboardx[i]=hboardx[i-1]+random(300,380);

    hboardx[i]=boardx[i+2]+random(200,210);

  }

  trix=new float[360];//板子底下带的陷阱

  for(int i=0;i<360;i++){

   if(i%2==0) trix[i]=hboardx[i/2]+50;

   else trix[i]=hboardx[(i-1)/2]+50+50;

  }

  hboardy=new float[190];//更高的板子y

  hboardy[0]=150;

  for(int i=1;i<190;i++){

    if(hboardy[i-1]>=170){hboardy[i]=hboardy[i-1]-20;}

    else if(hboardy[i-1]<=120){hboardy[i]=hboardy[i-1]+20;}

    else hboardy[i]=hboardy[i-1]+random(-20,10);

  }

  triy=new float[360];//板子下的陷阱y

  triy[0]=150+20;

  for(int i=1;i<360;i++){

   if(i%2==0) triy[i]=hboardy[i/2]+20;//贴近板子

   else triy[i]=hboardy[(i-1)/2]+20;

  }

  hboardw=new float[190];//更高的板子宽度

  hboardw[0]=150;

  for(int i=1;i<190;i++){

    hboardw[i]=hboardw[i-1];

  }

  rx=new float[180];//距离较远时会出现的小板子x

  for(int i=0;i<180;i++){

    rx[i]=boardx[i+8]+boardw[i+8]+10;

  }

  ry=new float[280];//距离较远时会出现的小板子y

  for(int i=0;i<280;i++){

    ry[i]=170;

  }

  md=new float[190];//板子上下移动的速度

  for(int i=0;i<190;i++){

    md[i]=random(0.3,0.6);

  }

  mdt=new float[360];//陷阱上下移动的速度

  for(int i=0;i<360;i++){

    mdt[i]=(md[i/2]/0.4001)*0.1335;

  }

  bubblex=new float[10];//方块身后气泡

  bubbley=new float[10];

  for(int i=0;i<10;i++){

    bubblex[i]=0;

    bubbley[i]=300;

  }

  

}

float usery=300, vy=0, bgx=0, speed=0;

//md=0.4001,mdt=0.1335;

boolean gameOver=false;

boolean onBoard=false;

boolean onhBoard=false;

boolean onr=false;

int condition=0;

int wait=0;

void mousePressed(){///場景切換

  if (mouseButton == LEFT) condition=1;

}

void draw(){

  if(condition==0){//初始画面

    image(img6,0,0,600,400);

    fill(255);

    text("按下滑鼠左鍵開始遊戲",150,50);

    text("上鍵跳躍 下鍵無敵",170,350);

    textFont(myFont);

    wait=millis()/1000;

  }

  if(condition==1){

    if(gameOver && hacking==false) bgm.pause();//游戏结束则bgm暂停

    else bgm.play();//否则正常播放

    if(score>=0 && score<30) image(img1,0,0,600,400);//到一定阶段会更换背景

    if(score>=20 && score<40) image(img4,0,0,600,400);

    if(score>=40) image(img5,0,0,600,400);

    

    speed=(score/4)*0.3;//速度会随分数增加而增加

    bgx=bgx+3.3+speed;

    fill(#F5ADCF);

    for(int i=0;i<1200;i++){

      now=i;

      if(collision()) gameOver=true;//碰到陷阱则游戏结束

      triangle(badx[i]-bgx,310,badx[i]-25-bgx,350,badx[i]+25-bgx,350);

  }

    fill(#F5ADCF);

    for(int i=0;i<360;i++){

      now2=i;

      if(collision2()) gameOver=true;

      triangle(trix[i]+25-bgx,(triy[i]+=mdt[i])+40,trix[i]-bgx,triy[i]+=mdt[i],trix[i]+50-bgx,triy[i]+=mdt[i]);

      if(triy[i]<130) mdt[i]=abs(mdt[i]);//控制陷阱在一定范围内

      if(triy[i]>280) mdt[i]=-abs(mdt[i]);

    }

    fill(#003E6C); rect(0,350,600,400);//地板

    fill(#FFEC17);

    image(img7,150,usery,50,50);//玩家角色以及贴图

    if(jumping){//跳跃改变y以及加速度

      usery+=vy;

      vy+=0.98/2.5;

      if(usery>300){//停留在地上

        jumping=false;

        usery=300;

      }

    }

    fill(#AD0051);

    for(int i=0;i<200;i++){

      rect(boardx[i]-bgx,boardy[i],boardw[i],20);

      if(boardID==i){

        if(onBoard==true && (boardx[i]+boardw[i]<150+bgx) ){

          onBoard=false;jumping=true;

        }

      }

      if(jumping && usery+50<boardy[i] && usery+50+vy>boardy[i] && boardx[i]<150+50+bgx && 150+bgx<boardx[i]+boardw[i]){

        usery=boardy[i]-50;vy=0;jumping=false;onBoard=true;boardID=i;//方块停留在板子上

      }

    }

    fill(#AD0051);

    for(int i=0;i<190;i++){

      hboardy[i]+=md[i];//让板子上下移动

      rect(hboardx[i]-bgx,hboardy[i],hboardw[i],20);

      if(hboardy[i]<110) md[i]=abs(md[i]);

      if(hboardy[i]>260) md[i]=-abs(md[i]);//限制板子移动在一个范围内

      if(hboardID==i){

        if(onhBoard==true && (hboardx[i]+hboardw[i]<150+bgx) ){

          onhBoard=false;jumping=true;

        }

      }

      if(jumping && usery+50<hboardy[i] && usery+50+vy>hboardy[i] && hboardx[i]<150+50+bgx && 150+bgx<hboardx[i]+hboardw[i]){

        usery=hboardy[i]-50;vy=0;jumping=false;onhBoard=true;hboardID=i;

      }

    }

    if(onhBoard==true) usery+=md[hboardID];//角色能跟着板子上下移动

    fill(#AD0051);

    for(int i=0;i<180;i++){//在小板子上

      rect(rx[i]-bgx,ry[i],70,20);

      if(rID==i){

        if(onr==true && (rx[i]+70<150+bgx) ){

          onr=false;jumping=true;

        }

      }

      if(jumping && usery+50<ry[i] && usery+50+vy>ry[i] && rx[i]<150+50+bgx && 150+bgx<rx[i]+70){

        usery=ry[i]-50;vy=0;jumping=false;onr=true;rID=i;

      }

    }

    for(int i=9;i>0;i--){//身后的气泡

      bubblex[i]=bubblex[i-1];

      bubbley[i]=bubbley[i-1];

      fill(#FFF586);

      rect(bubblex[i]+150-bgx,bubbley[i]+40,10,10);

    }

    bubblex[0]=bgx;

    bubbley[0]=usery;

    if(hacking){//下键无敌

      fill(255,0,0);

      text("作弊中",150,100);

    }

    if(gameOver==false || hacking){//计分方式

    score=millis()/1000-wait;

    if(score<20) text("分數: "+score+"分  你好菜",150,50);

    else if(score<40) text("分數: "+score+"分  還不錯",150,50);

    else if(score>=40) text("分數: "+score+"分  不可思議",150,50);

    }

    else if(gameOver && hacking==false){//死亡及结束画面

      gameover.play();

      background(255);

      image(img2,0,0,600,350);

      fill(255,0,0);

      if(score<20) text("評價:你好菜",220,50);

      else if(score<40) text("評價:還不錯",220,50);

      else if(score>=40) text("評價:不可思議",220,50);

      text("最終得分: "+score+"分",200,350);

    }

  }

}

boolean jumping=false;

boolean hacking=false;

void keyPressed(){//下键开启无敌

  if(keyCode==DOWN){

    if(hacking==false){

      hacking=true;

    }

  }

  if(keyCode==UP){//上键跳跃

    jump.rewind();

    jump.play();//跳跃音效

    if(jumping==false){

      jumping=true;

      vy=-10;

    }

  }

}

boolean collision(){//前几周做的碰撞侦测

   boolean b1=insideTriangle(150,usery);

   boolean b2=insideTriangle(200,usery);

   boolean b3=insideTriangle(200,usery+50);

   boolean b4=insideTriangle(150,usery+50);

   if(b1 || b2 || b3 || b4) return true;

   else return false;

}

boolean insideTriangle(float x,float y){

    float c1=cross(x,y,badx[now]-bgx,310,badx[now]-25-bgx,350);

    float c2=cross(x,y,badx[now]-25-bgx,350,badx[now]+25-bgx,350);

    float c3=cross(x,y,badx[now]+25-bgx,350,badx[now]-bgx,310);

    if(c1>=0 && c2>=0 && c3>=0) return true;

    else return false;

}

boolean collision2(){

   boolean t1=insideTriangle2(150,usery);

   boolean t2=insideTriangle2(200,usery);

   boolean t3=insideTriangle2(200,usery+50);

   boolean t4=insideTriangle2(150,usery+50);

   if(t1 || t2 || t3 || t4) return true;

   else return false;

}

boolean insideTriangle2(float x,float y){

    float tc1=cross(x,y,trix[now2]+25-bgx,triy[now2]+40,trix[now2]-bgx,triy[now2]);

    float tc2=cross(x,y,trix[now2]-bgx,triy[now2],trix[now2]+50-bgx,triy[now2]);

    float tc3=cross(x,y,trix[now2]+50-bgx,triy[now2],trix[now2]+25-bgx,triy[now2]+40);

    if(tc1<=0 && tc2<=0 && tc3<=0) return true;

    else return false;

}

float cross(float xp,float yp,float x0,float y0,float x1,float y1){

  return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);

}


4.游戏说明

其他组员意见:

聆聽輕快的音樂再搭配上緊張刺激的跑酷遊戲!

Geometry Dash是我很喜歡玩的遊戲

每次死掉重來都令人懊惱但又激發了玩家不服輸的性格

雖然我們的重製沒能做出像原作般與音樂的完美契合

但緊張刺激的跑酷部分還是有還原到

也搭配上原作的首關音樂

希望可以讓更多人認識這款遊戲

游戏操作:

上鍵跳跃

下鍵作弊模式(不死)


每20分換背景與更新評價 40分封頂

隨著遊戲進行速度會越來越快


遊戲影片:https://youtu.be/OqANg5hwqAw

前面是正常遊玩 後半部作弊模式看40分以上

用时半个月,每周做一点,前几周做大致的框架和基本的程式码,最后一周做细节的修改,总共用时大约1-2天。

2021年12月27日 星期一

ᐇ Week16

Week16
本周进行跳上/落下板子的程式码,直接用if和Boolean进行判断。

1.跳上板子
利用if的判断,当四个条件全都成立时,方块会落在板子上,同时jumping的Boolean值变为false

int boardX=300;
int boardY=100;
int boardW=1000;
void setup(){
  size(500,300);
}
float x=30,y=150,vx=3,vy=0;
float scrolling=0;//相对运动
boolean jumping=false;
void draw(){
  background(#162390);
  line(0,200,500,200);
  rect(x-scrolling,y,50,50);
  x+=vx;
  if(jumping){
    y+=vy;
    vy+=0.98;
    if(y>150){//在地面
      y=150;vy=0;jumping=false;
    }
  }
  scrolling=(x-30);
  for(int i=0;i<1;i++){
    rect(boardX-scrolling,boardY,boardW,20);
    if(jumping && y+50<boardY && y+50+vy>boardY && boardX<x+50 && x<boardX+boardW){
      y=boardY-50;vy=0;jumping=false;//落在板子上
    }
  }
}
void keyPressed(){
  if(keyCode==UP){
    jumping=true;
    vy=-15;
  }
}

2.落下板子
增加Boolean值onBoard,如果onBoard为true且不超过板子右侧,则jumping为false,到一定边界方块会落下板子

int []boardX={300,400};
int []boardY={100,50};
int []boardW={800,300};
void setup(){
  size(500,300);
}
float x=30,y=150,vx=3,vy=0;
float scrolling=0;
boolean jumping=false,onBoard=false;
int boardID=0;
void draw(){
  background(#162390);
  line(0,200,500,200);
  rect(x-scrolling,y,50,50);
  x+=vx;
  if(jumping){
    y+=vy;
    vy+=0.98;
    if(y>150){
      y=150;vy=0;jumping=false;
    }
  }
  scrolling=(x-30);
  for(int i=0;i<2;i++){
    rect(boardX[i]-scrolling,boardY[i],boardW[i],20);
    if(boardID==i){
      if(onBoard==true && (boardX[i]+boardW[i]<x) ){//如果不在板子上会掉落
        onBoard=false;jumping=true;
      }
    }
    if(jumping && y+50<boardY[i] && y+50+vy>boardY[i] && boardX[i]<x+50 && x<boardX[i]+boardW[i]){
      y=boardY[i]-50;vy=0;jumping=false;onBoard=true;boardID=i;
    }
  }
}
void keyPressed(){
  if(keyCode==UP){
    jumping=true;
    vy=-15;
  }
}

3.geometry dash程式码

float []badx,bubblex,bubbley,boardx,boardy,boardw;
int now,score;
int boardID=0;
void setup(){
  size(600,400);
  textSize(40);
  badx=new float[100];
  badx[0]=300+random(200,300);
  for(int i=1;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);
  }
  boardx=new float[100];
  boardx[0]=500+random(200,300);
  for(int i=1;i<100;i++){
    boardx[i]=boardx[i-1]+random(350,600);
  }
  boardy=new float[100];
  boardy[0]=260;
  for(int i=1;i<100;i++){
    boardy[i]=boardy[i-1]+random(-20,10);
  }
  boardw=new float[100];
  boardw[0]=100;
  for(int i=1;i<100;i++){
    boardw[i]=boardw[i-1]+random(20,50);
  }
  bubblex=new float[10];
  bubbley=new float[10];
  for(int i=0;i<10;i++){
    bubblex[i]=0;
    bubbley[i]=300;
  }
}
float usery=300, vy=0, bgx=0;
boolean gameOver=false;
boolean onBoard=false;
void draw(){
  background(#FF0A7D);
  bgx+=4;
  fill(#F5ADCF);
  for(int i=0;i<100;i++){
    now=i;
    if(collision()) gameOver=true;
    triangle(badx[i]-bgx,310,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
}
  fill(#AD0051); rect(0,350,600,400);
  rect(150,usery,50,50);
  if(jumping){
    usery+=vy;
    vy+=0.98/2.5;
    if(usery>300){
      jumping=false;
      usery=300;
    }
  }
  fill(#AD0051);
  for(int i=0;i<100;i++){//新增程式码,跳跃中落在板子上
    rect(boardx[i]-bgx,boardy[i],boardw[i],20);
    if(boardID==i){
      if(onBoard==true && (boardx[i]+boardw[i]<150+bgx) ){
        onBoard=false;jumping=true;
      }
    }
    if(jumping && usery+50<boardy[i] && usery+50+vy>boardy[i] && boardx[i]<150+50+bgx && 150+bgx<boardx[i]+boardw[i]){
      usery=boardy[i]-50;vy=0;jumping=false;onBoard=true;boardID=i;
    }
  }
  for(int i=9;i>0;i--){
    bubblex[i]=bubblex[i-1];
    bubbley[i]=bubbley[i-1];
    ellipse(bubblex[i]+150-bgx,bubbley[i],10,10);
  }
  bubblex[0]=bgx;
  bubbley[0]=usery;
  if(gameOver==false){
  score=millis()/1000;
  fill(0);
  text("score: "+score,200,50);
  }
  else if(gameOver){
    background(0);
    fill(255,0,0);
    text("Goog luck next time!",100,100);
    text("score: "+score,200,150);
  }
}
boolean jumping=false;
void keyPressed(){
  if(jumping==false){
    jumping=true;
    vy=-10;
  }
}
boolean collision(){
   boolean b1=insideTriangle(150,usery);
   boolean b2=insideTriangle(200,usery);
   boolean b3=insideTriangle(200,usery+50);
   boolean b4=insideTriangle(150,usery+50);
   if(b1 || b2 || b3 || b4) return true;
   else return false;
}
boolean insideTriangle(float x,float y){
    float c1=cross(x,y,badx[now]-bgx,310,badx[now]-25-bgx,350);
    float c2=cross(x,y,badx[now]-25-bgx,350,badx[now]+25-bgx,350);
    float c3=cross(x,y,badx[now]+25-bgx,350,badx[now]-bgx,310);
    if(c1>=0 && c2>=0 && c3>=0) return true;
    else return false;
}
float cross(float xp,float yp,float x0,float y0,float x1,float y1){
  return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
}

2021年12月20日 星期一

ᐇ Week15

 Week15

本周完成geometry dash的gameover的检测以及结束画面


1.gameover游戏结束侦测

利用上周碰撞侦测加入到生成陷阱的for回圈,使正方形碰到陷阱则gameover的boolean值为true


boolean gameOver=false;

  for(int i=0;i<100;i++){

    now=i;

    if(collision()) gameOver=true;//如果碰到,则gameover的boolean值为true

    triangle(badx[i]-bgx,310,badx[i]-25-bgx,350,badx[i]+25-bgx,350);

}

boolean collision(){

   boolean b1=insideTriangle(150,usery);

   boolean b2=insideTriangle(200,usery);

   boolean b3=insideTriangle(200,usery+50);

   boolean b4=insideTriangle(150,usery+50);

   if(b1 || b2 || b3 || b4) return true;

   else return false;

}

boolean insideTriangle(float x,float y){

    float c1=cross(x,y,badx[now]-bgx,310,badx[now]-25-bgx,350);

    float c2=cross(x,y,badx[now]-25-bgx,350,badx[now]+25-bgx,350);

    float c3=cross(x,y,badx[now]+25-bgx,350,badx[now]-bgx,310);

    if(c1>=0 && c2>=0 && c3>=0) return true;

    else return false;

}

float cross(float xp,float yp,float x0,float y0,float x1,float y1){

  return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);

}

2.游戏结束以及分数画面

使用if判断gameover的true和false,用text打出分数


boolean gameOver=false;

void draw(){

  if(gameOver==false){//没结束则运行

  score=millis()/1000;

  fill(0);

  text("score: "+score,200,50);

  }

  else if(gameOver){//结束了跳出背景

    background(0);

    fill(255,0,0);

    text("Goog luck next time!",100,100);

    text("score: "+score,200,150);

  }

游戏中计分
游戏结束界面

2021年12月13日 星期一

ᐇ Week14

Week14:

本周主要解决游戏中物件碰撞的问题,利用两个物体接触侦测解决,有顶点包含和外积解法


1.正方形与正方形碰撞侦测

正方形与正方形之间碰撞侦测的方法,确保正方形的顶点在另一个正方形当中,需要做出两个侦测,不然会导致其中一个正方形出现差错。该方法根据两个正方形顶点的位置关系进行判断,容易理解。

float x1,y1,w1,h1;

float x2=0,y2=0,w2=100,h2=100;

void setup(){

  size(400,400);

  w1=random(40,80);

  h1=random(40,80);

  x1=random(400-w1);

  y1=random(400-h1);

}

void draw(){

  background(128);

  if(testCollision() || testCollision2()) fill(255,0,0);//如果两个侦测回传值都为true,则正方形变红

  else fill(255);

  

  rect(x1,y1,w1,h1);

  noFill(); rect(x2,y2,w2,h2);

  x2=mouseX-w2/2;

  y2=mouseY-h2/2;

}

boolean testCollision2(){//将正方形四个顶点放入oneCollision2函式经行侦测

  if(oneCollision2(x1,y1)) return true;

  else if(oneCollision2(x1+w1,y1)) return true;

  else if(oneCollision2(x1+w1,y1+h1)) return true;

  else if(oneCollision2(x1,y1+h1)) return true;

  else return false;

}

boolean oneCollision2(float x,float y){//如果四个顶点都在另一个正方形的里面,回传true

  if(x2<x && x<x2+w2 && y2<y && y<y2+h2) return true;

  else return false;  

}

boolean testCollision(){

  if(oneCollision(x2,y2)) return true;

  else if(oneCollision(x2+w2,y2)) return true;

  else if(oneCollision(x2+w2,y2+h2)) return true;

  else if(oneCollision(x2,y2+h2)) return true;

  else return false;

}

boolean oneCollision(float x,float y){

  if(x1<x && x<x1+w1 && y1<y && y<y1+h1) return true;

  else return false;  

}


2-1.三角形和正方形的碰撞侦测
该方法和上面的正方形与正方形碰撞侦测类似,都是用顶点位置判断,但对于三角形和正方形不适用,因为如果三角形三个顶点都没在四边形里,但正方形刚好进入,则会侦测失败,因此该方法不采用,用外积法。

float tx,ty;
float rx,ry;
void setup(){
  size(300,300);
  tx=random(100,200);
  ty=random(100,200);
}
void draw(){
  background(0);
  fill(255); triangle(tx,ty,tx-25,ty+25,tx+25,ty+40);
  if(collision()) fill(255,0,0);
  else fill(255); 
  rect(rx,ry,50,50);
  rx=mouseX-25;
  ry=mouseY-25;
}
boolean collision(){
  if(insideRect(tx,ty) || insideRect(tx-25,ty+40) || insideRect(tx+25,ty+40)) return true;
  else return false;
}
boolean insideRect(float x,float y){
  if(rx<x && x<rx+50 && ry<y && y<ry+50) return true;
  else return false;
}
顶点在正方形中则成功
但这种情况下会侦测不到

2-2.三角形和正方形的碰撞侦测
该方法为外切法,又称交叉相乘,原理是检测四边形四个顶点和三角形三条边夹角的关系,只要有一点在三角形内就发生碰撞。

float tx,ty;
float rx,ry;
void setup(){
  size(300,300);
  tx=random(100,200);
  ty=random(100,200);
}
void draw(){
  background(0);
  fill(255); triangle(tx,ty,tx-25,ty+40,tx+25,ty+40);
  if(collision()) fill(255,0,0);//碰撞函式
  else fill(255); 
  triangle(tx,ty,tx-25,ty+40,tx+25,ty+40);
  rect(rx,ry,50,50);
  rx=mouseX-25;
  ry=mouseY-25;
}
boolean collision(){//把四个点放入侦测函式
  boolean b1=insideTriangle(rx,ry);
  boolean b2=insideTriangle(rx+50,ry);
  boolean b3=insideTriangle(rx+50,ry+50);
  boolean b4=insideTriangle(rx,ry+50);
  if(b1 || b2 || b3 || b4) return true;
  else return false;
}
boolean insideTriangle(float x,float y){//检测四个点和三条边关系
  float c1=cross(x,y,tx,ty,tx-25,ty+40);
  float c2=cross(x,y,tx-25,ty+40,tx+25,ty+40);
  float c3=cross(x,y,tx+25,ty+40,tx,ty);
  if(c1>0 && c2>0 && c3>0) return true;
  else return false;
}
float cross(float xp,float yp,float x0,float y0,float x1,float y1){//交叉相乘,外积
  return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
}

3.geometry dash碰撞侦测
与上周进度相比,增加了上层移动的木板,以及玩家方块与陷阱三角形的碰撞侦测。

float []badx,bubblex,bubbley,board;
int now;
void setup(){
  size(600,400);
  badx=new float[100];
  badx[0]=300+random(200,300);
  for(int i=1;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);
  }
  board=new float[100];
  board[0]=500+random(200,300);
  for(int i=1;i<100;i++){
    board[i]=board[i-1]+random(350,600);
  }
  bubblex=new float[10];
  bubbley=new float[10];
  for(int i=0;i<10;i++){
    bubblex[i]=0;
    bubbley[i]=300;
  }
}
float usery=300, vy=0, bgx=0;
void draw(){
  background(#FF0A7D);
  fill(#F5ADCF);
  for(int i=0;i<100;i++){
    now=i;
    if(collision()) fill(255,0,0);
    triangle(badx[i]-bgx,310,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
}
  fill(#AD0051);
  for(int i=0;i<100;i++){
    rect(board[i]-bgx,230,150,20);
  }
  fill(#AD0051); rect(0,350,600,400);
  rect(150,usery,50,50);
  if(jumping){
    usery+=vy;
    vy+=0.98/2.5;
    if(usery>300){
      jumping=false;
      usery=300;
    }
  }
  for(int i=9;i>0;i--){
    bubblex[i]=bubblex[i-1];
    bubbley[i]=bubbley[i-1];
    ellipse(bubblex[i]+150-bgx,bubbley[i],10,10);
  }
  bubblex[0]=bgx;
  bubbley[0]=usery;
  bgx+=4;
}
boolean jumping=false;
void keyPressed(){
  if(jumping==false){
    jumping=true;
    vy=-10;
  }
}
boolean collision(){
   boolean b1=insideTriangle(150,usery);
   boolean b2=insideTriangle(200,usery);
   boolean b3=insideTriangle(200,usery+50);
   boolean b4=insideTriangle(150,usery+50);
   if(b1 || b2 || b3 || b4) return true;
   else return false;
}
boolean insideTriangle(float x,float y){
    float c1=cross(x,y,badx[now]-bgx,310,badx[now]-25-bgx,350);
    float c2=cross(x,y,badx[now]-25-bgx,350,badx[now]+25-bgx,350);
    float c3=cross(x,y,badx[now]+25-bgx,350,badx[now]-bgx,310);
    if(c1>=0 && c2>=0 && c3>=0) return true;
    else return false;
}
float cross(float xp,float yp,float x0,float y0,float x1,float y1){
  return (xp-x0)*(y1-y0)-(yp-y0)*(x1-x0);
}



2021年12月6日 星期一

ᐇ Week13

 Week13

1.俄罗斯方块

int[][]grid={

  {1,1,1,1,1,1,1,1,1,1,1,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,0,0,0,0,0,0,0,0,0,0,1},

  {1,1,1,1,1,1,1,1,1,1,1,1}

};

void one(int x,int y){

  fill(255,0,0);

  if(grid[y][x]==0) rect(x*25,y*25,25,25);//四周的墙

}

void setup(){

  size(300,500);

}

void draw(){

  background(0);

  for(int x=0;x<12;x++){

    for(int y=0;y<20;y++){

      if(grid[y][x]==1) fill(128);

      else if(grid[y][x]==2) fill(255,0,0);

      else fill(0);

      rect(x*25,y*25,25,25);

    }

  }

  one(nowX,nowY);

  if(frameCount%60==0){//方块向下移动

    if(grid[nowY+1][nowX]==0) nowY++;

    else{//石化

      grid[nowY][nowX]=2;

      nowX=6; nowY=1;

    }

  }

}

int nowX=6, nowY=1;

2.砍树人

int []tree=new int[30];//0:no 1:left 2:right

int pos=0;//0:left 1:right

void setup(){

  size(300,600);

  tree[0]=0;

  for(int i=1;i<30;i++){

    tree[i]=int(random(3));

  }

}

void draw(){

  if(gameOver){

    background(255,0,0);

  }

  background(255,0,255);

  for(int i=0;i<30;i++){

    if(tree[i]==0){//empty

      fill(#28C3E8); rect(100,500-i*100,100,100);

    }else if(tree[i]==1){//left

      fill(#28C3E8); rect(0,500-i*100,200,100);

    }else if(tree[i]==2){//right

      fill(#28C3E8); rect(100,500-i*100,200,100);

    }

  }

  if(pos==0){

    fill(255,0,0); ellipse(50,550,100,100);

  }else if(pos==1){

    fill(255,0,0); ellipse(250,550,100,100);

  }

}

void keyPressed(){

  if(keyCode==RIGHT){ pos=1; checkAndUpdate();}

  if(keyCode==LEFT) { pos=0; checkAndUpdate();}

}

void checkAndUpdate(){

  if(tree[1]==1 && pos==0) die();

  else if(tree[1]==2 && pos==1) die();

  else{

    //score++;

    for(int i=0;i<30-1;i++){

      tree[i]=tree[i+1];

    }

    tree[29]=int(random(3));

  }

}

void die(){

  gameOver=true;

}

boolean gameOver=false;

3.弓箭传说

void setup(){

  size(300,500);

}

float heroX=150,heroY=250;

float []arrowX=new float[24];

float []arrowY=new float[24];

float []arrowVX=new float[24];

float []arrowVY=new float[24];

boolean shooting=false;

void draw(){

  background(255,204,84);

  ellipse(heroX,heroY,50,50);

  if(shooting){

    for(int i=0;i<24;i++){

      arrowX[i]+=arrowVX[i];

      arrowY[i]+=arrowVY[i];

      ellipse(arrowX[i],arrowY[i],10,10);

      if(frameCount%10==0){

        for(int k=23;k>0;k--){//后面子弹跟着跑

          arrowX[k]=arrowX[k-1];

          arrowY[k]=arrowY[k-1];

          arrowVX[k]=arrowVX[k-1];

          arrowVY[k]=arrowVY[k-1];

        }

      }

    }

  }

}

void mousePressed(){

  shooting=true;

  arrowX[0]=heroX;

  arrowY[0]=heroY;

  arrowVX[0]=-1;

  arrowVY[0]=1;

}

4.小鸡过马路

int chinkID=0;

float []chinkX=new float[10];

float []chinkY=new float[10];

float []chinkVX=new float[10];

float []chinkVY=new float[10];

boolean []run=new boolean[10];

void setup(){

  size(400,300);

  for(int i=0;i<10;i++){

    chinkX[i]=random(10,150-10);

    chinkY[i]=random(10,300-10);

    chinkVX[i]=random(-0.3,0.3);

    chinkVY[i]=random(-0.3,0.3);

  }

}

void draw(){

  background(122,171,185);

  fill(102,166,28);

  rect(0,0,150,300);

  for(int i=0;i<10;i++){

    if(chinkID==i) strokeWeight(3);

    else strokeWeight(1);

    fill(255); ellipse(chinkX[i],chinkY[i],20,50);

    chinkX[i]+=chinkVX[i];

    chinkY[i]+=chinkVY[i];

    if(chinkY[i]<0) chinkVY[i]=abs(chinkVY[i]);//圈住小鸡

    if(chinkY[i]>300) chinkVY[i]=-abs(chinkVY[i]);

    if(chinkX[i]<0) chinkVX[i]=abs(chinkVX[i]);

    if(run[i]==false && chinkX[i]>150) chinkVX[i]=-abs(chinkVX[i]);//run为false可以出圈

  }

}

void keyPressed(){//鸡的走动

  int i=chinkID;

  if(keyCode==RIGHT) {chinkVX[i]=1; chinkVY[i]=0;}

  else if(keyCode==LEFT) {chinkVX[i]=-1; chinkVY[i]=0;}

  else if(keyCode==UP) {chinkVX[i]=0; chinkVY[i]=-1;}

  else if(keyCode==DOWN) {chinkVX[i]=0; chinkVY[i]=1;}

  run[i]=true;

}

void mousePressed(){//点击更换鸡

  for(int i=0;i<10;i++){

    if(dist(mouseX,mouseY,chinkX[i],chinkY[i])<20) chinkID=i;

  }

}

5.小朋友下楼梯

PImage imgBrick,imgBoard01;

float []boardX=new float[9];

float []boardY=new float[9];

void setup(){

  size(600,400);

  imgBrick=loadImage("brick.png");

  imgBoard01=loadImage("board01.png");

  for(int i=0;i<9;i++){

    boardX[i]=random(15,400-15-80);

    boardY[i]=i*40;

  }

}

float rolling=0;//滚动的背景

void draw(){

  rect(10,80,400,320);

  for(int i=0;i<30;i++){

    image(imgBrick,10,80+i*27-rolling);

    image(imgBrick,400+10-13,80+i*27-rolling);

  }

  for(int i=0;i<9;i++){

    image(imgBoard01,boardX[i],80+boardY[i]-rolling);

    if(boardY[i]-rolling<0){//回收板子再利用

      boardX[i]=random(15,400-15-80);

      boardY[i]=boardY[i]+360;

    }

  }

  rolling+=1.5;

}

6.一二三木头人

void setup(){

  size(600,300,P3D);//openGL

  noStroke();

  genRandomTime();

}

void genRandomTime(){

  time=millis()+random(3000,5000);

}

float time=0;

float angle=-90;

float speed=3;

void draw(){

  background(#FFD436);

  if(time<millis()){//要动了

    //ghostMoving=true;

    angle+=speed;

    if(angle>=90){//鬼在看

      angle=90;

      time=millis()+3000;

      speed=-speed;

    }else if(angle<-90){

      angle=-90;

      genRandomTime();

      speed=10;

    }

  }

  ghost(angle);//看的角度,-90背对没看,0看前面

}

void ghost(float angle){

  fill(237,137,63);

  rect(100,100,100,100);

  pushMatrix();

    lights(); ortho();

    translate(150,50);//把头移到上面去

    rotateY(radians(angle));

    fill(190,162,95);

    sphere(50);

    pushMatrix();

      translate(40,-10,40);

      fill(0); sphere(10);

    popMatrix();

    pushMatrix();

      translate(-40,-10,40);

      fill(0); sphere(10);

    popMatrix();

  popMatrix();

}

2021年11月29日 星期一

ᐇ Week12

 Week12

這周主要規劃期末作品内容,每周逐步完成。

1.小人移動網址

https://openprocessing.org/sketch/911326

2.sprite animation人物移動

PImage img;

void setup(){

  size(500,500);

  img=loadImage("img.jpg");

  imageMode(CENTER);

}

int a=0, b=0, x=250, y=250;//ab用於更換行列圖片

void draw(){

  background(255);

  //image( img, 0,0);

  image(  img.get(141*a, 211*b, 141,211), x,y);//選擇所需圖片

  if(frameCount%30==0) a = (a+1)%4;

}

void keyPressed(){

  if(keyCode==RIGHT){ b=3; x++; }//可通過改變x大小調整速度

  if(keyCode==LEFT) { b=2; x--; }

  if(keyCode==UP) { b=1; y--; }

  if(keyCode==DOWN){ b=0; y++; }

}

3.期末規劃

(1)内容大綱

我們組選擇做出類似Geometry dash的作品,每周都加上調整

(2)示意圖
我們將使用滑鼠或是鍵盤控制一個正方形的彈跳,使其不能碰到三角形或其他有傷害的障礙物,在此期間我們會不斷前進,帶來不同位置的障礙物。
跳躍的正方形
躲避三角形
(3)Youtube影片
https://youtu.be/k90y6PIzIaE
該視頻將會簡單介紹游戲流程
(4)原理,初始程式碼

1.準備陷阱和背景
float []badx;//陷阱
void setup(){
  size(600,400);
  badx=new float[100];//準備100個陷阱
  badx[0]=random(200,300);
  for(int i=0;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);//陷阱間隔
  }
}
void draw(){
  background(#FF0A7D);
}
2.角色和背景移動
float []badx;//陷阱
void setup(){
  size(600,400);
  badx=new float[100];//準備100個陷阱
  badx[0]=300+random(200,300);//預留距離
  for(int i=1;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);//陷阱間隔
  }
}
float usery=300, bgx=0;//方塊y坐標,三角形背景x的移動
void draw(){
  background(#FF0A7D);
  fill(#F5ADCF);
  for(int i=0;i<100;i++){
    triangle(badx[i]-bgx,300,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
  }
  fill(#AD0051); rect(0,350,600,400);//地面
  rect(150,usery,50,50);
  bgx+=3;//移動
}
3.跳躍
float []badx;//陷阱
void setup(){
  size(600,400);
  badx=new float[100];//準備100個陷阱
  badx[0]=300+random(200,300);//預留距離
  for(int i=1;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);//陷阱間隔
  }
}
float usery=300, vy=0, bgx=0;//方塊y坐標,三角形背景x的移動
void draw(){
  background(#FF0A7D);
  fill(#F5ADCF);
  for(int i=0;i<100;i++){
    triangle(badx[i]-bgx,300,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
  }
  fill(#AD0051); rect(0,350,600,400);//地面
  rect(150,usery,50,50);
  if(jumping){
    usery+=vy;
    vy+=0.98/2;//重力加速度
    if(usery>300){//停留在地面
      jumping=false;
      usery=300;
    }
  }
  bgx+=3;//移動
}
boolean jumping=false;
void keyPressed(){
  if(jumping==false){
    jumping=true;//true時跳躍
    vy=-10;//往上跳
  }
}
4.方塊后影子
float []badx,bubblex,bubbley;//陷阱
void setup(){
  size(600,400);
  badx=new float[100];//準備100個陷阱
  badx[0]=300+random(200,300);//預留距離
  for(int i=1;i<100;i++){
    badx[i]=badx[i-1]+random(200,250);//陷阱間隔
  }
  bubblex=new float[10];
  bubbley=new float[10];
  for(int i=0;i<10;i++){
    bubblex[i]=0;
    bubbley[i]=300;//準備影子
  }
}
float usery=300, vy=0, bgx=0;//方塊y坐標,三角形背景x的移動
void draw(){
  background(#FF0A7D);
  fill(#F5ADCF);
  for(int i=0;i<100;i++){
    triangle(badx[i]-bgx,300,badx[i]-25-bgx,350,badx[i]+25-bgx,350);
  }
  fill(#AD0051); rect(0,350,600,400);//地面
  rect(150,usery,50,50);
  if(jumping){
    usery+=vy;
    vy+=0.98/2;//重力加速度
    if(usery>300){//停留在地面
      jumping=false;
      usery=300;
    }
  }
  for(int i=9;i>0;i--){
    bubblex[i]=bubblex[i-1];
    bubbley[i]=bubbley[i-1];
    ellipse(bubblex[i]+150-bgx,bubbley[i],10,10);
  }
  bubblex[0]=bgx;
  bubbley[0]=usery;
  bgx+=3;//移動
}
boolean jumping=false;
void keyPressed(){
  if(jumping==false){
    jumping=true;//true時跳躍
    vy=-10;//往上跳
  }
}








2021年11月22日 星期一

ᐇ Week11

Week11

上課內容為類似接金筆互動,先產生球並給y方向速度下落,之後產生兩個,用for和array產生多個球,加上if判斷調整vy方向,碰撞判斷和boolean的true和false值,陣列變數和大小,random隨機亂數,class物件導向,加速度,特訓99

1.產生圓並按一定速度落下
在x,y位置產生圓並給速度vy

float x=250,y=0,vx=0,vy=3;
void setup(){
  size(500,600);
}
void draw(){
  background(255);
  ellipse(x,y,50,50);
  //y++;
  //y=y+3;
  y=y+vy;//vy是速度
}
2.產生兩個圓並按一定速度落下
增加x2,y2,vx2,vy2變數,有兩個球出現

float x=250,y=0,vx=0,vy=3;
float x2=150,y2=50,vx2=0,vy2=2;
void setup(){
  size(500,600);
}
void draw(){
  background(255);
  ellipse(x,y,50,50);
  ellipse(x2,y2,50,50);
  y=y+vy;
  y2=y2+vy2;
}
3.用for和陣列產生多個圓並落下
陣列產生多個值 

float []x={250,150,350,300};
float []y={0,50,80,100};
float []vx={0,0,0,0};
float []vy={3,2,2.5,4};
void setup(){
  size(500,600);
}
void draw(){
  background(255);
  for(int i=0;i<4;i++){
    ellipse(x[i],y[i],50,50);
    y[i]=y[i]+vy[i];
  }
}
4.加上互動使球來回碰撞
只能在y為0-600的範圍移動

if(y[i]>600) vy[i]=-vy[i];//碰到下方
if(y[i]<0) vy[i]=-vy[i];//接到上方
5.判斷碰撞
用dist距離判斷是否碰撞

float []x={250,150,350,300};
float []y={0,50,80,100};
float []vx={0,0,0,0};
float []vy={3,2,2.5,4};
void setup(){
  size(500,600);
}
void draw(){
  background(255);
  for(int i=0;i<4;i++){
    fill(255,255,0); ellipse(x[i],y[i],50,50);
    if(dist(mouseX,mouseY,x[i],y[i])<=50){//判斷碰撞
      continue;
    }
    y[i]=y[i]+vy[i];
    if(y[i]>600) vy[i]=-vy[i];//碰到下方
    if(y[i]<0) vy[i]=-vy[i];//接到上方
  }
  fill(255,0,0); ellipse(mouseX,mouseY,50,50);
}
6.boolean陣列
用boolean的false和true值調整球的存活狀態

float []x={250,150,350,300};
float []y={0,50,80,100};
float []vx={0,0,0,0};
float []vy={3,2,2.5,4};
boolean []dead={false,false,false,false,false};//false=0,true=1
void setup(){
  size(500,600);
}
void draw(){
  background(255);
  for(int i=0;i<4;i++){
    if(dist(mouseX,mouseY,x[i],y[i])<=50){//判斷碰撞
      dead[i]=true;//碰到就沒了
    }
    if(dead[i]==true) continue;//死了換下一個
    fill(255,255,0); ellipse(x[i],y[i],50,50);//沒死畫它
    y[i]=y[i]+vy[i];
    if(y[i]>600) vy[i]=-vy[i];//碰到下方
    if(y[i]<0) vy[i]=-vy[i];//接到上方
  }
  fill(255,0,0); ellipse(mouseX,mouseY,50,50);
}
7.boolean解釋練習
boolean的false為不成立,true為成立

boolean down=true;//按下
void setup(){
  size(500,300);
}
void draw(){
  if(mousePressed) down=true;
  else down=false;
  print(down);
  if(down) background(255,0,0);//紅色
  else background(0,255,0);//綠色
}
8.陣列大小和random亂數
產生更多球和隨即生成亂數

float []x;//宣告陣列變數
float []y;
float []vy;
boolean []dead;
int N=20;
void setup(){
  size(500,600);
  x=new float[N];//決定陣列大小
  y=new float[N];
  vy=new float[N];
  dead=new boolean[N];
  for(int i=0;i<N;i++){
    x[i]=random(500);//500以下亂數
    y[i]=random(100,200);
    vy[i]=random(3,4);//3,4中間亂數
    dead[i]=false;//沒有死掉
  }
}
void draw(){
  background(255);
  for(int i=0;i<N;i++){
    if(dist(mouseX,mouseY,x[i],y[i])<=50){//判斷碰撞
      dead[i]=true;//碰到就沒了
    }
    if(dead[i]==true) continue;//死了換下一個
    fill(255,255,0); ellipse(x[i],y[i],50,50);//沒死畫它
    y[i]=y[i]+vy[i];
    if(y[i]>600) vy[i]=-vy[i];//碰到下方
    if(y[i]<0) vy[i]=-vy[i];//接到上方
  }
  fill(255,0,0); ellipse(mouseX,mouseY,50,50);
}
9.class物件導向
主程式碼更短

class Ball{//發明Ball物件
  float x,y,vx,vy;
  boolean dead;
  Ball(){//建構同名
  x=random(500);
  y=random(100,200);
  vy=random(3,4);
  dead=false;
  }
  void draw(){
  if(dead==true) return;//離開函式
  ellipse(x,y,50,50);
  if(dist(mouseX,mouseY,x,y)<50){
    dead=true;
  }
  y=y+vy;
  if(y>500) vy=-vy;
  if(y<0) vy=-vy;
  }
}
Ball []balls;
void setup(){
  size(500,500);
  balls=new Ball[20];
  for(int i=0;i<20;i++){
    balls[i]=new Ball();
  }
}
void draw(){
  background(255);
  for(int i=0;i<20;i++){
    balls[i].draw();
  }
}
10.加入vx變數
增加x方向的速度

class Ball{//發明Ball物件
  float x,y,vx,vy;
  boolean dead;
  Ball(){//建構同名
  x=random(500);
  y=random(500);
  vy=random(-4,4);
  vx=random(-4,4);
  dead=false;
  }
  void draw(){
  if(dead==true) return;
  ellipse(x,y,50,50);
  if(dist(mouseX,mouseY,x,y)<50){
    dead=true;
  }
  x=x+vx;
  y=y+vy;
  if(y>500 || y<0) vy=-vy;
  if(x>500 || x<0) vx=-vx;
  }
}
11.加上重力

vy+=0.98;
12.特訓99
用以下程式碼做出簡單的特訓99游戲

class Ball{//發明Ball物件
  float x,y,vx,vy;
  boolean dead;
  Ball(){//建構同名
  reborn();
  }
  void reborn(){
    x=random(500);
    y=random(500);
    vy=random(-2,2);
    vx=random(-2,2);
    dead=false;
  }
  void draw(){
  if(dead==true) return;
  fill(255,0,0); ellipse(x,y,5,5);
  if(dist(mouseX,mouseY,x,y)<5){
    dead=true;
    gameOver=true;
  }
  x=x+vx;
  y=y+vy;
  if(y>500 || y<0) reborn();
  if(x>500 || x<0) reborn();
  }
}
Ball []balls;
void setup(){
  size(500,500);
  balls=new Ball[99];
  for(int i=0;i<99;i++){
    balls[i]=new Ball();
  }
}
boolean gameOver=false;
void draw(){
  background(0);
  for(int i=0;i<99;i++){
    balls[i].draw();
  }
  if(gameOver) background(255,0,0);
  
}






2021年11月15日 星期一

ᐇ Week10

 Week 10


教學內容為複習前幾周以及text和textSize(顯示文字和文字內容,可用fill改變顏色),frameCount計數frame,mills計數,hour,minute,second分別顯示時分秒,textFont更改字型,PFont,字串,倒計時互動,用圖片秀字


1.textSize和text顯示文字和文字內容

textSize可以調整文字大小,text可以顯示文字內容,50,50為text的位置


size(500,500);

fill(255,0,0);//填充顏色

textSize(80);//文字大小

text("Hello",50,50);//文字內容與位置

2.準備互動
加上setup和draw準備後續

void setup(){

    size(500,500);

    fill(255,0,0);//填充顏色

    textSize(80);//文字大小

}

void draw(){

    text("Hello",50,100);//文字內容與位置

}

3.frameCount計數frame
frameCount顯示當前frame數,1秒60frame,用+連接

void setup(){
  size(500,500);
  fill(255,0,0);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(255);//白
  text("Time"+frameCount,50,100);//文字內容與位置
}//每秒60frame,過了幾個frame

4.mills較為準確的計時
frameCount會delay,比較不準確,通常會使用mills()計秒數

void setup(){
  size(500,500);
  fill(255,0,0);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(255);//白
  text("Time:"+frameCount/60,50,100);//不太準確,會delay
  text("Mills:"+millis()/1000,50,200);//較為準確
}//mills千分

5.hour()minute()和second()
使用hour,minute,second函式呼叫,用text顯示出時分秒

void setup(){
  size(500,500);
  fill(255,0,0);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(255);//白
  text(hour()+":"+minute()+":"+second(),50,100);//時分秒
  text("Mills:"+millis()/1000,50,200);//較為準確
}//mills千分
6.不能顯示中文
目前暫時不能顯示中文,需要之後加程式

text("中文"+"Mills:"+millis()/1000,50,200);
7.印出系統目前所有字型

println(PFont.list());
8.更改字型,印出中文
使用PFont,creatFont,textFont印出中文字

PFont myFont;//宣告變數myFont
void setup(){
  size(500,500);
  myFont=createFont("標楷體",100);//字型名稱以及大小
  textFont(myFont);//更改字型為標楷體
  text("中文",100,100);
}
9.滑鼠點擊切換字型
宣告兩個變數,使用mousePressed函式進行切換

PFont font1,font2;//宣告多個變數
void setup(){
  size(500,500);
  font1=createFont("標楷體",100);
  textFont(font1);
  font2=createFont("微軟正黑體 Bold",100);
}
void draw(){
  background(0);
  text("中文",100,100);
  if(mousePressed) textFont(font2);//按下切換為font2
  else textFont(font1);
}
10.字串
使用字串String產生%02d的效果

void setup(){
  size(500,500);
  fill(255,0,0);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(255);//白
  String hh=nf(hour(),2);
  String mm=nf(minute(),2);
  String ss=nf(second(),2);
  text(hh+":"+mm+":"+ss,50,100);
}
11.倒計時
換算現在和下課,相減得出倒計時

void setup(){
  size(500,500);
  fill(255);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(#075BB2);
  String hh=nf(hour(),2);
  String mm=nf(minute(),2);
  String ss=nf(second(),2);
  text(hh+":"+mm+":"+ss,50,100);
  text("15:40:00",50,200);
  
  int now=hour()*60*60+minute()*60+second();//計算現在時間
  int next=15*60*60+40*60+0;//換算下課時間
  int remain=next-now;//相減
  text(remain,50,300);
}
12.修改倒計時格式
將倒計時改爲hour,minute,second的形式,使用餘數和除法

PFont font1;
void setup(){
  size(800,500);
  fill(255);//填充顏色
  textSize(80);//文字大小
}
void draw(){
  background(#075BB2);
  String hh=nf(hour(),2);
  String mm=nf(minute(),2);
  String ss=nf(second(),2);
  font1=createFont("標楷體",100);
  textFont(font1);
  text("現在:"+hh+":"+mm+":"+ss,50,100);
  text("上課:15:50:00",50,200);
  
  int now=hour()*60*60+minute()*60+second();
  int next=15*60*60+50*60+0;
  int remain=next-now;
  text("剩餘:"+remain,50,300);
  hh=nf(remain/60/60%60,2);//取餘數
  mm=nf(remain/60%60,2);
  ss=nf(remain%60,2);
  text("剩下:"+hh+":"+mm+":"+ss,50,400);
}
13.圖片秀字
for回圈按順序顯示數字0-9

PImage []img=new PImage[10];
void setup(){
  size(1120,450);
  for(int i=0;i<10;i++) img[i]=loadImage(i+".png");//載入圖片檔案名稱
}
void draw(){
  for(int i=0;i<10;i++){
    int x=(i%5)*224 , y=(i/5)*225;//圖片位置x,y
    image(img[i],x,y);
  }
}
14.倒計時秀字
用圖片顯示出倒計時的數字

PImage [] img = new PImage[10];
PFont font;
void setup(){
  size(  1120, 450  );//把全部的圖,都秀出來
  for(int i=0; i<10; i++) img[i]=loadImage(i+".png");
  fill(255);
  font = createFont("標楷體",80);
  textFont(font);
}
void draw(){
  background(#075BB2);
  String hh=nf(hour(),2);
  String mm=nf(minute(),2);
  String ss=nf(second(),2);
  text("現在:"+hh+":"+mm+":"+ss, 50,100);
  text("下課:15:40:00", 50,200);
  
  int now = hour()*60*60 + minute()*60 + second();//現在總秒數
  int next = 16   *60*60 + 40      *60 + 0;//下課總秒數
  int remain = next-now;//剩下的時間 (秒數來算)
  if(remain<0) remain += 24*60*60;
  text("剩下:"+remain, 50,300);
  hh = nf(remain/60/60%60, 2);
  mm = nf(remain/60%60, 2);
  ss = nf(remain%60, 2);
  text("剩下:"+hh+":"+mm+":"+ss, 50,400);
  int x=800;
  while(remain>0){
    int n = remain%10;//得到餘數
    remain = remain / 10;//取上一位數
    image( img[n], x,100,100,100);
    x-=100;//x的位置往左移動100
  }
}