O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

Snake Game - JavaScript + SVG

Iniciado por MayLeone, 30/11/2018 às 18:24

Olá, fiz um snake game com JavaScript (usando o jQuery pra deixar o código mais limpo) e SVG para desenhar os elementos na tela. O HTML foi usado apenas pra criar a estrutura básica da página.
O objetivo era ser simples mesmo.

Caso queiram jogar, acesse: http://snakegamejs.orgfree.com/Snake

Código completo:
<!DOCTYPE html>
<html lang = "pt-br">
	<head>
		<title> Snake in Javascript</title>
		<meta charset = "utf-8"/>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
		<script>
			document.onkeydown = CheckKey;
			var resolution = 30; // Set pixel resolution to snake and food
			var width_Screen, heigth_Screen;
			var svgNS = "http://www.w3.org/2000/svg";
			var interval_a = window.setInterval(function(){Move();}, 80);
			var body = [];
			var pointsX = [];
			var pointsY = [];
			var Directions = {Rigth:1, Left:2, Up:3, Down:4 };
			var direction = Directions.Right;
			var colors = ["gray", "yellow", "green", "blue", "white", "magenta", "blueviolet", "brown", "chartreuse", "cyan", "greenyellow", "orange", "lime"];
			var xDir = -resolution;
			var yDir = 0;
			var score = 0;
			var index = 0;
			var gameOn = false;
			
			function Define(){
				$("#food").attr("width", resolution);
				$("#food").attr("height", resolution);
				var screen = $("#mySVG");
				var screenX = screen.attr("width");
				var screenY = screen.attr("height");
			
			if (screenX % resolution != 0){
				screen.attr("width", RoundByMultiple(screenX, resolution));
			}
			if (screenY % resolution != 0){
				screen.attr("height", RoundByMultiple(screenY, resolution));
			}
			width_Screen = screen.attr("width");
			heigth_Screen = screen.attr("height");
			$("#svgText").attr("font-size", screenX/10 + "px");
		
				for (var i = resolution; i < width_Screen; i+=resolution){
					pointsX[index] = i;
					index++;
				}
			
				index = 0;
			
				for (var j = resolution; j < heigth_Screen; j+=resolution){
					pointsY[index] = j;
					index++;
				}
			
			}

			
			function StartGame(){
				$("#svgText").hide();
				$("#food").show();
				gameOn = true;
				for (var i = 0; i <5; i++){
					CreateRect((resolution*5) - (i*resolution), resolution, resolution, resolution);
				}
				RandomFood();
			}

			function CreateRect(x, y, w, h){
				snake = $(document.createElementNS(svgNS,"rect")); 
				snake.attr("x",x);
				snake.attr("y",y);
				snake.attr("width",w);
				snake.attr("height",h);
				var a = false;
					if (body.length >= 1){
						while (!a){
							c = RandomValues(colors.length);
							if (body[body.length-1].attr("fill") != colors[c]){
								a = true;
							}
						} 
					} else {
						c = RandomValues(colors.length);
					}
				snake.attr("fill",colors[c]);
				body.push(snake);
				$("#mySVG").append(snake);
		}
		function Move(){
			for (var i = body.length -1; i > 0; i--){
				body[i].attr("x", body[i-1].attr("x"));
				body[i].attr("y", body[i-1].attr("y"));
			}
			body[0].attr("x", body[0].attr("x") - xDir);
			body[0].attr("y", body[0].attr("y") - yDir);
			CheckEat();
			CheckDeath();
		}
		
		function RandomFood(){
			var X = RandomValues(pointsX.length);
			var Y = RandomValues(pointsY.length);
			$("#food").attr("x", pointsX[X]);
			$("#food").attr("y", pointsY[Y]);
			for (var i = 0; i < body.length; i++){
				var bX = body[i].attr("x");
				var bY = body[i].attr("y");
				fX = $("#food").attr("x");
				fY = $("#food").attr("y");
				if (bX == fX && bY == fY){
					RandomFood();
				}
			}
		}
		
		function CheckEat(){
			bX = body[0].attr("x");
			bY = body[0].attr("y");
			if (bX == fX && bY == fY){
				score++;
				$("#score-display").html(score);
				CreateRect(body[body.length-1].attr("x"),
				body[body.length-1].attr("y"), resolution, resolution);
				RandomFood();
			}
		}

		function CheckDeath(){
			for (var i = body.length-1; i >1; i--){
				var aX = body[i].attr("x");
				var aY = body[i].attr("y");
				if (direction == Directions.Right || direction == Directions.Left){
					if (bX - xDir == aX  && bY == aY)
					GameOver();
				} if (direction == Directions.Up || direction == Directions.Down){
					if (bX == aX && bY -yDir == aY)
					GameOver();
				}
			}
			
			if (bX < 0 || bX == width_Screen || bY < 0 || bY == heigth_Screen)
					GameOver();
		}


		
		function GameOver(){
			clearInterval(interval_a);
			setTimeout(function() {
				location.reload();
				}, 1000);

		}
		
		function CheckKey(e) {
				if (e.keyCode == "13" && !gameOn) {
					StartGame();
				}
				
				if ((e.keyCode == "68" || e.keyCode == "39") && direction != Directions.Left){
					xDir = -resolution;
					yDir = 0;
					direction = Directions.Right;
				}
				if ((e.keyCode == "65" || e.keyCode == "37") && direction != Directions.Right){
					xDir = resolution;
					yDir = 0;
					direction = Directions.Left;
				}
				if ((e.keyCode == "87"|| e.keyCode == "38") && direction != Directions.Down){
					xDir = 0;
					yDir = resolution;
					direction = Directions.Up;
				}
				if ((e.keyCode == "83" || e.keyCode == "40") && direction != Directions.Up){
					xDir = 0;
					yDir = -resolution;
					direction = Directions.Down;
				}
			}
			
			function RandomValues(value){
				return Math.floor(Math.random() * value);
			}
			
			function RoundByMultiple(value, res){
				return res*(Math.floor(value/res));
			}

		</script>
	</head>
	<body onload = "Define()">
		<svg id = "mySVG" xmlns="http://www.w3.org/2000/svg" width = "400" height = "220" style = "background-color:#000000; border:2px solid blue">
			<text id = "svgText" x="50%" y="50%" alignment-baseline="middle" text-anchor="middle" fill = "white"> Press enter to play</text>
			<rect id = "food" x = "0" y = "0"fill = "red" style = "display:none"/>
		</svg>
		<div>
			<h1>Your score: <span id ="score-display">0</span></h1>
		</div>
	</body>
