搞什麼飛雞

利用酷酷的 Processing 寫出 Flappy Bird!

大綱

Lecture 1

  1. Procssing 簡介
  2. 基本 Processing 語法介紹
  3. If-else 流程控制

Lecture 2

  1. Flappy Bird 介紹
  2. 遊戲邏輯
  3. 遊戲實作!

連結們

連結們

Processing ?

Processing ?

  • 利用視覺化的方式學習程式語言
  • 後來被用在電子藝術、視覺設計及多媒體互動
  • 語法簡單,就算沒有程式基礎也可以很容易上手

Processing ?

  • 要怎麼做出動畫呢?

Processing ?

  • 要怎麼做出動畫呢?
  • 不斷更新畫面

基本 Processing 語法

void setup(){
  // 開始畫畫前的準備
  // 畫筆粗細、背景顏色、畫框大小等等
  // 只會執行一次
}

void draw(){
  // 緊接在 setup 函數後執行
  // 開始不斷地作畫
  // 在程式中會不斷執行
  // 每執行一次就是一個畫面 (一幀)
}

基本 Processing 語法

蛤?

void setup() 是什麼

基本 Processing 語法

基本 Processing 語法

函數 Function

​void setup() 是什麼

回傳型態

函數名稱

傳入變數

基本 Processing 語法

蛤?型態?變數?

基本 Processing 語法

資料型態 Data Type

  • int: 整數
  • float: 小數
  • boolean: 布林代數 (真或假)
  • String: 字串 (一串文字)

基本 Processing 語法

宣告變數

int x = 10;

資料型態

變數名稱

變數值

基本 Processing 語法

宣告變數

float pi = 3.14159;

資料型態

變數名稱

變數值

基本 Processing 語法

宣告變數

boolean processing_is_easy = true;

資料型態

變數名稱

變數值

基本 Processing 語法

宣告變數

String name = "NYCU_twyc";

資料型態

變數名稱

變數值

基本 Processing 語法

變數命名規則

  • 只能用英文、數字及底線
    • 開頭第一個字元不能是數字 ( 2car )
  • 大小寫有別
  • 不能有空格
    • processing_is_fun (snake_case)
    • processingIsFun (camelCase)

基本 Processing 語法

函數 Function

void setup()
  • 沒有回傳值
  • 沒有傳入值

基本 Processing 語法

函數 Function

int add(int x, int y)
  • 回傳的資料型態為整數 (int)
  • 傳入兩個整數 x 和 y

基本 Processing 語法

int add(int x, int y){
  return x + y;
}

回傳右邊的計算出的數值

函數 Function

{ } 為函數的範圍

基本 Processing 語法

開始畫畫吧!

基本 Processing 語法

300

300

200

200

基本 Processing 語法

void setup(){
  // 視窗大小為 300 x 300
  size(300, 300); 
  // 繪製一個左上角座標為 (50, 50)
  // 長寬為 200 的長方形
  // YOUR CODE HERE //
}

void draw(){
  // skip
}

基本 Processing 語法

void setup(){
  // 視窗大小為 300 x 300
  size(300, 300); 
  // 繪製一個左上角座標為 (50, 50)
  // 長寬為 200 的長方形
  // YOUR CODE HERE //
}

void draw(){
  // skip
}
(A) rect(200, 50, 50, 200);
(C) rect(50, 50, 200, 200);
(B) rect(200, 200, 50, 50);
(D) rect(50, 200, 50, 200);

基本 Processing 語法

void setup(){
  // 視窗大小為 300 x 300
  size(300, 300); 
  // 繪製一個左上角座標為 (50, 50)
  // 長寬為 200 的長方形
  // YOUR CODE HERE //
}

void draw(){
  // skip
}
(A) rect(200, 50, 50, 200);
(C) rect(50, 50, 200, 200);
(B) rect(200, 200, 50, 50);
(D) rect(50, 200, 50, 200);

基本 Processing 語法

void setup(){
  // 視窗大小為 300 x 300
  size(300, 300); 
  // 繪製一個左上角座標為 (50, 50)
  // 長寬為 200 的長方形
  rect(50, 50, 200, 200); 
}

void draw(){
  // skip
}

基本 Processing 語法

基本 Processing 語法

基本 Processing 語法

rect(a, b, c, d)

