Как бы мне создать коллайдер, который останавливает игру, когда она сталкивается с «персонажем»?

#javascript #p5.js

#javascript #p5.js

Вопрос:

Я все еще новичок в этом деле, поэтому не знаю, как создать коллайдер. Моя конечная цель — создать игру, подобную игре Chrome dinosaur. Те же принципы, и все. Однако мой вопрос в том, как мне вообще создать коллайдер. Я буду использовать .gif для «динозавра». Я хотел бы сделать так, чтобы, если этот коллайдер коснется другого коллайдера, игра остановится и будет показано «game over». Я пытался создать коллайдер, но они просто продолжают отображаться под экраном, на котором показана игра. Советы, рекомендации или рекомендации Ant? Спасибо

Код выглядит следующим образом:

 let img; //background
var bgImg; //also the background
var x1 = 0;
var x2;

var scrollSpeed = 4; //how fast background is

let music; //for music

let catBus; //catbus

//collider variables
let tinyToto;
let tiniestToto;
let hin;
let totoWithBag;
let noFace;
let happySoot;

var mode; //determines whether the game has started

let gravity = 0.2; //jumping forces
let velocity = 0.1;
let upForce = 7;

let startY = 730; //where cat bus jumps from
let startX = 70;

let totoX = 900;
let totoY = 70;

let tinToX = 900;
let tinToY = 70;

var font1; //custom fonts
var font2;

p5.disableFriendlyErrors = true; //avoids errors

function preload() {
  bgImg = loadImage("backgwound.png"); //importing background

  music = loadSound("catbus theme song.mp3"); //importing music

  font1 = loadFont("Big Font.TTF");

  font2 = loadFont("Smaller Font.ttf");

  //tinyToto.setCollider("rectangle",0,25,75,75)
}

function setup() {
  createCanvas(1000, 1000); //canvas size

  img = loadImage("backgwound.png"); //background in

  x2 = width;

  music.loop(); //loops the music

  catBus = {
    //coordinates for catbus
    x: startX,
    y: startY,
  };
  /*
  tinyToto = {
  x: totoX,
  y: totoY,
  }

  tinTo = {
  x : tinToX,
  y: tinToY,
  }
  */
  catGif = createImg("catgif.gif"); //creates catbus
  catGif.position(catBus.x, catBus.y); //creates position
  catGif.size(270, 100); //creates how big
  /*
  tinyToto = createImg("TinyToto.gif")
 tinyToto.position(tinyToto.x, tinyToto.y)
  tinyToto.size(270,100)

  tiniestTo = createImg("tiniest Toto.gif")
  tiniestTo.position(tinToX.x, tinToY.y)
  tiniestTo.size(270,100)
  */

  mode = 0; //game start
  textSize(50); //text size
}

function draw() {
  let time = frameCount; //start background loop

  image(img, 0 - time, 0);

  image(bgImg, x1, 2, width, height);
  image(bgImg, x2, 2, width, height);

  x1 -= scrollSpeed;
  x2 -= scrollSpeed;

  if (x1 <= -width) {
    x1 = width;
  }
  if (x2 <= -width) {
    x2 = width;
  } //end background loop

  fill(128   sin(frameCount * 0.05) * 128); //text colour
  if (mode == 0) {
    textSize(20);
    textFont(font1);
    text("press SPACE to start the game!", 240, 500); //what text to type
  }

  fill("white");
  if (mode == 0) {
    textSize(35);
    textFont(font2);
    text("CATBUS BIZZARE ADVENTURE", 90, 450); //what text to type
  }

  catBus.y = catBus.y   velocity; //code for jumping
  velocity = velocity   gravity;

  if (catBus.y > startY) {
    velocity = 0;
    catBus.y = startY;
  }

  catGif.position(catBus.x, catBus.y);

  //setCollider("tinyToto")
}

