java - 为坦克游戏实现简单的 AI(敌人炮塔旋转、射击)
问题描述
因为我希望我的游戏是单人游戏(玩家对 COM),所以我需要一种方法来告诉敌人(COM)该做什么。现在我实施了一种方法,以便他在炮塔对齐时转向玩家并射击。但这似乎不切实际,老实说有点无聊。
所以我想到了一个主意:为什么不使用人工智能呢?我想使用某种库,因为考虑到我的技能,我认为我无法自己制作一个。我想通过与 COM1 与 COM2 战斗来训练坦克,以生存时间/杀戮(我不知道该选择什么???)。虽然神经网络真的很数学,但我理解它们是如何工作的。我希望我的敌人能够向左或向右转动他的炮塔和/或射击(3 个输出)。这应该通过输入带有玩家坦克(及其上的障碍物)的地图来完成。对于玩 AI 来说,这听起来并不难。我尝试按照 AI 教程进行操作,但我无法弄清楚如何为我的游戏实现该教程。此外,这个小地图(例如敌方坦克的概述)如何作为输入?隐藏层应该有多少个神经元?
总之:我需要一个库/易于调整的初学者代码(甚至可能是几个或只有一个没有外部资源的单个 Java 类)两个操纵敌人的炮塔向左或向右,甚至不转动它并射击/不射击(不必须是最快的学习者)。我将如何选择我的输入类型?最简单的 AI 在 IntelliJ 中完美运行,但它们只是用数字计算,而且仍然非常复杂/无法用于任何目的。隐藏层推荐多少个神经元?推荐多少隐藏层?我如何让坦克进行训练,以及如何保存一些最好的作为每个游戏中创建的新坦克的演员?拯救一些 X 世代的 AITank 并在每场比赛中对他进行变异是可能的吗?
感谢您提供的任何答案!
到目前为止,在 Greenfoot 中为敌方坦克编写代码:
import greenfoot.*;
import java.util.List;
public class GoldTank extends EnemyTank
{
private int shootCoolDown = 200;
public GoldTank() {
this.tankImage = new GreenfootImage("Tank_Gold_Base_Idle.png");
setImage(tankImage);
getImage().scale(35,20);
this.speed = 0;
this.coolDownTime = 100;
}
public void act() {
if(shootCoolDown > 0) {
shootCoolDown--;
}
int rotOffset = (int)calculateTurretRotation() - turret.getRotation();
if(Math.abs(rotOffset) <= 90 || Math.abs(rotOffset) >= 270) {
if(rotOffset == 0) {
if(shootCoolDown == 0) {
shoot();
shootCoolDown = 200;
}
} else if(rotOffset < 180 && rotOffset > 0 || rotOffset < -180) {
getTurret().turn(50);
} else if(rotOffset > 180 || rotOffset > -180 && rotOffset < 0) {
getTurret().turn(-50);
}
}
else {
/**
* Too smart.. turns in right direction for scanning: JUST WAIT OR SO?
*/
if(rotOffset < 180 && rotOffset > 0 || rotOffset < -180) {
getTurret().turn(15);
} else if(rotOffset > 180 || rotOffset > -180 && rotOffset < 0) {
getTurret().turn(-15);
}
}
}
public double calculateTurretRotation() {
List<PlayerTank> playerTanks = getWorld().getObjects(PlayerTank.class);
PlayerTank playerTank = playerTanks.get(0);
int px = playerTank.getX();
int py = playerTank.getY();
int tx = getX();
int ty = getY();
double xres = px-tx;
double yres = py-ty;
double m = (yres/xres);
double result = (Math.atan(m)*360)/(2*Math.PI);
double magicNumber;
double xresabs = Math.abs(xres);
double yresabs = Math.abs(yres);
if(yres > 0) {
if(xres < 0){
magicNumber = 180;
result += magicNumber;
}
} else if(yres < 0){
if(xres < 0){
magicNumber = 180;
result += magicNumber;
} else {
magicNumber = 360;
result += magicNumber;
}
}
return result;
}
public void directionMove(int steps, int rotation) {
int oldRot = getRotation();
setRotation(rotation);
move(steps);
setRotation(oldRot);
}
}
解决方案
推荐阅读
- api - Kotlin 通用发布请求
- javascript - 用Javascript计算假期
- javascript - 将对象中的键映射到出现的键
- c++ - 将 CMake 与 C++ 继承结合使用时,我应该如何组织我的目录结构?
- math - 从一对浮子到单个浮子的近似可逆函数?
- java - 如何从Java中的给定字符串中删除注释?
- ruby-on-rails - 在 ruby on rails 中显示嵌套的 JSON
- acumatica - PXUIField 属性如何在 2019 R1 中禁用处理页面上的文本编辑框?
- symfony - Symfony 4:属性 App\Entity\Ad::$site 不存在(但无法在代码中找到?)
- postman - 导出 G Suite 中所有群组的列表