2016-09-26 5 views
1

私はこの短期間を保つつもりですが、私は空き時間がある間に私はタワーディフェンスのゲームをミニプロジェクトとして作っており、タワーをどのように実装できるかを考えようとしています彼らがdistを使って範囲に入ったときにenimiesを撮影するが、私はちょうどenimiesの位置とtowersの位置を使う方法を実装する方法を知らない。誰かが私は素晴らしいことだゾッとを撃つことができるの塔を作って行くだろうかに関して、私にいくつかのguidenceを与えることができれば、私はそれを取り除くしない場合でも、CreepSpritesのArrayListのタワーズ処理タワー防衛ゲーム - タワーズが敵を攻撃する

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

を持っていますそれらのうち、ちょうどそれらを撃つことができる素晴らしいでしょう。

乾杯

+1

をスピードアップするための二乗半径。あなたはたぶん、タワーとクリープのためのxとyの位置を持っています。だから最初に距離を計算する必要があります。これは簡単です: '' 'xd = x2-x1、yd = y2-y1、dist = sqrt(xd * xd + yd * yd)' ''次に、クリープが移動するたびにチェックする更新ループが必要ですそれは範囲に来る、またはそれから出る。もしそうなら、塔は撃つかもしれません。 –

+0

私はメソッドを作成し、60fpsで実行されるdrawクラスを置くことを考えていましたが、メソッドにはifステートメントがあります – Michael

答えて

1

あなたは、Xを表現するために、あなたの図のy座標を表すPoint2Dクラスを使用することができます。このクラスには、半径に対してチェックできる事前実装が実装されています(distance method)。

+1

これは[タグ:処理中]の質問です。処理には既に 'dist()'関数とポイントを表す 'PVector'クラスがあります。 –

+0

Wops。それを見ていない。ヒントをありがとう。 – GoneUp

6

@ゴーンアップの答えは正しい方向です。 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

そのポイントの後には、(乗算)したい任意のサイズにベクトルをスケーリングするのは簡単です。

タワーの位置がわかっている場合は、各フレームに弾丸を描画する場所を計算するために、このスケールされた速度を追加するだけです。

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

あなたが実際にプレビュー怒鳴ると遊ぶことができます。

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()経由二乗距離を使用して計算
関連する問題