Skip to content

Instantly share code, notes, and snippets.

@taskie
Last active April 12, 2016 13:51
Show Gist options
  • Save taskie/88cc43292e8e59194fd669409272b6fd to your computer and use it in GitHub Desktop.
Save taskie/88cc43292e8e59194fd669409272b6fd to your computer and use it in GitHub Desktop.
P. B. C. (UTMC 2016年度初心者向けプログラミング講習会サンプルコード/シンプルな避けゲー 魔改造例)
//P. B. C. (Periodic Boundary Condition) by taskie
//derived from simple yoke-game sample by MASA
//color scheme: http://ethanschoonover.com/solarized
float boxW, boxH, boxX, boxY;
float bulletX[], bulletY[];//bullet position (x, y)
float bulletVx[], bulletVy[];//bullet velocity (x, y)
boolean isMyBullet[];
float bulletR = 5;//bullet radius
float playerX = width / 2, playerY = height / 2;
float playerR = 7, playerA; //player radius, angle
boolean playerIsOverdrived;
int frame, score, highScore;
boolean gameover;
int mousePressCounter;
void setup(){
size(640, 480);//set window size
//initialize arrays
bulletX = new float[0];
bulletY = new float[0];
bulletVx = new float[0];
bulletVy = new float[0];
isMyBullet = new boolean[0];
playerA = PI / 2;
frame = 0;
score = 0;
gameover = false;
}
void update(){
//update box
int boxFrame = frame - 15 * 60;
if (boxFrame < 0) {
boxW = 300;
boxH = 300;
} else {
float scale = min(150, 30 + boxFrame / 100.0);
boxW = 300 + scale * sin(boxFrame / 130.0);
boxH = 300 + scale * sin(boxFrame / 110.0);
}
boxX = (width - boxW) / 2;
boxY = (height - boxH) / 2;
//update characters' state
for(int i = 0; i < bulletX.length; i++){
//update bullet position by velocity
bulletX[i] += bulletVx[i];
bulletY[i] += bulletVy[i];
if(bulletX[i] < boxX || bulletX[i] > boxX + boxW){//reset bullet
bulletX[i] = (bulletX[i] + boxW - boxX) % boxW + boxX;
isMyBullet[i] = false;
}
if(bulletY[i] < boxY || bulletY[i] > boxY + boxH) {
bulletY[i] = (bulletY[i] + boxH - boxY) % boxH + boxY;
isMyBullet[i] = false;
}
}
//player position restraints
playerX = min(max(mouseX, boxX + playerR), boxX + boxW - playerR);
playerY = min(max(mouseY, boxY + playerR), boxY + boxH - playerR);
playerIsOverdrived = mousePressed;
if (playerIsOverdrived) {
playerA -= 0.02;
} else {
playerA += 0.01;
}
if (frame % 90 == 60 || (playerIsOverdrived && frame % 90 == 15)) {
// shoot a bullet
bulletX = (float[])append(bulletX, playerX + playerR * cos(playerA));
bulletY = (float[])append(bulletY, playerY + playerR * sin(playerA));
float speed = 1.0 + frame / 1000.0;
if (playerIsOverdrived) { speed *= 1.25; }
bulletVx = (float[])append(bulletVx, speed * cos(playerA));
bulletVy = (float[])append(bulletVy, speed * sin(playerA));
isMyBullet = (boolean[])(append(isMyBullet, true));
}
for(int i = 0; i < bulletX.length; i++){
if(isMyBullet[i]){
for (int j = 0; j < bulletX.length; j++) {
if (isMyBullet[j]) { continue; }
if (pow(bulletX[j] - bulletX[i], 2) + pow(bulletY[j] - bulletY[i], 2) < pow(bulletR * 2, 2)) {//detect collision between my bullet and enemy's bullet
isMyBullet[j] = true;
score += 100;
}
}
} else if (pow(playerX - bulletX[i], 2) + pow(playerY - bulletY[i], 2) < pow(playerR + bulletR, 2)){//detect collision between a bullet and player
gameover = true;
}
}
++frame;
score += bulletX.length / 10.0 + 1;
highScore = max(highScore, score);
}
void draw(){
if (!gameover && boxX < mouseX && mouseX < boxX + boxW && boxY < mouseY && mouseY < boxY + boxH) {
noCursor();
} else {
cursor();
}
if (mousePressed) {
if (mousePressCounter >= 0) {
mousePressCounter++;
} else {
mousePressCounter = 0;
}
} else {
if (mousePressCounter < 0) {
mousePressCounter--;
} else {
mousePressCounter = -1;
}
}
if(gameover){
if (mousePressCounter == 0) {
setup();
return;
}
}else{
update();
}
//draw background
background(253, 246, 227);
int nx = ceil(boxX / boxW);
int ny = ceil(boxY / boxH);
for (int dx = -nx; dx <= nx; dx++) {
float biasX = dx * boxW;
for (int dy = -ny; dy <= ny; dy++) {
float biasY = dy * boxH;
if (dx != 0 || dy != 0) {
stroke(131, 148, 150, 255);
if (gameover) {
fill(220, 50, 47);
} else {
fill(0, 43, 54);
}
rect(boxX + biasX, boxY + biasY, boxW, boxH);
}
}
}
//draw objects
for (int dx = -nx; dx <= nx; dx++) {
float biasX = dx * boxW;
for (int dy = -ny; dy <= ny; dy++) {
float biasY = dy * boxH;
stroke(0, 0, 0, 0);
for(int i = 0; i < bulletX.length; i++){//draw bullets
if (dx != 0 || dy != 0) {
if (isMyBullet[i]) {
fill(147, 161, 161);
} else {
fill(238, 232, 213);
}
}else{
if (isMyBullet[i]) {
fill(238, 232, 213);
} else {
fill(38, 139, 210);
}
}
ellipse(bulletX[i] + biasX, bulletY[i] + biasY, bulletR * 2, bulletR * 2);
}
color playerColor;
if (playerIsOverdrived) {
playerColor = color(203, 75, 22);
} else {
playerColor = color(131, 148, 150);
}
fill(playerColor);
float px = playerX + biasX, py = playerY + biasY;
ellipse(px, py, playerR * 2, playerR * 2); //draw player
stroke(playerColor);
line(px, py, px + playerR * 1.5 * cos(playerA), py + playerR * 1.5 * sin(playerA));
}
}
//draw score
if (gameover) {
fill(0, 43, 54);
} else {
fill(131, 148, 150);
}
text("Score: " + score + "\nHighScore: " + highScore, 5, 15);
}
//「『あれは、当機です!』『自分だろうと、あれは敵だ』」(円城塔『Self-Reference ENGINE』)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment