No BSD License  

Highlights from
PONG: a tribute to the game created by Atari Inc.

image thumbnail
from PONG: a tribute to the game created by Atari Inc. by Jerome Briot
A tribute to the game created by Atari Inc.

pong
function pong

% PONG Matlab version of the eponym game
% 
%   PONG was created in the early 70's by Nolan Bushnell from Atari Inc. 
%   This code should be considered as a tribute.
%   More info on Wikipedia:
%       http://en.wikipedia.org/wiki/Pong
%       http://en.wikipedia.org/wiki/Atari
% 
%   Controls: 
%       Right player uses mouse
%       Left player uses up/down keyboard arrows
% 
%   Players can also use following keys:
%       P: game paused
%       S: switch sound on/off
%       Esc: quit game
%
        
%   Author: Jrme Briot
%   Contact: dutmatlab@yahoo.fr
%   Creation: Sep 2006
% 
%   Revision: 
%   #1: Oct 2006 - improve ball management
%                - add sound options
% 

% Get screen size
set(0,'units','pixels')
scr=get(0,'screensize');

% Create figure
figure('units','pixels','position',[.25*scr(3) .25*scr(4) .5*scr(3) .5*scr(4)],...
    'color','k',...
    'toolbar','none',...
    'menubar','none',...
    'numbertitle','off',...
    'name','PONG - dutmatlab@yahoo.fr - Sept 2006',...
    'doublebuffer','on',...
    'pointer','custom',...
    'pointershapecdata',repmat(nan,16,16),...
    'closerequestfcn',[])

% Separate the next line because of bug in R12.1 
set(gcf,'resize','off')

% Create axes  
axes('units','normalized','position',[0 0 1 1],...
    'xtick',[],'ytick',[],'color','k','xlim',[0 1],'ylim',[0 1])

% Create animated splash screen
t(1)=text(.35,.75,'P','fontname','courier','fontsize',60,'color','k','hor','center','fontweight','bold');
t(2)=text(.45,.75,'O','fontname','courier','fontsize',60,'color','k','hor','center','fontweight','bold');
t(3)=text(.55,.75,'N','fontname','courier','fontsize',60,'color','k','hor','center','fontweight','bold');
t(4)=text(.65,.75,'G','fontname','courier','fontsize',60,'color','k','hor','center','fontweight','bold');
t(5)=text(.50,.55,'A tribute to the eponym game by ATARI Inc.','fontname','courier','fontsize',20,'color','k','hor','center','fontweight','bold');
t(6)=text(.50,.35,'by Jrme Briot','fontname','courier','fontsize',35,'color','k','hor','center','fontweight','bold');
t(7)=text(.50,.25,'dutmatlab@yahoo.fr','fontname','courier','fontsize',20,'color','k','hor','center','fontweight','bold');
t(8)=text(.50,.15,'(Hit a key)','fontname','courier','fontsize',20,'color','k','hor','center','fontweight','bold');

map=gray(128);

for m=1:length(t)
    
    for n=1:size(map,1)
        
        set(t(m),'color',map(n,:))
        drawnow
        
    end
    
end

% Wait for player to hit a key to remove the splash screen 
pause

set(gcf,'closerequestfcn','closereq')
delete(t)

hold on

% Draw line at the middle
plot([.5 .5],[.05 .95],'r:','color',[.8 .8 .8],'linewidth',6)

% Draw upper line
patch([0 1 1 0],[.95 .95 .98 .98],[0 0 0 0],'facecolor','w','edgecolor','w',...
    'handlevisibility','off')

% Draw lower line
patch([0 1 1 0],[.02 .02 .05 .05],[0 0 0 0],'facecolor','w','edgecolor','w',...
    'handlevisibility','off')

% Draw left player racket
patch([.05 .07 .07 .05],[.455 .455 .545 .545],[0 0 0 0],'facecolor','w','edgecolor','k',...
    'tag','left_player')

% Draw right player racket
patch([.95 .93 .93 .95],[.455 .455 .545 .545],[0 0 0 0],'facecolor','w','edgecolor','k',...
    'tag','right_player')

% Draw the ball
h_ball=patch([.492 .508 .508 .492],[.492 .492 .508 .508],[-1 -1 -1 -1],'facecolor','w','edgecolor','w',...
    'tag','ball');

% Add text for score
text(.425 , .86,'0','fontname','courier','fontsize',60,'color','w','hor','center',...
    'tag','score_left')
text(.575 , .86,'0','fontname','courier','fontsize',60,'color','w','hor','center',...
    'tag','score_right');

% Add pause text 
t_pause=text(.5,.5,'Game paused','fontname','courier','fontsize',60,'color','w','hor','center','fontweight','bold',...
    'visible','off');

% Set player controls
% Left player -> KeyPressFcn
% Right player -> WindowButtonMotionFcn
set(gcf,'keypressfcn',@kpfcn,'windowbuttonmotionfcn',@wbmfcn)

% Load the sound for the rebonds
[pong_sounds(1).Y,pong_sounds(1).FS]=wavread('pong.wav');
setappdata(gcf,'pong_sounds',pong_sounds)

% Set random direction for the ball
rand('state',sum(100*clock));

a=rand;

xdir=[-1 1];
x_sign=randperm(2);
xdir=xdir(x_sign(1));

ydir=[-1 1];
y_sign=randperm(2);
ydir=ydir(y_sign(1));

% Wait for player to hit a key to start the game
pause
set(gcf,'currentchar','a')

% Set sound parameter to on
sound_level=1;

% Initialize variables
flag=1;
incr=.025;
map=gray(256);
tempo_init=0.1;
elapsed_time=0;

