Cosiderado primer videojuego arcade de la historia, Pong es el clásico de los clásicos. Juega online, 100% javascript con programación orientada a objetos y hojas de estilo CSS, más sencillo imposible.
Aquí tienes mi repositorio de Javascript game Pong en GitHub
Utiliza por supuesto javascript pero también una hoja de estilos CSS para dibujar el juego. Este código está escrito y publicado bajo licencia GNU GPL, puedes modificarlo y reutilizarlo como quieras pero mantén siempre las referencias a su autor.
<div id="pong_game" style="padding:0 20px 0 10px"> <div id="pong_header"> <div class="pong_titulo">PONG - Crossbrowser xhtml javascript Pong game v.1.0</div> <div id="pong_menu" class="pong_menu"></div> </div> <div id="contenedor"> <div id="pluck"></div> <div id="paddleL"></div> <div id="paddleR"></div> </div> <div id="pong_footer"> </div> </div>
.pong_game{background:#ffffff;color:#000000} .pong_titulo{font-weight:bold;font-size:12pt} .pong_titulo2{font-weight:bold;font-size:10pt} .pong_menu a{color:#0000ff} .pong_th{border-bottom:1px solid #000000} .pong_mini,#scoregoalsgame{font-size:75%} span.pong_score{font-weight:bold} div.pong_score{font-size:12pt;text-align:right} #pong_header{margin:0px auto;width:600px;text-align:left;background:#ffffff;color:#000000} #pong_menu{background:#e0e0e0} #pong_menu td{font-size:10pt} #contenedor{margin:0px auto;background:#000000;width:600px;height:400px;text-align:left} #pong_mensaje{margin:0px auto;width:400px;height:300px;background:#e0e0e0;color:#000000} #pong_mensajetxt{margin:10px auto;color:#000000} #pluck{position:relative;top:0px;left:0px;background:#ffffff;width:10px;height:10px;font-size:1px} #paddleL{position:relative;top:175px;left:40px;background:#ffffff;width:10px;height:50px;font-size:1px} #paddleR{position:relative;top:125px;left:550px;background:#ffffff;width:10px;height:50px;font-size:1px} #pong_footer{margin:0px auto;width:600px;text-align:center;background:#e0e0e0;color:#000000;font-size:12pt}
/** * Javascript Pong v.1.0 * 2009-01-26 * Jose Carlos Cruz Parra * josecarlos@programadorphpfreelance.com * http://programadorphpfreelance.com */ var pongGame = new Pong(); pongGame.Run(); function Pong(varName) { this.varName = varName ? varName : "pongGame"; this.pluck = new Pluck(this); this.paddleL = new Paddle("L"); this.paddleR = new Paddle("R"); this.scoreL = new Score(); this.scoreR = new Score(); this.gamegoals = 15; this.server = ''; this.paused = false; this.temp = ''; this.contenedor = document.getElementById('contenedor'); this.showingMessage = false; this.Run = function() { document.onkeydown = function(evt) { if(!evt) { var evt = window.event; } var key = window.Event ? evt.which : evt.keyCode; //No podemos utilizar this. porque este método será llamado onkeydown del documento var varName = document.getElementById('contenedor').name; switch(key) { case 87: //W eval(varName+".paddleL.MoveUp()"); break; case 83: //S eval(varName+".paddleL.MoveDown()"); break; case 79: //O eval(varName+".paddleR.MoveUp()"); break; case 76: //L eval(varName+".paddleR.MoveDown()"); break; case 80: //P eval(varName+".SwitchPause()"); break; case 81: //Q eval(varName+".Serves('L')"); break; case 73: //I eval(varName+".Serves('R')"); break; default: //alert(key); } } document.onkeyup = function(evt) { if(!evt) { var evt = window.event; } var key = window.Event ? evt.which : evt.keyCode; //No podemos utilizar this. porque este método será llamado onkeydown del documento var varName = document.getElementById('contenedor').name; switch(key) { case 87: //W case 83: //S eval(varName+".paddleL.Stop()"); break; case 79: //O case 76: //L eval(varName+".paddleR.Stop()"); break; } } this.contenedor.name = this.varName; document.getElementById('pong_menu').innerHTML = '<table cellpadding="0" cellspacing="0" width="100%"><tr><td><a href="javascript:'+this.varName+'.HowToPlay()">» How to play</a> <a href="javascript:'+this.varName+'.Settings()">» Settings</a> <a href="javascript:'+this.varName+'.Credits()">» Credits</a></td><td><div class="pong_score">Score: <span id="pong_scoreL" class="pong_score">0</span> - <span id="pong_scoreR" class="pong_score">0</span> <span class="pong_mini">(reach </span><span id="scoregoalsgame">15</span><span class="mini"> goals to win a game)</span></div></td></tr></table>'; this.newGame(); this.running(); } this.running = function() { if(!this.paused) { var r = this.pluck.Move(); switch(r) { case "L": case "R": this.goal(r); break; } this.paddleL.Move(); this.paddleR.Move(); } setTimeout(this.varName+".running()", 10); } this.SwitchPause = function(pause) { if(this.paused = pause == null ? !this.paused : pause) { this.statusMessage("Game paused (press P to continue)"); } else { this.statusMessage(); } } this.goal = function(goaler) { switch(goaler) { case 'L': var pNum = '1'; var pStr = 'left'; break; case 'R': var pNum = '2'; var pStr = 'right'; break; } this.statusMessage('Player '+pNum+' scores!!'); eval('this.score'+goaler+'.goals++'); if(eval('this.score'+goaler+'.goals') >= this.gamegoals) { this.statusMessage('Player '+pNum+' ('+pStr+') wins the game '+this.scoreL.goals+' to '+this.scoreR.goals); eval('this.score'+goaler+'.games++'); this.newGame(goaler); } else { this.newPoint(goaler == 'L' ? 'R' : 'L'); } this.RefreshScore(); } this.newPoint = function(server) { if(server == null) { server = Math.round(Math.random()) ? 'L' : 'R'; } switch(server) { case 'L': this.statusMessage('Player 1 serves (press Q)', true); this.pluck.X = 60; break; case 'R': this.statusMessage('Player 2 serves (press I)', true); this.pluck.X = 530; break; } this.pluck.Y = 195; this.pluck.Stop(); this.pluck.Position(); this.server = server; } this.newGame = function(server) { this.scoreL.goals = 0; this.scoreR.goals = 0; this.newPoint(server); } this.Serves = function(server) { if(!this.paused && server == this.server) { this.server = ''; this.pluck.incX = server == 'L' ? -5 : 5; this.statusMessage(); } } this.HowToPlay = function() { var msg = '<table>'; msg += '<tr><td class="pong_th" colspan="2">Player 1 (left)</td><td class="pong_th" colspan="2">Player 2 (right)</td><td class="pong_th" colspan="2">General</td></tr>'; msg += '<tr><td><b>W</b></td><td>Up</td><td><b>O</b></td><td>Up</td><td><b>P</b></td><td>Pause</td></tr>'; msg += '<tr><td><b>S</b></td><td>Down</td><td><b>L</b></td><td>Down</td><td></td><td></td></tr>'; msg += '<tr><td><b>Q</b></td><td>Serve</td><td><b>I</b></td><td>Serve</td><td></td><td></td></tr>'; msg += '</table>'; msg += '<p>When it\'s your turn to serve, put your paddle just behind the pluck, because it starts moving backward to you.</p>'; msg += '<p>Depending where the pluck touch your paddle, it will affect its moving one way or another.</p>'; msg += '<p>Enjoy!!</p>'; this.ShowMessage(msg,'How to play'); } this.Settings = function() { var msg = '<table>'; msg += '<tr><td>Pluck velocity</td><td><select id="pluckvelocity" name="pluckvelocity" onchange="'+this.varName+'.pluck.advance=parseInt(this.value)"><option value="3">slower</option><option value="4">slow</option><option value="5">normal</option><option value="6">fast</option><option value="7">faster</option></select></td></tr>'; msg += '<tr><td>Goals to win a game</td><td><select id="gamegoals" name="gamegoals" onchange="'+this.varName+'.gamegoals=parseInt(this.value);document.getElementById(\'scoregoalsgame\').innerHTML=this.value"><option value="3">3</option><option value="5">5</option><option value="7">7</option><option value="11">11</option><option value="15">15</option><option value="21">21</option></select></td></tr>'; msg += '</table>'; this.ShowMessage(msg,'Settings'); document.getElementById('pluckvelocity').value = this.pluck.advance; document.getElementById('gamegoals').value = this.gamegoals; } this.Credits = function() { var msg = '<table>'; msg += '<tr><td class="pong_th">Javascript programming and xhtml design</td></tr>'; msg += '<tr><td><b>José Carlos Cruz Parra</b></td></tr>'; msg += '<tr><td>Web developer / PHP programmer freelance</td></tr>'; msg += '<tr><td><a href="http://programadorphpfreelance.com" title="Web developer / PHP programmer freelance Homepage">http://programadorphpfreelance.com</a></td></tr>'; msg += '</table>'; this.ShowMessage(msg,'Credits'); } this.ShowMessage = function(msg,titulo) { this.paused = true; if(!this.showingMessage) { this.temp = this.contenedor.innerHTML; this.showingMessage = true; } this.contenedor.innerHTML = '<br /><br /><div id="pong_mensaje"><div class="pong_titulo">PONG</div><div class="pong_titulo2">'+titulo+'</div><div id="pong_mensajetxt">'+msg+'</div><div class="pong_menu"><a href="javascript:'+this.varName+'.HideMessage()">» Back to game</a></div></div>'; } this.HideMessage = function() { this.contenedor.innerHTML = this.temp; this.temp = ''; this.showingMessage = false; this.paused = false; } this.statusMessage = function(msg, add) { if(add) { document.getElementById('pong_footer').innerHTML += (' ' + (msg == null ? ' ' : msg)); } else { document.getElementById('pong_footer').innerHTML = msg == null ? ' ' : msg; } } this.RefreshScore = function() { document.getElementById('pong_scoreL').innerHTML = this.scoreL.goals; document.getElementById('pong_scoreR').innerHTML = this.scoreR.goals; } } function Pluck(pong) { this.pong = pong; this.X = 295; this.Y = 195; this.incX = 0; this.incY = 0; this.advance = 5; this.Move = function() { if(this.Y < 1 || this.Y > 390) { this.incY = -this.incY; } if(this.X < 1) { this.incX = this.advance; return "R"; } if(this.X > 590) { this.incX = -this.advance; return "L"; } if(this.X > 35 && this.X < 50 && this.Y > this.pong.paddleL.Y-10 && this.Y < this.pong.paddleL.Y+65) { var varIncY = this.calculateVarIncY(this.Y - (this.pong.paddleL.Y-10)); this.incX = this.incY == 0 && varIncY == 0 ? 2*this.advance : this.advance; this.incY += varIncY; } if(this.X > 540 && this.X < 555 && this.Y > this.pong.paddleR.Y+40 && this.Y < this.pong.paddleR.Y+115) { var varIncY = this.calculateVarIncY(this.Y - (this.pong.paddleR.Y+40)); this.incX = this.incY == 0 && varIncY == 0 ? -2*this.advance : -this.advance; this.incY += varIncY; } this.X += this.incX; this.Y += this.incY; this.Position(); return ""; } this.calculateVarIncY = function(diff) { if(diff < 11) return -3; if(diff < 21) return -2; if(diff < 31) return -1; if(diff < 46) return 0; if(diff < 56) return 1; if(diff < 66) return 2; return 3; } this.Stop = function() { this.incX = 0; this.incY = 0; } this.Position = function(x,y) { if(x != null) this.X = x; if(y != null) this.Y = y; document.getElementById("pluck").style.left = this.X+"px"; document.getElementById("pluck").style.top = this.Y+"px"; } } function Paddle(LorR) { this.incY = 0; if(LorR == "L") { this.LorR = "L"; this.minY = -1; this.maxY = 330; this.Y = 165; } else { this.LorR = "R"; this.minY = -51; this.maxY = 280; this.Y = 115; } this.MoveUp = function() { this.incY = -10; this.Move(); } this.MoveDown = function() { this.incY = 10; this.Move(); } this.Move = function() { if((this.incY < 0 && this.Y < this.minY) || (this.incY > 0 && this.Y > this.maxY)) { this.Stop(); } else { this.Y += this.incY; document.getElementById("paddle"+this.LorR).style.top = this.Y+"px"; } } this.Stop = function() { this.incY = 0; } } function Score() { this.goals = 0; this.games = 0; }