2

This is more of a logic question than a Phaser 3 question. I am trying to make the game 'snake'. I can move 1 body up, down, left, and right easily, however, I do have issues when there is more than 1 body of 'snake'. In snake, when the front of a snake switches directions, the others follow suit in such a way so that they stay behind the snake. I cannot seem to figure out how to do this- changing the direction respectively for all of the 'other' bodies behind the 'snake'. In short, this is basically one sprite following another sprite. I would appreciate some help on this. Here is my code so far:

create() {
    this.snake = this.physics.add.group()
    this.front = this.snake.create(25,25,"tile").setScale(0.12)
}

This is where I create my snake, as well as the 'front' of the snake.

 update() {
    this.cursors = this.input.keyboard.createCursorKeys()
    if (this.cursors.right.isDown) {
        this.x_vel = this.vel
        this.y_vel = 0
        this.DIRECTION = "right"
    } if (this.cursors.left.isDown) {
        this.x_vel = -this.vel
        this.y_vel = 0
        this.DIRECTION = "left"
    } if (this.cursors.up.isDown) {
        this.x_vel = 0
        this.y_vel = -this.vel
        this.DIRECTION = "up"
    } if (this.cursors.down.isDown) {
        this.x_vel = 0
        this.y_vel = this.vel
        this.DIRECTION = "down"
    }
    this.front.x += this.x_vel
    this.front.y += this.y_vel

}

This is how I will move my snake. I am only moving the 'front' of the snake because I want all of the other snake 'bodies' to follow the 'front' of the snake.

I have tried looking at other snake projects, especially those on phaser discussions and on medium, but they don't go over the details that much and I have trouble following their code.

1 Answer 1

2

There are many different way's to do this, one easy solution is the way show on an official phaser game example (It uses the old Phaser "class" creation, but the idea is still the same)

Basically just use the built-in function Phaser.Actions.ShiftPosition here is the link to the documentation. This function shifts the position of all items in array, to the last position of the previous item. So basically this function hast all the logic, and move the snake.

You just need to create a Group (or you can use an array) with the body parts and pass it to the function, and the function will take care of moving each child.

Phaser.Actions.ShiftPosition(myObjects, 400, 300);

Phaser.Actions.ShiftPosition(...) is the function to call
myObjects is the list of snake parts you want to move
400,300 should be the new position for the first item in the Array

Tipp: In your posted code, I would move this line this.cursors = this.input.keyboard.createCursorKeys() into the create function, since you just have to set this.cursor once.

Here is a Short Demo:
(ShowCasing the shifting array)

const COLORS = [ 0x9bbc0f, 0x8bac0f, 0x306230, 0x0f380f ];

class DemoScene extends Phaser.Scene {
    
    preload(){
       //create texture for the demo
       let graphics  = this.make.graphics();
       graphics.fillStyle( 0xff0000 );
       graphics.fillRect(0, 0, 8, 8);
       graphics.generateTexture(`texture`, 8, 8);
    }

    create () {
        this.add.text(10,10,'Demo');
        
        this.snake = this.add.group();
        
        // create head
        this.snake.create(100, 100, 'texture');
       
        // body part1
        this.snake.create(90, 100, 'texture');    
        // body part2
        this.snake.create(80, 100, 'texture');    
                
        // move timer
        this.lastStep  = 0
        
    }
    
    update (delta) {
        //movement should be improved, this is just for the demo
        
        if(this.lastStep + 10 < delta ){
        
            let bodyParts = this.snake.getChildren();
            let {x, y} = bodyParts[bodyParts.length - 1];
            
            // here the magic happens
            Phaser.Actions.ShiftPosition( bodyParts, bodyParts[0].x + 1, bodyParts[0].y)   
            
            this.lastStep = delta
            
        }
    }

}

var config = {
    width: 540,
    height: 180,
    scene: DemoScene,
}; 

new Phaser.Game(config);

console.clear();
document.body.style = 'margin:0;';
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

Sign up to request clarification or add additional context in comments.

4 Comments

Hello there! Thanks for the quick answer. I have utilized your links and went to Phaser's lab code for the snake game, and I'm glad to say, both your and Phaser's demo code helped me in finding the solution! I will have to look at their documentation a bit more; they have helpful information. I managed to use the .ShiftPosition() function to my advantage, and now the snake turns just fine- but the transitions aren't smooth. The snake body isn't even when it turns left, right, up, or down. The blocks aren't aligned with each other.
I have tried decreasing and increasing the this.move time to see if that would help the blocks be more even on the turns, or decreasing the velocity, but that didn't help.
Never mind! I have figured it out. Here is the answer for anyone who happens to stumble upon this thread: I have setted up a timer where if the timer is greater than 100 milliseconds, I update my x's and y's values with this.vel. The snake body wasn't aligned because I have continuously updated my x's and y's values. By only updating them after 100 milliseconds have passed, my snake body became aligned and the tiles were even with each other.
Perfect that you could figure it out, and thank you for sharing you finding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.