% Game action
while flag
    
    % Increase the speed of the ball during the game
    tempo=tempo_init/(floor(elapsed_time/3)+1);
    
    % Check key pressed 
    if get(gcf,'currentchar')==112 | get(gcf,'currentchar')==80 % P => switch pause on/off
        
        set(gcf,'currentcharacter','a');
        
        set(t_pause,'visible','on')
        n=1;
        
        % Make the pause sentence to blink
        while get(gcf,'currentchar')~=112 & get(gcf,'currentchar')~=80 

           set(t_pause,'color',map(n,:));
           drawnow
           
           n=n+1;
           
           if n==257;
               
                map=map(end:-1:1,:);
                n=1;
                
           end   
            
        end
        
        set(t_pause,'visible','off')
        set(gcf,'currentchar','a')
        
    elseif get(gcf,'currentchar')==27 % Esc => quit game

        flag=0;
        cla
        text(.5,.5,'Bye !','fontname','courier','fontsize',60,'color','w','hor','center','fontweight','bold')
        pause(.5)
        break
        
    elseif get(gcf,'currentchar')==115 % S => switch sound on/off

        set(gcf,'currentchar','a')
        sound_level=~sound_level;
        
    end
    
    % Move the ball
    x=get(h_ball,'xdata')+xdir*0.025*a;
    y=get(h_ball,'ydata')+ydir*a*0.025;
    
    % Check the position of the ball
    [xdir,ydir,point]=checkpos(x,y,xdir,ydir,sound_level);

    if xdir==0 
       
        x=[.492 .508 .508 .492];
        y=[.492 .492 .508 .508];
        xdir=-1;
        a=rand;
        
    end
    
    if ydir==0
        
        x=[.492 .508 .508 .492];
        y=[.492 .492 .508 .508];
        xdir=1;
        a=rand;
        ydir=[-1 1];
        y_sign=randperm(2);
        ydir=ydir(y_sign(1));
        
    end        
    
    set(h_ball,'xdata',x,'ydata',y)
    
    % Reset ball speed in case of point
    if point
        
        elapsed_time=0;
        
    else
        
        elapsed_time=elapsed_time+tempo;
        
    end
    
    pause(tempo)
    drawnow
    
end

close

% End of the PONG function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function kpfcn(obj,event)

% KPFCN Control the racket of left player
%
%   KPFCN moves the racket of left player using keyboard
%

ck=get(obj,'currentkey');
h_left=findobj('tag','left_player');

idx=strcmp(ck,{'uparrow' 'downarrow'});

yd=get(h_left,'ydata'); 

yd=yd+.02*(idx(1) & yd(3)<.94)-.02*(idx(2) & yd(1)>.06);

set(h_left,'ydata',yd)
drawnow

% End of the KPFCN function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function wbmfcn(obj,event)

% WBMFCN    Control the racket of right player
%
%   KPFCN moves the racket of right player using mouse
%
%

h_right=findobj('tag','right_player');

cp=get(gca,'currentpoint');

cp=(cp(1,2)+[-.045 -.045 .045 .045]).*(cp(1,2)>.105 & cp(1,2)<.895)+...
    (.105+[-.045 -.045 .045 .045])*(cp(1,2)<.105)+(.895+[-.045 -.045 .045 .045])*(cp(1,2)>.895);

set(h_right,'ydata',cp)

% End of the WBMFCN function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [new_xdir,new_ydir,point]=checkpos(x,y,xdir,ydir,sound_level)

% CHECKPOS  Check the position of the ball
%

% Find rackets object
h_right=findobj('tag','right_player');
h_left=findobj('tag','left_player');
% Get rackets position
y_right=get(h_right,'ydata');
y_left=get(h_left,'ydata');

% Set sound feature
pong_sounds=getappdata(gcf,'pong_sounds');

if ~sound_level
    
    pong_sounds(1).Y=0;
    
end

% Check if the ball hits any racket
keeper_right=any(inpolygon(x+.008,y+.008,get(h_right,'xdata'),get(h_right,'ydata')));
keeper_left=any(inpolygon(x-.008,y-.008,get(h_left,'xdata'),get(h_left,'ydata')));

% The ball hits the upper/lower limit
if y(3)>.942 | y(1)<.058
    
    wavplay(pong_sounds(1).Y,pong_sounds(1).FS)
    
    new_ydir=-ydir;
    new_xdir=xdir;
    point=0;
    
% The ball hits the racket of the right player
elseif keeper_right
    
    wavplay(pong_sounds(1).Y,pong_sounds(1).FS)
    
    new_xdir=-xdir;
    new_ydir=ydir;  
    point=0;
    
% The ball hits the racket of the left player
elseif keeper_left
    
    wavplay(pong_sounds(1).Y,pong_sounds(1).FS)
    
    new_xdir=-xdir;
    new_ydir=ydir;   
    point=0;
    
% One point for the right player
elseif (x+.008)>.93 
    
    sc_left=findobj('type','text','tag','score_left');
    score=get(sc_left,'string')-48+1;
    set(sc_left,'string',score);
    new_xdir=0;
    new_ydir=1;
    point=1;
    
% One point for the left player
elseif (x+.008)<.0.07 
    
    sc_right=findobj('type','text','tag','score_right'); 
    score=get(sc_right,'string')-48+1;
    set(sc_right,'string',score)
    new_xdir=1;
    new_ydir=0;
    point=1;
    
% The ball keep moving
else new_xdir=xdir;
     new_ydir=ydir;
     point=0;
     
end

% End of the CHECKPOS function
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Contact us at files@mathworks.com