Sfoglia il codice sorgente

рефактор структуры

toomanysugar 3 anni fa
parent
commit
8a6987e70c

+ 126 - 0
cmd/web/connector.go

@@ -0,0 +1,126 @@
+
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"encoding/json"
+	"database/sql"
+	_ "github.com/go-sql-driver/mysql"
+)
+
+type ConnectionProperties struct {
+	User 	string
+	Pass 	string
+	Host	string
+	Db 		string
+}
+
+type connection struct {
+	dBOpenStr string
+}
+
+func (c *connection) Init(filepath string){
+	b, err := ioutil.ReadFile(filepath)
+    if err != nil {
+      fmt.Print(err)
+    }
+    propJson := string(b)
+	var connProperties ConnectionProperties
+
+	json.Unmarshal([]byte(propJson), &connProperties)
+	fmt.Printf("Connection data:\n%s\n%s\n%s\n%s\n", connProperties.User, connProperties.Pass,connProperties.Host,connProperties.Db)
+	c.dBOpenStr = connProperties.User + ":" + connProperties.Pass + "@tcp(" + connProperties.Host + ")/" + connProperties.Db
+	fmt.Printf("Connecting with:\n%s\n", c.dBOpenStr)
+	db, err := sql.Open("mysql", c.dBOpenStr)
+
+	if err != nil {
+		panic(err)
+	}
+
+	defer db.Close()
+}
+
+func (c connection) LogIn(username string, password string) bool{
+	fmt.Printf("Connecting with:\n%s\n", c.dBOpenStr)
+	db, err := sql.Open("mysql", c.dBOpenStr)
+
+	if err != nil {
+		panic(err)
+	}
+
+	defer db.Close()
+
+	var counter int
+	fmt.Printf("%s\n%s\n", username, password)
+	act_query := "SELECT count(*) FROM gosite.users WHERE username='" + username + "' AND password='" + password + "';"
+	db.QueryRow(act_query).Scan(&counter)
+	fmt.Println("we have", counter, "rows")
+    
+    if (counter == 0) {
+    	return false
+    }
+	return true
+
+}
+
+func (c connection) IsNameUsed(username string) bool {
+
+	db, err := sql.Open("mysql", c.dBOpenStr)
+	if err != nil {
+		panic(err)
+	}
+	defer db.Close()
+
+	var counter int
+	act_query := "SELECT count(*) FROM gosite.users WHERE username='" + username + "';"
+	db.QueryRow(act_query).Scan(&counter)
+    
+	if (counter == 0) {
+		fmt.Printf("Username unused\n")
+    	return false
+    }
+	fmt.Printf("Username used\n")
+	return true
+}
+
+func (c connection) SigInUser(username string, password string) bool {
+	db, err := sql.Open("mysql", c.dBOpenStr)  
+    if err != nil {
+        panic(err)
+    } 
+    defer db.Close()
+     
+    result, err := db.Exec("INSERT INTO gosite.users (username, password) values (?, ?)", username, password)
+    if err != nil{
+        panic(err)
+    }
+
+    rowsCount, _ := result.RowsAffected()
+    if (rowsCount == 1) {
+	    fmt.Printf("Lines changed: %d\n", rowsCount)
+	    return true
+    } else {
+    	return false
+    }
+}
+
+/*
+func main() {
+
+	var dBConnector connection
+
+	dBConnector.Init("config.json")
+	if (dBConnector.LogIn("Alex", "09Alex09")) {
+		fmt.Printf("Succesfull logIn\n")
+	} else {
+		fmt.Printf("logIn error\n")
+	}
+
+	if (dBConnector.LogIn("Alax", "09Alex09")) {
+		fmt.Printf("Succesfull logIn\n")
+	} else {
+		fmt.Printf("logIn error\n")
+	}
+}
+*/

+ 244 - 0
cmd/web/main.go

