From ae27e5c611760bf7a71ebc3d1a24d58bed853990 Mon Sep 17 00:00:00 2001 From: Faruk Hammoud <farukhammoud@gmail.com> Date: Tue, 17 Mar 2020 10:38:58 +0100 Subject: [PATCH] collision implementation --- automafut_1.py | 10 ++++ automafut_2.py | 10 ++++ ball.py | 40 ++++++++++++++ game.py | 51 ++++++++++++++++++ online_game.py | 56 ++++++++++++++++++++ player.py | 35 +++++++++++++ stadium/automaplayer.pde | 27 ++++++++++ stadium/ball.pde | 54 +++++++++++++++++++ stadium/game.pde | 85 ++++++++++++++++++++++++++++++ stadium/player.pde | 73 ++++++++++++++++++++++++++ stadium/socket.pde | 66 +++++++++++++++++++++++ stadium/stadium.pde | 110 +++++++++++++++++++++++++++++++++++++++ stadium/team.pde | 59 +++++++++++++++++++++ team.py | 30 +++++++++++ 14 files changed, 706 insertions(+) create mode 100644 automafut_1.py create mode 100644 automafut_2.py create mode 100644 ball.py create mode 100644 game.py create mode 100644 online_game.py create mode 100644 player.py create mode 100644 stadium/automaplayer.pde create mode 100644 stadium/ball.pde create mode 100644 stadium/game.pde create mode 100644 stadium/player.pde create mode 100644 stadium/socket.pde create mode 100644 stadium/stadium.pde create mode 100644 stadium/team.pde create mode 100644 team.py diff --git a/automafut_1.py b/automafut_1.py new file mode 100644 index 0000000..d84b8a1 --- /dev/null +++ b/automafut_1.py @@ -0,0 +1,10 @@ +from online_game import OnlineGame + +def naive_ia(game): + return [1,1,1,1,1,1,1,1,1,1,1] + +game = OnlineGame('127.0.0.1',12345) # Server's address +game.connect() +game.set_ia(game.team,naive_ia) + +game.play() \ No newline at end of file diff --git a/automafut_2.py b/automafut_2.py new file mode 100644 index 0000000..d84b8a1 --- /dev/null +++ b/automafut_2.py @@ -0,0 +1,10 @@ +from online_game import OnlineGame + +def naive_ia(game): + return [1,1,1,1,1,1,1,1,1,1,1] + +game = OnlineGame('127.0.0.1',12345) # Server's address +game.connect() +game.set_ia(game.team,naive_ia) + +game.play() \ No newline at end of file diff --git a/ball.py b/ball.py new file mode 100644 index 0000000..d9360df --- /dev/null +++ b/ball.py @@ -0,0 +1,40 @@ +class Ball: + def __init__(self): + self.set_velocity(0,-1) + + def set_position(self,pos_x, pos_y): + self.pos_x = pos_x + self.pos_y = pos_y + + def set_velocity(self,vel_x,vel_y): + self.vel_x = vel_x + self.vel_y = vel_y + + def run(self,delta_t): + self.pos_x += self.vel_x*delta_t + self.pos_y += self.vel_y*delta_t + self.verify_borders() + + def verify_borders(self): + if self.pos_x < -100: + self.pos_x = -100 + self.vel_x = - self.vel_x + + if self.pos_x > 100: + self.pos_x = 100 + self.vel_x = - self.vel_x + + if self.pos_y < -50: + self.pos_y = -50 + self.vel_y = - self.vel_y + + if self.pos_y > 50: + self.pos_y = 50 + self.vel_y = - self.vel_y + + def get_pos_x(self): + return self.pos_x + + def get_pos_y(self): + return self.pos_y + \ No newline at end of file diff --git a/game.py b/game.py new file mode 100644 index 0000000..23593ff --- /dev/null +++ b/game.py @@ -0,0 +1,51 @@ +from team import Team +from ball import Ball +class Game: + def __init__(self): + #self.automaplayer_1 = AutomaPlayer(True) + #self.automaplayer_2 = AutomaPlayer(True) + self.team_1 = Team() + self.team_2 = Team() + self.ball = Ball() + self.on = False + + def start(self): + self.on = True + + def ready(self): + return False + + def run(self,delta_t): + self.ball.run(delta_t) + + def verify_colision(self): + pass + + def verify_borders(self): + self.team_1.verify_borders() + self.team_2.verify_borders() + + def set_ia(self,team,ia): + if team == 1: + self.team_1.set_ia(ia) + if team == 2: + self.team_2.set_ia(ia) + + def output(self,team): + if team == 1: + return self.team_1.ia(self) + if team == 2: + return self.team_2.ia(self) + + def input(self): + input = [] + for i in range(5): + input.append(self.team_1.players[i].get_pos_x()) + input.append(self.team_1.players[i].get_pos_y()) + for i in range(5): + input.append(self.team_1.players[i].get_pos_x()) + input.append(self.team_1.players[i].get_pos_y()) + input.append(self.ball.get_pos_x()) + input.append(self.ball.get_pos_y()) + return input + \ No newline at end of file diff --git a/online_game.py b/online_game.py new file mode 100644 index 0000000..86d7463 --- /dev/null +++ b/online_game.py @@ -0,0 +1,56 @@ +import socket # for socket +import sys +import json + +from game import Game + +class OnlineGame(Game): + + def __init__(self,server_ip,port,*args): + super().__init__(*args) + self.server_ip = server_ip + self.port = port + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.team = 1 + + def send_message(self,d): + try: + b = json.dumps(d).encode('utf-8') + self.sock.sendall(b) + st = str(self.sock.recv(4096), 'utf-8')#.split(';') + #print(st) + return st + except socket.error as err: + print ("socket creation failed with error",err) + return None + + def connect(self): + self.sock.connect((self.server_ip, self.port)) + d = {'msg_type':'[GET] Connection Request'} + self.team = int(self.send_message(d)) + print('Connected as team '+str(self.team)) + + def get_input(self): + d = {'msg_type':'[GET] Game State Request'} + r = self.send_message(d) + if (not r is None): + r = r.split(';') + input = [float(r[i]) for i in range(22)] + for i in range(5): + self.team_1.players[i].set_position(input[2*i],input[2*i+1]) + self.team_2.players[i].set_position(input[10+2*i],input[10+2*i+1]) + self.ball.set_position(input[20],input[21]) + + def send_output(self): + d = {'msg_type':'[POST] Refresh State','team':str(self.team),'output':str(self.output(self.team))} + self.send_message(d) + + def play(self): + while(True): + self.get_input() + self.send_output() + + + + + \ No newline at end of file diff --git a/player.py b/player.py new file mode 100644 index 0000000..b912b53 --- /dev/null +++ b/player.py @@ -0,0 +1,35 @@ +class Player: + + def __init__(self,goal_keeper): + self.name = "" + self.goal_keeper = goal_keeper + self.angle = 0 + + def set_direction(self,angle): + self.angle = angle + + def set_position(self,pos_x, pos_y): + self.pos_x = pos_x + self.pos_y = pos_y + + def get_pos_x(self): + return self.pos_x + + def get_pos_y(self): + return self.pos_y + + def verify_borders(self): + if (self.pos_x < -100): + self.pos_x = -100 + + if (self.pos_x > 100): + self.pos_x = 100 + + if (self.pos_y < -50): + self.pos_y = -50 + + if (self.pos_y > 50): + self.pos_y = 50 + + + diff --git a/stadium/automaplayer.pde b/stadium/automaplayer.pde new file mode 100644 index 0000000..0641a21 --- /dev/null +++ b/stadium/automaplayer.pde @@ -0,0 +1,27 @@ +class AutomaPlayer{ + String name; + Client client; + boolean connected; + + AutomaPlayer() { + this.connected = false; + } + void set_client(Client c){ + this.client = c; + } + void set_name(String name){ + this.name = name; + } + void say_hello(){ + client.write("Hello!"); + } + boolean connected(){ + return this.connected; + } + void set_connected(boolean connected){ + this.connected = connected; + } + void run(){ + + } +} diff --git a/stadium/ball.pde b/stadium/ball.pde new file mode 100644 index 0000000..54a698b --- /dev/null +++ b/stadium/ball.pde @@ -0,0 +1,54 @@ +class Ball { + float pos_x; + float pos_y; + float vel_x; + float vel_y; + Ball() { + this.set_velocity(0,-10); + } + void set_position(float pos_x, float pos_y) { + this.pos_x = pos_x; + this.pos_y = pos_y; + this.vel_y = -1; + } + void set_velocity(float vel_x, float vel_y) { + this.vel_x = vel_x; + this.vel_y = vel_y; + } + void run(float delta_t) { + this.pos_x += this.vel_x*delta_t; + this.pos_y += this.vel_y*delta_t; + this.verify_borders(); + } + void verify_borders() { + if (this.pos_x < -100) { + this.pos_x = -100; + this.vel_x = - this.vel_x; + } + + if (this.pos_x > 100) { + this.pos_x = 100; + this.vel_x = - this.vel_x; + } + + if (this.pos_y < -50) { + this.pos_y = -50; + this.vel_y = - this.vel_y; + } + if (this.pos_y > 50) { + this.pos_y = 50; + this.vel_y = - this.vel_y; + } + } + float get_pos_x() { + return this.pos_x; + } + float get_pos_y() { + return this.pos_y; + } + void show() { + noStroke(); + fill(255, 161, 31, 122+122*sin(millis()/50.0)); + ellipse(this.pos_x, this.pos_y, 3, 3); + } +} diff --git a/stadium/game.pde b/stadium/game.pde new file mode 100644 index 0000000..fa7b106 --- /dev/null +++ b/stadium/game.pde @@ -0,0 +1,85 @@ +class Game { + + Team team_1; + Team team_2; + Ball ball; + Game() { + this.team_1 = new Team(); + this.team_2 = new Team(); + this.ball = new Ball(); + } + void keep_distance(Player player_1, boolean inverted_1, Player player_2, boolean inverted_2) { + int s1 = 1; + int s2 = 1; + if (inverted_1){ + s1 = -1; + } + if (inverted_2){ + s2 = -1; + } + float xm = s1*player_1.get_pos_x()/2.0 + s2*player_2.get_pos_x()/2.0; + float ym = player_1.get_pos_y()/2.0 + player_2.get_pos_y()/2.0; + float dx = s1*player_1.get_pos_x() - xm; + float dy = player_1.get_pos_y() - ym; + float n = sqrt(pow(dx, 2)+pow(dy, 2)); + + if (n < 6) { + dx *= 6/n; + dy *= 6/n; + player_1.set_position(s1*(xm+dx), ym+dy); + player_2.set_position(s2*(xm-dx), ym-dy); + } + } + void verify_colision() { + Player[] players = new Player[10]; + for (int i=0; i<5; i++) { + players[i] = this.team_1.players[i]; + players[5+i] = this.team_2.players[i]; + } + for (int i=0; i<10; i++) { + for (int j=0; j<10; j++) { + if (i != j) { + keep_distance(players[i], i>=5, players[j],j>=5); + } + } + } + } + + void verify_borders() { + this.team_1.verify_borders(); + this.team_2.verify_borders(); + } + void refresh_team(int team, float[] output) { + if (team == 1) { + this.team_1.refresh_team(output); + } else if (team == 2) { + this.team_2.refresh_team(output); + } + } + float[] input() { + float[] input = new float[22]; + for (int i=0; i<5; i++) { + input[2*i] = this.team_1.players[i].get_pos_x(); + input[2*i+1] = this.team_1.players[i].get_pos_y(); + input[10+2*i] = this.team_1.players[i].get_pos_x(); + input[10+2*i+1] = this.team_1.players[i].get_pos_y(); + } + input[20] = this.ball.get_pos_x(); + input[21] = this.ball.get_pos_y(); + return input; + } + void run(float delta_t) { + this.ball.run(delta_t); + this.team_1.run(delta_t); + this.team_2.run(delta_t); + this.verify_colision(); + } + void show() { + this.team_1.show(); + pushMatrix(); + scale(-1, 1); + this.team_2.show(); + popMatrix(); + this.ball.show(); + } +} diff --git a/stadium/player.pde b/stadium/player.pde new file mode 100644 index 0000000..571e6ae --- /dev/null +++ b/stadium/player.pde @@ -0,0 +1,73 @@ +class Player { + String name; + boolean goal_keeper; + color _color; + float pos_x; + float pos_y; + float vel; + float angle; + Player(boolean goal_keeper) { + this.name = ""; + this.goal_keeper = goal_keeper; + this._color = color(0); + this.angle = 0; + } + void set_direction(float angle) { + this.angle = angle; + } + void set_velocity(float vel) { + this.vel = vel; + } + void set_color(color _color) { + this._color = _color; + } + int set_name(String name) { + this.name = name; + return 1; + } + void set_position(float pos_x, float pos_y) { + this.pos_x = pos_x; + this.pos_y = pos_y; + } + float get_pos_x() { + return this.pos_x; + } + float get_pos_y() { + return this.pos_y; + } + void verify_borders() { + if (this.pos_x < -93) { + this.pos_x = -93; + } + if (this.pos_x > 93) { + this.pos_x = 93; + } + if (this.pos_y < -43) { + this.pos_y = -43; + } + if (this.pos_y > 43) { + this.pos_y = 43; + } + } + void run(float delta_t) { + this.pos_x += this.vel*cos(angle)*delta_t; + this.pos_y += this.vel*sin(angle)*delta_t; + this.verify_borders(); + } + void showPos(){ + textSize(2); + fill(255,0,0); + text(str(this.pos_x)+","+str(this.pos_y),0,0); + } + void show() { + noStroke(); + fill(this._color); + pushMatrix(); + translate(this.pos_x, this.pos_y); + arc(0, 0, 12, 12, this.angle+PI/16, this.angle+2*PI-PI/16); + fill(0); + ellipse(0, 0, 10, 10); + //this.showPos(); + popMatrix(); + } +} diff --git a/stadium/socket.pde b/stadium/socket.pde new file mode 100644 index 0000000..f23305f --- /dev/null +++ b/stadium/socket.pde @@ -0,0 +1,66 @@ +Server s; +Client c; +String input; +int data[]; + +class Socket { + Socket() { + } + int listen_client() { + c = s.available(); + if (c != null) { + input = c.readString(); + JSONObject json = parseJSONObject(input); + if (json == null) { + println("JSONObject could not be parsed"); + } else { + String msg_type = json.getString("msg_type"); + if (msg_type.equals("[GET] Connection Request")) { + println("\'[GET] Connection Request\' received from "+c.ip()) ; + this.connect(c); + //float x = float(json.getString("x")); + } + else if (msg_type.equals("[GET] Game State Request")) { + println("\'[GET] Game State Request\' received from "+c.ip()) ; + this.send_input(c); + } + else if (msg_type.equals("[POST] Refresh State")) { + println("\'[POST] Refresh State\' received from "+c.ip()) ; + this.refresh_team(int(json.getString("team")), json.getString("output")); + c.write("Received!"); + } + else{ + println("\'unrecognized message\' received from "+c.ip()) ; + println(input); + } + } + } + return 1; + } + void refresh_team(int team, String input) { + String[] list = split(input.substring(1,input.length()-1), ','); + if (list.length != 11) { + println("Problem with refresh team "); + println(list); + } else { + float[] output = new float[11]; + for (int i =0; i<11; i++) { + output[i] = float(list[i]); + } + game.refresh_team(team,output); + } + } + + void connect(Client c) { + int r = stadium.connect(c, "no_name"); + c.write(str(r)); + } + void send_input(Client c) { + String s = ""; + float[] input = game.input(); + for (int i = 0; i<22; i++) { + s += str(input[i])+";"; + } + c.write(s); + } +} diff --git a/stadium/stadium.pde b/stadium/stadium.pde new file mode 100644 index 0000000..74e219a --- /dev/null +++ b/stadium/stadium.pde @@ -0,0 +1,110 @@ +import processing.net.*; + +Game game = new Game(); +Stadium stadium = new Stadium(game, width, height); +Socket socket = new Socket(); + +class Stadium { + + AutomaPlayer automaplayer_1; + AutomaPlayer automaplayer_2; + int size_x; + int size_y; + Game game; + + Stadium(Game game, int size_x, int size_y) { + this.automaplayer_1 = new AutomaPlayer(); + this.automaplayer_2 = new AutomaPlayer(); + this.size_x = size_x; + this.size_y = size_y; + this.game = game; + } + int connect(Client c, String name) { + if (this.automaplayer_1.connected()) { + if (this.automaplayer_2.connected()) { + return 0; + } else { + this.automaplayer_2.set_client(c); + this.automaplayer_2.set_name(name); + this.automaplayer_2.set_connected(true); + return 2; + } + } else { + this.automaplayer_1.set_client(c); + this.automaplayer_1.set_name(name); + this.automaplayer_1.set_connected(true); + return 1; + } + } + void say_hello() { + this.automaplayer_1.say_hello(); + this.automaplayer_2.say_hello(); + } + void draw_borders() { + noStroke(); + fill(255, 161, 31); + rect(3, 3, 5, this.size_y-6); //laterals + rect(this.size_x-8, 3, 5, this.size_y-6); + rect(3, 3, this.size_x-6, 5);//up + rect(3, this.size_y-8, this.size_x-6, 5);//down + fill(0); + rect(3, this.size_y*(2.0/8.0), 5, this.size_y*(4/8.0));//goal + rect(this.size_x-8, this.size_y*(2.0/8.0), 5, this.size_y*(4/8.0)); + noFill(); + stroke(255, 161, 31); + strokeWeight(5); + arc(5, this.size_y/2, this.size_x/3, this.size_x/3, -PI/2, +PI/2);//goal + arc(this.size_x-6, this.size_y/2, this.size_x/3, this.size_x/3, +PI/2, 2*PI-PI/2); + triangle(this.size_x/2-3, 8, this.size_x/2+3, 8, this.size_x/2, 12); + triangle(this.size_x/2-3, this.size_y-8, this.size_x/2+3, this.size_y-8, this.size_x/2, this.size_y-12); + } + void draw_layout() { + fill(255, 161, 31); + textSize(26); + text("Automafut v1.0", 5, 27); + text(str(this.game.team_1.get_score())+"x"+str(this.game.team_1.get_score()), this.size_x/2-30, 27); + strokeWeight(2); + noFill(); + if (this.automaplayer_1.connected()) { + stroke(0, 255, 0); + } else { + stroke(255, 0, 0); + } + ellipse(this.size_x-50, 15, 26, 26); + if (this.automaplayer_2.connected()) { + stroke(0, 255, 0); + } else { + stroke(255, 0, 0); + } + ellipse(this.size_x-20, 15, 26, 26); + } + void show() { + background(0); + this.draw_layout(); + translate(0, 30); + this.draw_borders(); + pushMatrix(); + scale(this.size_x/200.0, this.size_y/100.0); + translate(100, 50); + this.game.show(); + popMatrix(); + } + void run() { + if (this.automaplayer_1.connected() && this.automaplayer_2.connected()) { + this.game.run(0.1); + //this.say_hello(); // server only answers + } + + } +} +void setup() { + size(800, 430); + stadium.size_x = width; + stadium.size_y = height-30; + s = new Server(this,12345); // Start a simple server on a port +} +void draw() { + socket.listen_client(); + stadium.show(); + stadium.run(); +} diff --git a/stadium/team.pde b/stadium/team.pde new file mode 100644 index 0000000..5d4ed71 --- /dev/null +++ b/stadium/team.pde @@ -0,0 +1,59 @@ +class Team { + + Player[] players = new Player[5]; + int score = 0; + + Team() { + this.players[0] = new Player(true); + for (int i = 1; i<5; i++) { + this.players[i] = new Player(false); + } + this.initial_position(); + this.set_color(color(random(255), random(255), random(255))); + } + void refresh_team(float[] output) { + for (int i = 0; i<5; i++) { + this.players[i].set_velocity(output[i*2]); + this.players[i].set_direction(output[i*2+1]); + } + } + void initial_position() { + this.players[0].set_position(-80, 0); + this.players[1].set_position(-50, -30); + this.players[2].set_position(-50, 30); + this.players[3].set_position(-20, -20); + this.players[4].set_position(-20, 20); + } + int insert_names(String[] names) { + for (int i = 0; i<5; i++) { + this.players[i].set_name(names[i]); + } + return 1; + } + int get_score() { + return this.score; + } + void add_score() { + this.score +=1; + } + void verify_borders() { + for (int i = 0; i<5; i++) { + this.players[i].verify_borders(); + } + } + void set_color(color _color) { + for (int i = 0; i<5; i++) { + this.players[i].set_color(_color); + } + } + void run(float delta_t) { + for (int i = 0; i<5; i++) { + this.players[i].run(delta_t); + } + } + void show() { + for (int i = 0; i<5; i++) { + this.players[i].show(); + } + } +} diff --git a/team.py b/team.py new file mode 100644 index 0000000..d6e795c --- /dev/null +++ b/team.py @@ -0,0 +1,30 @@ +from player import Player +class Team: + + def __init__(self): + self.players = [] + self.ia = lambda x: None + self.players.append(Player(True)) + for i in range(1,5): + self.players.append(Player(False)) + self.initial_position() + self.score = 0 + + def set_ia(self,ia): + self.ia = ia + def get_score(self): + return self.score + + def add_score(self): + self.score += 1 + + def initial_position(self): + self.players[0].set_position(-80,0) + self.players[1].set_position(-50,-30) + self.players[2].set_position(-50,30) + self.players[3].set_position(-20,-20) + self.players[4].set_position(-20,20) + + def verify_borders(self): + for i in range(5): + self.players[i].verify_borders() -- GitLab