基本 Processing 語法

rect(a, b, c, d)
  • a: 長方形的 x 座標
    
  • b: 長方形的 y 座標
  • c: 長方形的寬
  • d: 長方形的高

基本 Processing 語法

rect(a, b, c, d)
  • a: 長方形的 x 座標
    
  • b: 長方形的 y 座標
  • c: 長方形的寬
  • d: 長方形的高

基本 Processing 語法

執行

基本 Processing 語法

y
x
(50, 50)
(300, 300)
(0, 0)

基本 Processing 語法

基本 Processing 語法

基本 Processing 語法

一個會跟著滑鼠跑的正方形

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  // YOUR CODE HERE //
}

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  // YOUR CODE HERE //
}

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  // YOUR CODE HERE //
}
(C) rect(mouseX, 50, mouseY, 50);
(D) rect(50, mouseX, 50, mouseY);
(A) rect(mouseX, mouseY, 50, 50);
(B) rect(50, 50, mouseX, mouseY);
  • mouseX: 滑鼠的 X 座標
  • mouseY: 滑鼠的 Y 座標

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  rect(mouseX, mouseY, 50, 50);
}
(A) rect(mouseX, mouseY, 50, 50);
(C) rect(mouseX, 50, mouseY, 50);
(B) rect(50, 50, mouseX, mouseY);
(D) rect(50, mouseX, 50, mouseY);

基本 Processing 語法

基本 Processing 語法

基本 Processing 語法

出現許多重複的正方形

基本 Processing 語法

出現許多重複的正方形

把原本畫的正方形蓋掉

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  // YOUR CODE HERE //
  // mouseX, mouseY 代表滑鼠的 x 和 y 座標
  rect(mouseX, mouseY, 100, 100); 
}
(A) fill(255, 255, 255); rect(0, 0, 800, 800);
(B) background(255, 255, 255);

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  // YOUR CODE HERE //
  // mouseX, mouseY 代表滑鼠的 x 和 y 座標
  rect(mouseX, mouseY, 100, 100); 
}
(A) fill(255, 255, 255); rect(0, 0, 800, 800);
(B) background(255, 255, 255);

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
}
void draw(){
  background(255, 255, 255);
  // mouseX, mouseY 代表滑鼠的 x 和 y 座標
  rect(mouseX, mouseY, 100, 100); 
}

(A) 方法會在畫面外緣加入一個外框,可以查一下怎麼移除

基本 Processing 語法

void setup(){
  size(800, 800);
  background(255, 255, 255);
  noFill(); // 不填色
  strokeWeight(5); // 長方形線寬
  rectMode(CENTER); // 座標代表長方形中間位置
}

void draw(){
  background(255, 255, 255);
  // mouseX, mouseY 代表滑鼠的 x 和 y 座標
  rect(mouseX, mouseY, 100, 100);
}

讓滑鼠黏在正方形的中間

基本 Processing 語法

基本 Processing 語法

rectMode(CORNER)

基本 Processing 語法

rectMode(CENTER)

休息!

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( ??? ) {
    background(red);
  } else if ( ??? ) {
    background(green);
  } else if ( ??? ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}

流程控制

line(a, b, c, d)
  • (a, b) 第一個點的座標
  • (c, d) 第二個點的座標

流程控制

if ( condition 1 ) {
  // 做某些事
}

如果 condition 1 成立

那就進行 { } 裡面的程式碼

流程控制

if ( 今天出大太陽 ) {
  出去玩一波大的;
}

流程控制

if ( condition 1 ) {
  // do something
} else {
  // do something else
}

如果 condition 1 成立

那就進行 { } 裡面的程式碼

否則執行 else 後面 { } 裡面的程式碼

流程控制

if ( 今天出大太陽 ) {
  出去玩一波大的;
} else {
  在宿舍睡一波大的;
}

流程控制

if ( condition 1 ) {
  // ...
} else if ( condition 2 ) {
  // ...
} else {
  // ...
}

如果 condition 1 成立,那就執行 condition 1 中的程式碼

如果不成立,則檢查 condition 2 是否成立

如果成立則執行 condition 2 中的程式碼

若 condition 1 和 2 都不成立,則執行 else 中的程式碼

流程控制