@@ -0,0 +1,244 @@
+
+package main 
+
+import (
+	"log"
+	
+	"os"
+	"time"
+	"fmt"
+	"net/http"
+	"html/template"
+	"github.com/gorilla/mux"
+	"github.com/gorilla/sessions"
+
+
+)
+
+type Page struct {
+    Title string
+    Body  []byte
+}
+
+var (
+	logger	*log.Logger
+	dBConnector connection
+	sessionsStore = sessions.NewCookieStore([]byte("mysecretcookie"))
+	indexTemplate = template.Must(template.ParseFiles("ui\\templates\\index.html"))
+	logInTemplate = template.Must(template.ParseFiles("ui\\templates\\login.html"))
+	signInTemplate = template.Must(template.ParseFiles("ui\\templates\\signin.html"))
+	gameTemplate = template.Must(template.ParseFiles("ui\\templates\\game.html"))
+)
+
+func indexHandler(w http.ResponseWriter, r *http.Request) {
+	data := struct {
+		User string
+		Title string
+		Items []string
+	}{
+		User: "",
+		Title: "My page",
+		Items: []string{
+			"My photos",
+			"My blog",
+			"More",
+		},
+	}
+	
+
+	session, _ := sessionsStore.Get(r, "session")
+
+	var (
+		password string
+		ok3 bool
+	)
+
+	untyped, ok := session.Values["username"]
+	if ok {
+		username, ok1 := untyped.(string)
+		if ok1 {
+			data.User = username
+			untyped, ok2 := session.Values["password"]
+			if ok2 {
+				password, ok3 = untyped.(string)
+				
+			} 
+		}
+	} 
+	
+
+	indexTemplate.Execute(w, data)
+
+	if ok3 {
+		w.Write([]byte(password))
+	}
+
+}
+
+func indexPostHandler(w http.ResponseWriter, r *http.Request) {
+	fmt.Print("POST")
+}
+
+func logInGetHandler(w http.ResponseWriter, r *http.Request) {
+	data := struct {
+		Username string
+		Password string
+		Error string
+	}{
+		Username: "",
+		Password: "",
+		Error: "",
+	}
+	logInTemplate.Execute(w, data)
+}
+
+func logInPostHandler(w http.ResponseWriter, r *http.Request) {
+	r.ParseForm()
+	username := r.PostForm.Get("username")
+	password := r.PostForm.Get("password")
+
+	if (dBConnector.LogIn(username, password)){
+
+		session, _ := sessionsStore.Get(r, "session")
+		session.Values["username"] = username
+		session.Values["password"] = password
+
+		session.Save(r,w)
+		fmt.Printf("%s\n%s\n",username,password)
+		http.Redirect(w, r, "/", http.StatusFound)
+	} else {
+		data := struct {
+			Username string
+			Password string
+			Error string
+		}{
+			Username: username,
+			Password: password,
+			Error: "Неверный логин либо пароль",
+		}
+		fmt.Printf("Login error")
+		logInTemplate.Execute(w, data)
+		//w.Write([]byte("Login error"))
+	}
+}
+
+func logOutGetHandler(w http.ResponseWriter, r *http.Request) {
+	session, _ := sessionsStore.Get(r, "session")
+	session.Options.MaxAge = -1
+	session.Save(r, w)
+	
+	untyped, ok := session.Values["username"]
+	if ok {
+		username, ok1 := untyped.(string)
+		if ok1 {
+			logger.Printf("User %s loged out", username)
+		}
+	}
+
+	http.Redirect(w, r, "/", http.StatusFound)
+}
+
+func signInGetHandler(w http.ResponseWriter, r *http.Request) {
+	signInTemplate.Execute(w, nil)
+}
+
+func signInPostHandler(w http.ResponseWriter, r *http.Request) {
+	r.ParseForm()
+	username := r.PostForm.Get("username")
+	password := r.PostForm.Get("password")
+	passwordRepeat := r.PostForm.Get("password-repeat")
+
+	data := struct {
+		Username string
+		Password string
+		PasswordRepeat string
+		Error string
+	}{
+		Username: username,
+		Password: password,
+		PasswordRepeat: passwordRepeat,
+		Error: "",
+	}
+
+	if dBConnector.IsNameUsed(username) {
+		data.Error = "Имя пользователя занято"
+	} else {
+		if (password != passwordRepeat) {
+			data.Error = "Введенные пароли не совпадают"
+		} else {
+			if dBConnector.SigInUser(username,password) {
+				
+				session, _ := sessionsStore.Get(r, "session")
+				session.Values["username"] = username
+				session.Values["password"] = password
+				session.Save(r,w)
+
+				http.Redirect(w, r, "/", http.StatusFound)
+			} else {
+				data.Error = "Произошла внутреняя ошибка при регистрации нового пользователя"
+			}
+		}
+	}
+	signInTemplate.Execute(w, data)
+}
+
+func gameGetHandler(w http.ResponseWriter, r *http.Request) {
+	gameTemplate.Execute(w, nil)
+}
+
+func gamePostHandler(w http.ResponseWriter, r *http.Request){ //TODO запись score в таблицу
+	if err := r.ParseForm(); err != nil {
+		fmt.Fprintf(w, "ParseForm() err: %v", err)
+		return
+	}
+	fmt.Printf("Post from website! r.PostFrom = %v\n", r.PostForm)
+	score := r.FormValue("score")
+	fmt.Fprintf(w,"score = %s\n", score)
+	fmt.Printf("score = %s\n", score)
+}
+
+func createLogger() {
+	startTime := time.Now()
+	logFileName := "logs/go-site_log_" + startTime.Format("2006-01-02_15-04-05") + ".txt"
+	file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
+	logger = log.New(file, "logger: ", log.Lshortfile)
+  	
+  	if err != nil {
+        	log.Fatal(err)
+    	}
+
+}
+
+type user struct{
+    idusers int
+    username string
+    password string
+}
+
+
+func main() {
+	
+	
+
+	createLogger()
+
+	logger.Print("Hello, log file!")
+
+	requestRouter := mux.NewRouter()
+
+	
+    dBConnector.Init("config.json")
+    
+
+    requestRouter.HandleFunc("/", indexHandler).Methods("GET")
+    //requestRouter.HandleFunc("/", indexPostHandler).Methods("POST")		//Есть ли нужда в обработке POST для /
+    requestRouter.HandleFunc("/login/", logInGetHandler).Methods("GET")
+    requestRouter.HandleFunc("/login/", logInPostHandler).Methods("POST")
+    requestRouter.HandleFunc("/logout/", logOutGetHandler).Methods("GET")
+    requestRouter.HandleFunc("/signin/", signInGetHandler).Methods("GET")
+    requestRouter.HandleFunc("/signin/", signInPostHandler).Methods("POST")
+    requestRouter.HandleFunc("/game/", gameGetHandler).Methods("GET")
+    requestRouter.HandleFunc("/", gamePostHandler).Methods("POST")
+    http.Handle("/", requestRouter)
+    logger.Fatal(http.ListenAndServe(":8080", nil))
+}

