处理塔防游戏 - 塔攻击敌人

2023-12-10

我会保持简短,我正在制作一个塔防游戏作为一个迷你项目,同时我有一些空闲时间,我正在尝试弄清楚如何实现塔,以便能够在敌人进入射程时使用 dist 射击敌人但我只是不知道如何实现使用敌人位置和塔位置的方法。我有一个 CreepSprites 和 Towers 的 ArrayList

CreepSprite[] CreepSprites;
ArrayList<Tower> AllTowers = new ArrayList<Tower>();
ArrayList<Creep> AllCreeps = new ArrayList<Creep>();

如果有人能给我一些指导,告诉我如何让塔能够射击小兵,那就太好了,即使它不能消灭它们,只要能够射击它们就太好了。

Cheers


@GoneUp 的答案是正确的。在处理中你有一个名为PVector它还提供了距离方法:dist()

PVector towerPos = new PVector(100, 100);
PVector enemyPos = new PVector(300, 300);

float towerAttackRadius = 200; 


void setup() {
  size(400, 400);
  rectMode(CENTER);
  strokeWeight(3);
}
void draw() {
  background(255);
  //draw tower
  noFill();

  //check range
  if(towerPos.dist(enemyPos) < towerAttackRadius){
    //tower engaged, draw in green
    stroke(0,192,0);
  }else{
    //tower in idle mode, draw in blue
    stroke(0, 0, 192);
  }

  //visualise tower attack radius
  //(towerAttackRadius * 2 -> radius * 2 = diameter (width/height))
  ellipse(towerPos.x, towerPos.y, towerAttackRadius * 2, towerAttackRadius * 2);
  //visualise tower
  rect(towerPos.x, towerPos.y, 30, 30);
  //draw enemy
  stroke(192, 0, 0);
  rect(enemyPos.x, enemyPos.y, 10, 10);
  //instructions
  fill(0);
  text("click and drag to move enemy",10,15);
}

void mouseDragged() {
  enemyPos.set(mouseX, mouseY);
}

我强烈推荐丹尼尔希夫曼的关于向量的代码性质章节。 这是一些线性代数,但它非常有用,特别是对于值得尽早掌握窍门的游戏。

例如,要射击子弹,您需要确定方向。 您可以通过使用向量减法来做到这一点。

此外,您可能想控制子弹在屏幕上朝该方向移动的速度。这也可以通过标准化向量来完成:保持其方向,但将其大小减小到 1.0:

vector normalization diagram from https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/36248/versions/1/screenshot.png

之后,可以轻松地将向量缩放(乘以)到您想要的任何大小。

如果您知道塔的位置,则只需添加此缩放速度即可计算每帧子弹应绘制的位置。

PVector 已经有一个函数可以同时执行以下两个操作:setMag()。 (set mag 是设置幅度(或向量长度)的缩写)

它还提供了一个标题()方便计算角度的功能。

这是一个基本的概念证明:

PVector towerPos = new PVector(100, 100);
PVector enemyPos = new PVector(300, 300);

float towerAttackRadius = 300; 

ArrayList<Bullet> bullets = new ArrayList<Bullet>(); 

void setup() {
  size(400, 400);
  rectMode(CENTER);
  strokeWeight(3);
}
void draw() {
  background(255);

  //check if an enemy is within range using dist()
  //if the distance is smaller than the radius, attack!
  if(towerPos.dist(enemyPos) < towerAttackRadius){

    //hacky frame based counter: please use a millis() based timer instead
    //shoot every 30 frames
    if(frameCount % 30 == 0){
      shoot();
    }

  }

  //update bullets
  for(Bullet b : bullets) {
    b.update();
  }

  //draw tower
  noFill();
  stroke(0, 0, 192);
  //visualise tower attack radius
  //(towerAttackRadius * 2 -> radius * 2 = diameter (width/height))
  ellipse(towerPos.x, towerPos.y, towerAttackRadius * 2, towerAttackRadius * 2);
  //visualise tower
  rect(towerPos.x, towerPos.y, 30, 30);
  //draw enemy
  stroke(192, 0, 0);
  rect(enemyPos.x, enemyPos.y, 10, 10);
  //instructions
  fill(0);
  text("click and drag to move enemy",10,15);
}

void mouseDragged() {
  enemyPos.set(mouseX, mouseY);
}

void shoot(){
  //make a new Bullet pointing from the tower to the enemy
  Bullet b = new Bullet(towerPos.x,towerPos.y,enemyPos.x,enemyPos.y);
  //add it to the list of bullets (for updates)
  bullets.add(b);

  println(b);
}

class Bullet {
  //where does the bullet shoot from (and it's current position)
  PVector position = new PVector();
  //where does the bullet shooting towards
  PVector target = new PVector();
  //how fast does the bullet move on screen
  float speed = 1.2;
  //how large goes the bullet appear on screen
  float size = 10;

  //bullet velocity
  PVector velocity;

