for Proce55ing
EDB0 - Source code
(C) Kenta Cho(ABA."Saba")
EDB0.java
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/**
* 0xEDB0.
*
* Copyright (C) Kenta Cho. Some rights reserved.
*
* @p5 description
* - [W][A][S][D]いずれかのキーを押してゲームを始めてください
* - キーが効かない場合はゲーム画面を一回クリックしてください
* - [W][A][S][D]で赤い数を操作して緑の数を倒してください
* - 白い数または緑の数に接触すると赤い数は破壊されます
* - 赤い数が3回破壊されるとゲームオーバーです
* - 左下に赤い数の残り数、右下にスコアが表示されます
* - 数の位置はすべて16進数で表されており、2進数に変換したビットが位置に相当します
* - 例) 4 -> 0100 B -> 1011
*/
public class EDB0 extends BApplet {
Pad pad;
HexadecimalScreen backScreen, bulletScreen, shipScreen, enemyScreen;
Ship ship;
Shot[] shot = new Shot[32];
Enemy[] enemy = new Enemy[128];
Bullet[] bullet = new Bullet[256];
BFont font;
int TITLE = 0;
int IN_GAME = 1;
int GAMEOVER = 2;
int state;
Title title;
Gameover gameover;
int aimEnemyAppInterval;
int laserEnemyAppInterval;
float rank;
int score;
int left;
boolean padPressed;
void setup() {
size(240, 480);
framerate(30);
smooth();
cursor();
font = loadFont("OCR-A.vlw.gz");
textFont(font);
pad = new Pad();
addKeyListener(pad);
backScreen = new HexadecimalScreen(8, 48, true);
bulletScreen = new HexadecimalScreen(8, 48, false);
shipScreen = new HexadecimalScreen(8, 48, false);
enemyScreen = new HexadecimalScreen(8, 48, false);
ship = new Ship();
for (int i = 0; i < shot.length; i++)
shot[i] = new Shot();
for (int i = 0; i < enemy.length; i++)
enemy[i] = new Enemy();
for (int i = 0; i < bullet.length; i++)
bullet[i] = new Bullet();
title = new Title();
gameover = new Gameover();
startTitle();
}
void startTitle() {
state = TITLE;
left = -1;
padPressed = true;
}
void startInGame() {
state = IN_GAME;
ship.init();
for (int i = 0; i < shot.length; i++)
shot[i].init();
for (int i = 0; i < enemy.length; i++)
enemy[i].init();
for (int i = 0; i < bullet.length; i++)
bullet[i].init();
aimEnemyAppInterval = laserEnemyAppInterval = 0;
rank = 1;
score = 0;
left = 2;
}
void startGameover() {
state = GAMEOVER;
gameover.start();
}
void loop() {
background(30, 40, 50);
fill(100, 100, 100);
backScreen.draw();
if (state == TITLE) {
title.loop();
} else if (state == IN_GAME) {
bulletScreen.clear();
shipScreen.clear();
enemyScreen.clear();
rank += 0.0025f;
aimEnemyAppInterval--;
if (aimEnemyAppInterval < 0) {
Enemy en = getEnemyInstance();
if (en != null)
en.set(random(enemyScreen.scDightWidth), en.TYPE_AIM);
aimEnemyAppInterval = (int) ((8 + random(3)) / (rank * 0.5f));
}
laserEnemyAppInterval--;
if (laserEnemyAppInterval < 0) {
for (int i = 0; i < (3 + random(2)) * rank; i++) {
Enemy en = getEnemyInstance();
if (en != null)
en.set(random(enemyScreen.scDightWidth), en.TYPE_LASER);
}
laserEnemyAppInterval = (int) (20 + random(5));
}
ship.loop();
for (int i = 0; i < shot.length; i++)
if (shot[i].isExist)
shot[i].loop();
for (int i = 0; i < enemy.length; i++)
if (enemy[i].isExist)
enemy[i].loop();
for (int i = 0; i < bullet.length; i++)
if (bullet[i].isExist)
bullet[i].loop();
fill(200, 255, 200);
enemyScreen.draw();
fill(255, 200, 200);
shipScreen.draw();
fill(255, 255, 255);
bulletScreen.draw();
} else if (state == GAMEOVER) {
gameover.loop();
}
textSize(24);
textMode(ALIGN_RIGHT);
text("0x" + Integer.toString(score, 16).toUpperCase(), width, height);
if (left >= 0) {
textMode(ALIGN_LEFT);
text("0x" + Integer.toString(left, 16).toUpperCase(), 0, height);
}
}
/**
* My ship.
*/
class Ship {
float SPEED = 1;
Vector pos = new Vector();
Vector ppos = new Vector();
int SHOT_INTERVAL = 6;
int shotCnt;
int cnt;
int RESTART_CNT = 100;
int INVINCIBLE_CNT = 75;
void init() {
restart();
cnt = 0;
}
void restart() {
pos.x = shipScreen.scDightWidth / 2;
pos.y = shipScreen.scHeight / 4 * 3;
shotCnt = SHOT_INTERVAL;
cnt = RESTART_CNT;
}
void loop() {
int dir = pad.getDirState();
if (cnt > INVINCIBLE_CNT) {
dir = 0;
shotCnt = SHOT_INTERVAL;
}
float mx = 0, my = 0;
if ((dir & pad.DIR_UP) != 0)
my = -1;
if ((dir & pad.DIR_DOWN) != 0)
my = 1;
if ((dir & pad.DIR_LEFT) != 0)
mx = -1;
if ((dir & pad.DIR_RIGHT) != 0)
mx = 1;
if (mx != 0 && my != 0) {
mx *= 0.71f;
my *= 0.71f;
}
mx *= SPEED;
my *= SPEED;
ppos.x = pos.x;
ppos.y = pos.y;
pos.x += mx;
pos.y += my;
if (pos.x < 0)
pos.x = 0;
else if (pos.x >= shipScreen.scDightWidth)
pos.x = shipScreen.scDightWidth - 0.01f;
if (pos.y < 0)
pos.y = 0;
else if (pos.y >= shipScreen.scHeight)
pos.y = shipScreen.scHeight - 0.01f;
shotCnt--;
if (shotCnt < 0) {
shotCnt = SHOT_INTERVAL;
Shot s = getShotInstance();
if (s != null)
s.set(pos, PI, 1);
}
if (cnt <= 0
&& (enemiesCheckHit(pos)
|| bulletsCheckHit(pos)
|| bulletsCheckHit(ppos))) {
for (int i = 0; i < 16; i++) {
Shot s = getShotInstance();
if (s != null)
s.set(pos, random(PI * 2), 0.5f + random(1.5f));
}
left--;
restart();
}
if (cnt <= 0 || (cnt < INVINCIBLE_CNT && cnt % 16 >= 8))
shipScreen.pset((int) pos.x, (int) pos.y);
if (cnt > 0) {
if (left < 0 && cnt <= INVINCIBLE_CNT)
startGameover();
if (cnt > INVINCIBLE_CNT / 2)
bulletsClear();
cnt--;
}
}
}
/**
* Ship's shot.
*/
class Shot {
Vector pos = new Vector();
float deg;
float speed;
boolean isExist;
void init() {
isExist = false;
}
void set(Vector p, float d, float s) {
pos.x = p.x;
pos.y = p.y;
deg = d;
speed = s;
isExist = true;
}
void loop() {
if (deg != PI)
pos.x += sin(deg) * speed;
pos.y += cos(deg) * speed;
if (pos.x < 0
|| pos.x >= bulletScreen.scDightWidth
|| pos.y < 0
|| pos.y >= bulletScreen.scHeight
|| enemiesCheckHit(pos)) {
isExist = false;
return;
}
shipScreen.pset((int) pos.x, (int) pos.y);
}
}
int shotIdx = 0;
Shot getShotInstance() {
for (int i = 0; i < shot.length; i++) {
if (!shot[shotIdx].isExist)
return shot[shotIdx];
shotIdx--;
if (shotIdx < 0)
shotIdx = shot.length - 1;
}
return null;
}
/**
* Enemy.
*/
class Enemy {
Vector pos = new Vector();
Vector vel = new Vector();
boolean isExist;
int TYPE_AIM = 0;
int TYPE_LASER = 1;
int type;
boolean loaded;
void init() {
isExist = false;
}
void set(float x, int t) {
pos.x = x;
pos.y = 0;
type = t;
vel.x = random(1.0f) - 0.5f;
switch (type) {
case 0 : //TYPE_AIM:
vel.y = 0.7f + random(0.3f);
break;
case 1 : //TYPE_LASER:
vel.y = 0.5f;
break;
}
isExist = true;
loaded = true;
}
void loop() {
pos.x += vel.x;
pos.y += vel.y;
vel.y -= 0.03f;
if (pos.x < 0
|| pos.x >= bulletScreen.scDightWidth
|| pos.y < 0
|| pos.y >= bulletScreen.scHeight) {
isExist = false;
return;
}
if (loaded && vel.y <= 0) {
loaded = false;
Bullet b = getBulletInstance();
if (b != null) {
if (type == TYPE_AIM)
b.set(
pos,
atan2(ship.pos.x - pos.x, ship.pos.y - pos.y),
0.5f);
else
b.set(pos, 0, 0.5f);
}
}
enemyScreen.pset((int) pos.x, (int) pos.y);
}
boolean checkHit(Vector p) {
if ((int) p.x == (int) pos.x && (int) p.y == (int) pos.y) {
isExist = false;
score++;
return true;
}
return false;
}
}
int enemyIdx = 0;
Enemy getEnemyInstance() {
for (int i = 0; i < enemy.length; i++) {
if (!enemy[enemyIdx].isExist)
return enemy[enemyIdx];
enemyIdx--;
if (enemyIdx < 0)
enemyIdx = enemy.length - 1;
}
return null;
}
boolean enemiesCheckHit(Vector p) {
boolean r = false;
for (int i = 0; i < enemy.length; i++)
if (enemy[i].isExist && enemy[i].checkHit(p))
r = true;
return r;
}
/**
* Bullets.
*/
class Bullet {
float SIZE = 4;
Vector pos = new Vector();
float deg;
float speed;
int cnt;
boolean isExist;
void init() {
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 >= bulletScreen.scDightWidth
|| pos.y < 0
|| pos.y >= bulletScreen.scHeight) {
isExist = false;
return;
}
cnt++;
bulletScreen.pset((int) pos.x, (int) pos.y);
}
boolean checkHit(Vector p) {
if ((int) p.x == (int) pos.x && (int) p.y == (int) pos.y) {
isExist = false;
return true;
}
return false;
}
}
int bulletIdx = 0;
Bullet getBulletInstance() {
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) {
boolean r = false;
for (int i = 0; i < bullet.length; i++)
if (bullet[i].isExist && bullet[i].checkHit(p))
r = true;
return r;
}
void bulletsClear() {
for (int i = 0; i < bullet.length; i++)
bullet[i].isExist = false;
}
/**
* 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 handler.
*/
class Title {
void loop() {
textSize(42);
textMode(ALIGN_CENTER);
fill(255, 255, 255);
text("0xEDB0", width / 2, height / 3);
if (pad.getDirState() != 0) {
if (!padPressed) {
startInGame();
}
padPressed = true;
} else {
padPressed = false;
}
}
}
/**
* Gameover handler.
*/
class Gameover {
int cnt;
void start() {
cnt = 0;
}
void loop() {
textSize(32);
textMode(ALIGN_CENTER);
fill(255, 255, 255);
text("0x76", width / 2, height / 3);
cnt++;
if (cnt > 300)
startTitle();
if (pad.getDirState() != 0) {
if (!padPressed && cnt > 30) {
startTitle();
}
padPressed = true;
} else {
padPressed = false;
}
}
}
/**
* Screen for drawing dots in a hexadecimal form.
*/
class HexadecimalScreen {
int[][] v;
int scWidth, scHeight, scDightWidth;
boolean drawZero;
float ox, oy, xscl;
float tSize;
HexadecimalScreen(int w, int h, boolean dz) {
scWidth = w;
scHeight = h;
scDightWidth = w * 4;
tSize = height / scHeight * 1.5f;
ox = width / scWidth;
oy = height / scHeight;
xscl = ox / oy * 1.25f;
ox /= xscl;
drawZero = dz;
if (!drawZero)
v = new int[w][h];
}
void clear() {
for (int x = 0; x < scWidth; x++)
for (int y = 0; y < scHeight; y++)
v[x][y] = 0;
}
void pset(int x, int y) {
v[x / 4][y] |= 8 >> (x % 4);
}
void draw() {
textMode(ALIGN_LEFT);
textSize(tSize);
float sx, sy;
push();
scale(xscl, 1);
sx = 0;
if (drawZero) {
for (int x = 0; x < scWidth; x++, sx += ox) {
sy = oy;
for (int y = 0; y < scHeight; y++, sy += oy) {
text("0", sx, sy);
}
}
} else {
for (int x = 0; x < scWidth; x++, sx += ox) {
sy = oy;
for (int y = 0; y < scHeight; y++, sy += oy) {
if (v[x][y] == 0)
continue;
text("0123456789ABCDEF".charAt(v[x][y]), sx, sy);
}
}
}
pop();
}
}
/**
* For Handling a simultaneous key input.
*/
class Pad implements KeyListener {
int DIR_UP = 1, DIR_DOWN = 2, DIR_LEFT = 4, DIR_RIGHT = 8;
int dir = 0;
public void keyPressed(KeyEvent e) {
int kc = e.getKeyCode();
if (kc == KeyEvent.VK_W)
dir |= DIR_UP;
if (kc == KeyEvent.VK_S)
dir |= DIR_DOWN;
if (kc == KeyEvent.VK_A)
dir |= DIR_LEFT;
if (kc == KeyEvent.VK_D)
dir |= DIR_RIGHT;
}
public void keyReleased(KeyEvent e) {
int kc = e.getKeyCode();
if (kc == KeyEvent.VK_W)
dir &= (0xFFFF ^ DIR_UP);
if (kc == KeyEvent.VK_S)
dir &= (0xFFFF ^ DIR_DOWN);
if (kc == KeyEvent.VK_A)
dir &= (0xFFFF ^ DIR_LEFT);
if (kc == KeyEvent.VK_D)
dir &= (0xFFFF ^ DIR_RIGHT);
}
public void keyTyped(KeyEvent e) {
}
public int getDirState() {
return dir;
}
}
}