File: ef230-2023-08/www/examples/space_invaders.m Download
%! Simple space invaders game
%! Example of simple real-time user interaction
%! Ugly code with minimal comments
% University of Tennessee : Will Schleter

function main
clear all; close all; clc;
global screen running
init;

while running
    update
end
close(42);
return

function keypress(src,evnt)
global running pos bulx buly
% disp(double(evnt.Character))
switch evnt.Character
    case 'q'
        gameover('q');
    case char(28)  % left arrow
        pos = pos - .2;
    case char(29)  % right arrow
        pos = pos + .2;
    case char(30)  % up arrow
        if length(bulx)<5
            bulx(end+1) = pos;
            buly(end+1) = 0;
        end
end

return

function init
global screen pos running bulx buly xoff yoff xdel ydel oldcnt boom ship imm
imm = menu('Meatlab Invaders','Retro ASCII ships','Cool spaceship image (slow)');
imm = imm-1;
figure(42)
set(42,'KeyPressFcn',@keypress);
nr=5;
nc=10;
oldcnt = nr*nc;
pos = 5;
running = 1;
buly = [];
bulx = [];
xoff = 0;
yoff = 0;
xdel = .05;
ydel = -.05;
screen = ones(nr,nc);
if imm
    getfiles('http://ef.engr.utk.edu/ef230-2009-08/modules/misc/',...
      {'spaceship.png','phaser.wav'});
    ship = imread('spaceship.png');
    boom = wavread('phaser.wav');
end
update;
return

function update
global screen pos bulx buly xoff yoff xdel ydel running oldcnt boom ship imm

[nr,nc] = size(screen);
clf(42);
set(gcf,'Color',[1 1 1])
hold on;
axis([0,nc+1,0,nr+1]);
axis off;
cnt=0;
eps=0.15;
x=[];
y=[];
for r=1:nr
    for c=1:nc
        if screen(r,c)
            for b=length(buly):-1:1
                if abs(c+xoff - bulx(b))<eps && abs(r+yoff-buly(b))<eps
                    screen(r,c)=0;
                    % beep;
                    if imm, wavplay(boom,88200,'async'); end
                    delbul(b)
                    continue;
                end
            end
            cnt=cnt+1;
            x(cnt)=c+xoff;
            y(cnt)=r+yoff;
        end
    end
end
if isempty(x)
    gameover('w');
    return;
end

if imm
    for i=1:length(x)
        image([x(i)-.25 x(i)+.25],[y(i)+.17,y(i)-.17],ship);
    end
else
    plot(x,y,'*')
end

if length(x)< (oldcnt/2)
    xdel = xdel*1.5;
    oldcnt=length(x);
    fprintf('Increasing speed to %.2f\n',abs(xdel));
end

if max(x)>=(nc+1) || min(x)<=0
    xdel=-xdel;
    yoff=yoff+ydel;
end
xoff = xoff + xdel;

if (min(y)<=0)
    gameover('l');
    return;
end
plot(pos,0,'o')
for b=length(buly):-1:1
    if buly(b)>(nr+1)
        delbul(b)
    else
        buly(b) = buly(b)+.1;
    end
end
plot(bulx,buly,'dr','markersize',5)
drawnow
return

function delbul(b)
global bulx buly
bulx = [bulx(1:b-1) bulx(b+1:end)];
buly = [buly(1:b-1) buly(b+1:end)];
return

function gameover(s)
global running
switch (s)
    case 'q'
        q = {'You gave up :('};
    case 'w'
        q = {'Woo Hoo - you won!'};
    case 'l'
        q = {'Boo Hoo - you lost :('};
end
q(3) = {'Play again?'};
resp = questdlg(q,'Game over','Yes','No','Yes');
running = strcmp(resp,'Yes');
if running
    init
end
return

function getfiles(url,filelist);
for i=1:length(filelist);
  urlwrite([url filelist{i}],filelist{i});
end
return