顯示具有 06160583_楊愷翔 標籤的文章。 顯示所有文章
顯示具有 06160583_楊愷翔 標籤的文章。 顯示所有文章

2022年1月17日 星期一

常闇的程式之路week 17

 我的作品也做得差不多了,這次做的作品是泡泡龍的小遊戲,雖然做了滿久的,但還是有些BUG存在。話不多說直接上程式碼吧ˊˇˋ


import ddf.minim.*;

Minim minim;

AudioPlayer BGM;

AudioPlayer GG;

AudioPlayer Hit;

PFont F;

float bx;//發射球之x座標

float by;//發射球之y座標

float bvx;//發射球之x方向速度

float bvy;//發射球之y方向速度

int bc = 0;//目前發射球之顏色

int []ec = new int [1000];//所有敵人顏色編號資料 *重要資料*

int bnext = 0;//下一顆發射球之顏色

int enemy[];//敵人數量,最多11行

float []ex = new float[1000];//所有敵人的x座標資料 *重要資料*

float []ey = new float[1000];//所有敵人的y座標資料 *重要資料*

//float []nx = new float [4];//發射球黏上敵人陣列後偵測上下左右敵人x座標 *重要資料*

//float []ny = new float [4];//發射球黏上敵人陣列後偵測上下左右敵人y座標 *重要資料*

boolean shoot = false;//觸發子彈發射

boolean appear;//觸發子彈繪製

float nearx = 10000;//距離發射求最近之敵人x座標 *重要資料*

float neary = 10000;//距離發射求最近之敵人y座標 *重要資料*

float near = 10000;//距離發射求最近之敵人歐幾理德距離 *重要資料*

int bulletsize = 50;//發射球之直徑參數 *重要資料*

int r = 50;//所有敵人之直徑參數 *重要資料*

int N = 0;//敵人總數

float []dx = new float[1000];//應該死掉的球x座標

float []dy = new float[1000];//應該死掉的球y座標

float []dc = new float[1000];//應該死掉的顏色標號

void setup(){

  size(550 ,600);

  minim=new Minim(this);

  BGM=minim.loadFile("Video Game Blockbuste.mp3",1024);

  BGM.play();

  BGM.loop();

  F = createFont("18thCentury" ,80);

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

      ec[i] = int(random(1 ,5));//給予所有位址隨機1~5整數以作為上色標準,0為空格

  }

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

    for(int j = 1 ;j <= 10 ;j++){

      N++;

      ex[N-1] = j * r;ey[N-1] = i * r;

    }

  }

  newbullet();

  bnext = int(random(1 ,5));

}


