changeset 27233:c241b1322f2b

*** empty log message ***
author Gerd Moellmann <gerd@gnu.org>
date Fri, 07 Jan 2000 12:20:57 +0000
parents 1c7665b7a026
children bf32d38f9721
files lisp/ChangeLog lisp/play/pong.el
diffstat 2 files changed, 474 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Fri Jan 07 02:30:49 2000 +0000
+++ b/lisp/ChangeLog	Fri Jan 07 12:20:57 2000 +0000
@@ -1,13 +1,17 @@
+2000-01-07  Gerd Moellmann  <gerd@gnu.org>
+
+	* play/pong.el: New file.
+
 2000-01-05  Carsten Dominik  <cd@gnu.org>
 
-	* textmodes/reftex-vars.el (reftex-parse-file-extension,
-	 reftex-index-phrase-file-extension): New options.
+	* textmodes/reftex-vars.el (reftex-parse-file-extension)
+	(reftex-index-phrase-file-extension): New options.
 
 	* textmodes/reftex-index.el (reftex-index-visit-phrases-buffer):
-	 Use new option `reftex-index-phrase-file-extension'.
+	Use new option `reftex-index-phrase-file-extension'.
 
 	* textmodes/reftex.el (reftex-access-parse-file): Use new option
-	 `reftex-parse-file-extension'.
+	`reftex-parse-file-extension'.
 
 2000-01-05  Dave Love  <fx@gnu.org>
 
@@ -19,8 +23,8 @@
 
 2000-01-05  Thien-Thi Nguyen  <ttn@delysid.gnu.org>
 
-	* progmodes/hideshow.el (hs-discard-overlays, hs-flag-region,
-	hs-show-block): Don't use `mapcar' when not accumulating.
+	* progmodes/hideshow.el (hs-discard-overlays, hs-flag-region)
+	(hs-show-block): Don't use `mapcar' when not accumulating.
 
 	Fix buglet in local variables initialization.
 
@@ -56,8 +60,8 @@
 	(ps-header-lines, ps-left-header, ps-right-header): No more buffer
 	local.
 	(ps-spool-config): Initialization fix.
-	(ps-print-prologue-1, ps-print-prologue-2,
-	ps-print-duplex-feature): PostScript code moved to separated file.
+	(ps-print-prologue-1, ps-print-prologue-2)
+	(ps-print-duplex-feature): PostScript code moved to separated file.
 	(ps-background-image): Little code reformating.
 	(ps-begin-file, ps-begin-job): Fix code.
 	(ps-postscript-code-directory, ps-mark-code-directory): New vars.
@@ -65,7 +69,7 @@
 
 2000-01-05  Vinicius Jose Latorre  <vinicius@cpqd.com.br>
 
