系統名稱: 傳奇戰役 (Rise of The Argonauts)
目的:
能夠單純使用一支手控制、遊玩一個2D橫軸的遊戲,能夠控制英雄在眾多怪獸中生存,依據殺敵數量不同而得到不同的分數。並能夠在排行榜中爭取高分!
遊戲畫面:
開始畫面(按下即可開始)
進入遊戲畫面,怪物一定間格時間會產生一隻,並隨機產生其中一種及方向
攻擊畫面,成功擊殺怪物分數增加
可以跳躍迴避攻擊
受到攻擊時,左上角的血量會減少
成績排行(白色代表你當次遊戲的成績)
遊戲設備介紹及控制方法:
控制手套(正面)
控制手套(背面)
以下同時為控制介紹:
正面(同時為遊戲初始狀態,靜止不動)
控制人物左移
控制人物右移
紅色按鈕為攻擊
附註:手向上甩,人物跳躍
如何製作:
環境:
作業系統:Windows 7
硬體主機板:Arduino
軟體撰寫:Processing(Java) + Arduino(C)
製作重點:
遊戲分為main、Hero Class以及Monster Class,主要撰寫的部分
是Class。在那二個Class中分別記錄大小、生命值、座標、方向、
向上跳躍的向量以及攻擊力及攻擊間隔,再各別撰寫函式去控制
。
。
而Serial傳遞數值的部分全部放在serialControl()函數裡面,以便
於撰寫及控制。排行部分則是使用reader and writer去讀取以及寫檔
。
程式碼:
Arduino:
#include <string.h>
int btn_left = 2;
int btn_right = 3;
int btn_atk = 4;
int past_leftState =1;
int past_rightState = 1;
int past_atkState = 1;
void setup() {
Serial.begin(9600);
pinMode(btn_left, INPUT_PULLUP);
pinMode(btn_right, INPUT_PULLUP);
pinMode(btn_atk, INPUT_PULLUP);
}
void loop(){
int leftState = digitalRead(btn_left);
int rightState = digitalRead(btn_right);
int atkState = digitalRead(btn_atk);
if(past_leftState != leftState) Serial.print(0);
if(past_rightState != rightState) Serial.print(1);
if(past_atkState != atkState && atkState == 0) Serial.print(2);
past_leftState = leftState ;
past_rightState = rightState ;
past_atkState = atkState ;
delay(10); // delay in between reads for stability
}
Processing
main
import processing.serial.*;
import java.io.*;
import java.util.*;
import ddf.minim.*;
import java.util.Arrays;
//define
final static int SIZE = 3;
final static int ATK_TIME = 15;
//file process about (in fact , is about rank )
BufferedReader rank;
PrintWriter rankin;
//Music about
Minim minim;
AudioPlayer groove,p;
//Serial
Serial myPort;
//linked list
List<monsterClass> lt;
//hero class
heroClass hero = new heroClass(50,75);
//control kind of avtivity
boolean[] ctl = new boolean[SIZE] ;
//Number Image
PImage[] num = new PImage[10];
//back ground img
PImage img_bg_game = loadImage(basicPath + "background\\gameBg.png");
PImage img_start = loadImage(basicPath + "background\\start.jpg");
//parameter
int ctlEnd = 0;
int grade=0;
int count;
int monsterNumber=0;
int nowRunFrame=0;
int monsterNewTime=50;
int dtime = 0;
//0:: game , 1:: rank , 2::start
int type = 2;
void setup()
{
size(640, 480);
//load music
minim = new Minim(this);
groove = minim.loadFile(basicPath + "sound\\1.mp3", 512);
p = minim.loadFile(basicPath + "sound\\atk.mp3", 512);
groove.loop();
//initialize
lt = new LinkedList<monsterClass>();
myPort = new Serial(this,"COM3", 9600);
for(int i=0;i<SIZE;i++) ctl[i] = false;
for(int i=0;i<10;i++) num[i] = loadImage(basicPath + "number\\" + i + "b.png");
}
void draw()
{
if(type == 0){
ctlEnd = 0 ;
//contorl monster create time
if(++nowRunFrame>monsterNewTime){
monsterNewTime = 50;
//add to list
monsterClass m = new monsterClass(50,75,(int)random(0,199.99));
lt.add(m);
monsterNumber++;
nowRunFrame=0;
}
image(img_bg_game,0,0);
fill(255,0,0);
rect(0,0,hero.getHealth()*2,50);
//show hero
hero.showImage();
//show grade
showGrade();
//detector monsters motion and attack
for(int i=0;i<lt.size();i++){
lt.get(i).move(hero.getPoint());
lt.get(i).showImage();
hero.setHealth(lt.get(i).atkDetector(hero.getPoint()));
if(hero.getHealth() <=0) type =1;
}
//serial control about
serialControl();
if(count>0) grade += hero.atk(lt);
//control attack img show time
count--;
}
else if(type == 2 ){
serialControl();
image(img_start,0,0,640,480);
dtime--;
}
else{
dtime--;
serialControl();
background(0);
rank=createReader(basicPath + "data\\rank.txt");
int[] rankArr = new int[11];
for(int i=0;i<10;i++){
try{
rankArr[i] = int(rank.readLine());
println(rankArr[i]);
}
catch (IOException e) {
e.printStackTrace();
}
}
rankArr[10] = grade;
Arrays.sort(rankArr);
for(int k=1;k<11;k++){
int temp=rankArr[k]*10;
fill(255);
if(grade == rankArr[k]) rect(650-240-k*25-5,100+(9-k)*35,230,35);
image(num[10-k],650-240-k*30-60,100+(9-k)*35,50,50);
for(int i=3;i>=0;i--)
image(num[(temp/=10)%10],650-60*(4-i)-k*25,100+(9-k)*35,40,40);
}
if(ctlEnd == 1 && dtime<=0){
rankin=createWriter(basicPath + "data\\rank.txt");
for(int i=1;i<11;i++) rankin.println(rankArr[i]);
rankin.flush();
rankin.close();
type = 2;
for(int i=0;i<lt.size();i++) lt.remove(i--);
hero.setHealth(100);
grade = 0;
dtime = 500;
}
}
}
void showGrade()
{
int temp=grade*10;
for(int i=3;i>=0;i--)
image(num[(temp/=10)%10],640-60*(4-i),0,60,60);
}
void serialControl()
{
int temp;
if ( myPort.available() > 0){
temp =myPort.read();
//If btn push is attack
if((temp - 48) == 2){
if(type == 1 ) ctlEnd = 1;
else if(type == 2 && dtime <= 0){
type = 0;
dtime = 500;
}
else if(type== 0){
grade += hero.atk(lt);
count=ATK_TIME;
p.play(0);
}
}
else ctl[temp-48] = !ctl[temp-48];
}
// if left and right together is jump
if(ctl[0] == true && ctl[1] == true) hero.setJump(17);
//left
else if(ctl[0] == true){
hero.setPoint(hero.getPoint().x-3,hero.getPoint().y);
hero.setState(FACE_LEFT);
}
//right
else if(ctl[1] == true){
hero.setPoint(hero.getPoint().x+3,hero.getPoint().y);
hero.setState(FACE_RIGHT);
}
}
//Keyboard use
void keyPressed() {
if (key == CODED) {
if (keyCode == RIGHT || ctl[1] == true) {
hero.setPoint(hero.getPoint().x+3,hero.getPoint().y);
hero.setState(FACE_RIGHT);
}
else if (keyCode == LEFT ) {
hero.setPoint(hero.getPoint().x-3,hero.getPoint().y);
hero.setState(FACE_LEFT);
}
else if(keyCode == UP){
hero.setJump(17);
}
else if(keyCode == DOWN){
grade += hero.atk(lt);
count=ATK_TIME;
p.play(0);
}
}
}
class
final static String basicPath = "D:\\修\\學校課業\\大三\\互動技術\\期末作業\\game\\";
final static int ATK_DURING = 100;
//This class use to save site and size ( 2D information )
class Index2D
{
public int x;
public int y;
public Index2D(int x,int y)
{
this.x = x;
this.y = y;
}
};
//define :: To make me more easy to know
final static int FACE_RIGHT = 1;
final static int FACE_LEFT = 0;
class heroClass
{
private Index2D point,size;
private int health ;
private int state ; //Face 0 :: left , 1 :: right
private PImage img,img_mirro ;
private PImage atk,atk_mirro ;
private int w,h;
private int vector;
private boolean lock;
public heroClass(int w,int h)
{
img = loadImage(basicPath + "role\\hero.png");
img_mirro= loadImage(basicPath + "role\\hero_mirro.png");
atk = loadImage(basicPath + "role\\attack.png");
atk_mirro= loadImage(basicPath + "role\\attack_mirro.png");
point = new Index2D(320-w,350-h);
size = new Index2D(w,h);
state = vector = 0;
lock = false;
health = 100;
}
public void setHealth(int x)
{
health += x ;
}
public int getHealth()
{
return health;
}
public PImage getImage()
{
return img;
}
public Index2D getPoint()
{
return point;
}
public Index2D getSize()
{
return size;
}
public void showImage()
{
point.y -= vector;
//Jump parameter
if(point.y +size.y!=350){
vector-=1;
lock = true;
}else{
vector = 0;
lock = false ;
}
//do not over the window board
point.x = point.x < 0 ? 0 : point.x;
point.x = point.x > 640-size.x ? 640-size.x : point.x;
//control face which site
if(state == FACE_LEFT ) image(img,point.x,point.y,size.x,size.y);
else image(img_mirro,point.x,point.y,size.x,size.y);
}
public void setPoint(int x , int y)
{
point.x = x;
point.y = y;
}
public void setState(int type)
{
state = type;
}
public void setJump(int h)
{
if(lock == false ) vector = h ;
}
public int atk(List<monsterClass> lt)
{
//return value is kill number and will add to grade
int tmp;
int killNum = 0;
if(state == FACE_LEFT ) image(atk,point.x-size.x,point.y,size.x,size.y);
else image(atk_mirro,point.x+size.x,point.y,size.x,size.y);
for(int i=0;i<lt.size();i++){
//get monster's x site
tmp =lt.get(i).getPoint().x;
if(state == FACE_LEFT){
//if is in range reduce their life point
if(tmp >= point.x-size.x && tmp <= point.x){
lt.get(i).setHealth(-5);
if( lt.get(i).getHealth()<=0){
lt.remove(i--);
killNum++;
}
}
}
else{
if(tmp >= point.x && tmp <= point.x+size.x){
lt.get(i).setHealth(-50);
if( lt.get(i).getHealth()<=0){
lt.remove(i--);
killNum++;
}
}
}
}
return killNum;
}
};
class monsterClass
{
private Index2D point,size;
private int health ;
private int state ; //Face 0 :: left , 1 :: right
private PImage img,img_mirro ;
private PImage atk;
private int w,h;
private int type;
private int during,atkPower; //during is how long will attack hero
private boolean lock ;
private int count;
public monsterClass(int w,int h,int t)
{
count = 0;
lock = false;
//t use to decide which kind monster will appear and their parameter
if( t < 10){
img = loadImage(basicPath + "role\\monster.png");
img_mirro= loadImage(basicPath + "role\\monster_mirro.png");
atk = loadImage(basicPath + "role\\matk.png");
health = (int)random(200,1000.99);
during = 40;
atkPower = -25;
type = 0;
}
else{
img = loadImage(basicPath + "role\\monster2.png");
img_mirro= loadImage(basicPath + "role\\monster2_mirro.png");
atk = loadImage(basicPath + "role\\matk.png");
health = 50;
during = 30;
atkPower = -5;
type = 1;
}
//decide which site will appear
if(t%2 == 1) state = FACE_LEFT;
else state = FACE_RIGHT;
if(state == FACE_LEFT) point = new Index2D(640,350-h);
else point = new Index2D(0-w,350-h);
//if is a stronge monster will become bigger;
if(type == 0){
size = new Index2D(w*2,h*2);
point.x -= w;
point.y -= h;
}
else size = new Index2D(w,h);
}
public void setHealth(int x)
{
health+=x;
}
public int getHealth()
{
return health;
}
public Index2D getPoint()
{
return point;
}
public void move(Index2D hero)
{
if(lock == false){
if (point.x < hero.x ) state = FACE_RIGHT ;
else state = FACE_LEFT ;
if(state == FACE_LEFT ){
if(type == 0) point.x -= 1;
else point.x-=2;
}
else{
if(type == 0) point.x += 1;
else point.x+=2;
}
}
}
public int atkDetector(Index2D hero)
{
//detector is hero in the attack range
//if yes !! will increase the during time
//when is over the threshold will attack and do not miss!! XD
if(hero.y >= point.y-5){
if(state == FACE_LEFT) {
if(hero.x > point.x - size.x && hero.x < point.x){
during++;
lock = true;
}
else lock = false;
}
else{
if(hero.x < point.x+size.x && hero.x > point.x){
during++;
lock = true;
}
else lock = false;
}
if(during > ATK_DURING){
during = 0;
count = 12;
return atkPower;
}
else return 0;
}
else return 0;
}
public void showImage()
{
if(state == FACE_LEFT ) image(img,point.x,point.y,size.x,size.y);
else image(img_mirro,point.x,point.y,size.x,size.y);
if(count-->0) atk();
}
public void atk()
{
if(state == FACE_LEFT ) image(atk,point.x-size.x,point.y,size.x,size.y);
else image(atk,point.x+size.x,point.y,size.x,size.y);
}
};
#include <string.h> int btn_left = 2; int btn_right = 3; int btn_atk = 4; int past_leftState =1; int past_rightState = 1; int past_atkState = 1; void setup() { Serial.begin(9600); pinMode(btn_left, INPUT_PULLUP); pinMode(btn_right, INPUT_PULLUP); pinMode(btn_atk, INPUT_PULLUP); } void loop(){ int leftState = digitalRead(btn_left); int rightState = digitalRead(btn_right); int atkState = digitalRead(btn_atk); if(past_leftState != leftState) Serial.print(0); if(past_rightState != rightState) Serial.print(1); if(past_atkState != atkState && atkState == 0) Serial.print(2); past_leftState = leftState ; past_rightState = rightState ; past_atkState = atkState ; delay(10); // delay in between reads for stability }
Processing
main
import processing.serial.*;
import java.io.*;
import java.util.*;
import ddf.minim.*;
import java.util.Arrays;
//define
final static int SIZE = 3;
final static int ATK_TIME = 15;
//file process about (in fact , is about rank )
BufferedReader rank;
PrintWriter rankin;
//Music about
Minim minim;
AudioPlayer groove,p;
//Serial
Serial myPort;
//linked list
List<monsterClass> lt;
//hero class
heroClass hero = new heroClass(50,75);
//control kind of avtivity
boolean[] ctl = new boolean[SIZE] ;
//Number Image
PImage[] num = new PImage[10];
//back ground img
PImage img_bg_game = loadImage(basicPath + "background\\gameBg.png");
PImage img_start = loadImage(basicPath + "background\\start.jpg");
//parameter
int ctlEnd = 0;
int grade=0;
int count;
int monsterNumber=0;
int nowRunFrame=0;
int monsterNewTime=50;
int dtime = 0;
//0:: game , 1:: rank , 2::start
int type = 2;
void setup()
{
size(640, 480);
//load music
minim = new Minim(this);
groove = minim.loadFile(basicPath + "sound\\1.mp3", 512);
p = minim.loadFile(basicPath + "sound\\atk.mp3", 512);
groove.loop();
//initialize
lt = new LinkedList<monsterClass>();
myPort = new Serial(this,"COM3", 9600);
for(int i=0;i<SIZE;i++) ctl[i] = false;
for(int i=0;i<10;i++) num[i] = loadImage(basicPath + "number\\" + i + "b.png");
}
void draw()
{
if(type == 0){
ctlEnd = 0 ;
//contorl monster create time
if(++nowRunFrame>monsterNewTime){
monsterNewTime = 50;
//add to list
monsterClass m = new monsterClass(50,75,(int)random(0,199.99));
lt.add(m);
monsterNumber++;
nowRunFrame=0;
}
image(img_bg_game,0,0);
fill(255,0,0);
rect(0,0,hero.getHealth()*2,50);
//show hero
hero.showImage();
//show grade
showGrade();
//detector monsters motion and attack
for(int i=0;i<lt.size();i++){
lt.get(i).move(hero.getPoint());
lt.get(i).showImage();
hero.setHealth(lt.get(i).atkDetector(hero.getPoint()));
if(hero.getHealth() <=0) type =1;
}
//serial control about
serialControl();
if(count>0) grade += hero.atk(lt);
//control attack img show time
count--;
}
else if(type == 2 ){
serialControl();
image(img_start,0,0,640,480);
dtime--;
}
else{
dtime--;
serialControl();
background(0);
rank=createReader(basicPath + "data\\rank.txt");
int[] rankArr = new int[11];
for(int i=0;i<10;i++){
try{
rankArr[i] = int(rank.readLine());
println(rankArr[i]);
}
catch (IOException e) {
e.printStackTrace();
}
}
rankArr[10] = grade;
Arrays.sort(rankArr);
for(int k=1;k<11;k++){
int temp=rankArr[k]*10;
fill(255);
if(grade == rankArr[k]) rect(650-240-k*25-5,100+(9-k)*35,230,35);
image(num[10-k],650-240-k*30-60,100+(9-k)*35,50,50);
for(int i=3;i>=0;i--)
image(num[(temp/=10)%10],650-60*(4-i)-k*25,100+(9-k)*35,40,40);
}
if(ctlEnd == 1 && dtime<=0){
rankin=createWriter(basicPath + "data\\rank.txt");
for(int i=1;i<11;i++) rankin.println(rankArr[i]);
rankin.flush();
rankin.close();
type = 2;
for(int i=0;i<lt.size();i++) lt.remove(i--);
hero.setHealth(100);
grade = 0;
dtime = 500;
}
}
}
void showGrade()
{
int temp=grade*10;
for(int i=3;i>=0;i--)
image(num[(temp/=10)%10],640-60*(4-i),0,60,60);
}
void serialControl()
{
int temp;
if ( myPort.available() > 0){
temp =myPort.read();
//If btn push is attack
if((temp - 48) == 2){
if(type == 1 ) ctlEnd = 1;
else if(type == 2 && dtime <= 0){
type = 0;
dtime = 500;
}
else if(type== 0){
grade += hero.atk(lt);
count=ATK_TIME;
p.play(0);
}
}
else ctl[temp-48] = !ctl[temp-48];
}
// if left and right together is jump
if(ctl[0] == true && ctl[1] == true) hero.setJump(17);
//left
else if(ctl[0] == true){
hero.setPoint(hero.getPoint().x-3,hero.getPoint().y);
hero.setState(FACE_LEFT);
}
//right
else if(ctl[1] == true){
hero.setPoint(hero.getPoint().x+3,hero.getPoint().y);
hero.setState(FACE_RIGHT);
}
}
//Keyboard use
void keyPressed() {
if (key == CODED) {
if (keyCode == RIGHT || ctl[1] == true) {
hero.setPoint(hero.getPoint().x+3,hero.getPoint().y);
hero.setState(FACE_RIGHT);
}
else if (keyCode == LEFT ) {
hero.setPoint(hero.getPoint().x-3,hero.getPoint().y);
hero.setState(FACE_LEFT);
}
else if(keyCode == UP){
hero.setJump(17);
}
else if(keyCode == DOWN){
grade += hero.atk(lt);
count=ATK_TIME;
p.play(0);
}
}
}
class
final static String basicPath = "D:\\修\\學校課業\\大三\\互動技術\\期末作業\\game\\";
final static int ATK_DURING = 100;
//This class use to save site and size ( 2D information )
class Index2D
{
public int x;
public int y;
public Index2D(int x,int y)
{
this.x = x;
this.y = y;
}
};
//define :: To make me more easy to know
final static int FACE_RIGHT = 1;
final static int FACE_LEFT = 0;
class heroClass
{
private Index2D point,size;
private int health ;
private int state ; //Face 0 :: left , 1 :: right
private PImage img,img_mirro ;
private PImage atk,atk_mirro ;
private int w,h;
private int vector;
private boolean lock;
public heroClass(int w,int h)
{
img = loadImage(basicPath + "role\\hero.png");
img_mirro= loadImage(basicPath + "role\\hero_mirro.png");
atk = loadImage(basicPath + "role\\attack.png");
atk_mirro= loadImage(basicPath + "role\\attack_mirro.png");
point = new Index2D(320-w,350-h);
size = new Index2D(w,h);
state = vector = 0;
lock = false;
health = 100;
}
public void setHealth(int x)
{
health += x ;
}
public int getHealth()
{
return health;
}
public PImage getImage()
{
return img;
}
public Index2D getPoint()
{
return point;
}
public Index2D getSize()
{
return size;
}
public void showImage()
{
point.y -= vector;
//Jump parameter
if(point.y +size.y!=350){
vector-=1;
lock = true;
}else{
vector = 0;
lock = false ;
}
//do not over the window board
point.x = point.x < 0 ? 0 : point.x;
point.x = point.x > 640-size.x ? 640-size.x : point.x;
//control face which site
if(state == FACE_LEFT ) image(img,point.x,point.y,size.x,size.y);
else image(img_mirro,point.x,point.y,size.x,size.y);
}
public void setPoint(int x , int y)
{
point.x = x;
point.y = y;
}
public void setState(int type)
{
state = type;
}
public void setJump(int h)
{
if(lock == false ) vector = h ;
}
public int atk(List<monsterClass> lt)
{
//return value is kill number and will add to grade
int tmp;
int killNum = 0;
if(state == FACE_LEFT ) image(atk,point.x-size.x,point.y,size.x,size.y);
else image(atk_mirro,point.x+size.x,point.y,size.x,size.y);
for(int i=0;i<lt.size();i++){
//get monster's x site
tmp =lt.get(i).getPoint().x;
if(state == FACE_LEFT){
//if is in range reduce their life point
if(tmp >= point.x-size.x && tmp <= point.x){
lt.get(i).setHealth(-5);
if( lt.get(i).getHealth()<=0){
lt.remove(i--);
killNum++;
}
}
}
else{
if(tmp >= point.x && tmp <= point.x+size.x){
lt.get(i).setHealth(-50);
if( lt.get(i).getHealth()<=0){
lt.remove(i--);
killNum++;
}
}
}
}
return killNum;
}
};
class monsterClass
{
private Index2D point,size;
private int health ;
private int state ; //Face 0 :: left , 1 :: right
private PImage img,img_mirro ;
private PImage atk;
private int w,h;
private int type;
private int during,atkPower; //during is how long will attack hero
private boolean lock ;
private int count;
public monsterClass(int w,int h,int t)
{
count = 0;
lock = false;
//t use to decide which kind monster will appear and their parameter
if( t < 10){
img = loadImage(basicPath + "role\\monster.png");
img_mirro= loadImage(basicPath + "role\\monster_mirro.png");
atk = loadImage(basicPath + "role\\matk.png");
health = (int)random(200,1000.99);
during = 40;
atkPower = -25;
type = 0;
}
else{
img = loadImage(basicPath + "role\\monster2.png");
img_mirro= loadImage(basicPath + "role\\monster2_mirro.png");
atk = loadImage(basicPath + "role\\matk.png");
health = 50;
during = 30;
atkPower = -5;
type = 1;
}
//decide which site will appear
if(t%2 == 1) state = FACE_LEFT;
else state = FACE_RIGHT;
if(state == FACE_LEFT) point = new Index2D(640,350-h);
else point = new Index2D(0-w,350-h);
//if is a stronge monster will become bigger;
if(type == 0){
size = new Index2D(w*2,h*2);
point.x -= w;
point.y -= h;
}
else size = new Index2D(w,h);
}
public void setHealth(int x)
{
health+=x;
}
public int getHealth()
{
return health;
}
public Index2D getPoint()
{
return point;
}
public void move(Index2D hero)
{
if(lock == false){
if (point.x < hero.x ) state = FACE_RIGHT ;
else state = FACE_LEFT ;
if(state == FACE_LEFT ){
if(type == 0) point.x -= 1;
else point.x-=2;
}
else{
if(type == 0) point.x += 1;
else point.x+=2;
}
}
}
public int atkDetector(Index2D hero)
{
//detector is hero in the attack range
//if yes !! will increase the during time
//when is over the threshold will attack and do not miss!! XD
if(hero.y >= point.y-5){
if(state == FACE_LEFT) {
if(hero.x > point.x - size.x && hero.x < point.x){
during++;
lock = true;
}
else lock = false;
}
else{
if(hero.x < point.x+size.x && hero.x > point.x){
during++;
lock = true;
}
else lock = false;
}
if(during > ATK_DURING){
during = 0;
count = 12;
return atkPower;
}
else return 0;
}
else return 0;
}
public void showImage()
{
if(state == FACE_LEFT ) image(img,point.x,point.y,size.x,size.y);
else image(img_mirro,point.x,point.y,size.x,size.y);
if(count-->0) atk();
}
public void atk()
{
if(state == FACE_LEFT ) image(atk,point.x-size.x,point.y,size.x,size.y);
else image(atk,point.x+size.x,point.y,size.x,size.y);
}
};
小組分工:
Processing、Arduino、硬體部分:徐修謙
購買硬體:謝睿峰
沒有留言:
張貼留言