if ( 今天出大太陽 ) {
  出去完一波大的;
} else if ( 明天要考試 ) {
  去圖書館讀書;
} else {
  在宿舍睡一波大的;
}

流程控制

  • 順序必須為 if - else if - else
  • else if 可以有很多個
  • if、else 只能各有一個
if ( ... ) {
  
} else if ( ... ) {
  
} else if ( ... ){

} else {

}

流程控制

if ( condition 1 ) {
  if ( condition 2 ) {
  
  } else {
  
  }
}

流程控制

if ( 今天出大太陽 ) {
  if ( 今天有放假 ) {
    直接玩個兩天;
  } else {
    去動物園看紅毛猩猩;
  }
}

流程控制

運算子 名稱
== 等於
!= 不等於
>= 大於等於
<= 小於等於
> 大於
< 小於

邏輯運算子

流程控制

邏輯運算子

int x = 1;
x == 1 (true)
x >= 1 (true)
x > 1 (false)
x != 2 (true)
x <= 10 (true)

流程控制

邏輯運算子

運算子 名稱
&&
||
! 否定

流程控制

邏輯運算子

流程控制

邏輯運算子

A B A && B
True True True
True False False
False True False
False False False

流程控制

邏輯運算子

A B A || B
True True True
True False True
False True True
False False False

流程控制

邏輯運算子

A !A
True False
False True

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( (1) ) {
    background(red);
  } else if ( (2) ) {
    background(green);
  } else if ( (3) ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}
0 <= mouseX < 300
300 <= mouseX < 600
600 <= mouseX < 900

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( 0 <= mouseX < 300 ) {
    background(red);
  } else if ( 300 <= mouseX < 600 ) {
    background(green);
  } else if ( 600 <= mouseX < 900 ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}
0 <= mouseX < 300
300 <= mouseX < 600
600 <= mouseX < 900

流程控制