+ 10 - 0
go.mod

@@ -0,0 +1,10 @@
+module go-site
+
+go 1.17
+
+require (
+	github.com/go-sql-driver/mysql v1.6.0 // indirect
+	github.com/gorilla/mux v1.8.0 // indirect
+	github.com/gorilla/securecookie v1.1.1 // indirect
+	github.com/gorilla/sessions v1.2.1 // indirect
+)

+ 636 - 0
ui/templates/game.html

@@ -0,0 +1,636 @@
+<!DOCTYPE html>
+<html>
+
+<head>	
+	<meta charset="UTF-8">
+	<title>Raid on river</title>
+	<style></style>
+</head>
+	<body>
+	<canvas id="gameCanvas" width="1280" height="720"></canvas>
+	<script type="text/javascript">
+		const FPS = 60;
+		const SCENE_SPEED = 3;
+		const SPEED_INCREASE = 0.2; //увеличение скорсоти на
+		const GEN_TIME = 5;
+		const LIFES = 1;
+		const PLANE_SIZE = 30; //plane height in pixels
+		const PLANE_ACCELERATION = 2/5; //TODO пока пиксели в секунду
+		const MISSLE_SPEED = 13; //TODO обдумать на размер сцены
+		const MISSLE_SIZEY = 20/3*2; //длина снаряда
+		const MISSLE_SIZEX = 5; //ширина снаряда
+		const SHOOT_COOLDOWN = 3/8; //в секундах
+		
+		const SHIPS_COUNT = 5; //начальное кол-во кораблей
+		const SHIP_SIZEY = 25; //высота корабля
+		const SHIP_SIZEX = 100; //ширина корабля
+		const CONTROL_START = 32;
+		const CONTROL_LEFT =  90; //90 - Z
+		const CONTROL_RIGHT = 88; //88 - X
+		const CONTROL_FIRE = 190; //190 - ,
+
+		const SHOW_BOUNDING = true;
+		const GOD = false;
+
+
+		/** @type {HTMLCanvasElement} */
+		var canv = document.getElementById("gameCanvas");
+		var ctx = canv.getContext("2d");
+
+		var score = 0;
+
+		var scene = { //хранит бэкраунд
+			lifes: LIFES,
+			speed: SCENE_SPEED,
+			gameOver: false,
+			genTimer: GEN_TIME * FPS,
+			blocks: []
+			//boundaries: []
+		}
+		addStartingBlock();
+
+		var plane;
+		newPlane();
+
+		var ships = [];
+		createShip();
+
+		//set up event handler
+		document.addEventListener("keydown", keyDown);
+		document.addEventListener("keyup", keyUp);
+
+		//game loop
+		setInterval(update, 1000 / FPS);
+
+		function addStartingBlock(){
+			var block = {
+				x: 0,
+				y: 0,
+				replaced: false,
+				boundaries: [],
+			} 
+			block.x = 0;
+			block.y = -3 * 720;
+			block.boundaries.push(addBounadry(0, block.y, 1280 / 4, 4 * 720));
+			block.boundaries.push(addBounadry(1280 - 1280 / 4, block.y, 1280 / 4, 4 * 720));
+
+			scene.blocks.push(block);
+		}
+
+		function addBounadry(bx,by,bw,bh){
+			var boundary = {
+				//replaced: false,
+				collision: {
+					x: bx,
+					y: by,
+					w: bw,
+					h: bh,
+				}
+			}
+			return boundary;
+		}
+
+		function createShip() {
+			ships = [];
+			for (var i = 0; i < 3; i++) {
+				var ship = newShip();
+				if (ship != null) {
+					ships.push(ship);
+				}
+			}
+		}
+
+		//key events
+		function keyDown(/** @type {KeyboardEvent} */ ev) {
+			switch (ev.keyCode) {
+				case CONTROL_LEFT: //Move to the left
+					if (!scene.gameOver){
+						plane.acceleration.negx = true;
+					}
+					break;
+				case CONTROL_RIGHT: //Move to the right
+					if (!scene.gameOver){
+						plane.acceleration.posx = true;
+					}
+					break;
+				case CONTROL_FIRE: //Fire the missle
+					if (!scene.gameOver){
+						plane.shooting = true;
+					}
+					break;
+				case CONTROL_START:
+					if (scene.gameOver){
+						newGame();
+					}
+					break;
+			}
+		}
+
+		function keyUp(/** @type {KeyboardEvent} */ ev) {
+			switch (ev.keyCode) {
+				case CONTROL_LEFT: //Move to the left
+					if (!scene.gameOver){
+						plane.acceleration.negx = false;
+					}
+					break;
+				case CONTROL_RIGHT: //Move to the right
+					if (!scene.gameOver){
+						plane.acceleration.posx = false;
+					}
+					break;
+				case CONTROL_FIRE: //Fire the missle
+					if (!scene.gameOver){
+						plane.shooting = false;
+					}
+					//plane.reload = false;
+					break;
+			}
+		}
+
+		function newGame() {
+			console.log("New Game!");
+			scene.blocks = [];
+			addStartingBlock();
+			newPlane();
+			createShip();
+			score = 0;
+			scene.gameOver = false;
+			scene.lifes = LIFES;
+			scene.speed = SCENE_SPEED;
+			scene.genTimer = GEN_TIME * FPS;
+		}
+
+		function newPlane() {
+			plane = {
+				x: canv.width / 2,
+				y: canv.height / 2 + 100,
+				r: PLANE_SIZE / 2,
+				a: 90 / 180 * Math.PI,
+				acceleration: {
+					posx: false,
+					negx: false,
+				},
+				speedx: 0,
+				shooting: false,
+				reload: false,
+				reloadtime: 0,
+				missles: [],
+				collision: {
+					x: 0,
+					y: 0,
+					w: PLANE_SIZE,
+					h: PLANE_SIZE,
+				},
+			}
+		}
+
+		function newShip(x) {
+			let direction
+			if (Math.floor(Math.random()*2) == 0) {
+				direction = -1; 
+			} else {
+				direction = 1;
+			}
+			var ship = {
+				x: 0,
+				y: 0 - SHIP_SIZEY,
+				a: direction,
+				collision: {
+					x: 0,
+					y: 0,
+					w: SHIP_SIZEX,
+					h: SHIP_SIZEY,
+				},
+			}
+			//console.log("shipgeneration");
+			var shipPosGeneration = 0;
+			while (shipPosGeneration != -1 && shipPosGeneration <= 10) {
+				ship.x = Math.floor(Math.random()*1280);
+				ship.collision.x = ship.x - SHIP_SIZEX / 2; 
+				shipPosGenerationInit = shipPosGeneration;
+				for (var i = scene.blocks.length - 1; i >= 0 ; i--) {
+					for (var j = scene.blocks[i].boundaries.length - 1; j >= 0 ; j--) {
+						if (checkRectangularCollision(ship.collision, scene.blocks[i].boundaries[j].collision)) {
+							shipPosGeneration++;
+							i = -1;
+							j = -1;
+						}
+					}
+				}
+				if (shipPosGeneration == shipPosGenerationInit) {
+					for (var i = ships.length - 1; i >= 0; i--){
+						if (checkRectangularCollision(ship.collision, ships[i].collision) ) {
+							shipPosGeneration++;
+							i = -1;
+						}
+					}
+				}
+				//console.log(shipPosGeneration);
+				if (shipPosGeneration == shipPosGenerationInit) {
+					shipPosGeneration = -1;
+				}
+
+			}
+			if (shipPosGeneration >= 10) {
+				return null;
+			}
+			console.log(ship.x);
+			return ship;
+		}
+
+		function shootMissle() {
+			if (!plane.reload && plane.shooting) {
+				plane.missles.push({
+					x: plane.x + 4 / 3 * plane.r * Math.cos(plane.a),
+					y: plane.y - 4 / 3 * plane.r * Math.sin(plane.a),
+					collision: {
+						x: plane.x + 4 / 3 * plane.r * Math.cos(plane.a) - MISSLE_SIZEX / 2,
+						y: plane.y - 4 / 3 * plane.r * Math.sin(plane.a),
+						w: MISSLE_SIZEX,
+						h: MISSLE_SIZEY,
+					},
+				})
+				console.log("*shoot*");
+				plane.reloadtime = SHOOT_COOLDOWN * FPS; 
+				plane.reload = true;
+			}
+
+		}
+
+		function death() {
+			scene.lifes--;
+			ships = [];
+			if (scene.lifes == 0) {
+				console.log("Game Over!"); //в функции gameOver
+				console.log("Your Score:");
+				console.log(score);
+				scene.gameOver = true;
+				scene.speed = 0;
+
+			}
+		}
+
+		function checkRectangularCollision(a, b){ //проверка коллизии 2х прямоугольных объекттов
+			if (a.x < b.x + b.w &&
+		        a.x + a.w > b.x &&
+		        a.y < b.y + b.h &&
+		        a.h + a.y > b.y) {
+				//console.log("collision detected");
+				return true
+			}
+			else {
+				//console.log("no collision");
+				return false;
+			}
+		}
+
+		function checkPlaneSceneCollision(x,y,c) { //проверка коллизии самолёта с сценой
+			var collsion = {
+				x: x + 4 / 3 * plane.r * Math.cos(plane.a) - PLANE_SIZE / 2,
+				y: y - 4 / 3 * plane.r * Math.sin(plane.a),
+				w: PLANE_SIZE,
+				h: PLANE_SIZE,
+			}
+
+			//plane.collision.x = 
+			//plane.collision.y = plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
+			var problem = false;
+			if  (collsion.x < c.x + c.w &&
+		        collsion.x + collsion.w > c.x &&
+		        collsion.y < c.y + c.h &&
+		        collsion.h + collsion.y > c.y) {
+				problem = true;
+			}
+			if (problem) {
+				if (collsion.x + PLANE_SIZE / 2 <= (c.x + c.w + PLANE_SIZE / 2) && collsion.x + PLANE_SIZE / 2 >= c.x + c.w / 2) { //левостороняя коллизия
+					return c.x + c.w + PLANE_SIZE / 2;
+				}
+				if (collsion.x + PLANE_SIZE / 2 > c.x - PLANE_SIZE / 2 && collsion.x + PLANE_SIZE / 2 < c.x + c.w / 2) { //правостороняя коллизия
+					return c.x - plane.r;
+				}
+
+			}
+			else {
+				return 0;
+			}
+			return 1280/2;
+		}
+
+
+		function drawCollision(a, color) { //Рисует коллизию объекта
+			ctx.strokeStyle = color;
+			ctx.strokeRect(a.x, a.y, a.w, a.h);
+		}
+
+		function update() {
+			//draw scene
+			ctx.fillStyle = "black";
+			ctx.fillRect(0,0, canv.width, canv.height)
+
+			//отрисовка бэкграунда
+			for (var i = 0; i < scene.blocks.length; i++) {
+				for (var j = 0; j < scene.blocks[i].boundaries.length; j++) {
+					if (SHOW_BOUNDING) {
+						drawCollision(scene.blocks[i].boundaries[j].collision,"green");
+					}
+				}
+			}
+
+
+			//проверка коллизии
+			//коллизия кораблей с самолётом
+			for (var i = 0; i < ships.length; i++){ 
+				if (checkRectangularCollision(ships[i].collision, plane.collision)) {
+					console.log("Plane collading with ship no. " + i);
+					if (!GOD) {
+						death();
+					} 
+				}
+			}
+			//коллизия снаряда с кораблями
+			for (var i = ships.length - 1; i >= 0; i--){
+				for (var j = plane.missles.length - 1; j >= 0; j--) {	
+					if (checkRectangularCollision(ships[i].collision, plane.missles[j].collision)) {
+						console.log("Missle no. " + j + " collading with ship no. " + i )
+						plane.missles.splice(j,1);
+						ships.splice(i,1);
+						score += 30;
+						console.log("New score: " + score);
+						var ship = newShip();
+						if (ship != null) {
+							ships.push(ship);
+						}
+					}
+				}
+			}
+
+
+			//move scene
+			//движение бэкграунда
+			for (var i = scene.blocks.length - 1; i >= 0; i--) {
+				if (scene.blocks[i].y > 720 ) { //удаление ушедшего блока
+					scene.blocks.splice(i,1);
+					continue;
+				}
+				if (scene.blocks[i].y > 0 && !scene.blocks[i].replaced)  { //подстановка нового блока
+
+					var block = {
+						x: 0,
+						y: scene.blocks[i].y - (4 * 720) + scene.speed,
+						replaced: false,
+						boundaries: [],
+					}
+					block.boundaries.push(addBounadry(0, block.y, 1280 / 4, 4 * 720));
+					block.boundaries.push(addBounadry(1280 - 1280 / 4, block.y, 1280 / 4, 4 * 720));
+					block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8, block.y + 720, 1280 / 4, 2 * 720));
+					block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8 + PLANE_SIZE / 2, block.y + 720 - PLANE_SIZE / 2, 1280 / 4 - PLANE_SIZE, 2 * 720 + PLANE_SIZE));
+					block.boundaries.push(addBounadry(1280 / 2 - 1280 / 8 + PLANE_SIZE, block.y + 720 - PLANE_SIZE, 1280 / 4 - 2 * PLANE_SIZE, 2 * 720 + 2 * PLANE_SIZE));
+					scene.blocks.push(block);
+					
+					scene.blocks[i].replaced = true;
+				} 
+
+				//движение блока, его баундари(TODO) и коллизий внутри
+				scene.blocks[i].y += scene.speed;
+
+				for (var j = scene.blocks[i].boundaries.length - 1; j >= 0; j--) {
+					scene.blocks[i].boundaries[j].collision.y += scene.speed; //TODO двигать не только коллизию
+				}
+			}
+
+
+			scene.genTimer--;
+			//console.log(scene.genTimer);
+			if (scene.genTimer == 0 && !scene.gameOver) {
+				if (ships.length < SHIPS_COUNT) {
+					var ship = newShip();
+					if (ship != null) {
+						ships.push(ship);
+					}
+				}
+				scene.speed += SPEED_INCREASE;
+				console.log("New speed:");
+				console.log(scene.speed);
+				scene.genTimer = 5 * FPS;
+			}
+
+			//двигаем объекты
+			//двигаем корабли
+			for (var i = ships.length - 1; i >= 0 ; i--){
+				if (ships[i].y > 720 + SHIP_SIZEY / 2) { //удаление снарядов за экраном
+					ships.splice(i,1);
+					var ship = newShip();
+					if (ship != null) {
+						ships.push(ship);
+					}
+					continue;
+				}
+				ships[i].y += scene.speed;
+				ships[i].collision.x = ships[i].x - SHIP_SIZEX / 2;
+				ships[i].collision.y = ships[i].y - SHIP_SIZEY / 2;
+				//console.log(ships[i].collision.w);
+			}
+
+			//рисуем корабли 
+			for (var i = 0; i < ships.length ; i++){
+
+				ctx.beginPath();
+				ctx.moveTo( //корабля
+					ships[i].x + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y - SHIP_SIZEY / 2
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * (SHIP_SIZEX / 20 ) + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y - SHIP_SIZEY / 2
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * (SHIP_SIZEX / 13) + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y - SHIP_SIZEY / 4
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * (SHIP_SIZEX / 5) + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y - SHIP_SIZEY / 4
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * (SHIP_SIZEX / 3) + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y + SHIP_SIZEY / 6
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * SHIP_SIZEX / 2,
+					ships[i].y + SHIP_SIZEY / 6
+				)
+				ctx.lineTo(
+					ships[i].x - ships[i].a * SHIP_SIZEX * 2 / 7,
+					ships[i].y + SHIP_SIZEY / 2
+				)
+				ctx.lineTo(
+					ships[i].x + ships[i].a * SHIP_SIZEX / 3,
+					ships[i].y + SHIP_SIZEY / 2
+				)
+				ctx.lineTo(
+					ships[i].x + ships[i].a * SHIP_SIZEX / 2 ,
+					ships[i].y + SHIP_SIZEY / 6
+				)
+				ctx.lineTo(
+					ships[i].x + ships[i].a * SHIP_SIZEX / 2 - ships[i].a * SHIP_SIZEX / 10 ,
+					ships[i].y + SHIP_SIZEY / 6
+				)
+
+				ctx.lineTo(
+					ships[i].x + ships[i].a * (SHIP_SIZEX / 6),
+					ships[i].y - SHIP_SIZEY / 4
+				)
+				ctx.closePath();
+
+				ctx.fillStyle = "red";
+				ctx.fill();
+
+				if (SHOW_BOUNDING) {
+					ctx.strokeStyle = "lime";
+					ctx.strokeRect(
+						ships[i].x - SHIP_SIZEX / 2,
+						ships[i].y - SHIP_SIZEY / 2,
+						SHIP_SIZEX,
+						SHIP_SIZEY
+					)
+				}
+			}
+
+
+			//draw plane
+			//ctx.lineWidth = PLANE_SIZE / 20;
+			ctx.beginPath();
+			ctx.moveTo( //nose of the plane
+				plane.x + 4 / 3 * plane.r * Math.cos(plane.a),
+				plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
+			);
+
+			ctx.lineTo( //rear left of the plane
+				plane.x - plane.r * (2 / 3 * Math.cos(plane.a) + Math.sin(plane.a)),
+				plane.y + plane.r * (2 / 3 * Math.sin(plane.a) - Math.cos(plane.a))
+			);
+
+			ctx.lineTo( //rear right of the plane
+				plane.x - plane.r * (2 / 3 * Math.cos(plane.a) - Math.sin(plane.a)),
+				plane.y + plane.r * (2 / 3 * Math.sin(plane.a) + Math.cos(plane.a))
+			);
+
+			ctx.closePath();
+			ctx.fillStyle = "yellow";
+			ctx.fill();
+			//ctx.strokeStyle = "yellow";
+			//ctx.stroke();
+
+			if (SHOW_BOUNDING) {
+					//console.log(plane.collision.x);
+					drawCollision(plane.collision,"blue");
+			}
+
+			//Рисуем снаряды
+			for (var i = 0; i < plane.missles.length; i++) {
+				ctx.beginPath();
+				ctx.moveTo( //верхушка снаряда
+					plane.missles[i].x,
+					plane.missles[i].y
+				)
+				ctx.lineTo( //левый верхний угол снаряда
+					plane.missles[i].x - MISSLE_SIZEX / 2,
+					plane.missles[i].y + MISSLE_SIZEX / 2
+				)
+				ctx.lineTo( //левый нижний угол снаряда
+					plane.missles[i].x - MISSLE_SIZEX / 2,
+					plane.missles[i].y + MISSLE_SIZEY
+				)
+				ctx.lineTo( //правый нижний угол снаряда
+					plane.missles[i].x + MISSLE_SIZEX / 2,
+					plane.missles[i].y + MISSLE_SIZEY
+				)
+				ctx.lineTo( //правый верхний угол снаряда
+					plane.missles[i].x + MISSLE_SIZEX / 2,
+					plane.missles[i].y + MISSLE_SIZEX / 2
+				)				
+				ctx.closePath();
+				//ctx.strokeStyle = "cyan";
+				ctx.fillStyle = "cyan";
+				ctx.fill();
+				if (SHOW_BOUNDING) {
+					drawCollision(plane.missles[i].collision,"pink");
+				}		
+			}
+
+			shootMissle();
+
+			//update acceleration
+			if (plane.acceleration.posx ^ plane.acceleration.negx){
+				//console.log("acceleration calc")
+				if (plane.acceleration.posx){
+					if (plane.speedx > 0) plane.speedx = 0 //исключение "пьяного" замедления
+					plane.speedx -= PLANE_ACCELERATION;
+				}
+
+				if (plane.acceleration.negx) {
+					if (plane.speedx < 0) plane.speedx = 0 //исключение "пьяного" замедления
+					plane.speedx += PLANE_ACCELERATION;
+				}
+			} else {
+				plane.speedx = 0;
+			}
+
+			//move the plane
+			//TODO размер сцены
+			if (!scene.gameOver) {
+				for (var i = 0; i < scene.blocks.length; i++) {
+					for (var j = 0; j < scene.blocks[i].boundaries.length; j++) {
+						var newPlaneX = checkPlaneSceneCollision(plane.x - plane.speedx, plane.y,scene.blocks[i].boundaries[j].collision)
+						if (newPlaneX != 0){
+							plane.speedx = 0;
+							plane.x = newPlaneX;
+							console.log("collsion with boundary no." + j + " in block no. " + i);
+						}
+					}
+				}
+				plane.x -= plane.speedx; 
+			}
+
+			/* 
+			rightBorder = 1280;
+			leftBorder = 0;
+			if ((plane.x - plane.speedx) <= (rightBorder - plane.r) && (plane.x - plane.speedx) >= (0 + plane.r))
+				{	plane.x -= plane.speedx;
+			} else {
+				if ((plane.x - plane.speedx) > (rightBorder - plane.r)){
+					plane.x =(rightBorder - plane.r);
+				} else {
+					if ((plane.x - plane.speedx) < (leftBorder + plane.r)) {
+						plane.x = (leftBorder + plane.r);
+					}
+				}
+			}
+			*/
+			plane.collision.x = plane.x + 4 / 3 * plane.r * Math.cos(plane.a) - PLANE_SIZE / 2;
+			plane.collision.y = plane.y - 4 / 3 * plane.r * Math.sin(plane.a)
+
+			//двигаем снаряды 
+			for (var i = plane.missles.length - 1; i >= 0 ; i--) {
+				if (plane.missles[i].y < 0 - MISSLE_SIZEY) { //удаление снарядов за экраном
+					plane.missles.splice(i,1);
+					continue;
+				}
+				plane.missles[i].y -= MISSLE_SPEED;
+
+				plane.missles[i].collision.x = plane.missles[i].x - MISSLE_SIZEX / 2;
+				plane.missles[i].collision.y = plane.missles[i].y;
+			}
+
+			if (plane.reload) { //перезарядка
+				if (plane.reloadtime <= 0){
+					console.log("reloaded");
+					plane.reload = false;
+				} else {
+					plane.reloadtime--;
+				}
+			} 
+		}
+	</script>
+	</body>
+</html>

