Implémentons la condition que la circonférence et l'intérieur de la forme Ougi soient inclus dans Java [Partie 1]

1. 1. introduction

J'avais joué à un jeu appelé Metal Gear Solid pour la première fois depuis un certain temps, mais je me suis soudainement demandé quel type d'algorithme le personnage contrôlé par le joueur serait visible par la caméra de surveillance et les soldats ennemis. Par conséquent, j'ai décidé de le faire moi-même, ainsi que d'étudier la programmation. Dans cet article, j'ai écrit comment l'implémenter, comment éliminer les bugs et quelles leçons j'ai apprises. Pour ceux qui viennent de commencer à étudier la programmation, le contenu est semblable à celui d'un enseignant: "Faites attention à ne pas faire une telle erreur."

2. Problème de réglage

Supposons les spécifications suivantes.

joueur

Il y a un joueur sur le plan des coordonnées. Le joueur reste immobile et ne bouge pas. ~~ Il est difficile de bouger. ~~ Le corps du joueur peut être considéré comme un point, et les coordonnées de ce point sont ($ p_x $, $ p_y $).

Caméra de surveillance

Les caméras de surveillance sont installées en unités $ N $ sur le plan de coordonnées. $ N $ est un entier supérieur ou égal à 1. La caméra de surveillance reste immobile et ne bouge pas. ~~ Quand il bouge (omis) ~~ La lentille de chaque caméra de surveillance peut être considérée comme un point, et les coordonnées de ce point sont ($ x_i $, $ y_i $). Cependant, $ i $ est un entier de 1 ou plus et $ N $ ou moins, ce qui indique le numéro de la caméra de surveillance.

Portée visible de chaque caméra de surveillance

La distance à laquelle chaque caméra de surveillance peut voir le joueur est $ d_i $ ($ d_i $> 0). Soit $ e_i $ l'angle représentant l'orientation de l'objectif de chaque caméra de surveillance, et $ f_i $ l'angle représentant le champ de vision de la caméra. $ e_i $ est l'angle entre la ligne droite représentant la direction de la caméra et la direction positive de l'axe $ x $, et les deux $ e_i $ et $ f_i $ sont de 0 ° ou plus et de moins de 360 °. En d'autres termes, la plage dans laquelle chaque caméra de surveillance peut voir le joueur est la circonférence et l'intérieur de la forme d'oie avec un rayon de $ d_i $ et un angle central de $ f_i $ comme le montre la figure suivante. quiita_おうぎ形 - コピー.png

Entrée / sortie de paramètre

Entrez les paramètres de la console au format suivant.      p_x p_y      N      x_1 y_1 d_1 e_1 f_1 (Omis)      x_i y_i d_i e_i f_i (Omis)      x_N y_N d_N e_N f_N Les paramètres de chaque ligne doivent être séparés par un espace d'une demi-largeur. De plus, chaque fois que les informations de chaque caméra de surveillance sont entrées, il est déterminé si la caméra de surveillance peut ou non voir le joueur, et si elle peut être vue, elle est sortie comme "visible", et si elle ne peut pas être vue, elle est sortie comme "non visible". Et.

3. 3. Implémentation de la structure des données

Tout d'abord, je voudrais décliner, mais cette fois le but est de considérer la condition que la circonférence et l'intérieur de la forme de la gourde incluent des points, il n'est donc pas possible d'implémenter strictement l'encapsulation et l'orientation de l'objet __ Ne pas __. Je ne peux pas dire ~~. ~~ Il peut y avoir de nombreux autres points qui ne peuvent être atteints, mais pardonnez-moi s'il vous plaît.

Tout d'abord, créez une classe Player qui gère les informations de position du joueur. Class Player a les coordonnées $ x $ et $ y $ et a la possibilité de renvoyer leurs valeurs selon les besoins. De plus, il n'est peut-être pas nécessaire de faire du joueur une classe, mais s'il s'agit d'un développement de système, il y a une possibilité qu'il y ait beaucoup de joueurs, donc "De toute façon, le joueur est caché. Je clarifierai l'idée __ qu'il a les informations et les fonctions de Kajika. De plus, la classe Player n'est qu'une idea (un concept abstrait d'un objet d'une manière compliquée), et nous allons créer un __player (d'une manière compliquée, une entité) qui existe dans le vrai sens plus tard. Par exemple, est-ce le sentiment qu'il existe un concept abstrait de l'humanité, et que vous et moi existons en tant que substance?

class Player {
	private double x; //Coordonnées du joueur x
	private double y; //Coordonnées du joueur y