-	* ps-vars.el: eliminated.
+	* ps-vars.el: Eliminated.
 
 	* ps-mule.el: ps-vars eliminated, ps-multibyte-buffer now is
 	`;;;###autoload'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/play/pong.el	Fri Jan 07 12:20:57 2000 +0000
@@ -0,0 +1,461 @@
+;;; pong.el - classical implementation of pong
+
+;; Copyright 1999, 2000 by Free Software Foundation, Inc.
+
+;; Author: Benjamin Drieu
+;; Keywords: games
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This is an implementation of the classical game pong.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(require 'gamegrid)
+
+;;; Customization
+
+(defgroup pong nil 
+  "Emacs-Lisp implementation of the classical game pong."
+  :tag "Pong"
+  :group 'games)
+
+(defcustom pong-buffer-name "*Pong*" 
+  "*Name of the buffer used to play."
+  :group 'pong
+  :type '(string))
+
+(defcustom pong-width 50
+  "*Width of the playfield."
+  :group 'pong
+  :type '(integer))
+
+(defcustom pong-height 30
+  "*Height of the playfield."
+  :group 'pong
+  :type '(integer))
+
+(defcustom pong-bat-width 3
+  "*Width of the bats for pong."
+  :group 'pong
+  :type '(integer))
+
+(defcustom pong-blank-color "black"
+  "*Color used for background."
+  :group 'pong
+  :type '(string))
+
+(defcustom pong-bat-color "yellow"
+  "*Color used for bats."
+  :group 'pong
+  :type '(string))
+
+(defcustom pong-ball-color "red"
+  "*Color used for the ball."
+  :group 'pong
+  :type '(string))
+
+(defcustom pong-border-color "white"
+  "*Color used for pong balls."
+  :group 'pong
+  :type '(string))
+
+(defcustom pong-left-key "4"
+  "*Alternate key to press for bat 1 to go up (primary one is [left])."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-right-key "6"
+  "*Alternate key to press for bat 1 to go down (primary one is [right])."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-up-key "8"
+  "*Alternate key to press for bat 2 to go up (primary one is [up])."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-down-key "2"
+  "*Alternate key to press for bat 2 to go down (primary one is [down])."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-quit-key "q"
+  "*Key to press to quit pong."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-pause-key "p"
+  "Key to press to pause pong."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-resume-key "p"
+  "*Key to press to resume pong."
+  :group 'pong
+  :type '(vector))
+
+(defcustom pong-timer-delay 0.1
+  "*Time to wait between every cycle."
+  :group 'pong
+  :type '(integer))
+
+
+;;; This is black magic.  Define colors used
+
+(defvar pong-blank-options
+  '(((glyph colorize)
+     (t ?\040))
+    ((color-x color-x)
+     (mono-x grid-x)
+     (color-tty color-tty))
+    (((glyph color-x) [0 0 0])
+     (color-tty pong-blank-color))))
+
+(defvar pong-bat-options
+  '(((glyph colorize)
+     (emacs-tty ?O)
+     (t ?\040))
+    ((color-x color-x)
+     (mono-x mono-x)
+     (color-tty color-tty)
+     (mono-tty mono-tty))
+    (((glyph color-x) [1 1 0])
+     (color-tty pong-bat-color))))
+
+(defvar pong-ball-options
+  '(((glyph colorize)
+     (t ?\*))
+    ((color-x color-x)
+     (mono-x grid-x)
+     (color-tty color-tty))
+    (((glyph color-x) [1 0 0])
+     (color-tty pong-ball-color))))
+
+(defvar pong-border-options
+  '(((glyph colorize)
+     (t ?\+))
+    ((color-x color-x)
+     (mono-x grid-x))
+    (((glyph color-x) [0.5 0.5 0.5])
+     (color-tty pong-border-color))))
+
+(defconst pong-blank	0)
+(defconst pong-bat	1)
+(defconst pong-ball	2)
+(defconst pong-border	3)
+
+
+;;; Determine initial positions for bats and ball
+
+(defvar pong-xx nil
+  "Horizontal speed of the ball.")
+
+(defvar pong-yy nil
+  "Vertical speed of the ball.")
+
+(defvar pong-x nil
+  "Horizontal position of the ball.")
+
+(defvar pong-y nil
+  "Vertical position of the ball.")
+
+(defvar pong-bat-player1 nil
+  "Vertical position of bat 1.")
+
+(defvar pong-bat-player2 nil
+  "Vertical position of bat 2.")
+
+(defvar pong-score-player1 nil)
+(defvar pong-score-player2 nil)
+
+;;; Initialize maps
+
+(defvar pong-mode-map
+  (make-sparse-keymap 'pong-mode-map) "Modemap for pong-mode.")
+
+(defvar pong-null-map
+  (make-sparse-keymap 'pong-null-map) "Null map for pong-mode.")
+
+(define-key pong-mode-map [left]	 'pong-move-left)
+(define-key pong-mode-map [right] 	 'pong-move-right)
+(define-key pong-mode-map [up]		 'pong-move-up)
+(define-key pong-mode-map [down]	 'pong-move-down)
+(define-key pong-mode-map pong-left-key  'pong-move-left)
+(define-key pong-mode-map pong-right-key 'pong-move-right)
+(define-key pong-mode-map pong-up-key	 'pong-move-up)
+(define-key pong-mode-map pong-down-key  'pong-move-down)
+(define-key pong-mode-map pong-quit-key  'pong-quit)
+(define-key pong-mode-map pong-pause-key 'pong-pause)
+
+
+;;; Fun stuff -- The code
+
+(defun pong-display-options ()
+  "Computes display options (required by gamegrid for colors)."
+  (let ((options (make-vector 256 nil)))
+    (loop for c from 0 to 255 do
+      (aset options c
+	    (cond ((= c pong-blank)
+		   pong-blank-options)
+                  ((= c pong-bat)
+		   pong-bat-options)
+                  ((= c pong-ball)
+		   pong-ball-options)
+                  ((= c pong-border)
+		   pong-border-options)
+                  (t
+		   '(nil nil nil)))))
+    options))
+
+
+
+(defun pong-init-buffer ()
+  "Initialize pong buffer and draw stuff thanks to gamegrid library."
+  (interactive)
+  (get-buffer-create pong-buffer-name)
+  (switch-to-buffer pong-buffer-name)
+  (use-local-map pong-mode-map)
+
+  (setq gamegrid-use-glyphs t)
+  (setq gamegrid-use-color t)
+  (gamegrid-init (pong-display-options))
+
+  (gamegrid-init-buffer pong-width
+			(+ 2 pong-height)
+			1)
+
+  (let ((buffer-read-only nil))
+    (loop for y from 0 to (1- pong-height) do
+	  (loop for x from 0 to (1- pong-width) do
+		(gamegrid-set-cell x y pong-border)))
+    (loop for y from 1 to (- pong-height 2) do
+	  (loop for x from 1 to (- pong-width 2) do
+		(gamegrid-set-cell x y pong-blank))))
+
+  (loop for y from pong-bat-player1 to (1- (+ pong-bat-player1 pong-bat-width)) do
+	(gamegrid-set-cell 2 y pong-bat))
+  (loop for y from pong-bat-player2 to (1- (+ pong-bat-player2 pong-bat-width)) do
+	(gamegrid-set-cell (- pong-width 3) y pong-bat)))
+
+
+
+(defun pong-move-left ()
+  "Move bat 2 up.
+This is called left for historical reasons, since in some pong
+implementations you move with left/right paddle."
+  (interactive)
+  (if (> pong-bat-player1 1)
+      (and
+       (setq pong-bat-player1 (1- pong-bat-player1))
+       (pong-update-bat 2 pong-bat-player1))))
+
+
+
+(defun pong-move-right ()
+  "Move bat 2 up."
+  (interactive)
+  (if (< (+ pong-bat-player1 pong-bat-width) (1- pong-height))
+      (and
+       (setq pong-bat-player1 (1+ pong-bat-player1))
+       (pong-update-bat 2 pong-bat-player1))))
+
+
+
+(defun pong-move-up ()
+  "Move bat 2 up."
+  (interactive)
+  (if (> pong-bat-player2 1)
+      (and
+       (setq pong-bat-player2 (1- pong-bat-player2))
+       (pong-update-bat (- pong-width 3) pong-bat-player2))))
+
+
+
+(defun pong-move-down ()
+  "Move bat 2 down."
+  (interactive)
+  (if (< (+ pong-bat-player2 pong-bat-width) (1- pong-height))
+      (and
+       (setq pong-bat-player2 (1+ pong-bat-player2))
+       (pong-update-bat (- pong-width 3) pong-bat-player2))))
+
+
+
+(defun pong-update-bat (x y)
+  "Move a bat (suppress a cell and draw another one on the other side)."
+
+  (cond
+   ((string-equal (buffer-name (current-buffer)) pong-buffer-name)
+    (gamegrid-set-cell x y pong-bat)
+    (gamegrid-set-cell x (1- (+ y pong-bat-width)) pong-bat)
+    (if (> y 1)
+	(gamegrid-set-cell x (1- y) pong-blank))
+    (if (< (+ y pong-bat-width) (1- pong-height))
+	(gamegrid-set-cell x (+ y pong-bat-width) pong-blank)))))
+  
+
+
+(defun pong-init ()
+  "Initialize a game."
+  
+  (define-key pong-mode-map pong-pause-key 'pong-pause)
+
+  (make-local-hook 'kill-buffer-hook)
+  (add-hook 'kill-buffer-hook 'pong-quit nil t)
+
+  ;; Initialization of some variables
+  (setq pong-bat-player1 (1+ (/ (- pong-height pong-bat-width) 2)))
+  (setq pong-bat-player2 pong-bat-player1)
+  (setq pong-xx -1)
+  (setq pong-yy 0)
+  (setq pong-x (/ pong-width 2))
+  (setq pong-y (/ pong-height 2))
+
+  (pong-init-buffer)
+  (gamegrid-kill-timer)
+  (gamegrid-start-timer pong-timer-delay 'pong-update-game)
+  (pong-update-score))
+
+
+
+(defun pong-update-game (pong-buffer)
+  "\"Main\" function for pong.
+It is called every pong-cycle-delay seconds and
+updates ball and bats positions.  It is responsible of collision
+detection and checks if a player scores."
+  (if (not (eq (current-buffer) pong-buffer))
+      (pong-pause)
+	
+    (let ((old-x pong-x)
+	  (old-y pong-y))
+      
+      (setq pong-x (+ pong-x pong-xx))
+      (setq pong-y (+ pong-y pong-yy))
+      
+      (if (and (> old-y 0)
+	       (< old-y (- pong-height 1)))
+	  (gamegrid-set-cell old-x old-y pong-blank))
+      
+      (if (and (> pong-y 0)
+	       (< pong-y (- pong-height 1)))
+	  (gamegrid-set-cell pong-x pong-y pong-ball))
+      
+      (cond
+       ((or (= pong-x 3) (= pong-x 2))
+	(if (and (>= pong-y pong-bat-player1) 
+		 (< pong-y (+ pong-bat-player1 pong-bat-width)))
+	    (and 
+	     (setq pong-yy (+ pong-yy
+			      (cond 
+			       ((= pong-y pong-bat-player1) -1)
+			       ((= pong-y (1+ pong-bat-player1)) 0)
+			       (t 1))))
+	     (setq pong-xx (- pong-xx)))))
+
+       ((or (= pong-x (- pong-width 4)) (= pong-x (- pong-width 3)))
+	(if (and (>= pong-y pong-bat-player2) 
+		 (< pong-y (+ pong-bat-player2 pong-bat-width)))
+	    (and 
+	     (setq pong-yy (+ pong-yy
+			      (cond 
+			       ((= pong-y pong-bat-player2) -1)
+			       ((= pong-y (1+ pong-bat-player2)) 0)
+			       (t 1))))
+	     (setq pong-xx (- pong-xx)))))
+   
+       ((<= pong-y 1)
+	(setq pong-yy (- pong-yy)))
+
+       ((>= pong-y (- pong-height 2))
+	(setq pong-yy (- pong-yy)))
+
+       ((< pong-x 1)
+	(setq pong-score-player2 (1+ pong-score-player2))
+	(pong-init))
+
+       ((>= pong-x (- pong-width 1))
+	(setq pong-score-player1 (1+ pong-score-player1))
+	(pong-init))))))
+
+
+
+(defun pong-update-score ()
+  "Update score and print it on bottom of the game grid."
+  (let* ((string (format "Score:  %d / %d" pong-score-player1 pong-score-player2))
+	 (len (length string)))
+    (loop for x from 0 to (1- len) do
+	  (if (string-equal (buffer-name (current-buffer)) pong-buffer-name)
+	      (gamegrid-set-cell x
+				 pong-height
+				 (aref string x))))))
+
+
+
+(defun pong-pause ()
+  "Pause the game."
+  (interactive)
+  (gamegrid-kill-timer)
+  ;; Oooohhh ugly.  I don't know why, gamegrid-kill-timer don't do the
+  ;; jobs it is made for.  So I have to do it "by hand".  Anyway, next
+  ;; line is harmless.
+  (cancel-function-timers 'pong-update-game)
+  (define-key pong-mode-map pong-resume-key 'pong-resume))
+
+
+
+(defun pong-resume ()
+  "Resume a paused game."
+  (interactive)
+  (define-key pong-mode-map pong-pause-key 'pong-pause)
+  (gamegrid-start-timer pong-timer-delay 'pong-update-game))
+
+
+
+(defun pong-quit ()
+  "Quit the game and kill the pong buffer."
+  (interactive)
+  (gamegrid-kill-timer)
+  ;; Be sure not to draw things in another buffer and wait for some
+  ;; time.
+  (run-with-timer pong-timer-delay nil 'kill-buffer pong-buffer-name))
+
+
+
+;;;###autoload
+(defun pong ()
+  "Play pong and waste time.
+This is an implementation of the classical game pong.
+Move left and right bats and try to bounce the ball to your opponent.
+
+pong-mode keybindings:
+   \\<pong-mode-map>
+
+   \\{pong-mode-map}"
+  (interactive)
+  (setq pong-score-player1 0)
+  (setq pong-score-player2 0)
+  (pong-init))
+
+
+
+(provide 'pong)