+ 42 - 0
ui/templates/index.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="UTF-8">
+		<title>{{.Title}}</title>
+	</head>
+	<script>
+		function post()
+		{
+		  var xhr = new XMLHttpRequest();// Создаём объект xhr
+		  xhr.open("POST", "/" , true);// Открываем асинхронное соединение
+		  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");// Отправляем кодировку
+		  var data = 'score=500';
+		  xhr.send(data); // Отправляем POST-запрос
+		  xhr.onreadystatechange = function() // Ждём ответа от сервера
+		  {
+		    if (xhr.readyState == 4) // возвращает текущее состояние объекта(0-4)
+		    {
+		      if(xhr.status == 200) // код 200 (если страница не найдена вернет 404)
+		      {
+		        alert(this.responseText);
+		      }
+		    }
+		  }
+		}
+	</script>
+	<body>
+		<h1>INDEX</h1>
+		<div>Вошли как 
+			{{if .User}}{{.User}}<br><a href="/logout/">Выйти</a><br>{{else}}гость<br><a href="/login/">Войти</a><br><a href="/signin/">Зарегистрироваться</a>{{end}}
+		</div>
+		<div>
+			<a href="/leaderboard/">Таблица лидеров</a>
+			<br>
+			{{if .User}}<a href="/myscores/">Мои результаты</a>{{end}}
+			<br>
+		</div>
+		{{range .Items}}<div style="font-size: 18pt">{{ . }}</div>{{else}}<div><strong>no rows</strong></div>{{end}}
+		<br>
+		<button onclick=post()>Клик</button>
+	</body>
+</html>

