2015-12-16 12 views
5

मैं थोड़ा छोटा टाइल इंजन गेम बना रहा हूं। मैं वर्तमान में सरल ब्लॉक आधारित टकराव का पता लगाने पर काम कर रहा हूं, हालांकि मुझे वास्तविक समस्याएं हैं। मैंने घंटों के लिए इसे विभिन्न कार्यान्वयन पर देखकर गुमराह किया है लेकिन मेरे सिर को इसके चारों ओर नहीं लग रहा है। मेरा वर्तमान प्रयास (केवल वर्तमान में टकराव का पता लगाने पर जब खिलाड़ी सही) चलाता है, ज्यादातर काम करता है लेकिन खिलाड़ी को बाधा के निचले भाग से गुज़रने की अनुमति देता है। टकराव टकराव का पता लगाने के लिए सामान्य मानचित्र सरणी का उपयोग करता है, मानचित्र में 2 का कोई भी मान एक ठोस वस्तु है।जावास्क्रिप्ट कैनवास गेम - टकराव का पता लगाने

मैं क्या मैं क्या करने की जरूरत के सिद्धांतों को समझें -। इससे पहले कि मैं अपने खिलाड़ी ले जाते हैं, की गणना क्या सेल खिलाड़ी में खत्म हो जाएगा की जाँच करें क्या मूल्य है कि सेल को सौंपा गया है। यदि यह 2 है, तो खिलाड़ी को स्थानांतरित करने की अनुमति न दें।

मेरा मुद्दा यह पता लगा रहा है कि प्लेयर किस तकनीकी रूप से तकनीकी रूप से समाप्त होगा, अंक पर, खिलाड़ी एक ही समय में 4 कोशिकाओं में हो सकता है। मैंने इसे पाने के लिए उत्पत्ति और 4 कोने का पता लगाने का प्रयास किया है, लेकिन मैं इसे काम नहीं कर सकता।

जे एस यहाँ फिडल - https://jsfiddle.net/j1xqxze8/

मेरे संहिता,

var Player = function() { 
     this.width = 16; 
     this.height = 16; 
     this.position = {}; 
     this.position.x = 32; 
     this.position.y = 32; 
     this.speed  = 8; 

     this.render = function() { 
      window.context.fillStyle = 'white'; 
      window.context.fillRect(this.position.x, this.position.y, this.width, this.height); 
     }; 

     var _self = this; 

     this.didCollide = function(dir) { 
      if(dir == 'right'){ 
       var newBlock = window.tileMap.getCell(Math.floor((_self.position.x + _self.width)/32), Math.floor((this.position.y + this.height/2)/32)); 

       if(newBlock == 2) 
        return true; 
      } 
     }; 

     window.addEventListener('keydown', function(e) { 
      if(e.keyCode == 38 || e.keyCode == 87){ 
       _self.position.y -= _self.speed; 
      } 

      if(e.keyCode == 40 || e.keyCode == 83){ 
       _self.position.y += _self.speed; 
      } 

      if(e.keyCode == 37 || e.keyCode == 65){ 
       _self.position.x -= _self.speed; 
      } 

      if(e.keyCode == 39 || e.keyCode == 68){ 
       if(!_self.didCollide('right')){ 
        _self.position.x += _self.speed; 
       } 
      } 
     }) 
    }; 

var TileMap = function() { 
    this.map = [ 
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
    ]; 

    this.tileSize = 32; 
    this.colors = ['black', 'red', 'green']; 

    this.getCell = function(x, y){ 
     return this.map[y][x]; 
    }; 

     this.render = function(){ 
      for(var x = 0; x < this.map.length; x++){ 
       for(var y = 0; y < this.map.length; y++){ 
        // SWAP Y AND X IN THE FILLSTYLE DUE TO BACKWARDS/MIRRORED JS ARRAY READING 
        window.context.fillStyle = this.colors[this.map[y][x]]; 
        window.context.fillRect((x * this.tileSize) - window.camera.position.x, (y * this.tileSize) - window.camera.position.y, this.tileSize, this.tileSize); 

        window.context.strokeStyle = 'yellow'; 
        window.context.strokeRect((x * this.tileSize) - window.camera.position.x, (y * this.tileSize) - window.camera.position.y, this.tileSize, this.tileSize); 
       } 
      } 
     } 
    }; 
+1

चूंकि आप प्रति कुंजीडाउन में 8 पदों को स्थानांतरित कर रहे हैं, तो कुंजीडाउन में आपको टकराव होने पर यह देखने के लिए उन 8 पदों में से प्रत्येक का परीक्षण करना होगा। – markE

+0

मैं गति की डिग्री बदलती, 1 सहित (ताकि केवल के रूप में स्थिति एक बार अद्यतन) और यहां तक ​​कि इस स्तर पर, समस्या अभी भी जहां आप गहराई से वस्तु के लिए क्लिप कर सकते हैं तब होता है के साथ इस की कोशिश की है - धन्यवाद, हालांकि :) – Lewis

+0

