Gabriel Pariat
2 years ago
21 changed files with 540 additions and 222 deletions
@ -1,65 +1,24 @@
@@ -1,65 +1,24 @@
|
||||
(in-package :pong.client) |
||||
|
||||
(defparameter *client* nil) |
||||
|
||||
(defclass client () |
||||
((ip :initarg :ip :initform nil :reader client-ip) |
||||
(port :initarg :port :initform nil :reader client-port) |
||||
(running-p :initform nil :accessor client-running-p) |
||||
(socket :initform nil :accessor client-socket))) |
||||
|
||||
(defmethod listen-to ((self client)) |
||||
(with-slots (running-p socket) self |
||||
(when (and running-p (usocket:wait-for-input socket :timeout 5) running-p) |
||||
(let ((data (cpk:decode-stream (usocket:socket-stream socket)))) |
||||
(format t "[CLIENT] Data received: ~a~%" data))))) |
||||
|
||||
(defmethod start ((self client)) |
||||
(with-slots (ip port running-p socket) self |
||||
(format t "uh?~%") |
||||
(unless running-p |
||||
(setf running-p t) |
||||
(setf socket (usocket:socket-connect ip port :element-type 'unsigned-byte))))) |
||||
|
||||
(defmethod stop ((self client)) |
||||
(with-slots (running-p socket) self |
||||
(setf running-p nil) |
||||
(when socket |
||||
(usocket:socket-close socket)) |
||||
(setf socket nil))) |
||||
|
||||
(defmethod write-to ((self client) data) |
||||
(let ((stream (usocket:socket-stream (client-socket self)))) |
||||
(format t "[CLIENT] Data sent: ~a~%" data) |
||||
(cpk:encode data :stream stream) |
||||
(force-output stream))) |
||||
|
||||
(defun handle-client () |
||||
(loop while (and *client* (client-running-p *client*)) |
||||
do (let ((data (listen-to *client*)))))) |
||||
|
||||
(defun start-client (ip port) |
||||
(unless *client* |
||||
(setf *client* (make-instance 'client :ip ip :port port)) |
||||
(start *client*) |
||||
(bt:make-thread #'handle-client))) |
||||
|
||||
(defun stop-client () |
||||
(when *client* |
||||
(stop *client*)) |
||||
(setf *client* nil)) |
||||
|
||||
(defun send-data-to-server (data) |
||||
(write-to *client* data)) |
||||
|
||||
(defun test-client () |
||||
(start-client "127.0.0.1" 54321) |
||||
(write-to *client* "hello!") |
||||
(sleep 1.015) |
||||
(write-to *client* "bye!") |
||||
(stop-client)) |
||||
|
||||
;; (test-client) |
||||
|
||||
;; (stop-client) |
||||
(defun main () |
||||
(let* ((last-time nil) |
||||
(current-time (get-internal-real-time))) |
||||
(r:with-window (800 600 "Pariatech's Pong") |
||||
(gui:with-gui |
||||
(open-main-menu) |
||||
|
||||
(r:set-config-flags r:+flag-window-resizable+) |
||||
(r:set-target-fps 60) |
||||
(r:set-exit-key 0) |
||||
(loop |
||||
until (or (r:window-should-close) (scene-should-close *scene*)) |
||||
do (setf last-time current-time) |
||||
(setf current-time (/ (get-internal-real-time) internal-time-units-per-second)) |
||||
|
||||
(let ((timelapse (- current-time last-time))) |
||||
(on-update *scene* timelapse)) |
||||
(r:with-drawing |
||||
(r:clear-background r:+gray+) |
||||
(on-draw *scene*) |
||||
(r:draw-fps 20 20))))))) |
||||
|
||||
|
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
(in-package #:gui) |
||||
|
||||
(defclass text-field (text) |
||||
((focusp :initarg :focusp :initform nil :accessor focusp) |
||||
(border :initarg :border :initform :solid :accessor border) |
||||
(border-color :initarg :border-color :initform r:+black+ :accessor border-color) |
||||
(border-thickness :initarg :border-thickness :initform 1 :accessor border-thickness) |
||||
(cursor :initarg :cursor :initform nil :accessor cursor) |
||||
(padding :initarg :padding :initform 0 :accessor padding))) |
||||
|
||||
(defmethod calculate-size ((txt text-field)) |
||||
(with-slots (w h font font-size text spacing padding) txt |
||||
(when (and font text) |
||||
(let ((size (r:measure-text-ex (load-font font font-size) |
||||
text |
||||
(float font-size) |
||||
spacing))) |
||||
(setf w (+ (v:vx size) (* padding 2))) |
||||
(setf h (+ (v:vy size) (* padding 2))) |
||||
(update-x txt) |
||||
(update-y txt))))) |
||||
|
||||
(defmethod draw ((self text-field)) |
||||
(with-slots (font font-size text screen-x screen-y w h color spacing visible focusp border border-thickness border-color cursor padding) self |
||||
(when visible |
||||
(when border |
||||
(r:draw-rectangle-lines-ex (r:make-rectangle :x screen-x |
||||
:y screen-y |
||||
:width w |
||||
:height h) |
||||
(float border-thickness) |
||||
border-color)) |
||||
(when focusp |
||||
(r:draw-line-e) |
||||
(r:draw-text-ex (load-font font font-size) |
||||
(concatenate 'string |
||||
(str:repeat cursor " ") |
||||
(string #\left_one_eighth_block)) |
||||
(v:vec (float (+ screen-x padding)) (float (+ screen-y padding))) |
||||
(float font-size) |
||||
spacing |
||||
color)) |
||||
(when text |
||||
(r:draw-text-ex (load-font font font-size) |
||||
text |
||||
(v:vec (float (+ screen-x padding)) (float (+ screen-y padding))) |
||||
(float font-size) |
||||
spacing |
||||
color))))) |
||||
|
||||
(defmacro make-text-field (&rest args) |
||||
`(make-instance 'text-field ,@args)) |
||||
|
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
(in-package :pong.client) |
||||
|
||||
(defclass join-online-game-scene (scene) |
||||
((name :initform "" :accessor join-online-game-scene-name) |
||||
(code :initform "" :accessor join-online-game-scene-code) |
||||
(title :initarg :title :initform nil :reader join-online-game-scene-title) |
||||
(name-field :initarg :name-field |
||||
:initform nil |
||||
:reader join-online-game-scene-name-field) |
||||
(name-prompt :initarg :name-prompt |
||||
:initform nil |
||||
:reader join-online-game-scene-name-prompt) |
||||
(code-field :initarg :code-field |
||||
:initform nil |
||||
:reader join-online-game-scene-code-field) |
||||
(code-prompt :initarg :code-prompt |
||||
:initform nil |
||||
:reader join-online-game-scene-code-prompt) |
||||
(join-button :initarg :join-button |
||||
:initform nil |
||||
:reader join-online-game-scene-join-button))) |
||||
|
||||
(defun open-join-online-game-scene () |
||||
(let ((root-element (gui:make-rectangle :color r:+darkgray+ |
||||
:h-align :center |
||||
:v-align :middle)) |
||||
(title (gui:make-text :color r:+white+ |
||||
:font +menu-font+ |
||||
:font-size +menu-title-font-size+ |
||||
:y +title-top-padding+ |
||||
:h-align :center |
||||
:text "Join online game")) |
||||
(name-field (gui:make-text-field :color r:+white+ |
||||
:font +menu-font+ |
||||
:font-size +menu-font-size+ |
||||
:focusp t |
||||
:border :solid |
||||
:border-color r:+white+ |
||||
:border-thickness 1 |
||||
:cursor 0 |
||||
:padding 5)) |
||||
(name-prompt (gui:make-text :color r:+white+ |
||||
:font +menu-font+ |
||||
:font-size +menu-font-size+ |
||||
:h-align :right |
||||
:v-align :middle |
||||
:text "What is your name?:"))) |
||||
|
||||
(gui:add-children root-element title name-field name-prompt) |
||||
|
||||
(set-scene (make-instance 'join-online-game-scene :root-element root-element |
||||
:title title |
||||
:name-field name-field |
||||
:name-prompt name-prompt)))) |
||||
|
||||
(defmethod on-update ((scene join-online-game-scene) timelapse) |
||||
(with-slots (name move-back) scene |
||||
;; Might be interesting to add repeating keys, but I don't care. |
||||
(loop for key = (r:get-key-pressed) |
||||
while (plusp key) |
||||
do (format t "~a~%" key) |
||||
when (= key r:+key-escape+) |
||||
do (open-main-menu) |
||||
when (= key r:+key-backspace+) |
||||
do (setf name (str:substring 0 -1 name)) |
||||
;; when (= key r:+key-enter+) |
||||
;; do (create-online-game name) |
||||
when (and (>= key 32) (<= key 96)) |
||||
do (setf name (str:concat name (string (code-char key)))))) |
||||
) |
||||
|
||||
(defmethod on-draw ((scene join-online-game-scene)) |
||||
(with-slots (name code root-element title name-field name-prompt) scene |
||||
(position-root root-element) |
||||
(setf (gui:x title) (floor (gui:w root-element) 2)) |
||||
(setf (gui:text name-field) name) |
||||
(setf (gui:x name-field) (+ (floor (gui:w root-element) 2) +score-padding+)) |
||||
(setf (gui:x name-prompt) (- (floor (gui:w root-element) 2) +score-padding+)) |
||||
(setf (gui:y name-field) (floor (gui:h root-element) 2)) |
||||
(setf (gui:y name-prompt) (floor (gui:h root-element) 2))) |
||||
) |
@ -1,5 +1,4 @@
@@ -1,5 +1,4 @@
|
||||
(defpackage :pong.client |
||||
(:use :cl) |
||||
(:local-nicknames (:r :raylib) |
||||
(:v :3d-vectors) |
||||
(:g :pong.game))) |
||||
(:v :3d-vectors))) |
||||
|
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
(in-package :pong.game) |
||||
|
||||
(defclass game-action-message () |
||||
((game-code :initarg :game-code :initform nil :reader game-code) |
||||
(game-action :initarg :game-action :initform nil :reader game-action))) |
||||
|
||||
(defclass state-updated-message () |
||||
((game-state :initarg :game-state :initform nil :reader game-state))) |
||||
|
||||
(defclass create-game-message () |
||||
((player-name :initarg :player-name :initform nil :reader player-name))) |
||||
|
||||
(defclass join-game-message () |
||||
((game-code :initarg :game-code :initform nil :reader game-code) |
||||
(player-name :initarg :player-name :initform nil :reader player-name))) |
||||
|
||||
(defclass game-created-message () |
||||
((game-code :initarg :game-code :initform nil :reader game-code) |
||||
(player-paddle :initarg :player-paddle :initform nil :reader player-paddle) |
||||
(game-state :initarg :game-state :initform nil :reader game-state))) |
||||
|
||||
(defclass game-joined-message () |
||||
((player-paddle :initarg :player-paddle :initform nil :reader player-paddle) |
||||
(game-state :initarg :game-state :initform nil :reader game-state))) |
||||
|
||||
(cpk:defencoding game-action-message game-code game-action) |
||||
(cpk:defencoding state-updated-message game-state) |
||||
(cpk:defencoding create-game-message player-name) |
||||
(cpk:defencoding join-game-message game-code player-name) |
||||
(cpk:defencoding game-created-message game-code player-paddle game-state) |
||||
(cpk:defencoding game-joined-message player-paddle game-state) |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
(defun print-object-readably (object) |
||||
(let ((slots (map 'list #'c2mop:slot-definition-name (c2mop:class-slots (class-of object)))) |
||||
(class (class-name (class-of object)))) |
||||
(cons class (remove-if #'null |
||||
(loop for slot in slots |
||||
collect (if (slot-boundp object slot) |
||||
(cons slot (slot-value object slot)))))))) |
||||
|
||||
(defun read-object (sexp) |
||||
(let* ((class (car sexp)) |
||||
(object (make-instance class))) |
||||
(loop for slot in (cdr sexp) |
||||
do (setf (slot-value object (car slot)) (cdr slot))) |
||||
object)) |
@ -1,3 +1,3 @@
@@ -1,3 +1,3 @@
|
||||
(defpackage :pong.server |
||||
(:use :cl) |
||||
(:local-nicknames (:g :pong.game))) |
||||
(:nicknames :s)) |
||||
|
Loading…
Reference in new issue