0 <= mouseX < 300
300 <= mouseX < 600
600 <= mouseX < 900
color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( 0 <= mouseX < 300 ) {
    background(red);
  } else if ( 300 <= mouseX < 600 ) {
    background(green);
  } else if ( 600 <= mouseX < 900 ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( (1) ) {
    background(red);
  } else if ( (2) ) {
    background(green);
  } else if ( (3) ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}
0 <= mouseX && mouseX < 300
300 <= mouseX && mouseX < 600
600 <= mouseX && mouseX < 900

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( 0 <= mouseX && mouseX < 300 ) {
    background(red);
  } else if ( 300 <= mouseX && mouseX < 600 ) {
    background(green);
  } else if ( 600 <= mouseX && mouseX < 900 ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}
0 <= mouseX && mouseX < 300
300 <= mouseX && mouseX < 600
600 <= mouseX && mouseX < 900

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( 0 <= mouseX && mouseX < 300 ) {
    background(red);
  } else if ( 300 <= mouseX && mouseX < 600 ) {
    background(green);
  } else if ( 600 <= mouseX && mouseX < 900 ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}

可以更簡化嗎?

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( mouseX < 300 ) {
    background(red);
  } else if ( mouseX < 600 ) {
    background(green);
  } else if ( mouseX < 900 ){
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}
mouseX < 300
mouseX < 600
mouseX < 900

流程控制

color red   = color(255, 0, 0);
color green = color(0, 255, 0);
color blue  = color(0, 0, 255);

void setup(){
  size(900, 900);
  strokeWeight(5); // 長方形線寬
}

void draw(){
  if ( mouseX < 300 ) {
    background(red);
  } else if ( mouseX < 600 ) {
    background(green);
  } else {
    background(blue);
  }
  line(300, 0, 300, 900);
  line(600, 0, 600, 900);
}

流程控制

小畫家!

流程控制

void setup(){
  size(800, 600); // 設定寬度為 800 pixel、長度為 600 pixel
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 筆畫寬度
}

void draw(){
  fill(0, 0, 0);
  if(mousePressed){
    // YOUR CODE HERE //
  }
}

流程控制

流程控制

void setup(){
  size(800, 600); // 設定寬度為 800 pixel、長度為 600 pixel
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 筆畫寬度
}

void draw(){
  fill(0, 0, 0);
  if(mousePressed){
    // YOUR CODE HERE //
  }
}
(A) rect(mouseX, mouseY, 5, 5);
(B) circle(mouseX, mouseY, 5);
(C) line(0, 0, mouseX, mouseY);
(D) line(pmouseX, pmouseY, mouseX, mouseY);

流程控制

void setup(){
  size(800, 600); // 設定寬度為 800 pixel、長度為 600 pixel
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 筆畫寬度
}

void draw(){
  fill(0, 0, 0);
  if(mousePressed){
    // YOUR CODE HERE //
  }
}
(A) rect(mouseX, mouseY, 5, 5);
(B) circle(mouseX, mouseY, 5);
(C) line(0, 0, mouseX, mouseY);
(D) line(pmouseX, pmouseY, mouseX, mouseY);

流程控制

流程控制

(pmouseX, pmouseY)
(mouseX, mouseY)

流程控制

增加橡皮擦的功能

流程控制

void setup(){
  size(800, 600);
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 寬度
}

void draw(){
  if( mousePressed && ??? ){
    stroke(0, 0, 0);
    strokeWeight(4);
    line(pmouseX, pmouseY, mouseX, mouseY);
  } else if( mousePressed && ??? ){
    stroke(255, 255, 255);
    strokeWeight(20);
    line(pmouseX, pmouseY, mouseX, mouseY);
  }
}

流程控制

流程控制

流程控制

void setup(){
  size(800, 600);
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 寬度
}

void draw(){
  if( mousePressed && mouseButton == LEFT ){
    stroke(0, 0, 0);
    strokeWeight(4);
    line(pmouseX, pmouseY, mouseX, mouseY);
  } else if( mousePressed && mouseButton == RIGHT ){
    stroke(255, 255, 255);
    strokeWeight(20);
    line(pmouseX, pmouseY, mouseX, mouseY);
  }
}

流程控制

如果要在小畫家上加一個指標

流程控制

void setup(){
  size(800, 600);
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 寬度
}

void draw(){
  if(mousePressed && mouseButton == LEFT){
    strokeWeight(4);
    stroke(0, 0, 0);
    line(pmouseX, pmouseY, mouseX, mouseY);
  } else if(mousePressed && mouseButton == RIGHT){
    stroke(255, 255, 255);
    strokeWeight(20);
    line(pmouseX, pmouseY, mouseX, mouseY);
  }
  strokeWeight(2);
  line(mouseX - 10, mouseY, mouseX + 10, mouseY);
  line(mouseX, mouseY - 10, mouseX, mouseY + 10);
}

流程控制

流程控制

void setup(){
  size(800, 600);
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(4); // 寬度
}

void draw(){
  background(255, 255, 255);
  if(mousePressed && mouseButton == LEFT){
    strokeWeight(4);
    stroke(0, 0, 0);
    line(pmouseX, pmouseY, mouseX, mouseY);
  } else if(mousePressed && mouseButton == RIGHT){
    stroke(255, 255, 255);
    strokeWeight(20);
    line(pmouseX, pmouseY, mouseX, mouseY);
  }
  strokeWeight(2);
  line(mouseX - 10, mouseY, mouseX + 10, mouseY);
  line(mouseX, mouseY - 10, mouseX, mouseY + 10);
}

流程控制

把滑鼠的座標存下來,每次都重新畫

流程控制

把滑鼠的座標存下來,每次都重新畫

每個座標都宣告兩個變數存

流程控制

把滑鼠的座標存下來,每次都重新畫

可能有上萬個座標

流程控制

把滑鼠的座標存下來,每次都重新畫

陣列 (Array) !

流程控制

陣列 (Array)

10
int x = 10;

流程控制

陣列 (Array)

int x1 = 10;
int x2 = 15;
int x3 = 21;
int x4 = 17;
int x5 = 18;

10
15
21
17
18

流程控制

陣列 (Array)

int[] x = new int[5];
10 15 21 17 18
x[0]
x[1]
x[2]
x[3]
x[4]

流程控制

陣列 (Array)

int[] x = new int[5];

資料型態

[] 代表陣列

變數名稱

一個 "新" 的陣列

陣列中有幾個變數

流程控制

For 迴圈

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

初始

執行條件

每次進行一次迴圈的操作

流程控制

For 迴圈

void setup() {
  int[] x = {1, 2, 3, 4, 5};
  for(int i=0;i<x.length;i++){
    println(x[i]);
  }
}

void draw(){
  // pass
}
可以使用 x.length 拿到陣列的大小

流程控制

int[] px = new int[10000];
int[] py = new int[10000];
int[] x = new int[10000];
int[] y = new int[10000];
int idx = 0;

void setup(){
  size(800, 600);
  background(255, 255, 255); // R, G, B
  stroke(0, 0, 0); // R, G, B
  strokeWeight(5); // 寬度
  noFill();
  noCursor(); // 不顯示滑鼠鼠標
}

void draw(){
  background(255, 255, 255); // R, G, B
  if(mousePressed){
    px[idx] = pmouseX;
    py[idx] = pmouseY;
    x[idx] = mouseX;
    y[idx] = mouseY;
    idx = idx + 1;
  }
  for(int i = 0; i < idx; i++) {
    strokeWeight(5);
    line(px[i], py[i], x[i], y[i]);
  }
  strokeWeight(2);
  line(mouseX - 10, mouseY, mouseX + 10, mouseY);
  line(mouseX, mouseY - 10, mouseX, mouseY + 10);
}

Lecture 2

Flappy Bird

Flappy Bird

Flappy Bird

鳥往右飛

Flappy Bird

鳥往右飛

水管往左跑

鳥在同一個 x 座標上上下移動

Flappy Bird

水管往左跑

pillar[] p = new pillar[3];
boolean end = false;
boolean intro = true;
int score = 0;

PImage bg, bird, pillar_up, pillar_down;

void setup() {
  bg = loadImage("background.jpg");
  bird = loadImage("bird.png");
  pillar_up = loadImage("pillar_up.png");
  pillar_down = loadImage("pillar_down.png");
  bg.resize(500, 800);
  size(500, 800);
  for (int i = 0; i < 3; i++) {
    p[i] = new pillar(i);
  }
}

void draw() {
  background(bg);
  for(int i=0;i<3;i++){
    p[i].drawPillar();
  }
  for(int i=0;i<3;i++){
    p[i].xPos -= 2;
  }
}

class pillar {
  float xPos, opening;
  pillar(int i){
    xPos = 100 + i * 200;
    opening = 400;
  }
  void drawPillar() {
    imageMode(CENTER);
    image(pillar_up, xPos, opening - 100 - 350, 40, 700);
    image(pillar_down, xPos, opening + 100 + 350, 40, 700);
  }
}

Flappy Bird

opening

100 px

100 px

opening_half_width

顯示柱子

Flappy Bird

opening

100 px

100 px

350 px

中心點

顯示柱子

Flappy Bird

pillar[] p = new pillar[3];
boolean end = false;
boolean intro = true;
int score = 0;

PImage bg, bird, pillar_up, pillar_down;

void setup() {
  bg = loadImage("background.jpg");
  bird = loadImage("bird.png");
  pillar_up = loadImage("pillar_up.png");
  pillar_down = loadImage("pillar_down.png");
  bg.resize(500, 800);
  size(500, 800);
  for (int i = 0; i < 3; i++) {
    p[i] = new pillar(i);
  }
}

void draw() {
  background(bg);
  for(int i=0;i<3;i++){
    p[i].drawPillar();
  }
  for(int i=0;i<3;i++){
    p[i].xPos -= 2;
  }
}

class pillar {
  float xPos, opening;
  pillar(int i){
    xPos = 100 + i * 200;
    opening = random(400) + 200;
  }
  void drawPillar() {
    imageMode(CENTER);
    image(pillar_up, xPos, opening - 100 - 350, 40, 700);
    image(pillar_down, xPos, opening + 100 + 350, 40, 700);
  }
}

水管往左跑

Flappy Bird

水管往左跑

pillar[] p = new pillar[3];
boolean end = false;
boolean intro = true;
int score = 0;

PImage bg, bird, pillar_up, pillar_down;

void setup() {
  bg = loadImage("background.jpg");
  bird = loadImage("bird.png");
  pillar_up = loadImage("pillar_up.png");
  pillar_down = loadImage("pillar_down.png");
  bg.resize(500, 800);
  size(500, 800);
  for (int i = 0; i < 3; i++) {
    p[i] = new pillar(i);
  }
}

void draw() {
  background(bg);
  for(int i=0;i<3;i++){
    p[i].drawPillar();
  }
  for(int i=0;i<3;i++){
    p[i].xPos -= 2;
    p[i].checkPosition();
  }
}

class pillar {
  float xPos, opening;
  pillar(int i){
    xPos = 100 + i * 200;
    opening = random(400) + 100;
  }
  void drawPillar() {
    imageMode(CENTER);
    image(pillar_up, xPos, opening - 100 - 350, 40, 700);
    image(pillar_down, xPos, opening + 100 + 350, 40, 700);
  }
  void checkPosition() {
    if(xPos < -10){
      xPos = xPos + 600;
      opening = random(400) + 100;
    }
  }
}

Flappy Bird

水管往左跑

pillar[] p = new pillar[3];
bird b = new bird();
boolean end = false;
boolean intro = true;
int score = 0;

PImage bg, bird, pillar_up, pillar_down;

void setup() {
  bg = loadImage("background.jpg");
  bird = loadImage("bird.png");
  pillar_up = loadImage("pillar_up.png");
  pillar_down = loadImage("pillar_down.png");
  bg.resize(500, 800);
  size(500, 800);
  for (int i = 0; i < 3; i++) {
    p[i] = new pillar(i);
  }
}

void draw() {
  background(bg);
  if(mousePressed || keyPressed){
    b.jump();
    intro = false;      
  }
  if (end == false) {
    b.move();
  }
  b.drawBird();
  if (end == false) {
    b.drag();
  }
  for(int i=0;i<3;i++){
    p[i].drawPillar();
  }
  for(int i=0;i<3;i++){
    p[i].xPos -= 2;
    p[i].checkPosition();
  }
}

class pillar {
  float xPos, opening;
  pillar(int i){
    xPos = 100 + i * 200;
    opening = random(400) + 100;
  }
  void drawPillar() {
    imageMode(CENTER);
    image(pillar_up, xPos, opening - 100 - 350, 40, 700);
    image(pillar_down, xPos, opening + 100 + 350, 40, 700);
  }
  void checkPosition() {
    if(xPos < -10){
      xPos = xPos + 600;
      opening = random(400) + 100;
    }
  }
}

class bird {
  float xPos, yPos, ySpeed;
  bird() {
    xPos = 200;
    yPos = 400;
  }
  void drawBird() {
    image(bird, xPos, yPos, 60, 60);
  }
  void jump() {
    ySpeed = -10;
  }
  void drag() {
    ySpeed += 0.4;
  }
  void move() {
    yPos += ySpeed;
    for (int i = 0; i < 3; i++) {
      p[i].xPos -= 3;
    }
  }
}

Flappy Bird

碰撞檢測

opening

100 px

100 px

40 px

Flappy Bird

碰撞檢測

100 px

100 px

40 px

Flappy Bird

碰撞檢測

100 px

100 px

40 px

Flappy Bird

碰撞檢測

100 px

100 px

40 px

Safe!

Flappy Bird

碰撞檢測

100 px

100 px

40 px

Flappy Bird

碰撞檢測

100 px

100 px

40 px

Flappy Bird

碰撞檢測

100 px

100 px

40 px

(xPos, yPos)

Flappy Bird

碰撞檢測

100 px

100 px

40 px

  • 如果鳥在水管的左右範圍
  • 且碰到上下其中一個水管

(xPos, yPos)

Flappy Bird

碰撞檢測

100 px

100 px

40 px

(xPos, yPos)

  • pillar[i].pos - 20 <= xPos && xPos <= pillar[i].pos + 20
  • 且碰到上下其中一個水管

Flappy Bird

碰撞檢測

100 px

100 px

40 px

(xPos, yPos)

  • pillar[i].pos - 20 <= xPos && xPos <= pillar[i].pos + 20
  • yPos <= pillar[i].opening - opening_half_width || yPos >= pillar[i].opening + opening_half_width

Flappy Bird

碰撞檢測

100 px

100 px

40 px

(xPos, yPos)

if((pillar[i].pos - 20 <= xPos && xPos <= pillar[i].pos + 20) && (yPos < p[i].opening - opening_half_width || yPos > p[i].opening + opening_half_width )){
  // collide!
}

陽明交大探索體驗營 教案

By jayinnn_nycu

陽明交大探索體驗營 教案

  • 471