	public Player(double x, double y) {
		this.x = x;
		this.y = y;
	}
	public double getX() {
		return this.x;
	}
	public double getY() {
		return this.y;
	}
}

Comme c'est un gros problème, je vais vous expliquer un peu l'encapsulation. Dans la classe Player, les valeurs sont stockées dans des variables de type double x et y, mais la personne qui écrit le programme (pas toujours moi. Peut collaborer avec quelqu'un ou le lancer à quelqu'un. Dans une situation où (!) Peut faire référence à et attribuer la valeur d'une variable de manière désordonnée, il y a un risque de décrire un processus (bug) différent de l'hypothèse d'origine. Par conséquent, afin de clarifier le traitement que le ou les rédacteurs de programme peuvent effectuer pour la classe Player, le code ci-dessus définit comme suit.

De cette manière, le mécanisme qui rassemble les informations et les traitements nécessaires et les empêche d'être réécrit aléatoirement est une classe ou une encapsulation. Il faut un peu plus de travail pour écrire le programme, mais à la place, Java fournit un mécanisme pour réduire le risque de créer des bogues. Plus l'échelle du développement est grande, plus un tel mécanisme devient important.

Ensuite, créez une caméra de classe qui gère les informations de la caméra de surveillance. La caméra de classe a les coordonnées x, y, la distance visible, l'orientation et l'angle de vue. Il a une configuration minimale maintenant, mais à mesure que nous implémenterons le processus à l'avenir, nous ajouterons plus de méthodes.

class Camera {
	private double x;	//Coordonnées X de la caméra de surveillance
	private double y;	//Caméra de surveillance coordonnée y
	private double distance;	//Distance que la caméra de surveillance peut voir
	private double dirAngle;	//Orientation de la caméra de surveillance(direction)Angle représentant
	private double viewAngle;	//Angle de vision de la caméra de surveillance

	public Camera(double x, double y, double d, double e, double f) {
		this.x = x;
		this.y = y;
		this.distance = d;
		this.dirAngle = e;
		this.viewAngle = f;
	}
}

4. Implémentation d'algorithme

contribution

Maintenant que nous avons décidé où et quel type d'informations stocker, nous allons enfin décrire le flux de traitement. Tout d'abord, de la méthode principale. Chaque fois que vous exécutez un programme Java, la méthode principale est appelée en premier. Par conséquent, vous ne devez écrire qu'une seule méthode principale dans tout le programme. Pour le moment, je ne créerai que la partie qui lit la valeur numérique saisie depuis la console.

class CameraTest {
	public static void main(String[] args) {
		//contribution
		Scanner sc = new Scanner(System.in);
		//joueur
		double px = sc.nextDouble();	//Coordonnées du joueur x
		double py = sc.nextDouble();	//Coordonnées du joueur y
		Player player = new Player(px, py);
		//Caméra de surveillance
		int N = sc.nextInt();		//Nombre de caméras de surveillance
		for (int n = 0; n < N; n ++) {
			//Entrée / traitement pour chaque caméra de surveillance
			double x = sc.nextDouble();	//Coordonnées X de la caméra de surveillance
			double y = sc.nextDouble();	//Caméra de surveillance coordonnée y
			double d = sc.nextDouble();	//Distance que la caméra de surveillance peut voir
			double e = sc.nextDouble();	//Orientation de la caméra de surveillance(direction)Angle représentant
			double f = sc.nextDouble();	//Angle de vision de la caméra de surveillance
			Camera camera = new Camera(x, y, d, e, f);
		}
		sc.close();
	}
}

C'est un peu comme static, Scanner, nextDouble, nextInt, etc., mais si vous commencez à les expliquer, cela s'écartera du but de cet article, je vais donc omettre l'explication. Quoi qu'il en soit, au moment de la création de ce qui précède, la valeur numérique saisie selon les spécifications peut être lue sans aucun problème.

La caméra de surveillance peut-elle voir le joueur?

Bien sûr, la simple lecture des chiffres n'a pas de sens, ajoutons donc un processus pour déterminer si la caméra peut réellement voir le joueur. Dans la classe Camera créée précédemment, créons une méthode findPlayer qui lit les informations de position d'un joueur et détermine si le joueur peut être reconnu visuellement. Cette méthode est la clé de cet article.

//Ajouter à la classe Appareil photo
public boolean findPlayer(Player player) {
	double px = player.getX();
	double py = player.getY();

	//Jugement à distance
	double d = Math.sqrt(Math.pow(this.x - px, 2) + Math.pow(this.y - py, 2));
	if (d > this.distance) {
		return false;
	}

	//Jugement par angle
	double a = Math.toDegrees(Math.atan2(py - this.y, px - this.x));
	double aMin = this.dirAngle - this.viewAngle/2;
	double aMax = this.dirAngle + this.viewAngle/2;
	if (a < aMin || aMax < a) {
		return false;
	}

	return true;
}

Maintenant, expliquons brièvement le flux de traitement. Il existe deux mots-clés, "distance" et "angle". Tout d'abord, la «distance», comme son nom l'indique, détermine si la distance entre la caméra de surveillance et le joueur est inférieure à la distance visible de la caméra de surveillance. La distance entre deux points ($ x_i $, $ y_i ), ( p_x $, $ p_y $)

\sqrt{(x_i - p_x)^2 + (y_i - p_y)^2}

Est requis à. Si celle-ci est inférieure à la distance de visualisation $ d_i $, vous pourrez peut-être la voir, mais si elle est supérieure à $ d_i $, c'est hors de question. Par conséquent, dans la partie qui juge par distance, dans ce dernier cas, faux est retourné soudainement de sorte qu'un traitement inutile après cela n'est pas nécessaire. Ensuite, concernant le traitement de "angle" après avoir effacé la condition de "distance", la fonction $ \ arctan $ (mathématiques du lycée) qui calcule la taille de l'angle entre la droite et l'axe des x à partir de l'inclinaison de la droite passant par les deux points. "Fonction triangulaire" et "fonction inverse") peuvent être utilisées, donc en les combinant pour deux points ($ x_i $, $ y_i ), ( p_x $, $ p_y $)