  Bullet(float startX,float startY, float endX, float endY) {
    position.set(startX,startY);
    target.set(endX,endY);

    //compute the difference vector (start to end) = direction
    velocity = PVector.sub(target,position);

    //normalize the vector = same direction but magnitude of 1 -> makes it easy to scale 
    //velocity.normalize();

    //scale by the speed to move on screen)
    //normalize + multiple = resize the vector -> same direction, different length
    //velocity.mult(speed);

    //or do both normalize and multiple using setMag()
    velocity.setMag(speed);  
  }
  void update() {
    //update position based on velocity (simply add velocity to current position)
    position.add(velocity);

    //render
    //compute rotation angle from velocity (implementation is 2D only btw)
    float angle = velocity.heading();
    pushMatrix();
    translate(position.x,position.y);
    rotate(angle);
    stroke(0);
    line(0,0,size,0);
    popMatrix();
  }

  String toString(){
    return position+"->"+target;
  }
}

preview

您实际上可以使用下面的预览来玩:

var towerPos,enemyPos;

var towerAttackRadius = 300; 

var bullets = [];

function setup() {
  createCanvas(400, 400);
  rectMode(CENTER);
  strokeWeight(3);
  
  
  towerPos = createVector(100, 100);
  enemyPos = createVector(300, 300);
}
function draw() {
  background(255);
  
  //check if an enemy is within range using dist()
  //if the distance is smaller than the radius, attack!
  if(towerPos.dist(enemyPos) < towerAttackRadius){
    
    //hacky frame based counter: please use a millis() based timer instead
    //shoot every 30 frames
    if(frameCount % 30 === 0){
      shoot();
    }
    
  }
  
  //update bullets
  for(var i = 0; i < bullets.length; i++) {
    bullets[i].update();
  }

  //draw tower
  noFill();
  stroke(0, 0, 192);
  //visualise tower attack radius 
  //(towerAttackRadius * 2 -> radius * 2 = diameter (width/height))
  ellipse(towerPos.x, towerPos.y, towerAttackRadius * 2, towerAttackRadius * 2);
  //visualise tower
  rect(towerPos.x, towerPos.y, 30, 30);
  //draw enemy
  stroke(192, 0, 0);
  rect(enemyPos.x, enemyPos.y, 10, 10);
  //instructions
  noStroke();
  fill(0);
  text("click and drag to move enemy",10,15);
}

function mouseDragged() {
  enemyPos.set(mouseX, mouseY);
}

function shoot(){
  //make a new Bullet pointing from the tower to the enemy
  var b = new Bullet(towerPos.x,towerPos.y,enemyPos.x,enemyPos.y);
  //add it to the list of bullets (for updates)
  bullets.push(b);
}

function Bullet(startX,startY,endX,endY) {
  //where does the bullet shoot from (and it's current position)
  this.position = createVector(startX,startY);
  //where does the bullet shooting towards
  this.target = createVector(endX,endY);
  //how fast does the bullet move on screen
  this.speed = 1.2;
  //how large goes the bullet appear on screen
  this.size = 10;

  //compute the difference vector (start to end) = direction
  this.velocity = p5.Vector.sub(this.target,this.position);
  //normalize the vector = same direction but magnitude of 1 -> makes it easy to scale 
  this.velocity.normalize();
  //scale by the speed to move on screen)
  //normalize + multiple = resize the vector -> same direction, different length
  this.velocity.mult(this.speed);
  
  this.update = function() {
    //update position based on velocity (simply add velocity to current position)
    this.position.add(this.velocity);
    
    //render
    //compute rotation angle from velocity (implementation is 2D only btw)
    var angle = this.velocity.heading();
    push();
    translate(this.position.x,this.position.y);
    rotate(angle);
    stroke(0);
    line(0,0,this.size,0);
    pop();
  }
  
}


//http://stackoverflow.com/questions/39698472/processing-tower-defence-game-towers-attacking-enemies
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>

祝PVectors 玩得开心! :) 一个重要的note: 上面的代码是概念证明,并未优化。 从长远来看,有很多塔和敌人,它会减慢速度。 一旦你得到了正确的数学/代码,你就可以开始做一些改进:

  • 管理项目符号/实例(例如,重复使用屏幕外的项目符号 而不是一直创建新实例)
  • 使用平方距离magSq()相反,使用平方半径来加速计算
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理塔防游戏 - 塔攻击敌人 的相关文章

