Skip to content

Commit

Permalink
Code: integrated pong game with the main release.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuno-Jesus committed Oct 1, 2024
2 parents 3be607b + aed9cc3 commit be4c2eb
Show file tree
Hide file tree
Showing 18 changed files with 815 additions and 4 deletions.
4 changes: 3 additions & 1 deletion backend/pong/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">


{% block head %}
{% endblock %}
</head>

<body>
Expand Down
19 changes: 19 additions & 0 deletions backend/pong/templates/pages/gamelocal.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
{% extends 'navs.html' %}
{% load static %}

{% block head %}
<link rel="stylesheet" href="{% static 'css/game/game.css' %}">
<link rel="stylesheet" href="{% static 'css/side-menu.css' %}">
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
}
}
</script>
{% endblock %}


{% block main_content %}
<div class="main-content non_compressed" id="main-content">
<div id="canvas-container"></div>
<div id="camera"></div>
</div>

<script id="game-engine" type="module" game-type="local" src="{% static 'js/game/main.js' %}" ></script>
{% endblock %}
5 changes: 3 additions & 2 deletions backend/pong/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
#router.register('users', UsersViewSet)


urlpatterns =[
urlpatterns = [

#! Pages
path('', views.loginview, name="login"),
path('home/', views.home, name="home"),
path('gamelocal/', views.gamelocal, name="gamelocal"),
path('gameonline/', views.gameonline, name="gameonline"),

path('tournaments/', views.tournaments, name="tournaments"),
path('tournaments/ongoing/<int:tournament_id>', views.ongoingtournaments, name="ongoingtournaments"),
path('signup/', views.signup, name='signup'),
Expand Down Expand Up @@ -98,7 +99,7 @@
path('signin42', views.signin42, name='signin42'),
path('home42/', views.login42, name='login42'),

#! DEBUG
#! Debug
path('tournaments', views.tournament_list, name='tournament-list'),

]
Expand Down
1 change: 0 additions & 1 deletion backend/pong/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,6 @@ def loginview(request):

return render(request, 'pages/login.html')


def resetpassword(request):
return render(request, 'pages/password_reset.html')

Expand Down
27 changes: 27 additions & 0 deletions backend/static/css/game/game.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#canvas-container {
width: 100%;
height: 100%;
z-index: -100;
}

#canvas-container > canvas {
border-radius: 8px;
}

#camera {
position: absolute;
left: 100px;
top: 20px;
width: 100px;
height: 100px;
color: lightgreen;
font-family: 'Courier New', Courier, monospace;
font-size: 20px;
z-index: 1000;
}

#gui {
position: absolute;
top: 0px;
right: 100px;
}
11 changes: 11 additions & 0 deletions backend/static/js/game/AIPlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Player } from './Player.js';

export class AIPlayer extends Player {
constructor () {
super(0, "AI Bot", null, null);
}

update() {

}
}
42 changes: 42 additions & 0 deletions backend/static/js/game/Arena.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as THREE from 'three';
import { ARENA_SEMI_HEIGHT, ARENA_SEMI_LENGTH, ARENA_SEMI_DEPTH } from './macros.js';

export class Arena extends THREE.Group {
constructor({ height, length, depth }) {
super();
this.semiHeight = height || ARENA_SEMI_HEIGHT;
this.semiLength = length || ARENA_SEMI_LENGTH;
this.semiDepth = depth || ARENA_SEMI_DEPTH;

this.upperBoundary = null;
this.lowerBoundary = null;
this.leftBoundary = null;
this.rightBoundary = null;

this.build();
}

build() {
const height = 2 * this.semiHeight;
const length = 2 * this.semiLength;
const depth = 2 * this.semiDepth;

this.upperBoundary = new THREE.Mesh(
new THREE.BoxGeometry(length, depth, depth),
new THREE.MeshPhongMaterial()
);
this.leftBoundary = new THREE.Mesh(
new THREE.BoxGeometry(depth, height, depth),
new THREE.MeshPhongMaterial()
);
this.lowerBoundary = this.upperBoundary.clone();
this.rightBoundary = this.leftBoundary.clone();

this.upperBoundary.position.set(0, this.semiHeight - this.semiDepth, 0);
this.lowerBoundary.position.set(0, -this.semiHeight + this.semiDepth, 0);
this.leftBoundary.position.set(-this.semiLength, 0, 0);
this.rightBoundary.position.set(this.semiLength, 0, 0);

this.add(this.lowerBoundary, this.upperBoundary, this.leftBoundary, this.rightBoundary);
}
}
50 changes: 50 additions & 0 deletions backend/static/js/game/Axis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as THREE from 'three';
/**
* This class contains a 3D axis representation
*/
export class Axis extends THREE.Group {

/**
* @param {number} size the size of each axis
* @param {number} baseRadius the base radius of each axis
* @param {number} xxColor the hexadecimal representation of the xx axis color
* @param {number} yyColor the hexadecimal representation of the xx axis color
* @param {number} zzColor the hexadecimal representation of the zz axis color
*/
constructor(size, baseRadius, xxColor, yyColor, zzColor) {
super();
this.size = size || 2;
this.baseRadius = baseRadius || 0.05;
this.xxColor = xxColor || 0xff0000
this.yyColor = yyColor || 0x00ff00
this.zzColor = zzColor || 0x0000ff

// a cone geometry for the xx axis
const xx = new THREE.ConeGeometry( this.baseRadius, this.size, 32 );
const xxMaterial = new THREE.MeshBasicMaterial( {color: this.xxColor} );
const xxMesh = new THREE.Mesh(xx, xxMaterial );
xxMesh.position.set(this.size/2,0,0);
xxMesh.rotation.z = -Math.PI / 2;
this.add( xxMesh );

// a cone geometry for the yy axis
const yy = new THREE.ConeGeometry( this.baseRadius, this.size, 32 );
const yyMaterial = new THREE.MeshBasicMaterial( {color: this.yyColor} );
const yyMesh = new THREE.Mesh(yy, yyMaterial );
yyMesh.position.set(0, this.size/2,0);
this.add( yyMesh );

// a cone geometry for the zz axis
const zz = new THREE.ConeGeometry( this.baseRadius, this.size, 32 );
const zzMaterial = new THREE.MeshBasicMaterial( {color: this.zzColor} );
const zzMesh = new THREE.Mesh(zz, zzMaterial );
zzMesh.position.set(0,0,this.size/2);
zzMesh.rotation.x = Math.PI / 2;
this.add( zzMesh );

// an axis helper
const axesHelper = new THREE.AxesHelper( 5 );
axesHelper.setColors ( new THREE.Color( this.xxColor ), new THREE.Color( this.yyColor ), new THREE.Color( this.zzColor ))
this.add( axesHelper );
}
}
117 changes: 117 additions & 0 deletions backend/static/js/game/Ball.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import * as THREE from 'three';
import { BALL_SPEED_FACTOR, BALL_START_SPEED, BALL_RADIUS,
PADDLE_SEMI_HEIGHT, PADDLE_SEMI_LENGTH } from './macros.js';