मैं एक (किसी न किसी तरह, untested) प्रत्येक अंतरिम स्थिति का परीक्षण करने के लिए कैसे अगर एक टक्कर होती है देखने के लिए दिखा जवाब जोड़ दिया है। – markE

उत्तर

1

जब से तुम खिलाड़ी keydown प्रति 8 पदों, keydown में आप उन 8 अंतरिम पदों में से प्रत्येक का परीक्षण करना चाहिए आगे बढ़ रहे हैं अगर एक टक्कर होती है देखने के लिए।

चेतावनी: - (! शायद) अपरीक्षित कोड कुछ फेरबदल

window.addEventListener('keydown', function(e) { 
    // save x,y before the move 
    var beginningX=_self.position.x; 
    var beginningY=_self.position.y; 

    // test each interim positon between the beginning & 
    // current position for collisions 
    // if a collision occurs, stop at the collision position 
    if(e.keyCode == 38 || e.keyCode == 87){ 
     _self.position.y -= _self.speed; 
     _self.position.y = testInterimVerticalCollisions(
      beginningY, _self.position.y, _self.position.x); 
    } 

    if(e.keyCode == 40 || e.keyCode == 83){ 
     _self.position.y += _self.speed; 
     _self.position.y = testInterimVerticalCollisions(
      beginningY, _self.position.y, _self.position.x); 
    } 

    if(e.keyCode == 37 || e.keyCode == 65){ 
     _self.position.x -= _self.speed; 
     _self.position.x = testInterimHorizontalCollisions(
      beginningX, _self.position.x, _self.position.y); 
    } 

    if(e.keyCode == 39 || e.keyCode == 68){ 
     _self.position.x += _self.speed; 
     _self.position.x = testInterimHorizontalCollisions(
      beginningX, _self.position.x, _self.position.y); 
     } 
    } 
}) 

// test if any interim movement caused a collision 
// if yes, return the x that caused the collision 
// if no, return the ending x 
function testInterimHorizontalCollisions(beginningX,endingX,y){ 
    for(var x=beginningX;x<=endingX;x++){ 
     // TODO: adjust for camera position offset 
     var cellX = parseInt(x/cellWidth); 
     var cellY = parseInt(y/cellHeight); 
     if(getCell(cellX,cellY)==2){return(x);} 
    } 
    return(endingX); 
} 

// test if any interim movement caused a collision 
// if yes, return the y that caused the collision 
// if no, return the ending y 
function testInterimVerticalCollisions(beginningY,endingY,x){ 
    for(var y=beginningY;y<=endingY;y++){ 
     // TODO: adjust for camera position offset 
     var cellX = parseInt(x/cellWidth); 
     var cellY = parseInt(y/cellHeight); 
     if(getCell(cellX,cellY)==2){return(y);} 
    } 
    return(endingY); 
} 
+1

धन्यवाद! मैं एक समाधान इस उत्तर के आधार पर के साथ जा रहा समाप्त हो गया। यह सब एक दिन मेरे लिए आसानी से आ जाएगा, लेकिन अभी तक;) – Lewis

2

आप जोड़ने/to/गति घटाकर वर्तमान x/y स्थिति से से खिलाड़ी की नई स्थिति की गणना करने की जरूरत है की आवश्यकता है। फिर आपको प्लेयर द्वारा कवर की गई पिक्सल की नई स्थिति में गणना करने की आवश्यकता है। फिर आपको पिक्सेल की सीमा से संबंधित कोशिकाओं की श्रेणी की गणना करने की आवश्यकता है। फिर आपको किसी भी टकराव होने के लिए कोशिकाओं की सीमा के माध्यम से लूप करने की आवश्यकता है। ध्यान दें कि जब सही/नीचे खिलाड़ी द्वारा कवर पिक्सेल कंप्यूटिंग, आप x/y और चौड़ाई/ऊंचाई को जोड़ने के लिए और फिर घटाना 1.

बदलें जरूरत है ...

this.didCollide = function(dir) { 
    if(dir == 'right'){ 
     var newBlock = window.tileMap.getCell(Math.floor((_self.position.x + _self.width)/32), Math.floor((this.position.y + this.height/2)/32)); 
     if(newBlock == 2) 
      return true; 
    } 
}; 

...

को
this.didCollide = function(dir) { 
    if(dir == 'right'){ 
     var col1 = Math.floor((_self.position.x + _self.speed)/32); 
     var col2 = Math.floor((_self.position.x + _self.speed + _self.width - 1)/32); 
     var row1 = Math.floor((_self.position.y)/32); 
     var row2 = Math.floor((_self.position.y + _self.height - 1)/32); 
     document.getElementById("player").textContent = "player: " + _self.position.x + " " + _self.position.y + " " + _self.width + " " + _self.height; 
     document.getElementById("cells").textContent = "cells: " + col1 + " " + col2 + " " + row1 + " " + row2; 
     for (var c = col1; c <= col2; c++) { 
      for (var r = row1; r <= row2; r++) { 
       var newBlock = window.tileMap.getCell(c, r); 
       if(newBlock == 2) { 
        return true; 
       } 
      } 
     } 
    } 
    return false; 
}; 
संबंधित मुद्दे