随机推荐

  • 如何在同一页面上的 Angular 应用程序和非 Angular 应用程序之间进行通信?

    我正在通过 Angular bootstrapping 使用 Angular 模块将一段非 Angular 网页转换为 Angular 版本 它工作得很好 除了它需要与页面的其他部分进行通信这一事实之外 不幸的是 我目前无法将页面的其余部分
  • 简单的计算由于某种原因不起作用

    好吧 我正在尝试计算两个值的百分比 这应该非常简单 但由于某些奇怪的原因它不起作用 我太累了 太笨了 无法弄清楚 这是我的代码 它一直返回 0 我在调试时检查了这些值 FilesCompleted 为 295 TotalFilesCount
  • 如何将小数四舍五入到小数点后 2 位 (Java)

    我对java相当陌生 我必须创建这个程序 但我不知道从哪里开始 有人可以帮助我做什么以及如何编写代码来开始吗 编写一个模拟收银机的程序 提示用户输入三件商品的价格 将它们加在一起即可得到小计 确定小计的税费 6 求销售小计加税的总金额 显示
  • 如何从 C# 或 VB.Net 使用 Win32 'DwmSetIconicThumbnail'?

    我想使用DwmSetIconicThumbnail函数为我的应用程序的缩略图预览设置静态图像 正如上面的参考链接中指出的 首先需要调用Dwm设置窗口属性启用DWMWA FORCE ICONIC REPRESENTATION and DWMW
  • Xamarin 项目在 Visual Studio 2015 中不可用

    我有一个 Xamarin 解决方案 我已经在 Mac 上工作了一段时间 但现在通过 Visual Studio 中的 Xamarin 集成 我想在 Windows 计算机上工作 我在 Visual Studio 2015 Enterpris
  • DropDownList 的编辑器模板

    我为字符串字段创建了一个 EditorTemplate 它实现了引导程序 如下所示 using MyProject model object div class form group Html LabelFor m gt m new cla
  • 无法将数据表绑定到图表控件

    我想在我的测试应用程序中使用极坐标图 我有一个包含几列的数据表 其中名称为 X 的列应提供 x 值成员 其他列应提供 y 值成员 我在 MSDN 上找到了一个教程 但它并没有真正起作用 因为该行 chart1 DataBindTable d
  • 使用 Highcharts 通过 JSON 重新加载图表数据

    我正在尝试根据页面中其他位置的按钮单击 通过 JSON 重新加载 Highcharts 图表的数据 最初 我想显示一组默认数据 按类别支出 然后根据用户输入加载新数据 例如 按月支出 我能想到的从服务器输出 JSON 的最简单方法是将 GE
  • 如何在“打开方式”对话框中设置程序名称?

    我想要程序读取VLC Move on end 我已将程序集信息修改为以下内容 但无济于事 如何更改 打开方式 对话框中显示的名称 它作为FriendlyAppName 值存储在注册表中的HKCR Applications YourExeNa
  • ASP.NET 中 Session 对象的使用

    我刚刚接到一项新任务来引导其他人创建的网站 但我对网络绝对是新手 该网站采用 ASP NET C 语言 除了Session对象之外 代码本身并不难理解 我不明白它在哪里 如何以及为什么使用 请问有人可以用一个可能的例子解释 Session
  • 如何在 Project Reactor 中实现轮询逻辑?

    我有一个方法发送请求以获取作业状态并返回状态 如下所示 Mono
  • JavaScript 中命名函数优于匿名函数吗? [复制]

    这个问题在这里已经有答案了 可能的重复 JavaScript var functionName function 与 function functionName 在 Javascript 中提取函数有两种可能的方法 var foo func
  • 自由飞行相机 - 绕 X 轴奇怪的旋转

    所以我几乎使用矢量和 gluLookAt 之类的东西实现了一个自由飞行相机 所有 4 个方向的移动和绕 Y 轴的旋转都可以正常工作 For the 绕Y轴旋转我计算眼睛和中心向量之间的向量 然后用旋转矩阵旋转它 如下所示 Vector te
  • 使用托管组件链接到静态库

    在为我的个人小应用程序创建 GUI 后 我尝试将其编译为静态库以在另一个项目中使用 GUI 已创建 并通过托管公共引用类执行其他任务 该类当前只有 5 个函数 但将添加到其中 这是我在静态库中的头文件 它将包含在另一个项目中 好吧 至少是一
  • 服务器和客户端的区别

    服务器和客户端有什么区别 它对某些软件安装有什么区别 例如 我检查了如何下载和安装 cvs 其中一位用户询问了服务器或客户端 服务器是等待传入请求的程序或机器 客户端是向服务器发送请求的程序或机器 维基百科 服务器 计算 客户端 计算 对于
  • 文件数量巨大时如何提高perl中的grep效率

    我想使用 perl 从位于以下目录结构的日志文件中 grep 一些日志信息 jobDir jobXXXX host log where XXXX是职位编号 从 1 到几千 下没有其他类型的子目录 jobDir除了下面的日志之外没有其他文件j
  • Oracle:如果行不存在,如何插入

    在 PL SQL oracle 中 如果行不存在 插入行的最简单方法是什么 我想要类似的东西 IF NOT EXISTS SELECT FROM table WHERE name jonny THEN INSERT INTO table V
  • Firefox 上的 event.target

    var x event target event srcElement document getElementById x id style left 200 px document getElementById x id style to
  • 创建项目后更改视图引擎

    我在asp net mvc4中创建了一个项目并将其视图引擎设置为ASPX 现在 我想将 View Engine 更改为 Razor 怎么做 我不想创建一个新项目 我想使用现有项目来更改视图引擎 我们可以从属性或其他方式更改视图引擎吗 应该像
  • 处理塔防游戏 - 塔攻击敌人

    我会保持简短 我正在制作一个塔防游戏作为一个迷你项目 同时我有一些空闲时间 我正在尝试弄清楚如何实现塔 以便能够在敌人进入射程时使用 dist 射击敌人但我只是不知道如何实现使用敌人位置和塔位置的方法 我有一个 CreepSprites 和