@ゴーンアップの答えは正しい方向です。 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);
}
私は暖かくダニエル・シフマンのNature of Code chapter on Vectorsをお勧めします:処理ではあなたにも距離法を提供PVectorというクラスを持っています。 これは少し線形代数ですが、特にゲームのために非常に便利です。早くそれを掛ける価値があります。
たとえば、弾丸を撃つには、方向を向ける必要があります。 これは、ベクトル減算を使用して行うことができます。
また、弾丸が画面上でその方向にどれくらい速く移動するかを制御したいと思うでしょう。それは方向だ保ち、それを低減することが1.0にサイズです:それはまた、ベクトルを正規化することによって行うことができます
![vector normalization diagram from https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/36248/versions/1/screenshot.png](https://i.stack.imgur.com/KL5HP.png)
そのポイントの後には、(乗算)したい任意のサイズにベクトルをスケーリングするのは簡単です。
タワーの位置がわかっている場合は、各フレームに弾丸を描画する場所を計算するために、このスケールされた速度を追加するだけです。
PVectorには、すでにsetMag()の両方の機能を備えています。 (セットマグはセットマグニチュード(またはベクトル長)の略)
また角度を練習するのに便利なheading()機能を提供します。ここで
がコンセプトの基本的な証拠です:
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](https://i.stack.imgur.com/yqeaZ.png)
あなたが実際にプレビュー怒鳴ると遊ぶことができます。
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を楽しんで!:) 重要なもの注: 上記のコードは概念の証明であり、最適化されていません。 多くのタワーと敵を持つ長期的には、それは減速します。
- は(画面 ではなく、新しいインスタンスのすべての時間を作るオフになっているなどの再利用弾)弾丸/インスタンスを管理
:あなたは数学/コード権を得れば は、あなたは、いくつかの改善をやって起動することができます
- は、私は非常にあなたが求めているものを取得しない代わりにmagSq()経由二乗距離を使用して計算
をスピードアップするための二乗半径。あなたはたぶん、タワーとクリープのためのxとyの位置を持っています。だから最初に距離を計算する必要があります。これは簡単です: '' 'xd = x2-x1、yd = y2-y1、dist = sqrt(xd * xd + yd * yd)' ''次に、クリープが移動するたびにチェックする更新ループが必要ですそれは範囲に来る、またはそれから出る。もしそうなら、塔は撃つかもしれません。 –
私はメソッドを作成し、60fpsで実行されるdrawクラスを置くことを考えていましたが、メソッドにはifステートメントがあります – Michael