function keyPressed() {
  if (keyCode === 32 amp;amp; velocity == 0) {
    //spacebar code
    mode = 1;
    velocity  = -upForce;
  }
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script> 

Комментарии:

1. Привет 🙂 Милая игра. Пожалуйста, сначала улучшите и очистите свой код; в примере кода, который у вас есть, на самом деле нет отображаемых целей, с которыми нужно столкнуться. Также есть некоторые ненужные переменные и проблемы с отступами и тому подобное ~~ : 3 кроме того, вы можете легко запустить этот код в виде фрагмента, если у вас есть fwonts, wemowe backwound mufic и использовать placekitten.com fow youw spwites и fow the backwound: 3

Ответ №1:

ну, вот как я обычно делаю такие штуки:

 function draw(){
     for(let i in objects) // objects would be cactuses or birds
            if(objects[i].x > player.x amp;amp;
               objects[i].x < player.x   player.width amp;amp;
               objects[i].y > player.y amp;amp;
               objects[i].y < player.y   player.height){
            noLoop()
            // maybe do something else here
        } // you could also use: for(let object of objects)
     }
 

или, если вы хотите делать классные вещи:

 let player = new Player()

class Entity {

    hasCollided_pointRect(_x, _y, _width, _height){
        if(this.x > _x          amp;amp;
           this.x < _x   _width amp;amp;
           this.y > _y          amp;amp;
           this.y < _y   _height){
            return true
        }
    }
}

class Cactus extends Entity {
    
    update(){
        if(hasCollided_pointRect(player.x, player.y, player.width, player.height))
            lossEvent()

    }
}

class Player {
    // ...
}

function lossEvent(){
    noLoop()
}
 

это довольно стильный способ сделать это, и для небольшой игры вам действительно не нужно все это

также в MDN есть хорошая статья о rect with rect amp; point with rect столкновениях, point with point столкновение — это просто (x == x amp;amp; y == y)

https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

это одна из моих недавних «функций» потери:

 if(flag.health <= 0){
    noLoop()
    newSplashText("You lost!nPress F5 to restart!", "center", "center", 1)
}
 

Ответ №2:

Способ, которым я обрабатывал игровые состояния в своих играх по обработке, заключался в создании для них отдельных классов. Тогда функция рисования моего основного эскиза выглядела примерно так

 fun draw()
{
    currentState.draw();
}
 

Затем каждое игровое состояние действовало как свои собственные эскизы (например, экран меню, воспроизведение, окончание игры и т. Д.) И Имело ссылку на основной эскиз, который создавал состояния. Затем они изменили бы основные currentState на, то есть на и т.д. new GameOverState() при необходимости.

На данный момент не беспокойтесь об этом слишком много, если все, что вам нужно, это действительно простой игровой экран с изображением и текстом.

Вместо этого я бы предложил такую структуру. Используйте этот псевдокод в своей основной функции рисования:

 fun draw()
{
    if (gameOver)
    {
        // show game over screen
        img(gameOver);
        text("game over!");
        // skip rest of the function
        return;   
    }

    // normal game code goes here
    foo();
    bar();
    
    // update game over after this frame's game code completes
    gameOver = checkGameOver();
}
 

Теперь вам нужен способ проверки на наличие столкновения, чтобы определить результат checkGameOver()

Для обработки столкновений ознакомьтесь с книгой / веб-сайтом Джеффри Томпсона по обработке столкновений. Это потрясающий ресурс, я настоятельно рекомендую вам его проверить.

С веб-сайта, на который я только что ссылался, вот выдержка с веб-сайта, в которой говорится об обработке столкновений между 2d-прямоугольниками.

введите описание изображения здесь

И вот измененная версия функции обработки столкновений, перечисленная там (я обновил имена переменных, чтобы они были немного более интуитивно понятными)

 boolean rectRect(float rect1X, float rect1Y, float rect1Width, float rect1Height, float rect2X, float rect2Y, float rect2Width, float r2h)
{

    // are the sides of one rectangle touching the other?

    if (rect1X   rect1Width >= rect2X amp;amp;    // r1 right edge past r2 left
        rect1X <= rect2X   rect2Width amp;amp;    // r1 left edge past r2 right
        rect1Y   rect1Height >= rect2Y amp;amp;    // r1 top edge past r2 bottom
        rect1Y <= rect2Y   r2h)
    {    // r1 bottom edge past r2 top
        return true;
    }
    return false;
 

Вы можете использовать эту функцию в своей checkGameOver() функции, которая будет возвращать bool в зависимости от того, соблюдены ли ваши критерии столкновения.
Для вашей игры вы должны перебирать каждое препятствие в своей игре и проверять, перекрываются ли динозавр и препятствие.

Псевдокод:

 boolean checkGameOver()
{
    foreach (Obstacle obstacle in obstacles)
    { 
       if (rectRect(dino, obstacle))
       { 
          return true;
       }
    }
    return false;
}