\arctan{\frac{y_i - p_y}{x_i - p_x}}

Vous pouvez le trouver sur. De plus, la plage d'angles que la caméra peut voir est représentée par $ e_i- \ frac {f_i} {2} $ ou plus et $ e_i + \ frac {f_i} {2} $ ou moins, donc l'angle obtenu à partir de l'inclinaison est cette plage. Renvoie vrai s'il y en a, faux sinon.

production

À ce stade, c'est presque terminé. La méthode findPlayer créée précédemment renvoie une valeur de type boolean, donc elle ne produit que le résultat en fonction de cette valeur. Ensuite, je publierai le programme terminé (?).

import java.util.Scanner;

class CameraTest {
	public static void main(String[] args) {
		//contribution
		Scanner sc = new Scanner(System.in);
		//joueur
		double px = sc.nextDouble();	//Coordonnées du joueur x
		double py = sc.nextDouble();	//Coordonnées du joueur y
		Player player = new Player(px, py);
		//Caméra de surveillance
		int N = sc.nextInt();		//Nombre de caméras de surveillance
		for (int n = 0; n < N; n ++) {
			//Entrée / traitement pour chaque caméra de surveillance
			double x = sc.nextDouble();	//Coordonnées X de la caméra de surveillance
			double y = sc.nextDouble();	//Caméra de surveillance coordonnée y
			double d = sc.nextDouble();	//Distance que la caméra de surveillance peut voir
			double e = sc.nextDouble();	//Orientation de la caméra de surveillance(direction)Angle représentant
			double f = sc.nextDouble();	//Angle de vision de la caméra de surveillance
			Camera camera = new Camera(x, y, d, e, f);
			if (camera.findPlayer(player)) {
				System.out.println("J'ai pu voir");
			} else {
				System.out.println("Je ne pouvais pas voir");
			}
		}
		sc.close();
	}
}

class Player {
	private double x; //Coordonnées du joueur x
	private double y; //Coordonnées du joueur y

	public Player(double x, double y) {
		this.x = x;
		this.y = y;
	}
	public double getX() {
		return this.x;
	}
	public double getY() {
		return this.y;
	}
}

class Camera {
	private double x;	//Coordonnées X de la caméra de surveillance
	private double y;	//Caméra de surveillance coordonnée y
	private double distance;	//Distance que la caméra de surveillance peut voir
	private double dirAngle;	//Orientation de la caméra de surveillance(direction)Angle représentant
	private double viewAngle;	//Angle de vision de la caméra de surveillance

	public Camera(double x, double y, double d, double e, double f) {
		this.x = x;
		this.y = y;
		this.distance = d;
		this.dirAngle = e;
		this.viewAngle = f;
	}
	public boolean findPlayer(Player player) {
		double px = player.getX();
		double py = player.getY();
	
		//Jugement à distance
		double d = Math.sqrt(Math.pow(this.x - px, 2) + Math.pow(this.y - py, 2));
		if (d > this.distance) {
			return false;
		}
	
		//Jugement par angle
		double a = Math.toDegrees(Math.atan2(py - this.y, px - this.x));
		double aMin = this.dirAngle - this.viewAngle/2;
		double aMax = this.dirAngle + this.viewAngle/2;
		if (a < aMin || aMax < a) {
			return false;
		}
		
		return true;
	}
}