+ 0 - 0
ui/templates/leaderboard.html


+ 28 - 0
ui/templates/login.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="UTF-8">
+		<title>Вход</title>
+	</head>
+	<body>
+		<h1>LOGIN</h1>
+		<form method="POST">
+			<p>
+				Логин:
+				<br>
+				<input name="username" value="{{.Username}}">
+			</p>
+			<p>
+				Пароль:
+				<br>
+				<input name="password" value="{{.Password}}">
+			</p>
+			<p>
+				<button type="submit">Войти</button>
+			</p>
+			{{if .Error}}<p>
+				{{.Error}}
+			</p>{{end}}
+		</form> 
+	</body>
+</html>

+ 0 - 0
ui/templates/myscores.html


+ 33 - 0
ui/templates/signin.html

@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="UTF-8">
+		<title>Регистрация</title>
+	</head>
+	<body>
+		<h1>SIGNIN</h1>
+		<form method="POST">
+			<p>
+				Логин:
+				<br>
+				<input name="username" value="{{.Username}}">
+			</p>
+			<p>
+				Пароль: 
+				<br>
+				<input name="password" value="{{.Password}}">
+			</p>
+			<p>
+				Подтвердить пароль:
+				<br>
+				<input name="password-repeat" value="{{.PasswordRepeat}}">
+			</p>
+			<p>
+				<button type="submit">Зарегистрироваться</button>
+			</p>
+			{{if .Error}}<p>
+				{{.Error}}
+			</p>{{end}}
+		</form>
+	</body>
+</html>