for Proce55ing
Pgk - Source code
(C) Kenta Cho(ABA."Saba")
Pgk.java
/**
* PGK wars.
*
* Copyright (C) 2004 Kenta Cho. Some rights reserved.
*
* @p5 description
* - 画面下の青い自機をマウスで操作してください
* - マウスボタンを押すと弾を発射します
* - 弾を画面中央のひし形に当てて画面上に押しやってください
* - すべてのひし形を中央より上に押しやるとあなたの勝ちです
* - 逆にすべてのひし形が中央より下にくると負けです
* - 弾に接触すると一定時間自機が操作できなくなります
*/
public class Pgk extends BApplet {
float BATTERY_SIZE = 10;
float BATTERY_FIRE_INTERVAL = 50;
Ship[] ship = new Ship[2];
int PLAYER = 0;
int COMPUTER = 1;
Battery[] battery = new Battery[10];
Bullet[] bullet = new Bullet[64];
Particle[] particle = new Particle[32];
BFont font;
int TITLE = 0;
int IN_GAME = 1;
int GAMEOVER = 2;
int state;
int winner;
Title title;
Gameover gameover;
void setup() {
size(200, 400);
framerate(30);
smooth();
cursor();
font = loadFont("OCR-A.vlw.gz");
textFont(font);
for (int i = 0; i < ship.length; i++)
ship[i] = new Ship();
ship[0].type = PLAYER;
ship[1].type = COMPUTER;
for (int i = 0; i < battery.length; i++)
battery[i] = new Battery();
for (int i = 0; i < bullet.length; i++)
bullet[i] = new Bullet();
for (int i = 0; i < particle.length; i++)
particle[i] = new Particle();
title = new Title();
gameover = new Gameover();
startTitle();
}
void startTitle() {
state = TITLE;
for (int i = 0; i < battery.length; i++) {
Battery bt = battery[i];
bt.start((int) random(BATTERY_FIRE_INTERVAL));
bt.pos.x = (i % 5) * (width / 5) + width / 10;
bt.pos.y = (i / 5) * (height / 4) + height / 8 * 3;
}
}
void startInGame() {
state = IN_GAME;
for (int i = 0; i < bullet.length; i++)
bullet[i].start();
for (int i = 0; i < ship.length; i++)
ship[i].start();
for (int i = 0; i < particle.length; i++)
particle[i].start();
}
void startGameover() {
state = GAMEOVER;
gameover.start();
}
void loop() {
background(80, 100, 50);
stroke(200, 255, 200);
line(0, height / 2, width, height / 2);
if (state == TITLE) {
for (int i = 0; i < battery.length; i++)
battery[i].loop();
title.loop();
} else if (state == IN_GAME) {
for (int i = 0; i < ship.length; i++)
ship[i].loop();
for (int i = 0; i < battery.length; i++)
battery[i].loop();
for (int i = 0; i < bullet.length; i++)
if (bullet[i].isExist)
bullet[i].loop();
for (int i = 0; i < particle.length; i++)
if (particle[i].cnt >= 0)
particle[i].loop();
if (batteriesCheckGameSet())
startGameover();
} else if (state == GAMEOVER) {
for (int i = 0; i < battery.length; i++)
battery[i].loop();
gameover.loop();
}
}
/**
* My ship and enemy's ship
*/
class Ship {
int RESPAWN_CNT = 240;
int INVINSIBLE_CNT = 120;
Vector pos = new Vector();
Vector vel = new Vector();
float MAX_SPEED = 8;
float speed;
Shot shot = new Shot();
int type;
Vector target = new Vector();
int cnt;
void start() {
shot.start();
if (type == PLAYER) {
shot.dir = -1;
} else if (type == COMPUTER) {
shot.dir = 1;
setTarget();
}
restart();
cnt = INVINSIBLE_CNT;
}
void restart() {
pos.x = width / 2;
if (type == PLAYER)
pos.y = height / 6 * 5;
else if (type == COMPUTER)
pos.y = height / 6;
vel.x = vel.y = 0;
speed = 0;
cnt = RESPAWN_CNT;
}
void loop() {
if (cnt > 0)
cnt--;
if (shot.isExist)
shot.loop();
if (cnt > INVINSIBLE_CNT)
return;
pos.x += vel.x;
pos.y += vel.y;
if (type == PLAYER) {
playerMove();
if (pos.y < height / 2)
pos.y = height / 2;
else if (pos.y > height)
pos.y = height;
} else if (type == COMPUTER) {
computerMove();
if (pos.y < 0)
pos.y = 0;
else if (pos.y > height / 2)
pos.y = height / 2;
}
if (pos.x < 0)
pos.x = 0;
if (pos.x > width)
pos.x = width;
if (cnt == 0 && bulletsCheckHit(pos)) {
for (int i = 0; i < 16; i++) {
Particle pt = particlesGetInstance();
pt.set(pos);
}
restart();
}
if (cnt == 0 || cnt % 20 > 10)
draw();
}
void playerMove() {
int mox = mouseX - (int) pos.x;
int moy = mouseY - (int) pos.y;
float mouseDst = sqrt(mox * mox + moy * moy);
if (mouseDst > 0) {
vel.x += (mox / mouseDst * speed - vel.x) * 0.1f;
vel.y += (moy / mouseDst * speed - vel.y) * 0.1f;
}
if (mouseDst > 5) {
speed += (MAX_SPEED - speed) * 0.3f;
} else {
speed *= 0.5f;
vel.x *= 0.2f;
vel.y *= 0.2f;
}
if (!shot.isExist) {
if (mousePressed)
shot.set(pos);
}
}
void computerMove() {
int mox = (int) (target.x - pos.x);
int moy = (int) (target.y - pos.y);
float mouseDst = sqrt(mox * mox + moy * moy);
if (mouseDst > 0) {
vel.x += (mox / mouseDst * speed - vel.x) * 0.1f;
vel.y += (moy / mouseDst * speed - vel.y) * 0.1f;
}
speed = MAX_SPEED;
if (mouseDst < 5)
setTarget();
if (!shot.isExist && checkBatteryFront(pos.x))
shot.set(pos);
}
void setTarget() {
int bi = (int) random(battery.length);
Battery tb = null;
for (int i = 0; i < battery.length; i++) {
tb = battery[bi];
if (tb.type == PLAYER)
break;
bi++;
if (bi >= battery.length)
bi = 0;
}
target.x = tb.pos.x;
target.y = random(tb.pos.y / 2);
}
boolean checkBatteryFront(float x) {
for (int i = 0; i < battery.length; i++) {
if (abs(battery[i].pos.x - x) < BATTERY_SIZE)
return true;
}
return false;
}
void draw() {
push();
translate(pos.x, pos.y);
if (type == PLAYER) {
fill(100, 100, 200);
stroke(180, 190, 250);
scale(1, -1);
} else if (type == COMPUTER) {
fill(200, 100, 100);
stroke(250, 190, 180);
}
beginShape(TRIANGLE_STRIP);
vertex(-6, -8);
vertex(0, 8);
vertex(0, -2);
vertex(6, -8);
endShape();
pop();
}
}
/**
* Ship's shot.
*/
class Shot {
float SPEED = 10;
Vector pos = new Vector();
float dir;
boolean isExist;
void start() {
isExist = false;
}
void setDir(float d) {
dir = d;
}
void set(Vector p) {
pos.x = p.x;
pos.y = p.y;
isExist = true;
}
void loop() {
pos.y += SPEED * dir;
if (pos.y < 0 || pos.y >= height || batteriesCheckHit(pos, dir))
isExist = false;
push();
translate(pos.x, pos.y);
fill(200, 200, 200);
stroke(250, 250, 250);
beginShape(QUADS);
vertex(-2, -5);
vertex(2, -5);
vertex(2, 5);
vertex(-2, 5);
endShape();
pop();
}
}
/**
* Battery.
*/
class Battery {
float SIZE = BATTERY_SIZE;
float FLIP_MOVE = 3;
Vector pos = new Vector();
Vector vel = new Vector();
int cnt;
float fireInterval;
int type;
void start(int c) {
vel.x = vel.y = 0;
cnt = c;
fireInterval = BATTERY_FIRE_INTERVAL;
}
boolean checkHit(Vector p, float d) {
if (p.dist(pos) < SIZE) {
vel.x += pos.x - p.x;
vel.y += FLIP_MOVE * d;
return true;
}
return false;
}
void loop() {
pos.x += vel.x;
if (pos.x < 0 || pos.x >= width) {
vel.x = -vel.x;
pos.x += vel.x * 2;
}
pos.y += vel.y;
if (pos.y < 50)
pos.y = 50;
if (pos.y > height - 50)
pos.y = height - 50;
if (pos.y > height / 2)
type = COMPUTER;
else
type = PLAYER;
vel.x *= 0.95f;
vel.y *= 0.95f;
cnt--;
if (cnt < 0) {
cnt = (int) fireInterval;
Bullet b = bulletsGetInstance();
if (b != null) {
Vector ap;
if (type == COMPUTER)
ap = ship[1].pos;
else
ap = ship[0].pos;
b.set(pos, atan2(ap.x - pos.x, ap.y - pos.y), 3);
}
}
if (fireInterval > 10)
fireInterval -= 0.01;
push();
translate(pos.x, pos.y);
if (type == COMPUTER) {
fill(200, 100, 100);
stroke(220, 200, 200);
} else {
fill(100, 100, 200);
stroke(200, 200, 220);
}
beginShape(QUADS);
vertex(SIZE, 0);
vertex(0, SIZE);
vertex(-SIZE, 0);
vertex(0, -SIZE);
endShape();
pop();
}
}
boolean batteriesCheckHit(Vector p, float d) {
boolean r = false;
for (int i = 0; i < battery.length; i++)
if (battery[i].checkHit(p, d))
r = true;
return r;
}
boolean batteriesCheckGameSet() {
int tp = battery[0].type;
for (int i = 1; i < battery.length; i++) {
if (battery[i].type != tp)
return false;
}
winner = tp;
return true;
}
/**
* Bullets generated from Battery.
*/
class Bullet {
float SIZE = 4;
Vector pos = new Vector();
float deg;
float speed;
int cnt;
boolean isExist;
void start() {
isExist = false;
}
void set(Vector p, float d, float s) {
pos.x = p.x;
pos.y = p.y;
deg = d;
speed = s;
cnt = 0;
isExist = true;
}
void loop() {
pos.x += sin(deg) * speed;
pos.y += cos(deg) * speed;
if (pos.x < 0 || pos.x >= width || pos.y < 0 || pos.y >= height) {
isExist = false;
return;
}
cnt++;
push();
translate(pos.x, pos.y);
fill(200, 200, 100);
stroke(250, 250, 100);
rotate(cnt * 0.11f);
beginShape(QUADS);
vertex(SIZE, 0);
vertex(0, SIZE);
vertex(-SIZE, 0);
vertex(0, -SIZE);
endShape();
pop();
}
}
int bulletIdx = 0;
Bullet bulletsGetInstance() {
for (int i = 0; i < bullet.length; i++) {
if (!bullet[bulletIdx].isExist)
return bullet[bulletIdx];
bulletIdx--;
if (bulletIdx < 0)
bulletIdx = bullet.length - 1;
}
return null;
}
boolean bulletsCheckHit(Vector p) {
for (int i = 0; i < bullet.length; i++) {
if (bullet[i].isExist) {
if (bullet[i].pos.dist(p) < 3)
return true;
}
}
return false;
}
/**
* Particle.
*/
class Particle {
Vector pos = new Vector();
Vector vel = new Vector();
int cnt;
int size;
void start() {
cnt = -1;
}
void set(Vector p) {
pos.x = p.x;
pos.y = p.y;
vel.x = random(10) - 5;
vel.y = random(10) - 5;
cnt = 15 + (int) random(15);
size = 5 + (int) random(5);
}
void loop() {
pos.x += vel.x;
pos.y += vel.y;
vel.x *= 0.96;
vel.y *= 0.96;
cnt--;
size++;
stroke(230, 250, 230);
noFill();
rect(pos.x, pos.y, size, size);
}
}
int particleIdx = 0;
Particle particlesGetInstance() {
particleIdx--;
if (particleIdx < 0)
particleIdx = particle.length - 1;
return particle[particleIdx];
}
/**
* Vector.
*/
class Vector {
float x, y;
public float dist(Vector v) {
float ax = abs(x - v.x);
float ay = abs(y - v.y);
if (ax > ay)
return ax + ay / 2;
else
return ay + ax / 2;
}
}
/**
* Title screen.
*/
class Title {
boolean startPressed;
void loop() {
boolean onStart;
if (mouseX > width / 2 - 60
&& mouseX < width / 2 + 60
&& mouseY > height - 100
&& mouseY < height - 60)
onStart = true;
else
onStart = false;
push();
translate(0, 0, 30);
textSize(32);
textMode(ALIGN_CENTER);
fill(255, 255, 255);
text("PGK wars", width / 2, height / 3);
stroke(250, 100, 50);
if (onStart)
fill(150, 250, 200);
else
fill(100, 200, 150);
strokeWeight(2);
rect(width / 2 - 50, height - 100, 100, 25);
strokeWeight(1);
fill(255, 255, 255);
textSize(25);
text("START", width / 2, height - 80);
pop();
if (onStart && mousePressed)
startPressed = true;
if (!mousePressed && startPressed) {
startPressed = false;
if (onStart)
startInGame();
}
}
}
/**
* Gameover screen.
*/
class Gameover {
int cnt;
void start() {
cnt = 0;
}
void loop() {
push();
translate(0, 0, 30);
textSize(24);
textMode(ALIGN_CENTER);
fill(255, 255, 255);
if (winner == PLAYER)
text("You won", width / 2, height / 3);
else
text("You lost", width / 2, height / 3);
pop();
cnt++;
if (cnt > 300 || (cnt > 30 && mousePressed)) {
startTitle();
return;
}
}
}
}