5. Exécution, et ...

Il est enfin temps de vérifier les performances de la caméra de surveillance. À titre de test, testons avec trois caméras de surveillance, avec les coordonnées où se trouve le joueur (10, 10). Tout d'abord, j'entrerai jusqu'au point où se déroulera le traitement de la première unité.

10 10
3
10 0 12 90 30
J'ai pu voir

La situation ci-dessous montre les informations saisies dans un diagramme. Vous pouvez parfaitement voir le joueur. La tension est montée. quiita_おうぎ形2.png

Passons au second.

10 5 10 180 90
Je ne pouvais pas voir

Je n'ai pas pu voir le second, mais ce n'est pas du tout un problème. En effet, la situation est celle illustrée dans la figure ci-dessous. J'ai pu effacer la condition de distance, mais la direction de la caméra de surveillance était erronée. Le jugement est parfait cette fois aussi! quiita_おうぎ形3.png

Ensuite, passons à la finale avec la troisième dernière voiture.

10 16 8 270 120
Je ne pouvais pas voir

quiita_おうぎ形4.png

À la fin, je peux voir le joueur stupide juste devant la caméra de surveillance ... __ Je ne peux pas le faire __. En termes de jeu de tir, c'est comme un placement frontal! (Lancement)

6. Et pour déboguer ...

C'est le début d'un travail de débogage amusant, mais cette fois, j'aimerais le couper ici et continuer avec la deuxième partie. Si vous vous demandez "Pourquoi n'est-ce pas?" Comme je l'étais avant, pensez-y avant de lire la deuxième partie. __Pourquoi la troisième caméra de surveillance ne pouvait-elle pas voir le joueur alors qu'il pouvait le voir? Aussi, comment dois-je modifier le programme? __

Recommended Posts

Implémentons la condition que la circonférence et l'intérieur de la forme Ougi soient inclus dans Java [Partie 2]
Implémentons la condition que la circonférence et l'intérieur de la forme Ougi soient inclus dans Java [Partie 1]
Ceci et cela de la mise en œuvre du jugement en temps réel des dates en Java
[Android 9.0 Pie Java] Implémentez setOnTouchListener dans la marge de RecyclerView et fermez le clavier virtuel
[Java] Que faire si le contenu enregistré dans la base de données et le nom de l’énumération sont différents dans l’énumération qui reflète la définition de la base de données
Un programme (Java) qui génère la somme des nombres pairs et impairs dans un tableau
Crier Java au cœur des technologies-Thèmes et technologies élémentaires que les ingénieurs Java devraient poursuivre en 2017-
JSON en Java et Jackson Partie 1 Renvoyer JSON à partir du serveur
[Java] Obtenez les dates des derniers lundi et dimanche dans l'ordre
Examinons la signification de "stream" et "collect" dans l'API Stream de Java.
Créons une application TODO en Java 5 Changer l'affichage de TODO
Spécifiez l'ordre dans lequel les fichiers de configuration et les classes sont chargés dans Java
Le problème que le contenu des paramètres est complètement affiché dans la vue [Rails]
L'histoire de l'oubli de fermer un fichier en Java et de l'échec
Pensons à ce qu'est la programmation déclarative en Java et Elm (partie 1)
Exemple de programme qui renvoie la valeur de hachage d'un fichier en Java
Trouvez le maximum et le minimum des cinq nombres saisis en Java
Revue des connaissances «étranges Java» et Java souvent oubliées dans Java Bronze
[Java] Implémenter une fonction qui utilise une classe implémentée dans le modèle Builder
[Introduction à l'informatique Partie 1: Essayons l'apprentissage automatique] Implémentons la méthode de calcul de la moyenne k en Java - À propos du concept de coordonnées -
Obtenez le résultat de POST en Java
Quelles sont les fonctionnalités mises à jour de Java 13
L'histoire de l'écriture de Java dans Emacs
Discrimination d'énum dans Java 7 et supérieur
J'ai reçu les données du voyage (application agenda) en Java et j'ai essayé de les visualiser # 001
[Java] Où est la classe d'implémentation de l'annotation qui existe dans BeanValidation?
10 barrages de dessin avec ● ou ■ qui sont susceptibles d'apparaître dans la formation (Java)