</html>


Imagem:


Pô, interessante. Já vi esse SVG sendo usado para animações, sempre achei que se limitava ao design. O joguinho ficou bem legal, meio rápido, mas legal. Não conseguir fazer mais que oito pontos.  :rick9:

E obrigado por disponibilizar o código, já copiei pra estudar. o/

D: Morri


Pelo espaço pequeno e velocidade alta isso dificulta no começo, mas tentando várias vezes eu fui indo mais longe a cada vez.

2010 ~ 2016 / 2024

Citação de: Corvo online 30/11/2018 às 19:04
Pô, interessante. Já vi esse SVG sendo usado para animações, sempre achei que se limitava ao design. O joguinho ficou bem legal, meio rápido, mas legal. Não conseguir fazer mais que oito pontos.  :rick9:

E obrigado por disponibilizar o código, já copiei pra estudar. o/

Ah sim o SVG trabalha muito bem com animações, mas eu gosto mais de usar ele para criar esses elementos gráficos na tela, apesar de que agora o HTML 5 trouxe o sistema de canvas que dá até gravidade pra esses elementos. Mas ainda preciso dar uma olhada melhor nisso.
Obrigada pelo comentário!  :heart:

Spoiler
Citação de: Vash online 30/11/2018 às 20:48
D: Morri


Pelo espaço pequeno e velocidade alta isso dificulta no começo, mas tentando várias vezes eu fui indo mais longe a cada vez.
[close]

Nossa, 21 pontos tem que ser ninja xD
Pois é, na verdade quando eu desenvolvi o jogo a tela era bem maior, se não me engano 640x480 mas daí eu mandei pra um amigo reduzido como desafio, aliás, foi por isso que eu hospedei o jogo no orgfree, daí ficou nessa resolução.
Mas para mudar, basta editar o HTML lá em baixo nessa linha:
<svg id = "mySVG" xmlns="http://www.w3.org/2000/svg" width = "400" height = "220">

Daí muda a resolução da tela.
Pra mudar a resolução da cobrinha, é nesse trecho aqui:
var resolution = 30; // Set pixel resolution to snake and food


Como o intuito era ser um código simples, eu não coloquei um menu de opções de dificuldade ou resolução, então troca-se pelo código mesmo, mas quem sabe eu não coloco tudo isso talvez?

E obrigada pelo feed!