export class Ball extends THREE.Object3D {
constructor ({ radius, color, speed }) {
super();

this.radius = radius || BALL_RADIUS;
this.speed = speed || {'x': BALL_START_SPEED.x, 'y': BALL_START_SPEED.y};
this.rally = 0;
this.ball = null;
this.build();
this.reset();
}

build() {
this.ball = new THREE.Mesh(
new THREE.SphereGeometry(this.radius),
new THREE.MeshNormalMaterial()
);

this.add(this.ball);
}

move(arcade) {
const { arena, player, enemy } = arcade;

this.position.x += this.speed.x;
this.position.y += this.speed.y;

this.collideWithVerticalBounds(arena);
this.collideWithPaddle(player.paddle, true);
this.collideWithPaddle(enemy.paddle, false);
return this.collidedWithGoals(arena, player, enemy);
}

collidedWithGoals(arena, player, enemy) {
const { rightBoundary, leftBoundary } = arena;

if (this.position.x - this.radius <= leftBoundary.position.x)
{
this.reset();
return player;
}
else if (this.position.x + this.radius >= rightBoundary.position.x)
{
this.reset();
return enemy;
}
return null;
}

collideWithVerticalBounds(arena) {
const { upperBoundary, lowerBoundary } = arena;

if (this.position.y + this.radius >= upperBoundary.position.y)
this.speed.y = -Math.abs(this.speed.y);
else if (this.position.y - this.radius <= lowerBoundary.position.y)
this.speed.y = Math.abs(this.speed.y);
}

collideWithPaddle(paddle, isPlayer){
const paddleRange = {
'x': {
'start': paddle.position.x - PADDLE_SEMI_LENGTH,
'end': paddle.position.x + PADDLE_SEMI_LENGTH
},
'y': {
'start': paddle.position.y - PADDLE_SEMI_HEIGHT,
'end': paddle.position.y + PADDLE_SEMI_HEIGHT
}
}
const ballRange = {
'x': {
'start': this.position.x - BALL_RADIUS,
'end': this.position.x + BALL_RADIUS
},
'y': {
'start': this.position.y - BALL_RADIUS,
'end': this.position.y + BALL_RADIUS
}
}

const minX = paddleRange.x.start < ballRange.x.start ? paddleRange.x : ballRange.x;
const maxX = minX == paddleRange.x ? ballRange.x : paddleRange.x;
const minY = paddleRange.y.start < ballRange.y.start ? paddleRange.y : ballRange.y;
const maxY = minY == paddleRange.y ? ballRange.y : paddleRange.y;

if (minX.end < maxX.start || minY.end < maxY.start)
return ;

//! - Change ball speed according to the speed of the paddle at the time
if (isPlayer) {
this.position.x = paddle.position.x + PADDLE_SEMI_LENGTH + this.radius;
this.speed.x = Math.abs(this.speed.x) + BALL_SPEED_FACTOR;
}
else {
this.position.x = paddle.position.x - PADDLE_SEMI_LENGTH - this.radius;
this.speed.x = -(Math.abs(this.speed.x) + BALL_SPEED_FACTOR);
}

this.rally += 1;
}

reset() {
this.rally = 0;
this.speed.x = BALL_START_SPEED.x;
this.speed.y = BALL_START_SPEED.y;
this.position.set(0, 0, 0);
}

dispose() {
this.ball.geometry.dispose();
this.ball.material.dispose();
}
}
Loading

0 comments on commit be4c2eb

Please sign in to comment.