Something I did on a boring Sunday afternoon. It's amazing how quickly these things can be done nowadays, as the programming can be extremely lazy. (Cough) I followed a "if it works don't look back" style of programming so obviously it could be a lot shorter and more efficient. I wanted to relax anyway.
I have no idea if it will work smoothly on different computers. The video shows roughly how it plays on my Linux Mint/Mate with 3GHz and a Radeon EAH5750 display adapter. Different Java implementations may result in different sync.
Install Processing, Copy/paste the following onto the sketch and off you go. The arrow keys control the ship. Up arrow is fire. Q resets the game anytime.
// Invaders game by Tero Heikkinen
// left/right arrows - Move
// up arrow - Fire
// q - restart game
// Made in one evening 26.7.2015
int MAXOBJECTS=100;
int []g_x=new int [MAXOBJECTS];
int []g_y=new int [MAXOBJECTS];
int []g_t=new int [MAXOBJECTS];
int []g_vx=new int [MAXOBJECTS];
int []g_vy=new int [MAXOBJECTS];
int []g_score=new int[10];
int g_pulse,g_level,g_aframe;
boolean g_joyr,g_joyl,g_joyf;
void setup()
{
size(600,400);noSmooth();noStroke();fill(255,255,255);
resetgame();
}
void create_wave()
{
int diffi,xon,flip;
float floi;
g_level++;
diffi=g_level;flip=0;
if(diffi>10){diffi=10;}
for(int j=0;j<=3;j++){
for(int i=0;i<=7;i++){
floi=0;
if(g_level==4||g_level==8||g_level==16){
floi=float(i);
}
xon=64*i;
if(g_level==6||g_level==10||g_level==14||g_level==20){xon=64*i+flip*32;}
addobject(xon,32+diffi*16+26*j+int(cos(floi)*16),1,0,2);
}
flip++;if(flip>1){flip=0;}
}
int mzip=-2;
if(random(100)<50){mzip=2;}
//add motherships
addobject(width*2,32,mzip,0,25);
addobject(width*4,32,mzip,0,25);
}
void resetgame()
{
for(int i=0;i<=9;i++){g_score[i]=0;}
clearobjects();g_level=0;
addobject(width/2-16,height-32,0,0,1);
}
void graphic(int x,int y,String gfx)
{
int xc,yc,xp,yp;
xc=0;yc=0;
for (int i=0;i<gfx.length();i++){
if(gfx.charAt(i)=='1'){
xp=x+xc*4;yp=y+yc*2;
if(xp>=0&&xp<=width-4&&yp>=0&&yp<=height-2){
pixels[xp+(yp)*width]=0xffffffff;
pixels[xp+(yp)*width+1]=0xffffffff;
pixels[xp+(yp)*width+2]=0xffffffff;
pixels[xp+(yp)*width+3]=0xffffffff;
}
//rect(x+xc*4,y+yc*2,4,2);
}
xc++;
if(gfx.charAt(i)==' '){xc=0;yc++;}
}
}
void addobject(int x,int y,int vx,int vy,int t)
{
int first;
first=0;
if(t!=1){first=1;}
//alien bullet check fit
if(t==4){
for(int i=0;i<MAXOBJECTS;i++){
if(g_t[i]==2){
if(x>g_x[i]&&x<g_x[i]+24&&y>g_y[i]-4&&y<g_y[i]+16){
return;
}
}
}
}
// add an object
for(int i=first;i<MAXOBJECTS;i++){
if(g_t[i]==0){
g_vx[i]=vx;g_vy[i]=vy;
g_x[i]=x;g_y[i]=y;g_t[i]=t;return;
}
}
}
void clearobjects()
{
for(int i=0;i<MAXOBJECTS;i++){
g_t[i]=0;g_vx[i]=0;g_vy[i]=0;g_x[i]=0;g_y[i]=0;
}
}
void command_fleet(int com)
{
for(int i=0;i<MAXOBJECTS;i++){
if(g_t[i]==2){
if(com<5){
g_vx[i]=com;
g_x[i]=g_x[i]+com;
}
if(com==16&&g_t[0]==1){
g_y[i]=g_y[i]+12;
}
}
}
}
void addscore(int ss)
{
int okay;
okay=0;
g_score[0]=g_score[0]+ss;
while(okay==0){
okay=1;
for(int i=0;i<=9;i++){
if(g_score[i]>9){g_score[i+1]++;g_score[i]=g_score[i]-10;okay=0;}
}
}
}
void drawobjects()
{
int aliens,multip,order;
loadPixels();
aliens=0;multip=1;order=0;
for(int i=0;i<MAXOBJECTS;i++){
if(g_t[i]==2){aliens++;}
}
if(aliens==0){create_wave();}
if(aliens<=9){multip=2;}
if(aliens<=3){multip=3;}
if(aliens==1){multip=4;}
g_aframe=g_aframe+multip;
if(g_aframe>31){g_aframe=g_aframe-32;}
for(int i=0;i<MAXOBJECTS;i++){
switch(g_t[i]){
case 1:
graphic(g_x[i],g_y[i],"00011000 00011000 01111110 00111100 11111111 11111111");
break;
case 2:
if(g_aframe<=15){
graphic(g_x[i],g_y[i],"00000000 11011011 00111100 11011011 11111111 00100100 01100110");
}
else
{
graphic(g_x[i],g_y[i],"10000001 01011010 00111100 11011011 11111111 01000010 11000011");
}
g_x[i]=g_x[i]+g_vx[i]*multip;
g_y[i]=g_y[i]+g_vy[i]*multip;
if(g_y[i]>g_y[0]-16&&g_t[0]==1){g_t[0]=8;}
if(g_x[i]>width-32){order=1;}
if(g_x[i]<=0){order=2;}
aliens++;
int frate;
frate=g_level*multip;
if(frate>200){frate=200;}
if(random(400)<frate){
int zzoo;
zzoo=2;
if(g_level>=4){zzoo=4;}
if(g_level>=8){zzoo=6;}
addobject(g_x[i]+12,g_y[i]+24,0,zzoo,4);
}
break;
case 3:
graphic(g_x[i],g_y[i],"11 11");
if(g_y[i]<0){g_t[i]=0;}
for(int j=0;j<MAXOBJECTS;j++){
if((g_t[j]==2||g_t[j]==25)&&g_x[i]>g_x[j]-8&&g_x[i]<g_x[j]+32&&g_y[i]>g_y[j]&&g_y[i]<g_y[j]+16){addscore(1*g_t[j]);g_t[j]=8;g_t[i]=0;}
}
g_x[i]=g_x[i]+g_vx[i];
g_y[i]=g_y[i]+g_vy[i];
break;
case 4:
graphic(g_x[i],g_y[i],"11 11 11");
if(g_y[i]>height){g_t[i]=0;}
int j=0;
if(g_t[j]==1&&g_x[i]>g_x[j]-6&&g_x[i]<g_x[j]+30&&g_y[i]>g_y[j]&&g_y[i]<g_y[j]+16){g_t[j]=8;g_t[i]=0;}
g_x[i]=g_x[i]+g_vx[i];
g_y[i]=g_y[i]+g_vy[i];
break;
case 8:
graphic(g_x[i],g_y[i],"10010011 01010110 00111100 11000011 0111100 01101010 11001001");
g_vy[i]++;if(g_vy[i]>3){g_vy[i]=0;g_t[i]=9;}
break;
case 9:
graphic(g_x[i],g_y[i],"00000000 01010010 00000000 10000001 0000000 01001010 0000000");
g_vy[i]++;if(g_vy[i]>3){g_vy[i]=0;g_t[i]=0;}
break;
case 25: //mothership
graphic(g_x[i],g_y[i],"00111110 01010101 01111111 00100010 00011100");
g_x[i]=g_x[i]+g_vx[i];
g_y[i]=g_y[i]+g_vy[i];
if(g_x[i]<-32){g_x[i]=width*6;}
if(g_x[i]>width*6){g_x[i]=-32;}
break;
}
}
if(order==1){command_fleet(16);command_fleet(-1);}
if(order==2){command_fleet(16);command_fleet(1);}
if(g_t[0]==0){
graphic(32,16,"00111100 01000010 01000010 01010010 01001010 00111100");
}
scoreboard();
updatePixels();
}
void scoreboard()
{
int s,x,y;
x=96+4*32;y=16;
s=1;
for(int i=0;i<=4;i++){
switch(g_score[i]){
case 0:graphic(x,y,"00111100 01000010 01000010 01000010 01000010 00111100");break;
case 1:graphic(x,y,"00001000 00011000 00101000 00001000 00001000 00111110");break;
case 2:graphic(x,y,"00111100 01000010 00000010 00111110 01000000 01111110");break;
case 3:graphic(x,y,"01111110 00000010 00011100 00000010 01000010 00111100");break;
case 4:graphic(x,y,"00011100 00100100 01000100 01111110 00000100 00000100");break;
case 5:graphic(x,y,"01111110 01000000 01111100 00000010 01000010 00111100");break;
case 6:graphic(x,y,"00111100 01000000 01111110 01000010 01000010 00111100");break;
case 7:graphic(x,y,"01111110 00000010 00011110 00000010 00000100 00001000");break;
case 8:graphic(x,y,"00111100 01000010 00111100 01000010 01000010 00111100");break;
case 9:graphic(x,y,"00111100 01000010 01111110 01000010 00000010 00111100");break;
}
x=x-32;
}
}
void keyPressed()
{
if(key=='q'){resetgame();}
if(key==CODED){
if(keyCode==RIGHT)g_joyr=true;
if(keyCode==LEFT)g_joyl=true;
if(keyCode==UP)g_joyf=true;
}
}
void keyReleased()
{
if(key==CODED){
if(keyCode==RIGHT){g_joyr=false;}
if(keyCode==LEFT){g_joyl=false;}
if(keyCode==UP){g_joyf=false;}
}
}
void draw()
{
background(0,0,0);
drawobjects();
if(g_joyr){if(g_x[0]<width-36){g_x[0]=g_x[0]+4;}}
if(g_joyl){if(g_x[0]>4){g_x[0]=g_x[0]-4;}}
if(g_joyf&&g_pulse==0){g_pulse=10;if(g_t[0]==1){addobject(g_x[0]+12,g_y[0],0,-8,3);}}
if(g_pulse>0){g_pulse--;}
}