void draw(){

  background(#242DFF);

  fill(#FFB624);rect(100 ,100 ,350 ,350);

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

    if(ec[i] == 1) {fill(#FC8585);ellipse(ex[i] ,ey[i] ,r ,r);}//紅

    if(ec[i] == 2) {fill(#FAFA86);ellipse(ex[i] ,ey[i] ,r ,r);}//黃

    if(ec[i] == 3) {fill(#86FA9C);ellipse(ex[i] ,ey[i] ,r ,r);}//綠

    if(ec[i] == 4) {fill(#8696FA);ellipse(ex[i] ,ey[i] ,r ,r);}//藍

    if(dist(bx ,by ,ex[i] ,ey[i]) < r){

      shoot = false;

      appear = false;

      N++;

      near = (dist(nearx * r ,neary * r ,bx ,by));

      for(int k = 1 ;k <= 10 ;k++){

        for(int l = 1 ;l <= 11 ;l++){

          if(dist(l * r ,k * r ,bx ,by) < near){

            nearx = l;

            neary = k;

            near = dist(nearx * r ,neary * r ,bx ,by);

            ex[N-1] = nearx * r;

            ey[N-1] = neary * r;

            ec[N-1] = bc;

            dx[N-1] = ex[N-1];

            dy[N-1] = ey[N-1];

            dc[N-1] = ec[N-1];

            S_Hit();

            if(ey[N-1] == 10 * r) {gameover();}

          }  

        }

      }

      for(int a = N-2 ;a >= 0 ;a--){

        if(ec[a] == dc[N-1] && dist(dx[N-1] ,dy[N-1] ,ex[a] ,ey[a]) <= 1.4*r){

          println(ex[N-1] ,ey[N-1] ,ec[N-1]);

          //ec[a] = 0;

          ex[N-1] = 1000;

          ey[N-1] = 1000;

          dx[N-1] = ex[a];

          dy[N-1] = ey[a];

          ex[a] = 1000;

          ey[a] = 1000;

        }

      }

      for(int a = 0 ;a <= N-2 ;a++){

        if(ec[a] == dc[N-1] && dist(dx[N-1] ,dy[N-1] ,ex[a] ,ey[a]) <= 1.4*r){

          println(ex[a] ,ey[a] ,ec[a]);

          //ec[a] = 0;

          ex[N-1] = 1000;

          ey[N-1] = 1000;

          dx[N-1] = ex[a];

          dy[N-1] = ey[a];

          //dc[N-1] = ec[a];

          ex[a] = 1000;

          ey[a] = 1000;

        }

      }

      newbullet();

    }

    if(ey[N-1] == 10 * r) {

      gameover();

      appear = false;

      bnext = 0;

      M_Stop();

      break;

    }

  }

  if(bnext == 1) {fill(#FC8585);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 2) {fill(#FAFA86);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 3) {fill(#86FA9C);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 4) {fill(#8696FA);ellipse(275,575 ,bulletsize ,bulletsize);}

  

  if(appear){

    if(bc == 1) {fill(#FC8585);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 2) {fill(#FAFA86);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 3) {fill(#86FA9C);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 4) {fill(#8696FA);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(shoot){

      bx+=bvx;

      by+=bvy;

      if(bx >= width-(bulletsize/2) || bx <= bulletsize/2) {bvx=-(bvx);S_Hit();}

      

      if(by >= height-(bulletsize/2) || by <= bulletsize/2) {bvy=-(bvy);S_Hit();}

    }

  }

}

void newbullet(){

  bx=275;

  by=575;

}


void gameover(){

  background(255);

  fill(0);

  textFont(F);

  text("GAME OVER" ,100 ,300);

  minim=new Minim(this);

  GG=minim.loadFile("Sad Trombone.mp3",1024);

  GG.play();

}


void nextbullet(){

  bnext = int(random(1 ,5));

}

void M_Stop()

{

  BGM.close();

  minim.stop();

  super.stop();

}

void S_Hit(){

  minim=new Minim(this);

  Hit=minim.loadFile("Pop sound effect.mp3",1024);

  Hit.play();

}

void mousePressed(){

  appear=true;

  shoot=true;

  bc = bnext;

  float dx=mouseX-275, dy=mouseY-575;

  float len=sqrt(dx*dx + dy*dy);

  bvx = dx*10/len;

  bvy = dy*10/len;

  nextbullet();

}

這是遊戲的外觀:

大致上就是這樣,雖然該消的球似乎沒辦法每次都完整消光,音樂到後期好像也會有點問題,但遊戲性還是沒啥大問題,我應該還會用點時間把這部分完善,就這樣囉ˊˇˋ




2022年1月3日 星期一

常闇的程式之路week 15

 我想讓發射出去的球能感應到上方的敵人,進而黏在空格上,但我意識到這是非常難的事情。其中有一個很大的原因,那就是我的敵人是用二維陣列繪製的。這讓每顆球的編號變得難以辨識,所以要解決這事情只能將敵人也用一維陣列繪製了,謝謝老師教我如何做這個判定:

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

    for(int j = 1 ;j <= 10 ;j++){

      N++;

      ex[N-1] = j * r;ey[N-1] = i * r;

    }

  }

用這個二層迴圈給定一個總數為N的敵人顏色。

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

    if(ec[i] == 1) {fill(#FC8585);ellipse(ex[i] ,ey[i] ,r ,r);}//紅

    if(ec[i] == 2) {fill(#FAFA86);ellipse(ex[i] ,ey[i] ,r ,r);}//黃

    if(ec[i] == 3) {fill(#86FA9C);ellipse(ex[i] ,ey[i] ,r ,r);}//綠

    if(ec[i] == 4) {fill(#8696FA);ellipse(ex[i] ,ey[i] ,r ,r);}//藍

這樣就能用單一迴圈繪製繪製二維方向的敵人囉,這樣判定起來簡單多了。

2021年12月27日 星期一

常闇的程式之路week 14

  我的球,沒辦法做碰撞判定啊啊啊!

事情是這樣的,我發現我的子彈跟敵人都是陣列,沒辦法進行逐一判定。這是個大問題,真的。

所以我想要先把子彈的部分從陣列解放出來,有辦法嗎?其實也是很簡單,畢竟繪製這個東西本來就是從單個單個繪製開始的嘛。所以這其實只需要回歸原始,我們用布林函式來判定繪製與否,那就判定布林函式有沒有被啟動,若啟動就繪製,這樣就是一次一顆了,因為是個單體,我就能輕鬆賦予其顏色與座標等重要屬性了,這樣就離實現距離判定的時刻不遠了。

好,上程式碼:

void mousePressed(){

  appear=true;

  shoot=true;

  bc = bnext;

  float dx=mouseX-275, dy=mouseY-575;

  float len=sqrt(dx*dx + dy*dy);

  bvx = dx*10/len;

  bvy = dy*10/len;

  nextbullet();

}

這是滑鼠按下時該做的事,其中的appear跟shoot兩布林函式分別代表繪製子彈與射擊子彈兩部分的控制,這是為了讓另外一個函式得以執行,也就是繪製下一顆球的函式。如果不知道下一顆球長怎樣,這遊戲也太難了,每顆要發射的球都是隨機上色,總不能用猜的吧?appear就是用在這裡的。他是用於控制繪製現在要發射出去的球的繪製,在它的值為true之前並不會繪製要發射的球的。

  if(bnext == 1) {fill(#FC8585);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 2) {fill(#FAFA86);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 3) {fill(#86FA9C);ellipse(275,575 ,bulletsize ,bulletsize);}

  if(bnext == 4) {fill(#8696FA);ellipse(275,575 ,bulletsize ,bulletsize);}

  

  if(appear){

    if(bc == 1) {fill(#FC8585);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 2) {fill(#FAFA86);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 3) {fill(#86FA9C);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(bc == 4) {fill(#8696FA);ellipse(bx,by ,bulletsize ,bulletsize);}

    if(shoot){

      bx+=bvx;

      by+=bvy;

      if(bx >= width-(bulletsize/2) || bx <= bulletsize/2) {bvx=-(bvx);S_Hit();}

      

      if(by >= height-(bulletsize/2) || by <= bulletsize/2) {bvy=-(bvy);S_Hit();}

    }

如上面的程式碼,我會先繪製下一顆球的顏色在原地,然後用一個函式操控生成顏色,然後在滑鼠按下時將下一顆球的顏色bnext指定給要發射的球的顏色bc,然後用random(1 ,5)再生成一個新的bnext繪製在原地。這就是繪製發射的方法了,

話題回到發射的部分,由於一次只繪製一顆子彈,所以我就能輕易地給予它獨立的x與y的座標量,以及顏色編號,這樣要進行判定真的會輕鬆很多。好啦,先這樣啦,下周見!

2021年12月20日 星期一

常闇的程式之路week 13

啊...我的作品,該怎麼做......繪製敵人......OK,繪製子彈......OK,讓子彈飛......OK,判定黏住......OK,判定消除......OK。這麼多OK,但除了繪製一二點的東西出來之外其他的每個都像個高牆,還是一座比一座高的那種,算了,總之先搞個繪製出來吧,其餘別想了。

首先我需要一個二維陣列來繪製上方的敵人,然後一個一維陣列來畫子彈。先寫!
float x ,y;
float []bx = new float[1000];
float []by = new float[1000];
float []bvx = new float[1000];
float []bvy = new float[1000];
int []bullet = new int[1000];//子彈數量,最多1000個
int [][]enemy = new int[11][11];//敵人數量,最多11行
color[]c = {#FC8585 ,#FAFA86 ,#86FA9C ,#8696FA};//四種球色
int N = 0;//計算第幾顆子彈
int ballsize = 50;

void setup(){
  size(550 ,600);
  for(int i = 0 ;i < 10 ;i++){
    for(int j = 0 ;j < 6 ;j++){
      enemy[i][j] = int(random(4));//給予所有位址隨機整數以作為上色標準
    }
  }
  for(int k = 0 ;k < 1000 ;k++){
    bullet[k] = int(random(4));
    bvx[k] = 0;
    bvy[k] = 0;
    shoot[k] = false;
  }
}

void draw(){
  background(#242DFF);
  fill(#FFB624);rect(100 ,100 ,350 ,350);
  for(int i = 0 ;i < 10 ;i++){
    for(int j = 0 ;j < 6 ;j++){
      if(enemy[i][j] == 0) {fill(#FC8585);ellipse((i+1)*50 ,(j+1)*50 ,50 ,50);}
      if(enemy[i][j] == 1) {fill(#FAFA86);ellipse((i+1)*50 ,(j+1)*50 ,50 ,50);}
      if(enemy[i][j] == 2) {fill(#86FA9C);ellipse((i+1)*50 ,(j+1)*50 ,50 ,50);}
      if(enemy[i][j] == 3) {fill(#8696FA);ellipse((i+1)*50 ,(j+1)*50 ,50 ,50);}
      //x = (i+1)*50;y = (j+1)*50;
      //println(x ,y);
    }   
  }
  for(int i = 0 ;i < 10 ;i++){
    for(int j = 0 ;j < 6 ;j++){
      x = (i+1)*50;y = (j+1)*50;
    }   
  }
  for(int k = 0 ;k < 1000 ;k++){
    if(appear[k]==true){
      if(bullet[k] == 0) {fill(#FC8585);}
      if(bullet[k] == 1) {fill(#FAFA86);}
      if(bullet[k] == 2) {fill(#86FA9C);}
      if(bullet[k] == 3) {fill(#8696FA);}
      ellipse(bx[k],by[k] ,ballsize ,ballsize);

OK,這樣就能繪製我要的東西了,採用網路上的做法,把球用隨機變數上編號,然後指定什麼編號上什麼色,然後用迴圈把陣列畫出來,這樣就有基本的東西了!

2021年12月13日 星期一

常闇的程式之路week12

 我的期末作業想做的是那種類似泡泡龍的遊戲,但我只有一個人,恐怕也沒辦法搞得太複雜,特殊泡泡啊,排名系統啊之類的大概一時半毀做不出來,不如就把概念想簡單一點好了。

首先會有幾排的敵人排在畫面上方,顏色隨機。然後要發射的球在下方,發射了一顆要補上一顆,顏色也是隨機。像是這樣:

顏色相同相鄰的敵人,會在被同顏色的子彈射中後消失。然後敵人的排數到達一定的量後就輸了。基本上就是泡泡龍遊戲嘛,感覺是不會太複雜,至少流程都有了。只等到時候開始動手農程式碼了,先這樣啦~~

2021年12月6日 星期一

常闇的程式之旅week11

 其實我對於要做什麼還是有點疑慮,畢竟我只有一個人,而且實力也不怎夠,所以在要做什麼的部分明明應該可以很快得到想法,但卻很害怕,上個禮拜老師要我們決定自己想做什麼遊戲,我本來是想要做彈幕遊戲的,但有其他組別已經決定,我不得不想想其他主題,不然挑戰一下好了,消除類遊戲除了俄羅斯方塊外似乎還沒有很多,就作泡泡龍吧,應該是不會太複雜吧我想。

(未來人常闇回來編輯一下:我後悔了,複雜的要死要活,做得好累wwwww)

2021年11月29日 星期一

常闇的程式之路week10

 這禮拜的主要範例是利用方向鍵來讓畫面中有動作變化的小人像這不同方向移動,這是老師的範例程式:

PImage img;

void setup(){

size(500,500);

img=loadImage("img.jpg");

imageMode(CENTER);

}

int a=0, b=0, x=250, y=250;

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++; }

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

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

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

}

首先先用PImage定義一個資料型態為圖片的變數img,然後把img指定為一個匯入的圖片img.jpg,並將指定方式設定成置中,這樣img這個變數就會是img.jpg這張圖了。

!!注意,這裡的img.jpg是一個上面有連續動作變換的連環圖,這裡不知道的話後面也不必說了。!!

好的,接著就是印出img的部分了。繪製背景別忘記,image(  img.get(141*a, 211*b, 141,211), x,y);這件事是什麼呢,它的意思就是依照a與b的值,對於image印出的img這張圖的位置與大小,img.get(x ,y ,x_size ,y_size)這個函數能夠令img這個變數只印出x座標與y座標上,範圍為141,211的那一部分。後者的image(x ,y)的部分則是為了後面判斷圖片位置移動而作的變數,接下來將會以鍵盤操控的方法控制這兩變數,進而實現移動圖片的動作。

這裡使用if(frameCount%30==0) a = (a+1)%4;這判斷式可讓a隨著時間遞增,這樣一來便能讓img.get隨著時間換位置。還記得這張img.jpg是個連環圖吧?一次顯示一部分,看起來人物就動起來了。

接著是方向鍵控制的部分,每個鍵的觸發都要額外寫一個void已進行函式判斷。接下來就是簡單的加減法了。

這裡有一個要注意的地方:在按下上下左右的時候,b會變化,那是因為b在img.set()中所代表的位置便是人物面對上下左右時的圖樣。如此控制便能讓人物看起來永遠都是面向他索前進的方向。這就是對於這次的範例,我所得到的理解。


至於我的期末作業要做什麼......我暫時還拿不定主意,下禮拜再確定吧。

2021年11月22日 星期一

常闇的程式之路week7

 

















常闇的程式之路week 09

 今天開始,我們將要開始統合之前所學到的方法,在Process3上製作簡易的小遊戲。

首先我們製作一個能夠下墜的物體:


接著我們試著做出另一顆不一樣速度的物體:


真不錯,但是這樣如果想要更多物體,就要有更多得程式碼,這樣麻煩。所以我們可以試試陣列作法:


不過球過了框界之後也不會回來,我們想讓它們在框界裡頭彈跳的話,就得設定物體彈跳的條件,改變速度方向:


接著就是創造一個能夠與這些物體互動的可控物體囉:


在這裡我們放上了一個判定式,始可控的紅球在碰到其餘黃球時能使其消失,主要是設定兩物體在距離不超過50時,使用continue函式,跳過了繪製黃色球體的過程,並達到消失的效果。

接著我想要讓這程式碼成為一個有機制的遊戲,所以我希望這黃色的物體在被可控的紅色物體碰到後就永久消除:





我們使用布林涵式,來對上述觸碰事件判定,如果判定有碰到,便直接消除該物體並阻止其再繪製。

至於什麼是布林函式呢,布林函式是一種能夠判斷影響程式判斷的真假值,有true以及false兩種值。以下我們用一個小程式解釋概念:



以上面程式為例,我們用down作為布林函式的判斷變數,當滑鼠為按下時,down的值為false;而按下時,則為true。這便是基本的布林函式。

以下是示範用程式碼:

boolean down;//滑鼠按下

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);//綠

}

接下來我們要對於遊戲的程式碼進行更深的調整,讓它更加完整:


這裡我們針對所有變數的做法進行改進,我們將所有變數的陣列於setup區域中進行random化處理,並將球的生成數設定為N,這麼一來便可透過對N的設定,直接對所有與N相關的數值統一改變,random的設計也能進一步增加遊戲的隨機性。

不過這麼一來,程式就會變得非常複雜,這時我們可以使用一個新方法──class:


Class可以被視為一個獨立的函式,它的作用在於整合數個小物件,使之成為一個複合的大物件,這些被整合的小物件能夠透過在主函式中呼叫該Class,進行同時的使用。

既然我們成功精簡了程式碼,那我們就來加更多的難度吧,比如讓球在四面八方亂彈,而不是只有上下:


這裡我們給予x方向不同速度,讓它們能夠在左右的維度上移動。

雖然吃球的遊戲也不錯玩,但是還是閃子彈的遊戲刺激多了對吧。所以我們改一下程式碼,讓吃到球的情況變成遊戲結束的紅畫面:


首先讓子彈小點也多點,接著讓速度也慢點,設定子彈飛出後在隨機位置重生,保持場面上的子彈數量。接著設定碰到游標後進入紅色的gameover畫面,這樣就大功告成啦。

以下是全部的程式碼:

class Ball{//定義Ball物件

  float x ,y ,vx ,vy;

  boolean dead;

  Ball(){//建構同名物件

    reborn();

  }

  void reborn(){

    x = random(500);

    y = random(100 ,200);

    vy = random(-1 ,1);

    vx =random(-1 ,1);

    dead = false;

  }

  void draw(){

    if(dead == true) return;

    ellipse(x ,y ,10 ,10);

    if(dist(mouseX ,mouseY ,x ,y) < 10){

      gameOver = true;

    }

    y = y + vy;

    x = x + vx;

    if(y > 500 || y < 0) reborn();

    if(x > 500 || x < 0) reborn();

  }

}


Ball [] balls;


void setup(){

  size(500 ,500);

  balls = new Ball[100];

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

    balls[i] = new Ball();

  }

}

boolean gameOver = false;

void draw(){

  background(255);

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

    balls[i].draw();

  }

  if(gameOver) background(255 ,0 ,0);

}

2021年9月27日 星期一

常闇的程式之路week 01

 


今天是互動技術的第一周上課,這禮拜主題是簡單介紹Processing3的程式。我們先用簡易的程式碼製作企鵝圖騰。